Skip to content

Commit

Permalink
added Assembler struct
Browse files Browse the repository at this point in the history
  • Loading branch information
bobbinth committed Nov 8, 2021
1 parent 4f0900f commit f3b26f6
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 34 deletions.
70 changes: 44 additions & 26 deletions assembly/src/v1/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,38 +20,53 @@ const BEGIN: &str = "begin";
const PROC: &str = "proc";
const END: &str = "end";

// ASSEMBLY COMPILER
// ASSEMBLER
// ================================================================================================

/// TODO: add comments
pub fn compile_script(source: &str) -> Result<Script, AssemblyError> {
let mut tokens = TokenStream::new(source);
let mut proc_map = BTreeMap::new();

// parse procedures and add them to the procedure map; procedures are parsed in the order
// in which they appear in the source, and thus, procedures which come later may invoke
// preceding procedures
while let Some(token) = tokens.read() {
match token[0] {
PROC => parse_proc(&mut tokens, &mut proc_map)?,
_ => break,
}
pub struct Assembler {}

impl Assembler {
pub fn new() -> Assembler {
Self {}
}

// make sure script body is present
let next_token = tokens
.read()
.ok_or_else(|| AssemblyError::missing_begin(tokens.pos()))?;
if next_token[0] != BEGIN {
return Err(AssemblyError::dangling_ops_after_proc(
next_token,
tokens.pos(),
));
/// TODO: add comments
pub fn compile_script(&self, source: &str) -> Result<Script, AssemblyError> {
let mut tokens = TokenStream::new(source);
let mut proc_map = BTreeMap::new();

// parse procedures and add them to the procedure map; procedures are parsed in the order
// in which they appear in the source, and thus, procedures which come later may invoke
// preceding procedures
while let Some(token) = tokens.read() {
match token[0] {
PROC => parse_proc(&mut tokens, &mut proc_map)?,
_ => break,
}
}

// make sure script body is present
let next_token = tokens
.read()
.ok_or_else(|| AssemblyError::missing_begin(tokens.pos()))?;
if next_token[0] != BEGIN {
return Err(AssemblyError::dangling_ops_after_proc(
next_token,
tokens.pos(),
));
}

// parse script body and return the resulting script
let script_root = parse_script(&mut tokens, &proc_map)?;
Ok(Script::new(script_root))
}
}

// parse script body and return the resulting script
let script_root = parse_script(&mut tokens, &proc_map)?;
Ok(Script::new(script_root))
impl Default for Assembler {
fn default() -> Self {
Self::new()
}
}

// PARSERS
Expand Down Expand Up @@ -153,7 +168,10 @@ fn validate_proc_label(label: &str, token: &[&str], step: usize) -> Result<Strin
}

// a label can contain only number, letters, underscores, and colons
if !label.chars().all(|c| c.is_ascii_alphanumeric() || c == '_' || c == ':') {
if !label
.chars()
.all(|c| c.is_ascii_alphanumeric() || c == '_' || c == ':')
{
return Err(AssemblyError::invalid_proc_label(label, token, step));
}

Expand Down
20 changes: 12 additions & 8 deletions assembly/src/v1/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,46 +3,50 @@

#[test]
fn single_span() {
let assembler = super::Assembler::new();
let source = "begin push.1 push.2 add end";
let program = super::compile_script(source).unwrap();
let script = assembler.compile_script(source).unwrap();
let expected = "begin span push(1) push(2) add end end";
assert_eq!(expected, format!("{}", program));
assert_eq!(expected, format!("{}", script));
}

#[test]
fn span_and_simple_if() {
let assembler = super::Assembler::new();

// if with else
let source = "begin push.1 push.2 if.true add else mul end end";
let program = super::compile_script(source).unwrap();
let script = assembler.compile_script(source).unwrap();
let expected = "\
begin \
join \
span push(1) push(2) end \
if.true span add end else span mul end end \
end \
end";
assert_eq!(expected, format!("{}", program));
assert_eq!(expected, format!("{}", script));

// if without else
let source = "begin push.1 push.2 if.true add end end";
let program = super::compile_script(source).unwrap();
let script = assembler.compile_script(source).unwrap();
let expected = "\
begin \
join \
span push(1) push(2) end \
if.true span add end else span noop end end \
end \
end";
assert_eq!(expected, format!("{}", program));
assert_eq!(expected, format!("{}", script));
}

// SCRIPTS WITH PROCEDURES
// ================================================================================================

#[test]
fn script_with_one_procedure() {
let assembler = super::Assembler::new();
let source = "proc.foo push.3 push.7 mul end begin push.1 push.2 add exec.foo end";
let program = super::compile_script(source).unwrap();
let script = assembler.compile_script(source).unwrap();
let expected = "begin span push(1) push(2) add push(3) push(7) mul end end";
assert_eq!(expected, format!("{}", program));
assert_eq!(expected, format!("{}", script));
}

0 comments on commit f3b26f6

Please sign in to comment.