diff --git a/src/init_analysis.cpp b/src/init_analysis.cpp index 5ec6866..7f6dec1 100644 --- a/src/init_analysis.cpp +++ b/src/init_analysis.cpp @@ -481,31 +481,23 @@ Result Analyzer::analyzeFor(NodeIdx idx, NameMap state) { Result Analyzer::analyzeMatch(NodeIdx idx, NameMap state) { // MatchNode: d.lhs = NodeIdx (scrutinee), d.rhs = ExtraIdx → - // [armCount, elseBodyCount, elseBody..., + // [armCount, // arm0_patIdx, arm0_bodyCount, arm0_body..., // arm1_patIdx, arm1_bodyCount, arm1_body..., ...] + // Catch-all is the wildcard pattern `_`; there is no `else` arm. const AstNode &n = nodes_.get(idx); auto r = analyze(n.lhs, std::move(state)); if (r.terminated) return r; ExtraIdx extra = n.rhs; uint32_t armCount = nodes_.getExtra(extra + 0); - uint32_t elseBodyCount = nodes_.getExtra(extra + 1); NameMap stateBefore = r.state; - // Else-arm body (catch-all). - Result mergedR{NameMap{}, true}; // start as "no arm taken yet" - if (elseBodyCount > 0) { - mergedR = Result{stateBefore, false}; - for (uint32_t i = 0; i < elseBodyCount; i++) { - if (mergedR.terminated) break; - NodeIdx s = nodes_.getExtra(extra + 2 + i); - mergedR = analyze(s, std::move(mergedR.state)); - } - } + // Start as "no arm taken yet"; merge each arm's outcome below. + Result mergedR{NameMap{}, true}; - uint32_t cursor = 2 + elseBodyCount; + uint32_t cursor = 1; for (uint32_t a = 0; a < armCount; a++) { // Arm pattern (index ignored for init analysis — patterns don't // touch existing-binding state in M1). diff --git a/tests/unit/test_enum.jam b/tests/unit/test_enum.jam index 4c0d003..5ef4485 100644 --- a/tests/unit/test_enum.jam +++ b/tests/unit/test_enum.jam @@ -12,7 +12,7 @@ fn classifyColor(c: Color) u8 { Color.Red { return 100; } Color.Green { return 200; } Color.Blue { return 50; } - else { return 0; } + _ { return 0; } } return 99; } @@ -28,7 +28,7 @@ fn colorAsByte(c: Color) u8 { Color.Red { return 0; } Color.Green { return 1; } Color.Blue { return 2; } - else { return 255; } + _ { return 255; } } return 99; } @@ -47,7 +47,7 @@ fn opposite(d: Direction) Direction { Direction.South { return Direction.North; } Direction.East { return Direction.West; } Direction.West { return Direction.East; } - else { return Direction.North; } + _ { return Direction.North; } } return Direction.North; } @@ -59,7 +59,7 @@ fn isOppositePair(d: Direction) u8 { Direction.South { return 2; } Direction.East { return 3; } Direction.West { return 4; } - else { return 99; } + _ { return 99; } } return 0; } @@ -74,7 +74,7 @@ tfn oppositeOfWest() { assert(isOppositePair(Direction.West), 3); } // East fn isHorizontal(d: Direction) u8 { match (d) { Direction.East | Direction.West { return 1; } - else { return 0; } + _ { return 0; } } return 0; } @@ -94,7 +94,7 @@ fn colorEqualsRed() u8 { const c: Color = defaultColor(); match (c) { Color.Red { return 1; } - else { return 0; } + _ { return 0; } } return 0; } @@ -111,7 +111,7 @@ fn step(s: State) State { State.Running { return State.Paused; } State.Paused { return State.Running; } State.Stopped { return State.Stopped; } - else { return State.Stopped; } + _ { return State.Stopped; } } return State.Stopped; } @@ -132,7 +132,7 @@ fn stateAsByte(s: State) u8 { State.Running { return 1; } State.Paused { return 2; } State.Stopped { return 3; } - else { return 99; } + _ { return 99; } } return 0; } @@ -154,7 +154,7 @@ fn cellsForShape(t: Tetromino) u8 { Tetromino.I | Tetromino.O | Tetromino.T | Tetromino.S | Tetromino.Z | Tetromino.J | Tetromino.L { return 4; } - else { return 0; } + _ { return 0; } } return 0; } @@ -163,7 +163,7 @@ fn tetrominoIsBalanced(t: Tetromino) u8 { // I and O are symmetric; the others are not. match (t) { Tetromino.I | Tetromino.O { return 1; } - else { return 0; } + _ { return 0; } } return 0; } diff --git a/tests/unit/test_enum_payload.jam b/tests/unit/test_enum_payload.jam index 8c48dfc..1429d1a 100644 --- a/tests/unit/test_enum_payload.jam +++ b/tests/unit/test_enum_payload.jam @@ -13,7 +13,7 @@ fn unwrapOrDefault(o: OneArg, def: u8) u8 { match (o) { OneArg.Nothing { return def; } OneArg.Just(x) { return x; } - else { return 99; } + _ { return 99; } } return 0; } @@ -37,7 +37,7 @@ fn srcReg(op: Op) u8 { Op.LdRR(d, s) { return s; } Op.Imm(v) { return v; } Op.Wide(w) { return 0xEE; } - else { return 0xCC; } + _ { return 0xCC; } } return 0; } @@ -45,7 +45,7 @@ fn srcReg(op: Op) u8 { fn dstReg(op: Op) u8 { match (op) { Op.LdRR(d, s) { return d; } - else { return 0xFF; } + _ { return 0xFF; } } return 0; } @@ -68,7 +68,7 @@ fn jumpAddr(o: WideOp) u16 { WideOp.Jp(addr) { return addr; } WideOp.Call(addr) { return addr; } WideOp.Mov(r, a) { return a; } - else { return 0; } + _ { return 0; } } return 0; } @@ -76,7 +76,7 @@ fn jumpAddr(o: WideOp) u16 { fn movRegister(o: WideOp) u8 { match (o) { WideOp.Mov(r, a) { return r; } - else { return 0; } + _ { return 0; } } return 0; } @@ -107,7 +107,7 @@ fn classifyMany(m: Many) u32 { Many.E(a, b, c) { return a + b + c; } Many.F { return 1000; } Many.G(big) { return big; } - else { return 0; } + _ { return 0; } } return 0; } @@ -130,7 +130,7 @@ fn passThroughGetValue() u8 { const o: Op = passThrough(Op.Imm(55)); match (o) { Op.Imm(v) { return v; } - else { return 99; } + _ { return 99; } } return 0; } @@ -148,7 +148,7 @@ fn isOk(r: Result) u8 { match (r) { Result.Ok(v) { return 1; } Result.Err { return 0; } - else { return 99; } + _ { return 99; } } return 0; } @@ -156,7 +156,7 @@ fn isOk(r: Result) u8 { fn unwrapOk(r: Result) u32 { match (r) { Result.Ok(v) { return v; } - else { return 0; } + _ { return 0; } } return 0; } diff --git a/tests/unit/test_match_basic.jam b/tests/unit/test_match_basic.jam index 1894780..d965bad 100644 --- a/tests/unit/test_match_basic.jam +++ b/tests/unit/test_match_basic.jam @@ -5,7 +5,7 @@ fn singleArmExact() u8 { var r: u8 = 0; match (1) { 1 { r = 99; } - else { r = 0; } + _ { r = 0; } } return r; } @@ -14,7 +14,7 @@ fn singleArmMisses() u8 { var r: u8 = 7; match (5) { 1 { r = 99; } - else { r = 0; } + _ { r = 0; } } return r; } @@ -26,7 +26,7 @@ fn dispatchSmall(x: u8) u8 { 1 { r = 20; } 2 { r = 30; } 3 { r = 40; } - else { r = 255; } + _ { r = 255; } } return r; } @@ -37,7 +37,7 @@ fn matchHexLiteral(x: u8) u8 { 0xCB { r = 1; } 0xFF { r = 2; } 0x00 { r = 3; } - else { r = 0; } + _ { r = 0; } } return r; } diff --git a/tests/unit/test_match_control.jam b/tests/unit/test_match_control.jam index 0f63b14..39b38bb 100644 --- a/tests/unit/test_match_control.jam +++ b/tests/unit/test_match_control.jam @@ -6,7 +6,7 @@ fn matchWithReturn(x: u8) u8 { match (x) { 0 { return 100; } 1..=9 { return 200; } - else { return 255; } + _ { return 255; } } return 99; // unreachable; every arm returns } @@ -16,7 +16,7 @@ fn matchSetsThenContinues(x: u8) u8 { match (x) { 1 { r = 10; } 2 { r = 20; } - else { r = 99; } + _ { r = 99; } } return r * 2; } @@ -28,16 +28,16 @@ fn nestedMatch(a: u8, b: u8) u8 { match (b) { 0 { r = 1; } 1 { r = 2; } - else { r = 3; } + _ { r = 3; } } } 1 { match (b) { 0 { r = 4; } - else { r = 5; } + _ { r = 5; } } } - else { r = 99; } + _ { r = 99; } } return r; } @@ -48,7 +48,7 @@ fn matchInsideWhile(start: u8) u8 { while (i < 5) { match (i) { 0 | 2 | 4 { sum = sum + 1; } // even: count - else { sum = sum + 10; } // odd: bigger contribution + _ { sum = sum + 10; } // odd: bigger contribution } i = i + 1; } @@ -60,7 +60,7 @@ fn matchInsideFor() u8 { for i in 0:10 { match (i) { 0..=4 { sum = sum + 1; } - else { sum = sum + 2; } + _ { sum = sum + 2; } } } return sum; @@ -71,7 +71,7 @@ fn matchBreak(start: u8) u8 { while (i < 100) { match (i) { 42 { break; } - else { i = i + 1; } + _ { i = i + 1; } } } return i; diff --git a/tests/unit/test_match_expression.jam b/tests/unit/test_match_expression.jam index 7acdb4a..4665c61 100644 --- a/tests/unit/test_match_expression.jam +++ b/tests/unit/test_match_expression.jam @@ -92,7 +92,7 @@ fn evalWithElse(op: Op) u8 { return match (op) { Op.Nop { 0 } Op.Add(x) { x } - else { 99 } + _ { 99 } }; } diff --git a/tests/unit/test_match_or.jam b/tests/unit/test_match_or.jam index dde1173..a49f544 100644 --- a/tests/unit/test_match_or.jam +++ b/tests/unit/test_match_or.jam @@ -5,7 +5,7 @@ fn twoAlternatives(x: u8) u8 { var r: u8 = 0; match (x) { 1 | 2 { r = 100; } - else { r = 0; } + _ { r = 0; } } return r; } @@ -15,7 +15,7 @@ fn manyAlternatives(x: u8) u8 { match (x) { 1 | 3 | 5 | 7 | 9 { r = 1; } // odd 1..9 2 | 4 | 6 | 8 { r = 2; } // even 2..8 - else { r = 0; } + _ { r = 0; } } return r; } @@ -25,7 +25,7 @@ fn orOrderInsensitive(x: u8) u8 { var r: u8 = 0; match (x) { 9 | 7 | 5 | 3 | 1 { r = 42; } - else { r = 0; } + _ { r = 0; } } return r; } @@ -35,7 +35,7 @@ fn orFirstMatchWins(x: u8) u8 { match (x) { 1 | 2 | 3 { r = 10; } 2 | 3 | 4 { r = 20; } // unreachable for x in {2,3} — first arm wins - else { r = 0; } + _ { r = 0; } } return r; } diff --git a/tests/unit/test_match_range.jam b/tests/unit/test_match_range.jam index 4b667af..31d68e1 100644 --- a/tests/unit/test_match_range.jam +++ b/tests/unit/test_match_range.jam @@ -5,7 +5,7 @@ fn smallRange(x: u8) u8 { var r: u8 = 0; match (x) { 10..=20 { r = 1; } - else { r = 0; } + _ { r = 0; } } return r; } @@ -15,7 +15,7 @@ fn boundsCheck(x: u8) u8 { var r: u8 = 0; match (x) { 5..=7 { r = 1; } - else { r = 0; } + _ { r = 0; } } return r; } @@ -26,7 +26,7 @@ fn multipleRanges(x: u8) u8 { 0x40..=0x47 { r = 1; } 0x48..=0x4F { r = 2; } 0x50..=0x57 { r = 3; } - else { r = 0; } + _ { r = 0; } } return r; } @@ -38,7 +38,7 @@ fn rangeMixedWithLiteral(x: u8) u8 { 1..=9 { r = 20; } 10 { r = 30; } 11..=99 { r = 40; } - else { r = 0; } + _ { r = 0; } } return r; } @@ -47,7 +47,7 @@ fn rangeOrLiteral(x: u8) u8 { var r: u8 = 0; match (x) { 0 | 5..=9 | 100 { r = 1; } - else { r = 0; } + _ { r = 0; } } return r; } diff --git a/tests/unit/test_match_types.jam b/tests/unit/test_match_types.jam index 129cb61..2cf127c 100644 --- a/tests/unit/test_match_types.jam +++ b/tests/unit/test_match_types.jam @@ -7,7 +7,7 @@ fn matchU8(x: u8) u8 { 0..=127 { r = 1; } 128..=254 { r = 2; } 255 { r = 3; } - else { r = 0; } + _ { r = 0; } } return r; } @@ -18,7 +18,7 @@ fn matchU16(x: u16) u16 { 0 { r = 1; } 1..=255 { r = 2; } 256..=4095 { r = 3; } - else { r = 4; } + _ { r = 4; } } return r; } @@ -28,7 +28,7 @@ fn matchU32(x: u32) u32 { match (x) { 0 { r = 1; } 1..=1000 { r = 2; } - else { r = 3; } + _ { r = 3; } } return r; } @@ -38,7 +38,7 @@ fn matchI32(x: i32) i32 { match (x) { 0 { r = 100; } 1..=10 { r = 200; } - else { r = 300; } + _ { r = 300; } } return r; } diff --git a/tests/unit/test_match_wildcard.jam b/tests/unit/test_match_wildcard.jam index 198f833..686fb83 100644 --- a/tests/unit/test_match_wildcard.jam +++ b/tests/unit/test_match_wildcard.jam @@ -17,7 +17,7 @@ fn wildcardInOr(x: u8) u8 { var r: u8 = 0; match (x) { 1 | _ { r = 5; } - else { r = 0; } + _ { r = 0; } } return r; } @@ -29,7 +29,7 @@ fn wildcardThenElse(x: u8) u8 { match (x) { 0 { r = 1; } _ { r = 7; } - else { r = 99; } + _ { r = 99; } } return r; } diff --git a/tests/unit/test_num_literals.jam b/tests/unit/test_num_literals.jam index 4ed2ed7..95df6b9 100644 --- a/tests/unit/test_num_literals.jam +++ b/tests/unit/test_num_literals.jam @@ -90,7 +90,7 @@ fn classifyMixed(x: u8) u8 { 0xDE | 0xAD { r = 2; } 0o17 { r = 3; } 0..=9 { r = 4; } - else { r = 0; } + _ { r = 0; } } return r; } @@ -110,7 +110,7 @@ fn rangeBases(x: u8) u8 { 0x10..=0x1F { r = 1; } 0b0010_0000..=0b0010_1111 { r = 2; } 0o100..=0o107 { r = 3; } - else { r = 0; } + _ { r = 0; } } return r; }