Commit 143e671
Phase V.3: self-hosting parser + type-aware equality fix
examples/self_hosting_parser.omc — a recursive-descent parser written
in OMNIcode that consumes the token stream from V.1/V.2 and emits an
AST as nested tagged arrays (the canonical Python OMC convention).
The language can now READ its own source (lexer V.1/V.2) and STRUCTURE
it (parser V.3). Two of four self-hosting steps in place.
## AST node shapes
["NUMBER", "42"] ["FLOAT", "3.14"] ["STRING", "hello"]
["BOOL", "true"] ["VAR", "x"]
["BINOP", "+", left, right]
["CALL", name, [arg1, arg2, ...]]
["VARDECL", name, value] ["ASSIGN", name, value]
["IF", cond, then_body, else_body]
["WHILE", cond, body]
["RETURN", value_or_null] ["PRINT", expr]
["FNDEF", name, params, body] ["EXPRSTMT", expr]
## Precedence ladder
parse_comparison (==, !=, <, <=, >, >=)
-> parse_additive (+, -)
-> parse_multiplicative (*, /, %)
-> parse_primary (literals, parens, calls, variables)
Mutually recursive across statements and expressions. Position is
threaded explicitly as a return-array pair `[ast_node, next_pos]`
because OMC has no mutable references.
## Verified on 4 demo inputs
1. h x = 89 + 144;
→ VARDECL x = (BINOP + 89 144)
2. if x == 89 { return x; } else { return 0; }
→ IF (==) then: RETURN(VAR x) else: RETURN(NUMBER 0)
3. fn fib(n) { return fib(n-1) + fib(n-2); }
→ FNDEF fib(n) body: RETURN(BINOP + (CALL fib (n-1)) (CALL fib (n-2)))
4. while i < 10 { sum = sum + i; i = i + 1; }
→ WHILE (< i 10) body: ASSIGN sum ... ASSIGN i ...
Tree-walk and VM produce bit-identical output.
## Bug surfaced: type-aware equality
The parser writes `if v == "null"` to check for body-less return. With
the old equality rule (coerce both sides to int, compare), this was
TRUE for any array v because:
to_int(["VAR", "x"]) -> 0
to_int("null") -> 0
0 == 0 -> true
Every RETURN value was being rendered as "(no value)".
V.1 (commit e85bb01) fixed the narrower String==String case. This
commit fixes the BROAD form via a values_equal helper used by both
the tree-walk interpreter and the VM's cmp_op:
- Same-type values: structural equality (recursive for arrays).
- String vs non-string: only equal if the string parses as the
corresponding numeric.
- Mixed Array / Circuit / Singularity vs anything else: never equal.
- Numeric / Bool / Null: standard int-or-float coercion.
This is the THIRD silent bug self-hosting work has flushed out. The
language stress-tests itself by being asked to do real work in itself.
## Tests
141 still passing. Canonical sweep still 22/30 in both modes.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>1 parent 4740d76 commit 143e671
4 files changed
Lines changed: 806 additions & 22 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 | + | |
| 47 | + | |
| 48 | + | |
7 | 49 | | |
8 | 50 | | |
9 | 51 | | |
| |||
0 commit comments