126 lines
2.8 KiB
Plaintext
126 lines
2.8 KiB
Plaintext
Animal :: enum {
|
|
dog
|
|
cat
|
|
bird
|
|
}
|
|
|
|
# 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
|
|
}
|
|
|
|
# tagged union with a synthesized tag enum
|
|
Shape :: union(enum) {
|
|
square i32 # side
|
|
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 {
|
|
match d {
|
|
.dog |age|: return age + 1
|
|
.bird |wingspan|: return wingspan + 2
|
|
}
|
|
}
|
|
|
|
# Value match: single-expression arms yield implicitly, a block arm yields explicitly.
|
|
area :: func(s Shape) i32 {
|
|
result :: match s {
|
|
.square |side|: side * side
|
|
.circle |r|: {
|
|
# 3 ~ pi, integer arithmetic
|
|
yield 3 * r * r
|
|
}
|
|
}
|
|
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
|
|
}
|
|
|
|
make_box :: func() Box {
|
|
return Box{ point = Point{ x = 4, y = 0 } }
|
|
}
|
|
|
|
main :: func() i32 {
|
|
acc i32 = 0
|
|
|
|
dog Data = Data{ dog = 9 }
|
|
bird Data = Data{ bird = 38 }
|
|
acc = acc + describe(dog) + describe(bird) # 10 + 40 = 50
|
|
|
|
# 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, .cat: rank = 1
|
|
.bird: rank = 3
|
|
}
|
|
acc = acc + rank # +3
|
|
|
|
# enum value match with a multi-pattern arm
|
|
legs :: match a {
|
|
.dog, .cat: 4
|
|
.bird: 2
|
|
}
|
|
acc = acc + legs # +2
|
|
|
|
# scalar match: a range arm, a multi-literal arm, and a mandatory else
|
|
bucket i32 = 0
|
|
match rank {
|
|
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
|
|
|
|
# void-payload variant: contextual construction (`.empty` coerces to Box) + no-capture arm
|
|
e Box = .empty
|
|
hit i32 = 0
|
|
match e {
|
|
.point |pt|: hit = pt.x
|
|
.empty: hit = 7
|
|
}
|
|
acc = acc + hit # +7
|
|
|
|
# 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)
|
|
|
|
# match directly on a call result (no need to bind it to a variable first)
|
|
match make_box() {
|
|
.point |p|: acc = acc + p.x # +4
|
|
.empty: hit = hit
|
|
}
|
|
|
|
# 50 + 47 + 3 + 2 + 5 + 7 + 10 + 4 = 128
|
|
return acc - 128
|
|
}
|