Skip to content

Commit

Permalink
Add errors for break/continue labels
Browse files Browse the repository at this point in the history
  • Loading branch information
jdkaplan committed May 20, 2024
1 parent 03764b8 commit 9d3db38
Show file tree
Hide file tree
Showing 32 changed files with 1,731 additions and 26 deletions.
17 changes: 8 additions & 9 deletions src/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ pub enum CompileError {
#[error("`self` used outside of method definition")]
SelfOutsideMethod,

#[error("no prior label for `break`: {}", .0.name)]
NoBreakLabel(Identifier),

#[error("no prior label for `continue`: {}", .0.name)]
NoContinueLabel(Identifier),

#[error("{0}")]
Other(String), // TODO: Define other compile errors
}
Expand Down Expand Up @@ -748,7 +754,6 @@ impl Compiler {
Primary::If(if_) => self.expr_if(if_),
Primary::Atom(atom) => self.atom(atom),
Primary::Group(expr) => self.expression(expr),
Primary::Object(obj) => self.expr_object(obj),
}
}

Expand Down Expand Up @@ -1272,10 +1277,7 @@ impl Loops {
return Ok(());
}
}
Err(CompileError::Other(format!(
"no label for break: {:?}",
name
)))
Err(CompileError::NoBreakLabel(name.clone()))
} else {
let lp = self.0.last_mut().ok_or(CompileError::Other(String::from(
"break statement outside of loop",
Expand All @@ -1293,10 +1295,7 @@ impl Loops {
return Ok(lp);
}
}
Err(CompileError::Other(format!(
"no label for continue: {:?}",
name
)))
Err(CompileError::NoContinueLabel(name.clone()))
} else {
self.0.last().ok_or(CompileError::Other(String::from(
"continue statement outside of loop",
Expand Down
3 changes: 1 addition & 2 deletions src/parse/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,6 @@ pub enum Primary {
Block(Block),
If(If),
Group(Box<Expression>),
Object(Object),

Atom(Atom),
}
Expand All @@ -193,7 +192,7 @@ pub struct List {
impl Primary {
pub fn self_terminating(&self) -> bool {
match self {
Primary::Block(_) | Primary::If(_) | Primary::Object(_) => true,
Primary::Block(_) | Primary::If(_) => true,
Primary::Atom(_) | Primary::Group(_) => false,
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
source: src/parse/lexer.rs
description: "loop outer {\n break inner;\n}\n"
input_file: test_programs/err_compile/break_label_missing.blis
---
[
Lexeme(
token: Loop,
text: "loop",
line: 1,
),
Lexeme(
token: Identifier,
text: "outer",
line: 1,
),
Lexeme(
token: LeftBrace,
text: "{",
line: 1,
),
Lexeme(
token: Break,
text: "break",
line: 2,
),
Lexeme(
token: Identifier,
text: "inner",
line: 2,
),
Lexeme(
token: Semicolon,
text: ";",
line: 2,
),
Lexeme(
token: RightBrace,
text: "}",
line: 3,
),
Lexeme(
token: Eof,
text: "",
line: 4,
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
source: src/parse/lexer.rs
description: "loop outer {\n continue inner;\n}\n"
input_file: test_programs/err_compile/continue_label_missing.blis
---
[
Lexeme(
token: Loop,
text: "loop",
line: 1,
),
Lexeme(
token: Identifier,
text: "outer",
line: 1,
),
Lexeme(
token: LeftBrace,
text: "{",
line: 1,
),
Lexeme(
token: Continue,
text: "continue",
line: 2,
),
Lexeme(
token: Identifier,
text: "inner",
line: 2,
),
Lexeme(
token: Semicolon,
text: ";",
line: 2,
),
Lexeme(
token: RightBrace,
text: "}",
line: 3,
),
Lexeme(
token: Eof,
text: "",
line: 4,
),
]
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
source: src/parse/lexer.rs
description: "println(\"1\" + 1);\n"
input_file: test_programs/err_runtime/bad_math.blis
input_file: test_programs/err_runtime/bad_math_1.blis
---
[
Lexeme(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
source: src/parse/lexer.rs
description: "println(1 + 2.0);\n"
input_file: test_programs/err_runtime/bad_math_2.blis
---
[
Lexeme(
token: Identifier,
text: "println",
line: 1,
),
Lexeme(
token: LeftParen,
text: "(",
line: 1,
),
Lexeme(
token: Integer,
text: "1",
line: 1,
),
Lexeme(
token: Plus,
text: "+",
line: 1,
),
Lexeme(
token: Float,
text: "2.0",
line: 1,
),
Lexeme(
token: RightParen,
text: ")",
line: 1,
),
Lexeme(
token: Semicolon,
text: ";",
line: 1,
),
Lexeme(
token: Eof,
text: "",
line: 2,
),
]
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
source: src/parse/lexer.rs
description: "func main() {\n let x = 0;\n loop twice {\n if x >= 2 {\n break;\n }\n\n println(\"twice before\", x);\n x = x + 1;\n println(\"twice after \", x);\n }\n println(\"out of twice\", x);\n\n loop outer {\n if x < 0 {\n println(\"break outer\", x);\n break;\n }\n\n loop inner {\n loop {\n break;\n }\n\n if x > 2 {\n println(\"break inner\", x);\n break;\n }\n\n println(\"inner before\", x);\n x = x + 1;\n println(\"inner after \", x);\n }\n println(\"out of inner\", x);\n // x = 3\n\n if x > 2 {\n x = -1;\n continue;\n }\n\n println(\"never happens\");\n x = x - 1;\n }\n println(\"out of outer\", x);\n}\n\nmain();\n"
description: "func main() {\n let x = 0;\n loop twice {\n if x >= 2 {\n break twice;\n }\n\n println(\"twice before\", x);\n x = x + 1;\n println(\"twice after \", x);\n }\n println(\"out of twice\", x);\n\n loop outer {\n if x < 0 {\n println(\"break outer\", x);\n break;\n }\n\n loop inner {\n loop {\n break;\n }\n\n if x > 2 {\n println(\"break inner\", x);\n break;\n }\n\n println(\"inner before\", x);\n x = x + 1;\n println(\"inner after \", x);\n }\n println(\"out of inner\", x);\n // x = 3\n\n if x > 2 {\n x = -1;\n continue;\n }\n\n println(\"never happens\");\n x = x - 1;\n }\n println(\"out of outer\", x);\n}\n\nmain();\n"
input_file: test_programs/loops.blis
---
[
Expand Down Expand Up @@ -99,6 +99,11 @@ input_file: test_programs/loops.blis
text: "break",
line: 5,
),
Lexeme(
token: Identifier,
text: "twice",
line: 5,
),
Lexeme(
token: Semicolon,
text: ";",
Expand Down
Loading

0 comments on commit 9d3db38

Please sign in to comment.