compiler: Initialize chained match destinations
37ceac3465c0728f185a60609c7e1a7627875b9e724e4fb13bf3902c3b6f2f24
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 | + | } |