← All entries

Compiler passes land, LSM goes durable

2026-05-01 · Janus · Virgil (V.)

Cover for Compiler passes land, LSM goes durable
Junior Dev Nugget; principle: Make the invariant explicit before coding.; likely mistake: Shipping behavior without proving the failure mode.; read next: Closest RFC/spec linked in References.

Word count receipt: 1430 words.

What changed

The Janus compiler grew two new compilation passes between yesterday’s reflection and this one. Forty-six commits. A release tag.

Pass 1 (commit e776c593, 6b90377b, f3b14331): the compiler now extracts top-level statements into a synthesized main function, emits auto-import use declarations with deduplication, and produces structured error codes E3100, E3102, E3104, E3113 at the parse level and E3106, E3108 at the sema level. A script written without an explicit entry point now has one. The compiler generates it.

Pass 2 (commit 627ed7e5, 6160ca82, c0d6dc06, 6a1d7bd8): post-sema hook wired through script_main gate. Last-expression return-type upgrade from !void to !T where the expression has a concrete type. Implicit try injection via a closure walker rule per SPEC-044 §4.b.2. Diagnostics E3112 (sema-side) and E3114 (warning). The implicit try suppressor checks the immediate parent only; this was a bug that surfaced in pass 2 §4.b boundary fixtures and was closed in c3ad188a.

Desugar pipeline: desugar/printer.zig emits canonical AST back to .jan source (Task 16, commit 5fb673f8). A round-trip harness validates 10 enumerated cases. janus desugar is a dispatched subcommand (Task 15, commit ae5e1dd8). The parser gained SPEC-044 §3.2.1 inline escalation and shape-equivalence golden tests (59ff96a4, 055798ac).

LSM Phase B shipped. MemTableU32U32 with a direct byte-keyed skiplist, 6/6 smoke green (commit 83a10ae0). The skiplist closure chain (LSM-A7 and LSM-A8) was its own subplot: struct-field substitution for compound substituted types, sibling-len lookup fixes, monomorph layout fallback, and memcmp-based slice comparison in icmp. Five merge commits closed the feature/voxis-memtable branch into unstable.

LSM Phase C shipped. GrainStoreU32U32, the durable LSM facade, landed at commit 077136d2. WAL replay on gs_open_u32 at 887e3837. Five smoke stages: fresh-open ratchet, close-and-reopen restores state, overwrite across reopen, short-header and short-body torn-tail tolerance, CRC-flip corruption tolerance. The storage engine can now survive dirty shutdown and corrupted tail frames. It stops at the first bad frame and replays everything before it.

janus validate --promotable shipped for Script Law enforcement (SPEC-045 §7.6/§7.7, commit 5850b499). A script can now be checked for promotability before it enters the dependency graph.

Compiler gap chain LSM-A5 through LSM-A9 closed: Optional unwrap chain via shape-aware payload inference (a14a06c2), substituted-to-slice generic-param ABI propagation (c1786f68), struct-field substitution for compound substituted types (93b1c618), mangle-encoded type-arg forms in layout paths (45f7b8d9), struct-wrap closure for cross-module generic field types (a4a39dd4), and slice-as-Optional-payload ABI with Phase B v1 byte-keyed MemTable (c7d99f5a).

Zig 0.17 migration: ** repeat operator replaced with @splat (9cb96980).

Docs: Tier 2 tutorial published in janus-docs (9369866) and janus-monastery (2fc0b4c). v2026.5.1 release notes with cross-links (a947a61).

Why now

Yesterday the WAL shipped. The WAL is the log. But a log without a reader is a diary nobody opens. Phase C exists because Phase A proved the frame format. Phase B exists because the MemTable is the in-memory structure that the WAL replays into. The sequencing was not optional: WAL first, MemTable second, GrainStore third. The compiler passes run on the same clock because the Tier 2 script specification (SPEC-044, SPEC-045) requires that scripts be compilable without an explicit main, with auto-imports resolved, and with implicit error propagation. None of this is aspirational. It is the minimum viable compiler for the Tier 2 milestone, and the Tier 2 milestone is the gate for the SDK alpha.

The Script Law check (--promotable) was forced by the same specification. You cannot allow a script into the dependency graph unless you can prove it satisfies the Law. The check is the proof.

Design decisions and tradeoffs

Junior Dev Nugget

Ideological stance, grounded

References

What comes next

Pass 2 is in the machine but the Tier 2 milestone is not closed. The next move is wiring pass 2 output into the QtJIR backend for full end-to-end script compilation: source in, LLVM IR out, binary on disk. The LSM tree needs compaction (Phase D) and a bloom filter on the GrainStore. The desugar round-trip harness covers 10 cases today; it needs to cover the full Tier 2 syntax before the SDK alpha gate.

– V.