void-payloads, multi-pattern arms, and range patterns (match statements)

This commit is contained in:
2026-06-29 19:52:05 +02:00
parent 462632554c
commit c82f070d55
8 changed files with 499 additions and 106 deletions
+59 -19
View File
@@ -4,7 +4,8 @@ Animal :: enum {
bird
}
# tagged union over an existing enum (variants are a subset of the enum's members)
# tagged union over an existing enum (variants are a subset of the enum's members);
# dog and bird share the same payload type (i32), so a multi-pattern arm may capture both.
Data :: union(Animal) {
dog i32
bird i32
@@ -16,6 +17,17 @@ Shape :: union(enum) {
circle i32 # radius
}
Point :: struct {
x i32
y i32
}
# tagged union with a void-payload variant (`empty` carries no value)
Box :: union(enum) {
point Point
empty void
}
# Statement match with payload capture; every variant returns, so the function needs
# no trailing return (the desugared if/else chain covers all paths).
describe :: func(d Data) i32 {
@@ -37,39 +49,67 @@ area :: func(s Shape) i32 {
return result
}
# Same-type multi-pattern capture: `.dog` and `.bird` are both i32, so one capture binds
# either payload (read once at the union's shared carrier offset).
payload_of :: func(d Data) i32 {
v :: match d {
.dog, .bird |n|: n
}
return v
}
main :: func() i32 {
acc i32 = 0
dog Data = Data{ dog = 9 }
bird Data = Data{ bird = 38 }
total i32 = describe(dog) + describe(bird) # 10 + 40 = 50
acc = acc + describe(dog) + describe(bird) # 10 + 40 = 50
# enum statement match, exhaustive without an `else`
# same-type multi-pattern capture
acc = acc + payload_of(dog) + payload_of(bird) # 9 + 38 = 47
# enum statement match, exhaustive, with a multi-pattern arm
a Animal = .bird
rank i32 = 0
match a {
.dog: rank = 1
.cat: rank = 2
.bird: rank = 3
.dog, .cat: rank = 1
.bird: rank = 3
}
acc = acc + rank # +3
# enum value match
# enum value match with a multi-pattern arm
legs :: match a {
.dog: 4
.cat: 4
.bird: 2
.dog, .cat: 4
.bird: 2
}
acc = acc + legs # +2
# integer match with a mandatory `else`
# scalar match: a range arm, a multi-literal arm, and a mandatory else
bucket i32 = 0
match rank {
1: bucket = 100
3: bucket = 5
else: bucket = 99
0..3: bucket = 1 # exclusive 0,1,2 — does not include 3
3, 4: bucket = 5 # rank is 3
else: bucket = 99
}
acc = acc + bucket # +5
sq Shape = Shape{ square = 4 }
ci Shape = Shape{ circle = 2 }
shapes i32 = area(sq) + area(ci) # 16 + 12 = 28
# void-payload variant: bare-key construction + a no-capture arm
e Box = Box{ empty }
hit i32 = 0
match e {
.point |pt|: hit = pt.x
.empty: hit = 7
}
acc = acc + hit # +7
# 50 + 3 + 2 + 5 + 28 = 88
return total + rank + legs + bucket + shapes - 88
# pointer capture mutates the subject's payload in place
b Box = Box{ point = Point{ x = 1, y = 2 } }
match b {
.point |@p|: p.x = 10
.empty: hit = hit
}
acc = acc + b.point.x # +10 (mutated through the @mut Point)
# 50 + 47 + 3 + 2 + 5 + 7 + 10 = 124
return acc - 124
}