@@ -174,3 +174,54 @@ Known constraints to design around:
174174 full corpus.
175175- Findings are the deliverable — recorded as ` SH-NNN ` entries in
176176 ` docs/ledgers/rss-selfhost-ledger.md ` ; green oracle runs are the floor, not the goal.
177+
178+ ---
179+
180+ ## Results (2026-07-01)
181+
182+ Implemented in worktree ` rsscript-wt-selfhost ` (detached off main), sub-agents porting,
183+ orchestrator gating parity. Harness lives in ` crates/rsscript/src/selfhost_parity.rs `
184+ (` #[cfg(test)] ` — zero new public API, zero new CLI; reaches the private lexer/parser and
185+ the VM entry point directly). It compiles each rss tool once (` reg_vm_compile_source ` ) and
186+ runs it on the reg-VM in-process, passing the corpus file's * content* as ` argv[0] ` .
187+
188+ | Phase | rss tool | Oracle | Corpus result |
189+ | -------| ----------| --------| ---------------|
190+ | 1 — lexer | ` selfhost/lexer.rss ` | ` crate::lexer::lex ` (canonical token dump) | ** 544/544 tier-0** , 0 run-failures |
191+ | 2 — parser | ` selfhost/parser.rss ` | ` crate::syntax::parse_source_raw ` (accept/reject) | ** 545/545 recognition** |
192+ | 3 — checker | ` selfhost/check.rss ` | ` crate::analyze_source ` (code ` RS0005 ` ) | ** 546/546** |
193+ | 4 — perf | lexer on VM vs native | wall-clock over corpus | ** ~ 5100× slower** (see SH-022) |
194+
195+ Gates (all green): ` cargo test -p rsscript --features native-jit --lib ` (3 tiny-sample
196+ tests); the corpus gates run with ` -- --ignored ` (` lexer_parity_corpus ` ,
197+ ` parser_parity_corpus ` , ` checker_parity_corpus ` , ` lexer_perf_corpus ` ).
198+
199+ ### Findings (ledger ` SH-016 ` … ` SH-023 ` )
200+ - ** SH-016** — no character-literal syntax; ` ' ` lexes to ` ? ` , cascading a misleading
201+ ` RS0013 ` . * (language + diagnostics)*
202+ - ** SH-017** — statement-level binary-operator expressions can't cross a newline; the
203+ leading-operator form ** compiles but is silently wrong** . * (language + correctness-grade
204+ diagnostics)*
205+ - ** SH-018** — no cursor/state object (no methods/` impl ` , ` mut ` params can't advance a
206+ cursor); stateful passes thread state positionally. * (language ergonomics)*
207+ - ** SH-019** — a ` fresh ` -returning fn can't build its result via ` mut ` + ` List.push `
208+ (` RS0601 ` ). * (analyzer/freshness ergonomics)*
209+ - ** SH-020** — recursive descent must encode ` (ok, new-index) ` as a sentinel ` Int ` . * (ergonomics)*
210+ - ** SH-021** — ` parse_source_raw ` defers body validation, so recognition parity under-tests
211+ the grammar (deep grammar is enforced in the analyzer, not the parser). * (methodology)*
212+ - ** SH-022** — ** the headline perf result:** the self-hosted lexer is ~ 5100× slower on the
213+ reg-VM than native Rust (79.5 s vs 15.3 ms over 712 KB). A controlled ` String.concat ` (O(n²))
214+ → ` StringBuilder ` (O(n)) swap moved nothing, isolating the cost to ** per-character intrinsic
215+ dispatch** (` List.get ` on ` List<Char> ` + ` Char.* ` peeks — VM value-representation +
216+ intrinsic-dispatch overhead), not string building. * (VM + stdlib)*
217+ - ** SH-023** — the checker reaches ` RS0005 ` parity; the load-bearing rule is the analyzer's
218+ ** merged callable namespace** (fn names + type-constructor names collide). * (insight)*
219+
220+ ### Highest-ROI next lever (from the data)
221+ SH-022 is the first real workload that unambiguously profiles as ** VM-dispatch-bound** . The
222+ indicated fix is a native ** string char/byte-cursor intrinsic** (iterate a ` String ` without
223+ materializing a boxed ` List<Char> ` ) plus lower per-intrinsic dispatch cost — this feeds the
224+ parked collection-representation / perf roadmap with real-workload evidence. Deeper checker
225+ passes (name resolution, exhaustiveness) are the natural next self-hosting step but require a
226+ real expression/statement/pattern parser (the depth ` parse_source_raw ` let Phase 2 skip —
227+ SH-021).
0 commit comments