Branches & patterns
Branches define what a machine does for a given call. Each branch declares a sequence of patterns; when a machine is called, the compiler picks the branch whose patterns match the call's arguments.
§Branch syntax
pattern* -> { body }
A branch has zero or more patterns followed by -> and a body block.
§Three kinds of pattern
§Typed parameter
Binds a value of a given type to a name.
n i64Matches any i64 argument and makes it available inside the body as n.
§Literal guard
Matches only when the argument equals a specific literal. The literal carries the type.
0 i64
"hello" strA literal guard does not introduce a binding — it filters the dispatch. Use a typed parameter for the catch-all.
§Wildcard
The lone underscore matches a no-argument branch. There is no type.
_This is how the entry point is written: main is { _ -> { ... } }. Once you have arguments to bind, use a typed parameter (or a literal guard).
§Putting them together
A branch may mix literal guards and typed parameters. Patterns are read left-to-right and separated by spaces.
@rt(rt_write)
answer is {
0 i64 -> { rt_write(1 "zero\n" 5) }
1 i64 -> { rt_write(1 "one\n" 4) }
n i64 -> { rt_write(1 "many\n" 5) }
}
main is {
_ -> {
answer(0)
answer(1)
answer(7)
}
}Three branches share the same arity and type signature (i64). The compiler picks the matching one in O(1) by hashing the argument's type and literal value.
§Multiple parameters
Patterns are space-separated.
sum is {
0 i64 acc i64 -> { rt_write(1 "done\n" 5) }
n i64 acc i64 -> { self(n-1 acc+n) }
}sum(0 acc) matches the first branch; everything else matches the second and recurses.
§Strings
String literals work as guards too.
@rt(rt_write)
reply is {
"hello" str -> { rt_write(1 "world\n" 6) }
"ping" str -> { rt_write(1 "pong\n" 5) }
s str -> { rt_write(1 "?\n" 2) }
}
main is {
_ -> {
reply("hello")
reply("ping")
reply("???")
}
}§Scope
Each branch has its own scope. Variables introduced by typed parameters or by let are visible only inside that branch's body.