compiler: Initialize chained match destinations

37ceac3465c0728f185a60609c7e1a7627875b9e724e4fb13bf3902c3b6f2f24
Alexis Sellier committed ago 1 parent 442ab96c
lib/std/lang/lower.rad +3 -5
3853 3853
3854 3854
        // Entry block: guard block if present, otherwise the body block.
3855 3855
        // The guard block must be created before the body block so that
3856 3856
        // block indices are in reverse post-order (RPO), which the register
3857 3857
        // allocator requires.
3858 -
        let mut entryBlock: BlockId = undefined;
3858 +
        let mut guardBlock: ?BlockId = nil;
3859 3859
        if hasGuard {
3860 -
            set entryBlock = try createBlock(self, "guard");
3860 +
            set guardBlock = try createBlock(self, "guard");
3861 3861
        }
3862 3862
        // Body block: where the case body lives.
3863 3863
        let mut bodyLabel = "case";
3864 3864
        if prong.arm == ast::ProngArm::Else {
3865 3865
            set bodyLabel = "else";
3866 3866
        }
3867 3867
        let mut bodyBlock = try createBlock(self, bodyLabel);
3868 -
        if not hasGuard {
3869 -
            set entryBlock = bodyBlock;
3870 -
        }
3868 +
        let entryBlock = guardBlock else bodyBlock;
3871 3869
        // Fallthrough block: jumped to when pattern or guard fails.
3872 3870
        let nextArm = try createBlock(self, "arm");
3873 3871
3874 3872
        // Emit pattern test: branch to entry block on match, next arm on fail.
3875 3873
        match prong.arm {
test/tests/match.guard.order.rad added +38 -0
1 +
//! returns: 0
2 +
3 +
/// Evaluate a guard and record its position.
4 +
fn guard(trace: &mut u32, digit: u32, accepted: bool) -> bool {
5 +
    set *trace = *trace * 10 + digit;
6 +
    return accepted;
7 +
}
8 +
9 +
/// Select a guarded arm or its unguarded fallback.
10 +
fn choose(value: u32, first: bool, second: bool, trace: &mut u32) -> u32 {
11 +
    match value {
12 +
        case 1 if guard(trace, 1, first) => return 10,
13 +
        case 1 if guard(trace, 2, second) => return 20,
14 +
        case 1 => return 30,
15 +
        else => return 40,
16 +
    }
17 +
}
18 +
19 +
/// Check guard order, short circuiting, and pattern failure.
20 +
@default fn main() -> u32 {
21 +
    for bits in 0..4 {
22 +
        let first = bits & 1 <> 0;
23 +
        let second = bits & 2 <> 0;
24 +
        let mut trace: u32 = 0;
25 +
        let result = choose(1, first, second, &mut trace);
26 +
        if first {
27 +
            assert result == 10;
28 +
            assert trace == 1;
29 +
        } else {
30 +
            assert result == (20 if second else 30);
31 +
            assert trace == 12;
32 +
        }
33 +
        set trace = 0;
34 +
        assert choose(2, first, second, &mut trace) == 40;
35 +
        assert trace == 0;
36 +
    }
37 +
    return 0;
38 +
}