Skip to content

Commit 9ef32e0

Browse files
olwangclaude
andcommitted
selfhost: results writeup (phases 1-4, findings SH-016..023, next lever)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 6a992be commit 9ef32e0

1 file changed

Lines changed: 51 additions & 0 deletions

File tree

docs/self-hosting-stress-test-plan.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)