Axiom 0.3.6
0.3.6 — 2026-08-28
The three compiler defects the language-server work found and 0.3.5
recorded under Found, not fixed are fixed, the server stops sending
semantic tokens so the grammar is the one source of colour, and the
grammar gains rainbow brackets. No gate was added: every change here
is covered by the thirty-seven gates that build the compiler under
test through gate_build_axc, and check-tree-sitter.sh learns one
more query file.
Removed
- Semantic tokens. 0.3.5's
textDocument/semanticTokens/fulland
/rangeare withdrawn, by decision rather than defect: the
tree-sitter grammar is the one source of colour, and two sources that
can disagree about the same token are worse than one. The SECTION HL
ofself_host/lsp.ax, its drive.py block and its sweep entry are
gone; the capability object shrinks by one key and the eight goldens
are re-blessed for that alone.docs/lsp.mdsays which editors take
colour from the grammar (Helix, Neovim, Emacs 29, Zed) and which
therefore have none from this repository (VS Code, which has no
tree-sitter and for which no TextMate grammar is shipped).
Added
- Rainbow brackets in the grammar.
tree-sitter-axiom/queries/ rainbows.scmnames every bracket-opening rule of the grammar as a
@rainbow.scope— 59 of them, checked againstsrc/node-types.json
so a hidden or aliased rule cannot be named — and the six bracket
tokens as@rainbow.bracket; Helix colours each pair by its nesting
depth with[editor] rainbow-brackets = true, and
rainbow-delimiters.nvim reads the same captures. Measured on
stdlib/Vec.ax: 868 brackets in 288 scopes.check-tree-sitter.sh
loads it against every.axfile besidehighlights.scm.
Fixed
-
A macro-generated
struct's fields carried the parser's float flag
where their type belonged.expBuildStructFieldsInsubstituted
wordbof each field — the float flag — as if it were the type and
stored the result back inb, leavingty0. Measured on the tree
before the change: a template spelling(f : Float)madecheck,
buildandsymbolsdie of SIGSEGV in expansion (a dereferenced
1); aFloatarriving through a parameter reached the checker as
a silent wildcard,symbolsprinted#fields=n:{unknown},f:{unknown}
beside the handwritten twin'sn:Int,f:Float, and(* p.f p.f)was
refused with a falseAX3004. The builder reads the type fromty,
recomputes the flag from what the substitution produced (as
expCtorFlagsalready does for constructors), and parks the type
where the parser does.tests/selfhost/396-macro-struct-field-types.ax
exits 139 on the old compiler and 73 on this one; the symbols zoo's
RecTwinrow now carriesRec's own#fields=. -
The formatter reserved thirty-two words the language does not.
axiom fmtrefused(fn (g data) data)whilecheckaccepted it;
docs/reference.mdhas always said a keyword is special only in the
position its rule claims.fpIsReservedWordreproduced the retired
Rust compiler's lexer, and the parity bank had pinned that answer as
070-keyword-in-exprsince the day it was materialized. Measured
over thirty-six shapes: every non-head keyword-spelled identifier was
checkOK (or a checker error) andfmtrefused; in head position
the parser refuses onlyconsumeandbegin(AX2004) — and the
printer PRINTED those two, outputcheckcannot read. Two words
replace the list (fpIsRefusedHead, the twoparseInnerrefuses);
070and131flip to rewrites,190–197pin the identifiers
that print and the refusals the parser shares. 48 parity cases, 24
rewrites and 24 refusals; the tree-sitter corpus gains the shape (38
cases). The ten identifiers renamed inf0a2fa3could be renamed
back. -
Every name the emitter invents begins with a byte no identifier can
spell.(fn (f t0) (+ t0 1))passedcheckand died inoptwith
multiple definition of local value named 't0' (AX4003): temporaries
were%tNand a parameter%name, one LLVM namespace, two schemes
that could spell the same string — andt<digits>was only the first;
measured one prefix at a time,label_3,f1,c0,d0,p1and a
lambda parameter named_enveach failed the same way. The fix is a
construction, not a list: every local value and block label the
emitter makes up now begins with.—%.t0,%.d0,.L3,%.env
— which LLVM accepts and no Axiom identifier can contain
(isIdentStart/isIdentCharleave byte 46 out), so the two
namespaces are disjoint by what they are made of; 28 label sites and
17 typed-temporary sites go throughtmpStr/labelStr. Global
symbols are untouched byte for byte (check-symbol-names,
check-freestanding,check-c-abi).tests/selfhost/955-source- names-vs-emitter-names.axnames a parameter after every old prefix:
exit 4 inopton 0.3.5, 42 here. The committed seed keeps its%tN
and the ladder built from it reaches its fixpoint on the new
spelling (check-bootstrap.sh). -
bootstrap-from-seed.sh --installcopied the compiler onto the
binary it was replacing.cponto an existing executable rewrites
the same inode, and macOS keeps a signature cached per inode for a
binary that was ever run: the rewritten.axiom-bin/axiompassed
codesign -vand was SIGKILLed — exit 137, no output — on every
exec, so everycheckin the tree died silently for three quarters
of an hour while three gates shared it. The install is a copy beside
the target and a rename over it now, which is atomic and a new inode.