x-lang

bare x: the reader

The syntax of x before any library loads — the surface any implementation of the reader (C, Rust, or otherwise) must match. The booted language’s syntax is syntax.md; this document is the floor it stands on.

The engine

The reader is type-driven: every registered type may carry an analyse hook (score a candidate token), a read hook (build the value), and a delimit hook (declare characters that terminate other tokens). The engine feeds the input to every analyse hook and takes the best score:

Literals at the bare layer

Integers. [+-]? then digits; 0x/0X prefixes hex. Signs are part of the literal: -1 and +7 are integers at every stage of boot — no arithmetic workaround is ever needed for a negative literal. (- and + alone decline the integer analyser and fall back to symbols, which is how the operators exist.)

Strings. "…" with escapes \" \\ \n \t \r \0 \xHH. Unknown escapes are preserved literally. \0 embeds a real NUL.

Characters. #\x (any single byte), #\€ (UTF-8 glyph), and the named set #\alarm #\backspace #\delete #\escape #\newline #\null #\return #\space #\tab. Character literals are part of the bare reader — they work from the first line of boot.

Symbols. The fallback: any run of characters not cut by a registered delimiter. Consequently a bare symbol may contain ", #, ', and anything else non-delimiting — abc"def is one symbol here. Dialects that want more punctuation add delimit hooks in-language; the core stays permissive.

Lists and pairs. (a b c), dotted tails (a . b), and the tail-only form ( . x), which reads as x itself — a list that is only a tail IS the tail. Its idiomatic use is the bare-variadic parameter list: (fn ( . rest) rest).

Comments. ; to end of line. No block comments.

What the bare layer is NOT

Known sharp edges (tracked in issue #45)