From 107cb3085b88364f75ba4f83e503f4f8e2b00a19 Mon Sep 17 00:00:00 2001 From: cassowarii Date: Tue, 7 Jul 2026 15:07:09 -0700 Subject: [PATCH] evaluate repeat..while/until condition inside block scope --- sample/project_euler/pe02.sa | 7 +++---- src/compile/ir.c | 20 ++++++++++++++++---- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/sample/project_euler/pe02.sa b/sample/project_euler/pe02.sa index 0b7ae20..33615a7 100644 --- a/sample/project_euler/pe02.sa +++ b/sample/project_euler/pe02.sa @@ -11,10 +11,9 @@ let next_fibonacci = (=> { let accumulator = 0 -let f = 0 -while f < 4_000_000 { - f = next_fibonacci() +repeat { + let f = next_fibonacci() accumulator = accumulator + f if f %% 2 -} +} while f < 4_000_000 accumulator diff --git a/src/compile/ir.c b/src/compile/ir.c index a0387e8..1afa198 100644 --- a/src/compile/ir.c +++ b/src/compile/ir.c @@ -539,7 +539,9 @@ static sbIrChunk *compile_ast_function(hIrProgram ir, sbAst paramsAst, sbAst seq return ck; } -static void compile_ast_stmtseq(hIrChunk ck, sbAst seqast, flag implicit_return) { +/* compile a sequence of statements, but don't close the scope yet (used so we can refer + * to inner variables in the condition of a repeat..while) */ +static usize compile_ast_stmtseq_open(hIrChunk ck, sbAst seqast, flag implicit_return) { /* create new scope to hold lexical block variables */ usize lowest_var = ck->program->varmapping.size / sizeof(varmapentry); @@ -609,7 +611,7 @@ static void compile_ast_stmtseq(hIrChunk ck, sbAst seqast, flag implicit_return) considering = considering->seq.right; if (ck->program->error_count > 0) { - return; + return lowest_var; } } @@ -617,6 +619,10 @@ static void compile_ast_stmtseq(hIrChunk ck, sbAst seqast, flag implicit_return) put_implicit_return(ck); } + return lowest_var; +} + +static void close_stmtseq_scope(hIrChunk ck, usize lowest_var) { /* remove extraneous statements, consolidate aliased labels */ usize nstmts = ck->stmts.size / sizeof(sbIrStmt*); usize i = 0; @@ -653,6 +659,11 @@ static void compile_ast_stmtseq(hIrChunk ck, sbAst seqast, flag implicit_return) sbBuffer_set_size(&ck->program->varmapping, lowest_var * sizeof(varmapentry)); } +static void compile_ast_stmtseq(hIrChunk ck, sbAst seqast, flag implicit_return) { + usize lowest_var = compile_ast_stmtseq_open(ck, seqast, implicit_return); + close_stmtseq_scope(ck, lowest_var); +} + static void compile_ast_stmt(hIrChunk ck, sbAst node, flag implicit_return) { sbIrExpr *E1; sbIrLabel *L1, *L2; @@ -824,10 +835,11 @@ static void compile_ast_stmt(hIrChunk ck, sbAst node, flag implicit_return) { */ L1 = new_label(ck); if (node->seq.right) { - E1 = compile_ast_expr(ck, node->seq.right, FALSE); put_label(ck, L1); - compile_ast_stmtseq(ck, node->seq.left, FALSE); + usize lowest_var = compile_ast_stmtseq_open(ck, node->seq.left, FALSE); + E1 = compile_ast_expr(ck, node->seq.right, FALSE); put_jump_if_yes(ck, E1, L1); + close_stmtseq_scope(ck, lowest_var); } else { put_label(ck, L1); compile_ast_stmtseq(ck, node->seq.left, FALSE); -- 1.8.3.1