Added break statements

This commit is contained in:
2024-05-04 18:57:35 -05:00
parent 3f1b8fd316
commit cd53a21e8f
13 changed files with 138 additions and 6 deletions
+1
View File
@@ -62,6 +62,7 @@ pub enum Macro {
Until,
Do,
End,
Break,
}
#[derive(Debug, PartialEq, Clone)]
+1 -1
View File
@@ -69,7 +69,7 @@ org_directive = { label_def? ~ ".org" ~ expr }
equ_directive = { label_def ~ ".equ" ~ expr }
include = { "include" ~ string }
control = { "if" | "unless" | "while" | "until" | "do" | "else" | "end" }
control = { "if" | "unless" | "while" | "until" | "do" | "else" | "end" | "break" }
preprocessor = {"#" ~ (control | include) }
blank = { WHITESPACE? ~ COMMENT? }
+1
View File
@@ -208,6 +208,7 @@ fn parse_macro(line: Pair) -> Macro {
"until" => Macro::Until,
"do" => Macro::Do,
"end" => Macro::End,
"break" => Macro::Break,
_ => unreachable!(),
},
Rule::include => Macro::Include(create_string(pre.only())),
+63 -2
View File
@@ -81,7 +81,10 @@ impl<T: IntoIterator<Item = String>, F: Fn(String) -> Result<T, AssembleError>>
// It's a macro, so do it and then try again
Ok(VASMLine::Macro(mac)) => {
self.handle_macro(mac);
match self.handle_macro(mac) {
None => {}
Some(err) => return Some(Err(err))
}
self.next()
}
@@ -214,6 +217,20 @@ impl<T: IntoIterator<Item = String>, F: Fn(String) -> Result<T, AssembleError>>
}
_ => return Some(AssembleError::MacroError(self.current_location())),
},
Macro::Break => {
let innermost_loop = self.control_stack.iter().rev().find(|cs| {
match cs {
ControlStructure::LoopDo(_, _) => true,
_ => false
}
});
if let Some(ControlStructure::LoopDo(_, after)) = innermost_loop {
self.emit(format!("jmpr @{}", after));
} else {
return Some(AssembleError::MacroError(self.current_location()))
}
}
}
None
}
@@ -227,10 +244,18 @@ mod tests {
fn lines_for(source: Vec<String>) -> Vec<VASMLine> {
let include = |_name: String| panic!();
let src = LineSource::new("blah", source, include);
let src = LineSource::new("<none>", source, include);
src.map(|line| line.unwrap().line).collect()
}
fn error_for(source: Vec<String>) -> Option<AssembleError> {
let include = |_name: String| panic!();
for line in LineSource::new("<none>", source, include) {
if line.is_err() { return line.err() }
}
None
}
fn stringify(a: Vec<&str>) -> Vec<String> {
a.into_iter().map(String::from).collect()
}
@@ -325,4 +350,40 @@ mod tests {
]
)
}
#[test]
fn test_preprocess_break() {
// First a working one
assert_eq!(
lines_for(stringify(vec!["#while", "#do", "#break", "#end"])),
vec![
VASMLine::LabelDef(Label("__gensym_1".to_string())),
VASMLine::Instruction(
None,
Brz,
Some(Node::RelativeLabel("__gensym_2".to_string()))
),
VASMLine::Instruction(
None,
Jmpr,
Some(Node::RelativeLabel("__gensym_2".to_string()))
),
VASMLine::Instruction(
None,
Jmpr,
Some(Node::RelativeLabel("__gensym_1".to_string()))
),
VASMLine::LabelDef(Label::from("__gensym_2"))
]
);
}
#[test]
fn test_malformed_break() {
// Malformed one
assert_eq!(
error_for(stringify(vec!["#while", "#break"])),
Some(AssembleError::MacroError(Location::from(2)))
)
}
}