Commit ddb553d
Phase V.5: SELF-HOSTING FIXPOINT — OMC compiles its own compiler
examples/self_hosting_fixpoint.omc — a single OMC program containing
the lexer (V.1/V.2), parser (V.3), and pretty-printer (V.4), with a
driver that verifies the formal closure property:
source₁ → tokens₁ → AST₁ → source₂
source₂ → tokens₂ → AST₂ → source₃
source₃ → tokens₃ → AST₃
Required:
AST₁ == AST₂ == AST₃ (structural equality on nested arrays)
source₂ == source₃ (source-level fixpoint after one
normalization pass)
If all three hold, the pretty-printer is a right inverse of the parser
and the compiler-in-OMC is closed under its own pipeline.
## 6 / 6 tests pass
1. h x = 89 + 144;
2. h y = 1 + 2 * 3; (precedence)
3. h i = 0; while i < 5 { i = i + 1; }
4. h x = 89; if x == 89 { return x; } else { return 0; }
5. fn fib(n) { return fib(n - 1) + fib(n - 2); }
6. fn double(x) { return x * 2; } h m = double(21); print(m);
For each, source₁ tokenizes + parses to AST₁; emit(AST₁) → source₂;
source₂ tokenizes + parses to AST₂; AST₁ == AST₂; one more round of
emit + re-parse stays stable at source₃ == source₂.
Tree-walk and VM produce bit-identical output on every test.
## Why this matters
A self-hosted compiler is one where the language can express its own
compilation. The fixpoint property is the conventional first concrete
milestone for self-hosting (the next is gen2 == gen3 on the back-end,
once codegen targets executable output rather than source).
The canonical Python OMNIcode tree explicitly set this as a goal in
SELF_HOSTING_PLAN.md and BOOTSTRAP_STATUS_CRITICAL.md. It produced a
480-line complete_lexer.omc that compiled to a native .exe, but the
fixpoint demonstrating gen2 == gen3 was never delivered.
Rust OMC reaches the lex/parse/print fixpoint here, in a single file,
runnable on both execution paths.
## Structural equality powered by V.3 fix
The `AST₁ == AST₂` check relies on the type-aware values_equal helper
introduced in V.3 (commit 143e671). That helper does recursive
structural comparison on nested arrays. Without it, the previous
to_int() coercion would have made every AST appear equal to every
other one (since arrays don't parse as integers, all become 0).
The self-hosting work has now flushed out three classes of silent bug
across V.1, V.3, and V.5 — each one a real semantic improvement to
the language. The phrase "the water sands the stone" wasn't a
metaphor; it was the work.
## Tests
141 still passing. Canonical sweep 22/30 in both modes.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>1 parent 4a460fb commit ddb553d
2 files changed
Lines changed: 808 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
7 | 47 | | |
8 | 48 | | |
9 | 49 | | |
| |||
0 commit comments