Skip to content

Commit 3c8cb82

Browse files
committed
fix(rivetc.codegen): fix break with defer statement
1 parent 3d75cd2 commit 3c8cb82

File tree

5 files changed

+37
-11
lines changed

5 files changed

+37
-11
lines changed

lib/core/src/test_runner.ri renamed to lib/core/src/TestRunner.ri

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,28 +14,28 @@ extern (Rivet) {
1414
static testRunner: TestRunner;
1515
}
1616

17-
public func bold(msg: string) -> string {
17+
func bold(msg: string) -> string {
1818
if !supportColor {
1919
return msg;
2020
}
2121
return "\x1b[1m{}\x1b[22m".fmt(msg);
2222
}
2323

24-
public func green(msg: string) -> string {
24+
func green(msg: string) -> string {
2525
if !supportColor {
2626
return msg;
2727
}
2828
return "\x1b[32m{}\x1b[39m".fmt(msg);
2929
}
3030

31-
public func red(msg: string) -> string {
31+
func red(msg: string) -> string {
3232
if !supportColor {
3333
return msg;
3434
}
3535
return "\x1b[31m{}\x1b[39m".fmt(msg);
3636
}
3737

38-
public func yellow(msg: string) -> string {
38+
func yellow(msg: string) -> string {
3939
if !supportColor {
4040
return msg;
4141
}
@@ -75,7 +75,7 @@ struct Test {
7575
mut err: Throwable;
7676
}
7777

78-
public struct TestRunner {
78+
struct TestRunner {
7979
tests: []mut Test;
8080
mut ok_tests: uint64;
8181
mut fail_tests: uint64;

rivetc/src/ast.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,14 +312,15 @@ def __init__(self, scope, lefts, right, pos):
312312
self.pos = pos
313313

314314
class WhileStmt:
315-
def __init__(self, cond, continue_expr, stmt, else_stmt, is_inf, pos):
315+
def __init__(self, scope, cond, continue_expr, stmt, else_stmt, is_inf, pos):
316316
self.cond = cond
317317
self.is_inf = is_inf
318318
self.continue_expr = continue_expr
319319
self.has_continue_expr = not isinstance(continue_expr, EmptyExpr)
320320
self.stmt = stmt
321321
self.else_stmt = else_stmt
322322
self.has_else_stmt = else_stmt != None
323+
self.scope = scope
323324
self.pos = pos
324325

325326
class ForStmt:

rivetc/src/codegen/__init__.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ def __init__(self, comp):
139139

140140
self.loop_entry_label = ""
141141
self.loop_exit_label = ""
142+
self.loop_scope = None
142143
self.while_continue_expr = None
143144

144145
def gen_source_files(self, source_files):
@@ -472,6 +473,8 @@ def gen_stmts(self, stmts):
472473

473474
def gen_stmt(self, stmt):
474475
if isinstance(stmt, ast.ForStmt):
476+
old_loop_scope = self.loop_scope
477+
self.loop_scope = stmt.scope
475478
old_while_continue_expr = self.while_continue_expr
476479
old_entry_label = self.loop_entry_label
477480
old_exit_label = self.loop_exit_label
@@ -537,8 +540,11 @@ def gen_stmt(self, stmt):
537540
self.cur_fn.add_label(self.loop_exit_label)
538541
self.loop_entry_label = old_entry_label
539542
self.loop_exit_label = old_exit_label
543+
self.loop_scope = old_loop_scope
540544
self.while_continue_expr = old_while_continue_expr
541545
elif isinstance(stmt, ast.WhileStmt):
546+
old_loop_scope = self.loop_scope
547+
self.loop_scope = stmt.scope
542548
old_while_continue_expr = self.while_continue_expr
543549
old_entry_label = self.loop_entry_label
544550
old_exit_label = self.loop_exit_label
@@ -587,6 +593,7 @@ def gen_stmt(self, stmt):
587593
self.cur_fn.add_label(self.loop_exit_label)
588594
self.loop_entry_label = old_entry_label
589595
self.loop_exit_label = old_exit_label
596+
self.loop_scope = old_loop_scope
590597
self.while_continue_expr = old_while_continue_expr
591598
elif isinstance(stmt, ast.StaticDeclStmt):
592599
if len(stmt.lefts) == 1:
@@ -2331,7 +2338,8 @@ def gen_expr(self, expr, custom_tmp = None):
23312338
self.cur_fn.add_br(self.loop_entry_label)
23322339
else:
23332340
self.gen_defer_stmts(
2334-
scope = expr.scope, run_defer_previous = True
2341+
scope = expr.scope, run_defer_previous = True,
2342+
scope_limit = self.loop_scope
23352343
)
23362344
self.cur_fn.add_br(self.loop_exit_label)
23372345
return ir.Skip()
@@ -2467,7 +2475,7 @@ def gen_defer_stmt_vars(self, defer_stmts):
24672475

24682476
def gen_defer_stmts(
24692477
self, gen_errdefer = False, last_ret_was_err = None, scope = None,
2470-
run_defer_previous = False
2478+
run_defer_previous = False, scope_limit = None
24712479
):
24722480
for i in range(len(self.cur_fn_defer_stmts) - 1, -1, -1):
24732481
defer_stmt = self.cur_fn_defer_stmts[i]
@@ -2477,11 +2485,15 @@ def gen_defer_stmts(
24772485
):
24782486
continue
24792487
if defer_stmt.mode == ast.DeferMode.ERROR and not gen_errdefer:
2480-
# Should be run only when an error occurs
2488+
# should be run only when an error occurs
24812489
continue
24822490
if defer_stmt.mode == ast.DeferMode.SUCCESS and gen_errdefer:
2483-
# Should not be run in case an error occurs
2491+
# should not be run in case an error occurs
24842492
continue
2493+
if scope_limit != None and defer_stmt.scope.start == scope_limit.start:
2494+
# do not generate `defer` that are in a scope greater than
2495+
# the established limit, this is used by `break`
2496+
break
24852497
defer_start = self.cur_fn.local_name()
24862498
defer_end = self.cur_fn.local_name()
24872499
self.cur_fn.add_comment(

rivetc/src/parser.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,7 @@ def parse_stmt(self):
576576
if self.accept(Kind.KwElse):
577577
else_stmt = self.parse_stmt()
578578
return ast.WhileStmt(
579-
cond, continue_expr, stmt, else_stmt, is_inf, pos
579+
self.scope, cond, continue_expr, stmt, else_stmt, is_inf, pos
580580
)
581581
elif self.accept(Kind.KwFor):
582582
pos = self.prev_tok.pos

tests/valid/src/defer_stmt.ri

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,3 +111,16 @@ test "`defer(success)` with throwed error" {
111111
throw_and_defer_error(err_defer) catch {};
112112
@assert(err_defer.i == 4);
113113
}
114+
115+
test "`defer` with `break`" {
116+
mut a := 0;
117+
mut i := 0;
118+
defer @assert(a == 12);
119+
defer a += 2;
120+
while i < 20 : i += 1 {
121+
defer a = 10;
122+
if i == 10 {
123+
break;
124+
}
125+
}
126+
}

0 commit comments

Comments
 (0)