Implementation Map
x2c translates its extensions into C expressions, statements, and runtime calls. This chapter identifies the parser, transforms, runtime modules, and tests for each feature.
To follow a feature from syntax to generated C, start with its entry below and read the files in the listed order.
What the features mean is documented elsewhere:
- language reference: syntax and behavior
- idioms: how to use each feature well
- standard library overview: runtime contracts
- architecture: the pipeline as a whole
The compiler API reference and runtime module reference describe individual functions and types.
Watching a feature get lowered
To see how a compiler stage transforms a feature, dump the AST before and after
that stage. Take a foreach loop:
int sum(List numbers) {
int total = 0;
foreach(Var n, numbers) total += n;
return total;
}
Ask for the AST after parsing and macro expansion:
./builds/0/x2c translate --dump-transforms sum.x
(block
(declare ("Var") (bindings (bind (binding 4 "n") ())))
(declare ("Iter")
(bindings (op = (bind (binding 5 "_x2c_macro_iterator_0") ())
(expr ("Iter") (call ... (ident (binding 10 "List_iter"))
(args ... (expr (* struct "Iter") (op & ...))))))))
(while
(expr (int) (call ... (ident (binding 11 "Iter_try_next")) ...))
(block ...)))
The built-in source macro in src/macros.x, etc/builtin-macros.xmacro, and
etc/builtin-macros.xlisp has replaced foreach with declarations and a
while loop that call List_iter and Iter_try_next. The final List_iter
argument is a zero-initialized compound literal whose block lifetime holds the
iterator state. The later transform pass replaces total += n with the
run-time compound assignment helper for that scalar tag. Compare --dump-ast
with --dump-transforms to see that second change. The full set of dump flags
is listed under compiler options.
Feature ownership
Collection and String literals
- Parse:
src/literals.x - Lower/generate:
src/transform.x,src/cache.x - Runtime:
lib/list.x,lib/array.x,lib/map.x,lib/string.x - Tests: literal-cache and mutable-empty fixtures, collection suites
- See also: collections
String interpolation
- Parse:
src/literals.xfor$nameand${expr}, which are separate sites - Type/convert:
Compiler.convert_segment_to_stringinsrc/expressions.xselects the conversion for each segment. A segment that is already aVar, canonical or aliased, renders throughVar_strwhatever its run-time tag; a numeric segment takes its nearest declaredT_strconverter when one exists and is boxed and rendered throughVar_strotherwise - Lower/generate:
src/transform.xjoins the segments withString_join - Runtime:
lib/string.x, plusVar.strfor the boxed segments - Tests: interpolation suite
- See also: values
Symbol and Atom literals
- Tokenize:
lib/tokenizer.x, using the scanners inlib/scan.x - Parse:
src/literals.x - Lower/generate:
src/emit.x - Runtime:
lib/symbol.xfor immediateSymbols,lib/atom.xfor spellings that do not fit aSymbol - Tests: symbol suite and checked symbol example
- See also: symbols and atoms
Indexing and slicing
- Parse/type:
src/expressions.x,src/type.x - Lower:
src/transform.x - Runtime: collection helpers plus the shared bounds normalizer in
lib/common.x - Tests: index/slice suite and checked indexing example
- See also: collections
Method-style calls
- Parse/type:
src/expressions.x,src/type.x - Lower:
src/transform.x - Runtime: statically selected module function
- Tests: unit suites across runtime types
Compile-time macros and decorators
- Parse, import, hygiene, and expand:
src/macros.x - Compile-time Lisp operations:
etc/compiler-sdk.xlisp - Embedded native bindings:
etc/lisp-bindings.xmacro,etc/lisp-bindings.xlisp,lib/lisp.x, andlib/func.x - Tests: macro import, template, decorator, inline-Lisp, and inferred-binding
compiler fixtures; Lisp and
Funcsuites; compile-time-macros, decorators, and inline-lisp examples - See also: compile-time macros
Package imports and with names
- Parse:
src/parse.x - Package name collection and resolution:
src/compiler.x,src/collect.x - Manifest and native build ownership:
src/project.x,src/build.x, andsrc/toolchain.x - Tests: import/package compiler fixtures and the import-greet example
- See also: packages and imports
Exact Var-tag tests with is and is not
- Parse and type selection:
src/expressions.x,src/type.x - Lower and emit:
src/transform.x,src/emit.x - Runtime tag representation:
lib/var.x,lib/common.x - Tests: is-type and is-not compiler fixtures plus
Varsuites - See also: exact Var-tag tests
List destructuring
- Parse declarations and binders:
src/parse.x,src/statements.x - Type and lower access:
src/type.x,src/transform.x - Runtime source values:
lib/list.x - Tests: destructuring suite and list-destructuring compiler fixtures
Inline Lisp bindings
- Parse and expand
$lisp.bind,$lisp.binding, and$lisp.install:src/macros.x,etc/lisp-bindings.xmacro, andetc/lisp-bindings.xlisp - Runtime call boundary:
lib/lisp.x,lib/func.x - Tests: Lisp binding compiler fixtures, Lisp/
Funcsuites, and the inline-lisp example - See also: compile-time macros
Var boxing, conversion, operations, and dispatch
- Type selection:
src/type.x - Typedef identity and scopes:
src/compiler.x,src/statements.x - Conversion lowering:
src/expressions.x - Operator and truthiness lowering:
src/transform.x,src/emit.x - Sentinel literal parsing and C spelling:
src/literals.x,src/emit.x; expression context distinguishes the literal from Cvoidtype positions - Runtime representation:
lib/common.x,lib/var.x,lib/scope.x - Numeric metadata, conversion, and failure causes:
lib/varconvert.x; shared representation declarations:lib/common.x - Arithmetic, truthiness, and compound assignment:
lib/varops.x - Comparison policy and nonnumeric dispatch:
lib/dispatch.x; exact numeric comparison mechanics delegate toVar.integer_compareandVar.integer_floating_compare - Typedefs: declarations are file-scope; direct and chained aliases of
Varuse the same conversions and operators asVar - Numeric conversion: all 15 numeric tags use one implementation that raises
the appropriate
Errorcause on failure;long/ulong,llong/ullong, andldoublename nativelong,long long, andlong doublefamilies rather than fixed widths - Limits: numeric-to-
Stringconversion remains partial; other nonnumeric values use their declared conversions; helper-backed collection, enum, and bit-field compound assignment are unsupported; the C compiler checks ordinary C lvalue legality - Sentinel contract: equality, identity, exact
is void, and rendering inspectvoid; hashing, ordering, truthiness, iteration, conversion, arithmetic, and updates retain<void-op>behavior - Tests:
Var/File/VarOps suites and wide/custom, var-alias-crossings, var-numeric-lowering, var-numeric-conversions, var-native-lvalue-boundaries, var-truthy-void, var-nonnumeric-operator, var-unary-operator, var-helper-compound, var-enum-compound, var-bitfield-compound, and local-typedef compiler fixtures - See also: values and Var
Scalar declarations, literals, and arithmetic
- Parse:
src/parse.x,src/literals.x,src/expressions.x - Canonical type owner:
src/type.x - Conversion:
src/transform.x,src/expressions.x - Runtime representation:
lib/var.x,lib/scope.x - Tests: canonical scalar fixture, invalid-scalar and overflow diagnostics,
Varsuite - See also: values and Var
Lambdas
- Parse:
src/literals.x - Lower and direct
Funccalls:src/lambda.x,src/transform.x,src/expressions.x - Runtime:
lib/func.xand receiving callback APIs - Tests: captured-lambda and lambda-lowering fixtures, lambda and
Funcsuites
Foreach
- Parse and expand: built-in source macro support in
src/macros.xandetc/builtin-macros.xmacro; private lowering inetc/builtin-macros.xlisp - Lower/generate the expanded loop:
src/transform.x,src/emit.x - Runtime:
lib/iter.xand collection adapters;Iter.try_nextowns status - Tests:
foreachfixture,Itersuite, and checked example - See also: iteration
Status-bearing Map operations
- Runtime owner:
lib/map.x - Literal boundary:
src/emit.xemits countedMap.update_nconstruction - Generic routing:
lib/dispatch.x - Compatibility:
Map.getandMap.del - Cursor contract: structural mutation invalidates outstanding traversal state
- Tests:
MapandItersuites plus thevoid-sentinel and rawNullcoverage - See also: collections
Counted Array construction
- Runtime owner:
lib/array.xthroughArray.update_nandArray.push - Literal boundary:
src/emit.xemits countedArray.update_nconstruction - Value contract: raw
Nullis data;voidis rejected - Tests:
Arraysuite and the counted-literal compiler fixture - See also: collections
Match statement
- Parse:
src/statements.x - Lower/generate:
src/transform.x,src/emit.x; emitted code callsList.match - Runtime:
lib/match.xowns pattern semantics and plan compilation;lib/match-machine.xexecutes plans over wordcode and state definitions fromlib/machine.x; patterns and binding sets are ordinaryLists fromlib/list.x - Tests: match suites and checked nested example
- See also: pattern matching
Raise, filtered catch, finally, and defer
- Parse:
src/statements.x - Lower/generate:
src/transform.x,src/emit.x - Runtime:
lib/exception.xowns the frame/jump engine for transfer and cleanup;lib/error.xowns handlers, policy, watermarks, accumulated records, matching, and transferring registration lifetime - Tests: optimized
defer/try and filtered-catch compiler fixtures, exception/defer/Errorsuites, and fatal/floor subprocess probes - See also: errors and cleanup, and scopes and lifetime for what cleanup releases
Type-owned initialization
- Parse:
src/parse.x - Lower/generate:
src/generate.x,src/cache.x - Runtime: generated guard plus
TYPE.initialize() - Boundary: non-static functions enter the guard; static helpers trust their guarded caller or the already-guarded initializer body
- Tests: type-initializer fixtures
Structured diagnostics
- Produce: all parser phases
- Collect/render:
src/diagnostics.x - Destination: standard error, written directly;
src/report.xsuspends the progress line first. Nothing is logged to a file - Tests: parse-error, diagnostic-width, and invalid-list-splice fixtures plus the diagnostics suite
The exact location fields, one-based coordinates, token-width rendering,
one-error compiler default, and reusable store limit are documented in
agents/logger-and-diagnostics-guide.md.
Compiler phase boundaries
The main translation steps are:
lib/tokenizer.xturns scanner results into tokens.src/parse.xcoordinates declarations and top-level source.src/expressions.x,src/statements.x, andsrc/literals.xconstruct typed AST forms;src/ast.xowns the shared node contracts they build to.src/type.xsupplies type facts and canonical forms.src/transform.xlowers most extensions;src/lambda.xowns lambda helper and adapter synthesis.src/generate.xpartitions the translation unit and installs init scaffolding;src/cache.xowns literal-cache initialization.src/emit.xemits C tokens andsrc/format.xformats them.
Global type information reaches the parser outside that
pipeline. src/collect.x gathers global symbol types by shallow-parsing raw
source and splicing quote-includes in preprocessor order, and
src/snapshot.x reads and writes the deterministic symbol snapshot that
covers the runtime under lib/.
src/compiler.x owns compiler state and symbol scopes. src/diagnostics.x
owns structured errors. src/utils.x owns host-environment and process
helpers, including the C preprocessor process boundary. src/main.x owns
process initialization, the translation loop, and phase dispatch;
src/cli.x owns the option table, command selection, and help rendering.
Each feature entry lists the relevant parser, transforms, runtime code, and tests so you can follow its complete implementation.