Reserved words
Mix's keyword lexemes, held to the lexer by
cargo test -p mix keyword_set_matches_lexer (the lib's
KEYWORDS list and the lexer match arms must agree, and
cargo test -p system --test man_pages holds this table to the same
set). Since 0.21 the old reserved-word footgun is retired: a keyword is
accepted anywhere it is unambiguously a name (bare map keys, .field
access, strict-data keys, send kwargs, parse … with delimiters) — see
Keywords as names below. What remains reserved: a keyword cannot be a
function name or fill any other bare-identifier slot.
The full set
The lexer reserves 48 words across 47 token kinds (fn and
function share one token):
| Group | Lexemes |
|---|---|
| Conditionals & matching | if then else elif end select when otherwise |
| Loops | for each in to step while loop break continue label — plus the legacy terminators next (for) and done (while/loop/on) |
| Functions | function fn return |
| Errors | try catch finally die |
| Template parsing | parse with |
| Bus messaging | send address emit on |
| Output | print eprint |
| Shell & loading | export alias source include sh |
| Operators & literals | and or not eq ne true false nil |
mix keywords prints the complete set and mix what NAME resolves every
one — no "core list" subset remains. All of them are equally reserved: each
fails identically as an identifier
(function step($x) → Parse error … expected identifier, got Step).
What is (and isn't) restricted
- Function names — no keyword may name a function:
function step(...),fn parse(...), evenfunction eq(...)are parse errors. Pick another name (phase, notstep). - Other bare-identifier slots — same rule: a loop label must be a plain identifier (
while true label outerworks,label tois a parse error). $-sigil variables are unaffected. The sigil is its own namespace — the lexer reads the name after$raw, so$to = 1,$step = 5,$if = 1, and even$fn = 1all work, as do keyword-named parameters (function f($to)).- Contextual barewords are not reserved — e.g.
async(fromon <cmd> async … end) is a valid function name. - Builtins are a separate rule, not keywords. Defining a user function with a builtin's name is accepted without error, but calls dispatch to the builtin — the user function is silently unreachable (
function trim($x) … endthentrim(" a ")still runs the builtin).
Keywords as names (0.21+)
A keyword is accepted wherever it is unambiguously a name:
$m = {label: 1, to: "x", on: true, parse: 2} -- bare map keys
print($m.to) -- field access -> x
$m.label = 5 -- field assignment
$v = data_parse("{to: 1, on: true}") -- strict-data keys, unquoted
send maild mailbox.move to=$dest -- send/emit/address kwargs
send ced ced.select anchor=0 -- dotted Bus verb segments (0.96.2)
on edit.select; reply("ok"); end -- ... and `on` handler names
parse $s with $a to $b -- literal delimiter word
parse … withexception: the block/branch terminator set —endelsecatchfinallywhenotherwisedonenext— still ends an inlineparsestatement, so those eight can't be delimiter words.- The one name exception is
fn: it lexes to the same token asfunction, so the original spelling is unrecoverable.{fn: 1}and$m.fnare parse errors (expected identifier, got Function) — use a quoted key{"fn": 1}and index access$m["fn"]. - The operator lexemes
eq/nealso work as bare keys and fields ({eq: 1},$m.eq). - Grammar adjacency holds:
for $i = $m.to to 7parses — dot-field consumption never crosses the following keyword.
Most keywords are covered in syntax, control flow, functions, operators, errors, Bus messaging and data (strict-data keys).
See also
- syntax · functions · builtins index ·
mix keywords