Files
brolang/examples/programs/match/main.bro
T
2026-06-30 19:38:28 +02:00

126 lines
2.7 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
}