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).
|
||||
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.
|
||||
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);
|
||||
}
|
||||
// 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 {
|
||||
let caseBlock: *Block = stmt.refStmtBlock;
|
||||
var caseCount: int = caseBlock.stmtCount;
|
||||
// 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 total: int = 0;
|
||||
var cs: *Stmt = caseBlock.firstStmt;
|
||||
while cs != null as *Stmt && ci < 8 {
|
||||
if ci == 0 { c0 = cs; }
|
||||
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;
|
||||
while cs != null as *Stmt {
|
||||
total = total + 1;
|
||||
cs = cs.nextStmt;
|
||||
}
|
||||
while caseCount > 0 {
|
||||
caseCount = caseCount - 1;
|
||||
var c: *Stmt = null as *Stmt;
|
||||
if caseCount == 0 { c = c0; }
|
||||
if caseCount == 1 { c = c1; }
|
||||
if caseCount == 2 { c = c2; }
|
||||
if caseCount == 3 { c = c3; }
|
||||
if caseCount == 4 { c = c4; }
|
||||
if caseCount == 5 { c = c5; }
|
||||
if caseCount == 6 { c = c6; }
|
||||
if caseCount == 7 { c = c7; }
|
||||
if c != null as *Stmt {
|
||||
let caseVal: *HirNode = Lcx_LowerExpr(ctx, c.child1);
|
||||
let caseBody: *HirNode = Lcx_LowerBlock(ctx, c.refStmtBlock, -1);
|
||||
var ri: int = total;
|
||||
while ri > 0 {
|
||||
ri = ri - 1;
|
||||
// Find ri-th case by walking from start
|
||||
var i: int = 0;
|
||||
cs = caseBlock.firstStmt;
|
||||
while cs != null as *Stmt && i < ri {
|
||||
cs = cs.nextStmt;
|
||||
i = i + 1;
|
||||
}
|
||||
if cs != null as *Stmt {
|
||||
let caseVal: *HirNode = Lcx_LowerExpr(ctx, cs.child1);
|
||||
let caseBody: *HirNode = Lcx_LowerBlock(ctx, cs.refStmtBlock, -1);
|
||||
let cond: *HirNode = bux_alloc(sizeof(HirNode)) as *HirNode;
|
||||
cond.kind = hBinary;
|
||||
cond.intValue = 74; // tkEq
|
||||
|
||||
Reference in New Issue
Block a user