void-payloads, multi-pattern arms, and range patterns (match statements)
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user