Built-ins reference
This page covers the language-level built-ins and compiler-recognized forms: operators, constructors, actions, datatype actions, and diagnostics. Two major built-ins have their own pages — the PARSE dialect and state machines (FSM/FST).
Operators
Arithmetic + - * / % (% is modulo), bitwise and shift << >> & | xor, comparisons
= == <> < > <= >=, and logical
and or. Precedence (higher binds tighter):
| Level | Operators |
|---|---|
| 20 | * / % |
| 10 | + - << >> & | xor (left to right) |
| 5 | = == <> < > <= >= |
| 3 | and or |
a: 10 + 5 * 2 ; 20 — multiplication binds tighter
b: (10 + 5) * 2 ; 30
f: as f32! a ; explicit cast with `as`
Constructors & conversions
make <type> <value>— the standard typed construction form, also used for typed bindings (x: make i32! 1).as <type> <value>— explicit cast / coercion.charset <chars>— builds abitset!forparse.size-of <abi-type>— lowers to Csizeof(...).offset-of <c-struct> <field>— lowers to Coffsetof(...).static-assert <cond> <message>— compile-time assertion (lowers to_Static_assert);condmust be constant.addr-of <binding>— address-of for addressable values.
bytes: size-of c-pointer!
ptr: addr-of x
static-assert (size-of i32!) = 4 "i32! must be 4 bytes"
Predicates & general helpers
none?— is a nullable valuenone(NULL)?errored?— is an error currently set in the global state? (zero-arity, consuming read)error?— is this specific value an error? (takes one operand)length?— datatype-driven length query.print— type-directed printing.form,mold— value-to-text conversions.load,load-as— data conversion forms.
ptr: none
if none? ptr [print "null"]
n: length? nums
Series, string, dict & block actions
Resolved through parser/type/runtime support, not as plain functions.
Native series state
freeze series— returns an immutable native series.thaw series— unlocks an owned series in place to mutable, non-growable.flex series— unlocks an owned series in place to mutable, growable.copy series— a fresh owned, writable duplicate;thaw/flexreject a string literal or a:nameborrow withB3006, so writeflex copy s.
Size-changing ops (#flexible only)
append— grows a#flexiblestring!/array! T/vector! T, or appends a tagged slot to a#flexible block!.insert— prepends at position 0.remove/last— pops the last element.
append, insert, and remove are valid
only on #flexible series. Non-flex
block!/string!/vector! are
static-size — no reallocation is allowed.
Dict / map style
pick— lookup;contains?— membership.get-or-put— lookup with insertion;update-or-insert— update helper.remove/key— removal;clear— clear where supported.take— supported on selected sequence/port APIs.
counts: make [#mutable dict! [string! i32!]] [string! i32!]
get-or-put counts "ok" 1
print pick counts "ok" ; 1
Extending types with extend
A user struct can implement built-in actions by mapping an action name to a Recoil function:
MyBuf!: make struct! [data: c-pointer! len: i64!]
mybuf-length: func [b [MyBuf!] return: [i64!]] [return b/len]
extend MyBuf! [
length? mybuf-length
]
n: length? mybuf ; lowers to mybuf_length(mybuf)
Rules: the action must be a known built-in (length?,
open?, query, …); the function must be defined before
the extend; its return type must match the action contract.
Diagnostics: T4200 (not a struct), T4201 (function
not defined), T4202 (return type mismatch).
Datatype actions
Built-in action coverage by type:
| Type | Actions |
|---|---|
file! | open? |
port! | open?, query, length? |
vector!, array!, block!, dict!, string!, slice!, c-string!, url! | length? |
fsm! | send |
Ownership & resource forms
defer [body]— run on function exit (LIFO).defer/error [body]— run only when an error is set.unused name— declare an intentionally unused binding.
Diagnostics
Compile-time failures are reported both as a human-readable string and as a structured object attached to the raised error.
Message format
TYPE ERROR: Cannot assign void return value to variable 'x'
BORROW CHECKER ERROR: 's1' used after move
CLI ERROR: Unknown option: --bogus
Prefixes include SYNTAX ERROR, TYPE ERROR,
BORROW CHECKER ERROR, MODULE ERROR,
STRUCT ERROR, COMPTIME ERROR,
FUNCTION HEADER ERROR, MODULE HEADER ERROR,
CLI ERROR, BUILD ERROR,
INTERNAL ERROR.
Structured shape
Each diagnostic carries stage (one of parser,
module, borrow-checker, ir,
codegen, cli, build), a
kind, a stable code such as P1000, a
message, and optional context / location.
The authoritative code list lives in the repository's
diagnostics doc.
Runtime error codes
Runtime errors carry a category type and a numeric code. Any value whose
type is >= ERR_TYPE_MATH (1) is treated as an error.
| Code | Category | Constant |
|---|---|---|
| 300 | Math — divide by zero | ERR_MATH_ZERO_DIVIDE |
| 301 | Math — integer overflow | ERR_MATH_OVERFLOW |
| 302 | Math — underflow | ERR_MATH_UNDERFLOW |
| 500 | FFI — null pointer | ERR_FFI_NULL_POINTER |
| 700 | Series — out of bounds | ERR_SERIES_OUT_OF_BOUNDS |
| 701 | Series — past end | ERR_SERIES_PAST_END |
| 800–841 | Port (TCP/TLS/HTTP/DNS) | ERR_PORT_* — see Ports |
| 850–853 | Parse / FST | ERR_PARSE_* |
| 860 | Channel — closed | ERR_CHANNEL_CLOSED |
| 900+ | User | via make error! |
The authoritative list lives in lib/runtime.rcl. See the
error-handling section of the guide for usage.
Known limits
Things Recoil deliberately does not do yet, so you can tell a gap from a bug. Sources: deferred-scope-0.12.md and current-map-block-json-limitations.md in docs/user/.
Concurrency and atomics
- Infix read-modify-write on an
#atomicbinding (counter: counter + 1) is rejected withB3012. Useatomic-add,atomic-sub,atomic-exchangeoratomic-compare-exchange. - esp-idf and browser-wasm keep a run-to-completion task queue: no yielding,
go/afterdelays ignored,sleepblocks the process. See Concurrency. #atomiccovers scalar storage only. Sharing a managed series across OS threads is unsupported; the docs say reference counts stay non-atomic and this is a compile-time error.
Macros
- Macros are expression-position only; a macro that returns a statement AST is rejected. Custom macro diagnostics, reflection APIs, generic struct expansion and statement-position macros are scheduled for 0.13.
map!, array!, JSON and typeset!
- Schema
map!declarations are closed, struct-backed object types; anonymous structuralmap!types do not exist. Baremap!is the open, string-keyed container ofvalue!cells. - Schema dynamic field paths (
obj/:field) work only with statically resolvable selectors; runtime string-to-field dispatch is out of scope. - Optional fields use
#optional, recognised only insidemake map! [...]field blocks. Absent-field reads are errors, so guard withpresent?; optionality does not extend to locals, params, returns or elements. - Typed JSON decode ignores unknown keys, and array-of-union decoding is not implemented.
load-jsonreturns avalue!: arrays as heterogeneousblock!, objects asmap!. Malformed input and excessive nesting are runtime errors. typeset!has syntax and normalization but incomplete runtime support;matchstayssum!-only. There are nojson!ortable!types.
Not re-checked against the compiler: the exact wording of the cross-thread sharing error, the per-item milestone assignments, and the typeset! and predicate-narrowing statements. Treat them as the docs' claims.