Experimental REPL
x2c repl evaluates a supported subset of x2c in a persistent session.
It uses the compiler’s typed syntax and compile-time Lisp evaluator. It does
not compile each submission to a native executable.
x2c repl
x2c repl --help
x2c repl --dump --stats
No source file or checkout is needed when using an installed development build. The command reads standard input and accepts no file operands.
Try a session
Enter these submissions in order:
x2c> int total = 10;
ok
x2c> int plus(int x) { return total + x; }
defined plus
x2c> plus(3);
=> 13
x2c> total = 20;
ok
x2c> plus(3);
=> 23
The function calls display => 13 and => 23: later calls read the current
value of total. Definitions display defined NAME; initializations and
statements display ok. A final expression displays its value using
Var.repr, so character and unsigned values retain their printed tags.
Submit one declaration or function at a time. Executable input may contain
several statements. Semicolons are required. Incomplete input continues at
the ... prompt until it forms a complete submission. Put a multiline
if/else in a block when necessary: a complete if can execute before the
next line supplies an else.
Inspect and control the session
| Command | Meaning |
|---|---|
:help | Show session commands. |
:symbols | List successfully defined names and their kinds. |
:ast plus | Show plus’s typed x2c AST. |
:lowered plus | Show the Lisp forms used to execute plus. |
:cancel | Discard incomplete input. |
:quit | Exit, discarding incomplete input. |
For the example above, :symbols prints the list template
%((function "plus") (value "total")). Typed AST output begins with
typed: %(; lowered Lisp is separately labeled lowered:. Inspection does
not execute the function, and earlier functions remain inspectable after
later submissions. Values have symbol entries but no function AST.
Help and inspection commands preserve incomplete input, including when a command reports an error. Colon commands are recognized on separate lines even inside an incomplete string or comment. Missing names, extra arguments, and unknown commands report errors.
--dump prints each available typed AST and lowered Lisp form to standard
error. --stats prints Lisp calls, word-machine entries, and machine errors
at exit. The options can be combined.
Supported subset
The current subset includes initialized simple variables, function
definitions, integer arithmetic and narrowing, assignment, conditionals,
for loops, self recursion, and calls to earlier functions. String values
and length, List literals and indexing, and Array construction, mutation,
and indexing are exercised by the focused checks.
Redefinition is disabled; assign to an existing variable to change its value.
Function replacement and mutually recursive forward declarations are not
supported. Names beginning __repl_ are reserved.
Native pointer and ABI operations, arbitrary C libraries, aggregate and type
definitions, imports, protocols, user macro/meta definitions, preprocessor
directives, and direct Lisp input are outside this subset. Variables need
initializers; declarator modifiers, const, and volatile are rejected.
Function-local static, extern, and threaded storage are also rejected:
the evaluator cannot provide their native lifetime or linkage semantics.
Other constructs depend on the existing lowering and may be declined. Full
native execution and reference/lifecycle parity are not established; for
example, the evaluator loses the distinction between Var void and an
empty List. A void function currently displays the lowering’s zero sentinel.
Failure and lifetime
Rejected submissions leave earlier definitions usable. A declaration publishes its names only after all initializers succeed. If a later initializer fails, none of that declaration’s names become available, including through inspection. Effects already made on existing values remain, both for failed initialization and failed statements.
Session storage lives until exit. Submission scratch is reclaimed, but canonical syntax, compiler caches, and evaluator allocations can accumulate. Long sessions do not have a bounded-memory guarantee. A one-million-step Lisp call budget interrupts runaway interpreted evaluation; native callbacks are not a preemptible sandbox.
EOF exits successfully unless input is incomplete, which exits with status
- With piped input, any submission or command error makes the final status
1, while later input still runs. In an interactive session, recovered errors
do not change a normal exit’s status from 0. Ctrl-C terminates the process;
use
:cancelto discard pending input and keep working.