Repository navigation
Track 1.0.0: self-hosted compiler with verified bootstrap fixpoint - #1
Conversation
… valued if/match, tuple returns, union payloads
The Cranelift backend lowered values with mixed I8/I32/I64 types and
declared cross-module imports with guessed signatures, which produced
garbage upper bits on bool returns and sign-lost C int results. All
values are now 64-bit words, matching the self-hosted C backend.
Also fixes:
- os_args_count/os_arg always saw 0 args (argv never reached runtime)
- && and || were bitwise (1 && 2 == 0) and did not short-circuit
- return inside match arms / while bodies / nested ifs panicked
("block already filled")
- if/match used as expressions read values from non-dominating blocks
- returning a tuple-literal local returned a dangling stack pointer
- string literal patterns compared pointers
- union payload variants lost their payload; enum explicit
discriminants were ignored; variant lookup used bare names
- runtime functions returning int lost the sign of -1 results
- str_substr/str_char_at scanned the entire string per call
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PQbdbWq7kNpFj8roT4CZSq
Move the runtime out of a Rust string into runtime/track_runtime.c so the self-hosted compiler can link the exact same implementation. Every exported function now takes and returns 64-bit words, which fixes Vec (a 16-byte struct return was truncated to its data pointer) and math_* (declared with double parameters but called with integers). Adds collection pop/truncate, a string builder, whole-file read/write, unformatted output, and track_str_bytes for O(1) source access. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PQbdbWq7kNpFj8roT4CZSq
trackc is written entirely in Track and compiles itself to a fixed point: stage1 (built by the Rust compiler) and stage2 (built by stage1) emit byte-identical C, and stage2/stage3 executables are identical. - base.trk: word vectors, string builders, interning, context, diagnostics - lexer.trk / parser.trk: complete Track grammar into a node pool - loader.trk: whole-program loading of imported modules - symbols.trk / checker.trk: ownership checker mirroring LinearChecker - cgen.trk: portable C99 backend on the shared word-ABI runtime - runtime_c.trk: generated by scripts/embed_runtime.sh Host fixes found along the way: constants used before their declaration, and constants used across modules compiled to 0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PQbdbWq7kNpFj8roT4CZSq
…ache staleness - scripts/bootstrap.sh runs stage0 -> stage3 and gates on identical C and identical stage2/stage3 executables - tests/selfhost_tests.rs: fixpoint, example parity (stdout + exit code), 22 accept/reject verdicts shared by both checkers, diagnostic frames, and the native suite under trackc - native tests for the new lexer, parser, checker, and C emitter Host fixes found by the parity tests: - codegen: bindings inside if/while/for/match/with blocks leaked into the enclosing scope (shadowing changed the outer variable) - checker: `let mut x` made every later `x` mutable, in any function; mutability is now lexically scoped and params/loop vars are immutable - checker: assignment to an undeclared variable was silently accepted - yard: the build cache keyed objects only on their own source, so compiler upgrades and changes to imported constants reused stale objects Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PQbdbWq7kNpFj8roT4CZSq
Bump track, yard, and trackc to 1.0.0. CI now checks the embedded runtime is current, builds and tests compiler/ with yard, and gates on the stage0 -> stage3 bootstrap fixed point. Docs: docs/bootstrap.md (pipeline, word ABI, C backend contract, runtime embedding), roadmap through v1.0.0, CHANGELOG, README, and SPEC sections on mutability and the runtime value model. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PQbdbWq7kNpFj8roT4CZSq
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PQbdbWq7kNpFj8roT4CZSq
Struct literals, field reads, and arrays parsed but evaluated to 0. Both backends now lower them to heap cells: structs are [name hash, fields in declaration order] (a field name shared by several structs dispatches on the tag) and arrays are [length, elements...] with bounds-checked get/set and slice copies. - p.x = v, t.0 = v, and a[i] = v update in place; the root variable must be let mut or a lens alias - struct patterns match and bind by field - array_len(&a); a[s..e] and a[s..] slices - unknown struct fields and unknown field names are compile errors Also fixes open-ended slices (a[2..]) failing to parse and generic calls inside index/slice expressions skipping monomorphization. The bootstrap fixed point still holds (20125 lines of identical C). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PQbdbWq7kNpFj8roT4CZSq
Neither compiler inserts frees at scope exit; the docs claimed both. State what v1.0 does (manual frees rejected, memory reclaimed at exit) and list scope-exit deallocation on the roadmap. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PQbdbWq7kNpFj8roT4CZSq
|
Caution Review failedThe pull request is closed. Walkthrough
Merge Risk:
|
Summary
Track is now self-hosting.
trackc(compiler/src/) is written entirely in Track and compiles itself to a fixed point: the Rust-built and Track-built compilers emit byte-identical C (20,125 lines), and the stage 2 and stage 3 executables are byte-identical.Self-hosted compiler
src/checker/), and a portable C99 backend.trackc build | run | check | emit-c | tokens | --version, witherror[Exxxx]diagnostics and source frames.runtime/track_runtime.c: one word-ABI runtime shared by both compilers (embedded into trackc byscripts/embed_runtime.sh).Bugs fixed in the Rust compiler
intresults lost their sign).os_args_count/os_arg.&&/||were bitwise and didn't short-circuit.returninsidematcharms /whilebodies / nestedifs panicked the backend.if/matchvalues, dangling returned tuples, pointer-compared string patterns, lost union payloads, ignored enum discriminants.0; constants used before declaration were rejected.let mutleaked across functions; assignment to undeclared variables was accepted.Vec/math_*runtime ABI bugs; O(n)str_substr/str_char_at; open-ended slices failed to parse.New language support (both compilers)
array_len.Verification
scripts/bootstrap.sh: stage 0 → 3 with the fixed-point gate (now in CI).tests/selfhost_tests.rs: fixed point, example parity (stdout + exit code), 29 shared accept/reject verdicts, diagnostic frames, native suite under trackc.tests/codegen_semantics_tests.rs: run-and-compare regressions for each backend fix.yard testpasses,cargo clippy -- -D warningsandcargo fmt --checkclean.Known limitations
yard, thetrackCLI, and the LSP remain in Rust.See
docs/bootstrap.mdandCHANGELOG.md.Generated by Claude Code
Summary by CodeRabbit
New Features
Documentation
Bug Fixes