feat: execute break and continue in while loops

This commit is contained in:
2026-10-10 01:26:32 +02:00
parent 0add5ab187
commit d51ca57c9e
16 changed files with 612 additions and 21 deletions
+22
View File
@@ -16,6 +16,12 @@ Storage :: struct {
index u32 = 0
}
@hide:file
LoopTargets :: struct {
guard ir.BlockId
exit ir.BlockId
}
@hide:file
State :: struct {
tree @ast.Tree
@@ -28,6 +34,7 @@ State :: struct {
function usize = 0
block ir.BlockId = ir.BlockId(0)
terminated bool = false
loop ?LoopTargets = null
}
#! lowers checked source into caller-owned executable storage; release with ir.deinit.
@@ -357,6 +364,9 @@ lower_while proc(state @mut State, id ast.NodeId) void ! (mem.AllocError | diagn
alternative = exit,
span = ast.node_span(state.tree, loop.condition),
}
previous_loop :: state.loop
state.loop = LoopTargets{ guard = guard, exit = exit }
defer state.loop = previous_loop
state.block = body
try lower_block(state, loop.body, true)
if (!state.terminated) {
@@ -374,6 +384,18 @@ lower_statement proc(state @mut State, id ast.NodeId) void ! (mem.AllocError | d
match ast.stmt_kind(tree, id) {
.if_stmt: try lower_if(state, id)
.while_stmt: try lower_while(state, id)
.break_stmt, .continue_stmt: {
if (trap_type(state, id)) return
if (state.loop) |targets| {
target := targets.exit
# continue restarts the whole guard, before any short-circuit branches.
if (ast.stmt_kind(tree, id) == .continue_stmt) target = targets.guard
state.module.functions.items[state.function].blocks.items[usize(state.block)].terminator = ir.Terminator{
kind = .jump, target = target, span = ast.node_span(tree, id),
}
state.terminated = true
} else unreachable
}
.assignment_stmt: {
assignment :: ast.assignment_stmt(tree, id)
if (trap_binding(state, assignment.target) or trap_type(state, id)) return