Skip to content

Commit 4e717f8

Browse files
committed
Implemented break and continue statements as well as added test cases for them
1 parent 54330dc commit 4e717f8

File tree

7 files changed

+102
-4
lines changed

7 files changed

+102
-4
lines changed

Diff for: src/lexer/identifier_state.rs

+2
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ impl IdentifierState {
4848
"for" => TokenKind::ForKeyword,
4949
"is" => TokenKind::IsKeyword,
5050
"null" => TokenKind::NullKeyword,
51+
"break" => TokenKind::BreakKeyword,
52+
"continue" => TokenKind::ContinueKeyword,
5153
_ => TokenKind::Identifier(identifier),
5254
}
5355
.at(self.start_source)

Diff for: src/lower/builder.rs

+4
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ pub struct Builder<'a> {
1010
basicblocks: BasicBlocks,
1111
current_basicblock_id: usize,
1212
poly_recipe: &'a PolyRecipe,
13+
pub break_basicblock_id: Option<usize>,
14+
pub continue_basicblock_id: Option<usize>,
1315
}
1416

1517
impl<'a> Builder<'a> {
@@ -21,6 +23,8 @@ impl<'a> Builder<'a> {
2123
basicblocks,
2224
current_basicblock_id: 0,
2325
poly_recipe,
26+
break_basicblock_id: None,
27+
continue_basicblock_id: None,
2428
}
2529
}
2630

Diff for: src/lower/expr/mod.rs

+27-4
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use super::{
66
cast::{integer_cast, integer_extend, integer_truncate},
77
datatype::lower_type,
88
error::{LowerError, LowerErrorKind},
9-
stmts::lower_stmts,
9+
stmts::{lower_stmts, lower_stmts_with_break_and_continue},
1010
};
1111
use crate::{
1212
asg::{
@@ -412,7 +412,16 @@ pub fn lower_expr(
412412
));
413413

414414
builder.use_block(true_basicblock_id);
415-
lower_stmts(builder, ir_module, &while_loop.block.stmts, function, asg)?;
415+
lower_stmts_with_break_and_continue(
416+
builder,
417+
ir_module,
418+
&while_loop.block.stmts,
419+
function,
420+
asg,
421+
Some(false_basicblock_id),
422+
Some(evaluate_basicblock_id),
423+
)?;
424+
416425
builder.continues_to(evaluate_basicblock_id);
417426

418427
builder.use_block(false_basicblock_id);
@@ -510,15 +519,29 @@ pub fn lower_expr(
510519
Ok(builder.push(ir::Instr::InterpreterSyscall(*syscall, values)))
511520
}
512521
ExprKind::Break => {
522+
let Some(target_basicblock_id) = builder.break_basicblock_id else {
523+
return Err(LowerErrorKind::Other {
524+
message: "Nowhere to break to".into(),
525+
}
526+
.at(expr.source));
527+
};
528+
513529
builder.push(ir::Instr::Break(Break {
514-
basicblock_id: todo!("break"),
530+
basicblock_id: target_basicblock_id,
515531
}));
516532

517533
Ok(ir::Value::Literal(Literal::Void))
518534
}
519535
ExprKind::Continue => {
536+
let Some(target_basicblock_id) = builder.continue_basicblock_id else {
537+
return Err(LowerErrorKind::Other {
538+
message: "Nowhere to continue to".into(),
539+
}
540+
.at(expr.source));
541+
};
542+
520543
builder.push(ir::Instr::Break(Break {
521-
basicblock_id: todo!("continue"),
544+
basicblock_id: target_basicblock_id,
522545
}));
523546

524547
Ok(ir::Value::Literal(Literal::Void))

Diff for: src/lower/stmts.rs

+22
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,25 @@ pub fn lower_stmts(
8686

8787
Ok(result)
8888
}
89+
90+
pub fn lower_stmts_with_break_and_continue(
91+
builder: &mut Builder,
92+
ir_module: &ir::Module,
93+
stmts: &[asg::Stmt],
94+
func: &asg::Func,
95+
asg: &Asg,
96+
break_basicblock_id: Option<usize>,
97+
continue_basicblock_id: Option<usize>,
98+
) -> Result<Value, LowerError> {
99+
let prev_break_basicblock_id = builder.break_basicblock_id;
100+
let prev_continue_basicblock_id = builder.continue_basicblock_id;
101+
102+
builder.break_basicblock_id = break_basicblock_id.or(builder.break_basicblock_id);
103+
builder.continue_basicblock_id = continue_basicblock_id.or(builder.continue_basicblock_id);
104+
105+
let result = lower_stmts(builder, ir_module, stmts, func, asg);
106+
107+
builder.break_basicblock_id = prev_break_basicblock_id;
108+
builder.continue_basicblock_id = prev_continue_basicblock_id;
109+
result
110+
}

Diff for: src/parser/parse_expr/primary/mod.rs

+8
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,14 @@ impl<'a, I: Inflow<Token>> Parser<'a, I> {
296296
source,
297297
))
298298
}
299+
TokenKind::BreakKeyword => {
300+
self.input.advance().kind.unwrap_break_keyword();
301+
Ok(ExprKind::Break.at(source))
302+
}
303+
TokenKind::ContinueKeyword => {
304+
self.input.advance().kind.unwrap_continue_keyword();
305+
Ok(ExprKind::Continue.at(source))
306+
}
299307
unexpected => Err(ParseError {
300308
kind: match unexpected {
301309
TokenKind::Error(message) => ParseErrorKind::Lexical {

Diff for: tests/success/break/main.adept

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
2+
pragma => adept("3.0")
3+
4+
#[foreign]
5+
func printf(format ptr#char, ...) int
6+
7+
func main {
8+
i := int(0)
9+
10+
while true {
11+
if i > 5 {
12+
break
13+
}
14+
15+
printf(c"%d\n", i)
16+
i += 1
17+
}
18+
}

Diff for: tests/success/continue/main.adept

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
2+
pragma => adept("3.0")
3+
4+
#[foreign]
5+
func printf(format ptr#char, ...) int
6+
7+
func main {
8+
i := int(1)
9+
10+
while i <= 10 {
11+
printf(c"%d", i)
12+
i += 1
13+
14+
if i > 6 {
15+
printf(c"\n")
16+
continue
17+
}
18+
19+
printf(c"!\n")
20+
}
21+
}

0 commit comments

Comments
 (0)