Builtins and Intrinsics
Vex does not expose a tiny builtin surface anymore. The current compiler ships a broader always-available set of helpers covering:
- runtime I/O and debugging
- panic and development traps
- low-level memory access
- timing helpers
- compile-time reflection and diagnostics
- autograd intrinsics
Some builtins also keep compatibility aliases for older spellings. This page documents the current surface you can actually rely on.
Prefix Families
In the current implementation, builtin names fall into three practical groups:
@...for autograd helpers$...for runtime helpers plus a few long-lived layout and shape intrinsics#...for compile-time helpers
Runtime I/O and Debugging
$print("partial line")
$println("done")
$eprint("warning: ")
$eprintln("bad state")
let rendered = $format("{0}:{1}", host, port)
let value = $dbg(rendered)The current builtin surface includes:
$print$println$eprint$eprintln$format$dbg
Runtime Traps and Development Helpers
$panic("fatal error")
$todo("finish this branch")
$unreachable()
$assertEq(left, right)Use these intentionally:
$panicaborts execution$todomarks unfinished runtime paths$unreachablepromises the path is impossible$assertEqis a runtime equality assertion with structured failure output
Memory and Low-Level Helpers
$drop(resource)
let value = $load(ptr)
$store(ptr_mut, value)
let slice = $ptrToSlice(raw_ptr, len)These helpers exist, but they are not the first choice for ordinary application code.
- Prefer
Ptr<T>,Span<T>, andRawBufover raw pointer helpers - Treat
$load,$store, and$ptrToSliceas unsafe building blocks - Use
$droponly when early destruction materially improves correctness or clarity
Timing
let start = $monotonicNow()
work()
let end = $monotonicNow()Both $monotonicNow() and $now() resolve to the same timing helper in the current compiler surface.
Layout, Shape, and Reflection
The implementation currently supports a mixed surface here.
let size_a = #sizeof<i64>()
let size_b = $sizeof<i64>()
let align_a = #alignof<f64>()
let align_b = $alignof<f64>()
let ty_name = $typeName<Vec<i32>>()
let len = $len(v)
let rank = $rank(tensor)
let shape = $shape(tensor)Current reflection helpers also include:
#typeInfo<T>()#getField(value, field)#setField(target, field, value)#fieldCount<T>()#variantCount<E>()
If you are doing serious compile-time work, move from this page to Comptime.
Compile-Time Diagnostics and Embedding
#staticAssert(#fieldCount<User>() > 0, "User must stay non-empty")
#warning("legacy path compiled")
let home = #env("HOME")
let text = #includeStr("banner.txt")
let bytes = #includeBytes("blob.bin")
let expr = #debugExpr(5 + 3)
let joined = #concat("hello", " ", "vex")
let name = #concatIdents(foo, bar)Useful helpers in this group:
#staticAssert#compileError#warning#debugExpr#env#includeStr#includeBytes#concat#stringify#concatIdents
Autograd Builtins
Autograd uses @... as the primary syntax today:
let x = @param(2.0)
let y = Math.sin(x)
$println(@val(y))
$println(@grad(y))Use these primary forms:
@param@val@grad@detach
Legacy $param and related spellings still normalize in parts of the compiler, but they should not be the documented form.
Guidance
- Prefer ordinary language constructs first and reach for builtins only when they make intent sharper.
- Prefer
Ptr<T>,Span<T>, andRawBufover$load,$store, and$ptrToSlicewhen the higher-level wrappers fit. - Keep
$dbgand$todotemporary. - Prefer
#...spellings for most compile-time helpers even if older aliases still parse.