Compiler self-hosting roadmap
Follow the stages and acceptance criteria for compiling ZBLC from ZBL source.
The compiler in compiler/bootstrap/main.zbl is written in ZBL. It lexes source, parses expressions and indentation, assigns local slots and emits stack IR. Its own complete source fits the supported subset and can be compiled by its own output.
Reproduce on Windows
Load the repository toolchain, build Zebvix and run the verifier from the repository root.
. ./scripts/toolchain.ps1
cargo build --locked -p zbl --bin zebvix
./scripts/verify-self-hosting.ps1 -Zebvix ./target/debug/zebvix.exe
The verifier creates a fresh directory and uses an isolated SDK home. It records the source and binary SHA-256 hashes, verifies the Stage 3 bytecode, and compares the self-compiled demo with the Rust-compiled reference. An alternate Rust build supplies a second seed. Its output must match both self-compiled stages.
Rust ZBLC -> Stage 1 compiler bytecode
Stage 1 + compiler source -> Stage 2 compiler bytecode
Stage 2 + compiler source -> Stage 3 compiler bytecode
Stage 2 == Stage 3 == output from alternate seed
The guest receives UTF-8 source as the text parameter of compile_source. It runs in ZBR with a dedicated fuel and allocation budget, a 1 MiB output cap and zero filesystem operations. A small Rust assembler resolves IR labels, checks instruction encoding and passes the module to the existing typed ZBC2 verifier. The verifier checks operand types, task signatures and initialized local slots. It then packages the verified module with its length and SHA-256 envelope. The source lexer, parser and lowering inside Stage 2 and Stage 3 run as ZBL code.
A compiler artifact can compile another file directly.
zebvix bootstrap-compile stage3.zbc demo.zbl demo.zbc
zebvix inspect demo.zbc
zebvix exec demo.zbc
Use the Zebvix binary built from this branch. The command requires a fresh output path and writes the artifact only after guest execution and bytecode verification succeed.
Supported source
- One UTF-8 source file up to 64 KiB. ASCII identifiers, four-space indentation, ordinary punctuation spacing, and hash or double-slash comments.
- Explicit tasks with typed parameters, a zero-argument unit main task, and explicit give on every reachable exit. Tasks may call tasks declared later or recurse.
- Function-body typed declarations, assignment, scalar literals, empty typed lists and maps, indexing and supported host functions. Loop variables are immutable, scoped to their range loop and unique within their task.
- Integer arithmetic, unary negation and boolean negation, comparisons, ranges, when/otherwise, repeat over ranges, show and task calls.
- UTF-8 text literals with the existing backslash escapes for quote, backslash, newline, carriage return and tab. Actual control characters in literals must use escapes for the bootstrap wire format.
Remaining compiler work
The existing SDK keeps Rust ZBLC for normal Zebvix build, check, run and test. The bootstrap compiler covers its own source and the documented subset. Full SDK language parity still requires project/module and package linking, inferred declarations, nonempty collection literals, richer collection and type syntax, generics, shapes, choices, pattern matching, structured errors, effects and ownership checks. Native and other code-generation targets require separate work. The Stage 2 and Stage 3 output uses ZBC2 and the existing ZBR runtime. Verification so far uses one Windows machine and alternate seeds, with cross-platform reproducibility still pending.
Windows test evidence
The SDK regression run passed 180 tests. The final bootstrap rerun passed all three integration tests. Stage 2, Stage 3 and the alternate-seed artifact each contained 121,535 bytes and shared SHA-256 747d72d918fd07c2e9090401e9247de66b04eb531daf8a778e6f35f9332e5f3d. The compiled demo printed 42 and Hello ZBL: "नमस्ते", matching the Rust-compiled reference. A malformed UTF-8 input produced no output file. Selecting an existing output path preserved its original bytes.
The verification script records CLI and artifact hashes in its local evidence JSON.