fix: switch lowering supports any number of cases (was capped at 8)
ci / build (ubuntu) (push) Has been cancelled
ci / unit + fmt (push) Has been cancelled
ci / examples (push) Has been cancelled
ci / goldens + tools (push) Has been cancelled
ci / apps (push) Has been cancelled
ci / selfhost smoke (push) Has been cancelled
ci / macos smoke (push) Has been cancelled
ci / windows smoke (push) Has been cancelled
ci / CI gate (push) Has been cancelled
selfhost-loop / bootstrap determinism (push) Has been cancelled
ci / build (ubuntu) (push) Has been cancelled
ci / unit + fmt (push) Has been cancelled
ci / examples (push) Has been cancelled
ci / goldens + tools (push) Has been cancelled
ci / apps (push) Has been cancelled
ci / selfhost smoke (push) Has been cancelled
ci / macos smoke (push) Has been cancelled
ci / windows smoke (push) Has been cancelled
ci / CI gate (push) Has been cancelled
selfhost-loop / bootstrap determinism (push) Has been cancelled
Replaced fixed-size locals (c0..c7) with O(n^2) linked-list walk that handles arbitrary case counts via reverse-index traversal. Added switch.bux test with 11 and 10 cases.
This commit is contained in:
@@ -5,7 +5,7 @@ BUILD_DIR := build
|
|||||||
# Project-local nimcache so CI can cache compiles (default is ~/.cache/nim).
|
# Project-local nimcache so CI can cache compiles (default is ~/.cache/nim).
|
||||||
NIMFLAGS ?= --nimcache:nimcache
|
NIMFLAGS ?= --nimcache:nimcache
|
||||||
|
|
||||||
EXAMPLES := hello fibonacci factorial structs enums methods algebraic_enums generics generics_struct generic_infer generic_infer2 extend_generic pattern_matching strings strings2 map result_option try_operator ownership ownership_checked ownership_release drop_early_return lifetime_elision ctfe ctfe_crc async concurrency os_time process json iter trait_bounds channel sync jwt stdlib_ergonomics tuples func_ptr map_remove array_iter_extra string_extra multi_closure iter_hof closure_control match_let string_interp iter_generic generic_infer_hof struct_tuple_pat match_block nested_patterns match_guards pattern_shadow move_field move_field_partial move_field_remaining move_field_nested move_field_ptr move_cross_fn c_precedence macro_twice macro_repeat macro_nested macro_hygiene macro_unhygienic macro_stmt_pat macro_tt macro_tt_raw macro_type collections_extra generic_enum
|
EXAMPLES := hello fibonacci factorial structs enums methods algebraic_enums generics generics_struct generic_infer generic_infer2 extend_generic pattern_matching strings strings2 map result_option try_operator ownership ownership_checked ownership_release drop_early_return lifetime_elision ctfe ctfe_crc async concurrency os_time process json iter trait_bounds channel sync jwt stdlib_ergonomics tuples func_ptr map_remove array_iter_extra string_extra multi_closure iter_hof closure_control match_let string_interp iter_generic generic_infer_hof struct_tuple_pat match_block nested_patterns match_guards pattern_shadow move_field move_field_partial move_field_remaining move_field_nested move_field_ptr move_cross_fn c_precedence macro_twice macro_repeat macro_nested macro_hygiene macro_unhygienic macro_stmt_pat macro_tt macro_tt_raw macro_type collections_extra generic_enum switch
|
||||||
|
|
||||||
# Platform smoke (macOS CI): full EXAMPLES still runs on Linux.
|
# Platform smoke (macOS CI): full EXAMPLES still runs on Linux.
|
||||||
EXAMPLES_SMOKE := hello ownership ownership_release strings map move_field move_field_partial move_field_remaining move_field_nested move_field_ptr move_cross_fn c_precedence macro_twice macro_repeat macro_nested macro_hygiene macro_unhygienic macro_stmt_pat macro_tt macro_tt_raw ctfe_crc
|
EXAMPLES_SMOKE := hello ownership ownership_release strings map move_field move_field_partial move_field_remaining move_field_nested move_field_ptr move_cross_fn c_precedence macro_twice macro_repeat macro_nested macro_hygiene macro_unhygienic macro_stmt_pat macro_tt macro_tt_raw ctfe_crc
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
// switch.bux — Test switch with many cases (>8)
|
||||||
|
|
||||||
|
import Std::Io::{PrintLine, PrintInt};
|
||||||
|
|
||||||
|
func Main() -> int {
|
||||||
|
var x: int = 7;
|
||||||
|
|
||||||
|
switch x {
|
||||||
|
case 0:
|
||||||
|
PrintLine("zero");
|
||||||
|
case 1:
|
||||||
|
PrintLine("one");
|
||||||
|
case 2:
|
||||||
|
PrintLine("two");
|
||||||
|
case 3:
|
||||||
|
PrintLine("three");
|
||||||
|
case 4:
|
||||||
|
PrintLine("four");
|
||||||
|
case 5:
|
||||||
|
PrintLine("five");
|
||||||
|
case 6:
|
||||||
|
PrintLine("six");
|
||||||
|
case 7:
|
||||||
|
PrintLine("seven");
|
||||||
|
case 8:
|
||||||
|
PrintLine("eight");
|
||||||
|
case 9:
|
||||||
|
PrintLine("nine");
|
||||||
|
case 10:
|
||||||
|
PrintLine("ten");
|
||||||
|
default:
|
||||||
|
PrintLine("other");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test with match at end
|
||||||
|
x = 15;
|
||||||
|
switch x {
|
||||||
|
case 0:
|
||||||
|
PrintLine("a");
|
||||||
|
case 1:
|
||||||
|
PrintLine("b");
|
||||||
|
case 5:
|
||||||
|
PrintLine("c");
|
||||||
|
case 10:
|
||||||
|
PrintLine("d");
|
||||||
|
case 15:
|
||||||
|
PrintLine("fifteen-ok");
|
||||||
|
case 20:
|
||||||
|
PrintLine("e");
|
||||||
|
case 25:
|
||||||
|
PrintLine("f");
|
||||||
|
case 30:
|
||||||
|
PrintLine("g");
|
||||||
|
case 35:
|
||||||
|
PrintLine("h");
|
||||||
|
case 40:
|
||||||
|
PrintLine("i");
|
||||||
|
default:
|
||||||
|
PrintLine("default");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
+18
-35
@@ -3475,46 +3475,29 @@ module HirLower {
|
|||||||
current = Lcx_LowerBlock(ctx, stmt.refStmtElse, -1);
|
current = Lcx_LowerBlock(ctx, stmt.refStmtElse, -1);
|
||||||
}
|
}
|
||||||
// Cases in reverse order (from caseBlock)
|
// Cases in reverse order (from caseBlock)
|
||||||
|
// Walk linked list: count total, then for each i from total-1 down to 0,
|
||||||
|
// walk from start to find the i-th case. O(n²) but handles any count.
|
||||||
if stmt.refStmtBlock != null as *Block {
|
if stmt.refStmtBlock != null as *Block {
|
||||||
let caseBlock: *Block = stmt.refStmtBlock;
|
let caseBlock: *Block = stmt.refStmtBlock;
|
||||||
var caseCount: int = caseBlock.stmtCount;
|
var total: int = 0;
|
||||||
// Collect cases into fixed-size locals for reverse iteration
|
|
||||||
var c0: *Stmt = null as *Stmt;
|
|
||||||
var c1: *Stmt = null as *Stmt;
|
|
||||||
var c2: *Stmt = null as *Stmt;
|
|
||||||
var c3: *Stmt = null as *Stmt;
|
|
||||||
var c4: *Stmt = null as *Stmt;
|
|
||||||
var c5: *Stmt = null as *Stmt;
|
|
||||||
var c6: *Stmt = null as *Stmt;
|
|
||||||
var c7: *Stmt = null as *Stmt;
|
|
||||||
var ci: int = 0;
|
|
||||||
var cs: *Stmt = caseBlock.firstStmt;
|
var cs: *Stmt = caseBlock.firstStmt;
|
||||||
while cs != null as *Stmt && ci < 8 {
|
while cs != null as *Stmt {
|
||||||
if ci == 0 { c0 = cs; }
|
total = total + 1;
|
||||||
if ci == 1 { c1 = cs; }
|
|
||||||
if ci == 2 { c2 = cs; }
|
|
||||||
if ci == 3 { c3 = cs; }
|
|
||||||
if ci == 4 { c4 = cs; }
|
|
||||||
if ci == 5 { c5 = cs; }
|
|
||||||
if ci == 6 { c6 = cs; }
|
|
||||||
if ci == 7 { c7 = cs; }
|
|
||||||
ci = ci + 1;
|
|
||||||
cs = cs.nextStmt;
|
cs = cs.nextStmt;
|
||||||
}
|
}
|
||||||
while caseCount > 0 {
|
var ri: int = total;
|
||||||
caseCount = caseCount - 1;
|
while ri > 0 {
|
||||||
var c: *Stmt = null as *Stmt;
|
ri = ri - 1;
|
||||||
if caseCount == 0 { c = c0; }
|
// Find ri-th case by walking from start
|
||||||
if caseCount == 1 { c = c1; }
|
var i: int = 0;
|
||||||
if caseCount == 2 { c = c2; }
|
cs = caseBlock.firstStmt;
|
||||||
if caseCount == 3 { c = c3; }
|
while cs != null as *Stmt && i < ri {
|
||||||
if caseCount == 4 { c = c4; }
|
cs = cs.nextStmt;
|
||||||
if caseCount == 5 { c = c5; }
|
i = i + 1;
|
||||||
if caseCount == 6 { c = c6; }
|
}
|
||||||
if caseCount == 7 { c = c7; }
|
if cs != null as *Stmt {
|
||||||
if c != null as *Stmt {
|
let caseVal: *HirNode = Lcx_LowerExpr(ctx, cs.child1);
|
||||||
let caseVal: *HirNode = Lcx_LowerExpr(ctx, c.child1);
|
let caseBody: *HirNode = Lcx_LowerBlock(ctx, cs.refStmtBlock, -1);
|
||||||
let caseBody: *HirNode = Lcx_LowerBlock(ctx, c.refStmtBlock, -1);
|
|
||||||
let cond: *HirNode = bux_alloc(sizeof(HirNode)) as *HirNode;
|
let cond: *HirNode = bux_alloc(sizeof(HirNode)) as *HirNode;
|
||||||
cond.kind = hBinary;
|
cond.kind = hBinary;
|
||||||
cond.intValue = 74; // tkEq
|
cond.intValue = 74; // tkEq
|
||||||
|
|||||||
Reference in New Issue
Block a user