Directives
Directives are compiler attributes that declare runtime functions. They are placed before machines.
@rt — Runtime Function
Binds a name to a built-in runtime function:
@rt(rt_write)
After this declaration, rt_write can be called directly from any branch. Unlike machine calls, runtime function calls do not spawn a new process — they execute inline.
Available Runtime Functions
| Function | Arguments | Description |
|---|---|---|
rt_write | fd data size | Write size bytes from data to file descriptor fd |
rt_exit | code | Exit the program with the given exit code |
rt_allocate | size | Allocate size bytes on the heap, returns fat pointer |
rt_store | ctx value size offset | Write value to memory at offset |
rt_load_u64 | ctx offset | Read a 64-bit value from memory at offset |
rt_mmap | addr size prot flags fd off | Raw mmap syscall |
rt_syscall | varies | Raw syscall wrapper |
Common Usage
Writing to stdout:
@rt(rt_write)
main is {
_ i64.0 -> {
rt_write(1 "hello, lake!\n" 14)
}
}
The arguments to rt_write are: file descriptor (1 = stdout), string data, and byte length.
@cfg — Per-Target Item Filtering
@cfg(arch="...") keeps an item only when compiling for a matching target
architecture; non-matching items are dropped before name resolution. The
supported values are "x86_64" and "aarch64". This lets you declare the
same name twice — once per architecture — without a collision:
@cfg(arch="x86_64")
pub const SYS_SOCKET = 41
@cfg(arch="aarch64")
pub const SYS_SOCKET = 198
Whichever variant matches the --target survives; the other is filtered
out, so SYS_SOCKET resolves to the architecture-correct value. The
standard library uses this in std.experimental.sys to give each Linux
syscall number a single name across both architectures.
Imports
A line beginning with + imports the named public items from a module:
+std.io.{ println eprintln }
+std.vec.{ vec_new vec_push }
Module paths nest with dots (std.crypto.sha256). See the
Standard Library chapter.
Constants
const declares a module-level compile-time constant with a literal value.
It is inlined at every use site. Prefix with pub to export it:
pub const FD_STDOUT = 1
pub const O_CREAT = 64
Placement
Directives are placed at the top of the file, before any machine definitions:
@rt(rt_write)
counter is {
n i64 -> {
when 0 == n {
true -> { rt_write(1 "done\n" 5) }
false -> { self(n-1) }
}
}
}
main is {
_ i64.0 -> {
counter(5)
}
}