Expressions
Expressions make up the body of branches.
§Literals
42 // i64
0 // i64
"hello\n" // str
true // bool
false // boolNumbers are i64. Strings support escapes: \n, \t, \r, \\, \".
§Variables
Names introduced by typed parameters in the enclosing branch:
counter is {
n i64 -> {
self(n-1) // n is in scope
}
}§Let bindings
let x i64 = 42Creates a local variable in the current branch's scope.
§Arithmetic
| Precedence | Operators |
|---|---|
| 10 | * / |
| 9 | + - |
All operators are left-associative and operate on i64.
n - 1
acc + n
acc1 + acc2Arithmetic is allowed in argument positions:
self(n-1 acc+n)§Comparisons
| Precedence | Operators |
|---|---|
| 8 | <= >= == < > |
0 == n
1 <= stepsLower precedence than arithmetic: a + b <= c parses as (a + b) <= c.
§When expression
when is an inline match on a value.
@rt(rt_write)
main is {
_ -> {
when 1 + 1 {
0 -> { rt_write(1 "zero\n" 5) }
1 -> { rt_write(1 "one\n" 4) }
2 -> { rt_write(1 "two\n" 4) }
}
}
}Arms match on literal values (numbers, booleans, or strings). If no arm matches, the when falls through silently.
The same machine could also be expressed without when by using literal-guard branches — see Branches & patterns. Use when for ad-hoc matching inside a body, and literal-guard branches for whole-machine dispatch.
§Wait expression
wait suspends the current process until a message arrives in its mailbox, then handles it.
wait {
n i64 -> { rt_write(1 "received\n" 9) }
}When a message arrives, it is dequeued from the mailbox and the matching handler runs with the message bound to its pattern.
If the mailbox is empty, the process is moved to the scheduler's wait array. As soon as another process sends, it is woken up.
Multiple messages? Wrap wait in a self-loop.
@rt(rt_write)
receiver is {
0 i64 -> {}
remaining i64 -> {
wait {
n i64 -> {
rt_write(1 ".\n" 2)
self(remaining-1)
}
}
}
}
main is {
_ -> {
let r pid = receiver(3)
r(1)
r(2)
r(3)
}
}§Sending a message
Calling a pid value sends — it does not spawn.
let p pid = worker()
p(42) // send 42 to the workerMessages are queued in a 256-slot ring buffer. If the receiver is currently waiting, sending wakes it up.
§Receive once
@rt(rt_write)
receiver is {
_ -> {
wait {
n i64 -> { rt_write(1 "got it\n" 7) }
}
}
}
main is {
_ -> {
let r pid = receiver()
r(42)
}
}main spawns receiver and stores the resulting pid in r. The receiver is suspended on wait until r(42) enqueues a message; the handler then prints got it and the process finishes.
Building richer protocols (ping-pong, supervisors, streaming) requires juggling pids through a small handshake. See the project's examples/ directory.