Feature complete
This commit is contained in:
+92
-13
@@ -66,7 +66,7 @@ impl From<Macro> for LoopType {
|
|||||||
match mac {
|
match mac {
|
||||||
Macro::While => LoopType::While,
|
Macro::While => LoopType::While,
|
||||||
Macro::Until => LoopType::Until,
|
Macro::Until => LoopType::Until,
|
||||||
_ => unreachable!()
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -74,6 +74,7 @@ impl From<Macro> for LoopType {
|
|||||||
enum ControlStructure {
|
enum ControlStructure {
|
||||||
Target(String),
|
Target(String),
|
||||||
Loop(String, LoopType),
|
Loop(String, LoopType),
|
||||||
|
LoopDo(String, String),
|
||||||
}
|
}
|
||||||
|
|
||||||
fn preprocess<'a, T, F>(iter: T, filename: String, include: &F) -> Result<Vec<Line>, AssembleError>
|
fn preprocess<'a, T, F>(iter: T, filename: String, include: &F) -> Result<Vec<Line>, AssembleError>
|
||||||
@@ -139,8 +140,7 @@ where
|
|||||||
return Err(AssembleError::MacroError(line_idx + 1));
|
return Err(AssembleError::MacroError(line_idx + 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Macro::While |
|
Macro::While | Macro::Until => {
|
||||||
Macro::Until => {
|
|
||||||
let label = gensym();
|
let label = gensym();
|
||||||
control_stack.push(ControlStructure::Loop(label.clone(), mac.into()));
|
control_stack.push(ControlStructure::Loop(label.clone(), mac.into()));
|
||||||
all_lines.push(Line {
|
all_lines.push(Line {
|
||||||
@@ -149,8 +149,45 @@ where
|
|||||||
file: filename_stack.last().unwrap().clone(),
|
file: filename_stack.last().unwrap().clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Macro::Do => {}
|
Macro::Do => {
|
||||||
Macro::End => {}
|
if let Some(ControlStructure::Loop(label, loop_type)) = control_stack.pop()
|
||||||
|
{
|
||||||
|
let after = gensym();
|
||||||
|
control_stack.push(ControlStructure::LoopDo(label, after.clone()));
|
||||||
|
let instr = match loop_type {
|
||||||
|
LoopType::While => "brz",
|
||||||
|
LoopType::Until => "brnz",
|
||||||
|
};
|
||||||
|
all_lines.push(Line {
|
||||||
|
line: parse_vasm_line(format!("{} @{}", instr, after).as_str())
|
||||||
|
.unwrap(),
|
||||||
|
line_num: line_idx + 1,
|
||||||
|
file: filename_stack.last().unwrap().clone(),
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
return Err(AssembleError::MacroError(line_idx + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Macro::End => match control_stack.pop() {
|
||||||
|
Some(ControlStructure::Target(label)) => all_lines.push(Line {
|
||||||
|
line: VASMLine::LabelDef(Label::from(label.as_str())),
|
||||||
|
line_num: line_idx + 1,
|
||||||
|
file: filename_stack.last().unwrap().clone(),
|
||||||
|
}),
|
||||||
|
Some(ControlStructure::LoopDo(start, after)) => {
|
||||||
|
all_lines.push(Line {
|
||||||
|
line: parse_vasm_line(format!("jmpr @{}", start).as_str()).unwrap(),
|
||||||
|
line_num: line_idx + 1,
|
||||||
|
file: filename_stack.last().unwrap().clone(),
|
||||||
|
});
|
||||||
|
all_lines.push(Line {
|
||||||
|
line: VASMLine::LabelDef(Label::from(after.as_str())),
|
||||||
|
line_num: line_idx + 1,
|
||||||
|
file: filename_stack.last().unwrap().clone(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
_ => return Err(AssembleError::MacroError(line_idx + 1)),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
normal_line => all_lines.push(Line {
|
normal_line => all_lines.push(Line {
|
||||||
line: normal_line,
|
line: normal_line,
|
||||||
@@ -632,12 +669,13 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_preprocess_if() {
|
fn test_preprocess_if_end() {
|
||||||
let include = |_name: String| Ok(vec![]);
|
let include = |_name: String| Ok(vec![]);
|
||||||
let lines = vec!["#if"];
|
let lines = vec!["#if", "#end"];
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
preprocess(lines, "blah".to_string(), &include),
|
preprocess(lines, "blah".to_string(), &include),
|
||||||
Ok(vec![Line {
|
Ok(vec![
|
||||||
|
Line {
|
||||||
line_num: 1,
|
line_num: 1,
|
||||||
file: "blah".to_string(),
|
file: "blah".to_string(),
|
||||||
line: VASMLine::Instruction(
|
line: VASMLine::Instruction(
|
||||||
@@ -645,7 +683,13 @@ mod test {
|
|||||||
Opcode::Brz,
|
Opcode::Brz,
|
||||||
Some(Node::relative_label("__gensym_1"))
|
Some(Node::relative_label("__gensym_1"))
|
||||||
)
|
)
|
||||||
}])
|
},
|
||||||
|
Line {
|
||||||
|
line_num: 2,
|
||||||
|
file: "blah".to_string(),
|
||||||
|
line: VASMLine::LabelDef(Label::from("__gensym_1"))
|
||||||
|
}
|
||||||
|
])
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -689,13 +733,11 @@ mod test {
|
|||||||
let lines = vec!["#while"];
|
let lines = vec!["#while"];
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
preprocess(lines, "blah".to_string(), &include),
|
preprocess(lines, "blah".to_string(), &include),
|
||||||
Ok(vec![
|
Ok(vec![Line {
|
||||||
Line {
|
|
||||||
line_num: 1,
|
line_num: 1,
|
||||||
file: "blah".to_string(),
|
file: "blah".to_string(),
|
||||||
line: VASMLine::LabelDef(Label("__gensym_1".to_string()))
|
line: VASMLine::LabelDef(Label("__gensym_1".to_string()))
|
||||||
}
|
}])
|
||||||
])
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -703,6 +745,20 @@ mod test {
|
|||||||
fn test_preprocess_until() {
|
fn test_preprocess_until() {
|
||||||
let include = |_name: String| Ok(vec![]);
|
let include = |_name: String| Ok(vec![]);
|
||||||
let lines = vec!["#until"];
|
let lines = vec!["#until"];
|
||||||
|
assert_eq!(
|
||||||
|
preprocess(lines, "blah".to_string(), &include),
|
||||||
|
Ok(vec![Line {
|
||||||
|
line_num: 1,
|
||||||
|
file: "blah".to_string(),
|
||||||
|
line: VASMLine::LabelDef(Label("__gensym_1".to_string()))
|
||||||
|
}])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_preprocess_do_end() {
|
||||||
|
let include = |_name: String| Ok(vec![]);
|
||||||
|
let lines = vec!["#while", "#do", "#end"];
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
preprocess(lines, "blah".to_string(), &include),
|
preprocess(lines, "blah".to_string(), &include),
|
||||||
Ok(vec![
|
Ok(vec![
|
||||||
@@ -710,6 +766,29 @@ mod test {
|
|||||||
line_num: 1,
|
line_num: 1,
|
||||||
file: "blah".to_string(),
|
file: "blah".to_string(),
|
||||||
line: VASMLine::LabelDef(Label("__gensym_1".to_string()))
|
line: VASMLine::LabelDef(Label("__gensym_1".to_string()))
|
||||||
|
},
|
||||||
|
Line {
|
||||||
|
line_num: 2,
|
||||||
|
file: "blah".to_string(),
|
||||||
|
line: VASMLine::Instruction(
|
||||||
|
None,
|
||||||
|
Opcode::Brz,
|
||||||
|
Some(Node::RelativeLabel("__gensym_2".to_string()))
|
||||||
|
)
|
||||||
|
},
|
||||||
|
Line {
|
||||||
|
line_num: 3,
|
||||||
|
file: "blah".to_string(),
|
||||||
|
line: VASMLine::Instruction(
|
||||||
|
None,
|
||||||
|
Opcode::Jmpr,
|
||||||
|
Some(Node::RelativeLabel("__gensym_1".to_string()))
|
||||||
|
)
|
||||||
|
},
|
||||||
|
Line {
|
||||||
|
line_num: 3,
|
||||||
|
file: "blah".to_string(),
|
||||||
|
line: VASMLine::LabelDef(Label::from("__gensym_2"))
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user