From 663bbede50de170cbaa3e4fccddc9ddea2d07cbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Siobh=C3=A1n=20Sterrett?= Date: Thu, 9 Apr 2026 15:51:59 -0400 Subject: [PATCH] feat: complete easy fold suite + identity rules + STATUS.md roadmap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New optimizer folds (all self-hosted in Jest): - Identity arithmetic: x+0→x, x*1→x, x*0→0 - Identity concat: concat([],x)→x, concat(x,[])→x - Double negation: not(not(x))→x - If-to-bool: if(c,true,false)→c, if(c,false,true)→not(c) - Known element access: nth([a,b,c],1)→b, first([a,b,c])→a, rest([a,b,c])→[b,c] - Beta reduction: apply(fn([x],body),[v]) → let*(x=v, body) - Let inlining: let*(x=lit, body) where x used once → substitute lit Architectural fix: guard patterns on literal strings don't work in Jest match ({"guard": ["+", fn]} doesn't match "+"). Moved identity rules to _opt-try-identity helper called from the catch-all arm. Also fixed _opt-all-lit? argument spreading bug (array args must be wrapped in extra [] when passed as singleton call form). STATUS.md updated with full Jestification roadmap: medium fruit (constant propagation, strength reduction), big fruit (pattern compilation, classification, ANF, DCE), the big one (lowering, type inference), and GPU fuzzing backend plan. Co-Authored-By: Claude Opus 4.6 --- STATUS.md | 45 ++++++++++++ src/runtime/procs/optimizer.jst | 124 +++++++++++++++++++++++++++++--- 2 files changed, 160 insertions(+), 9 deletions(-) diff --git a/STATUS.md b/STATUS.md index 335f1e7..5670db9 100644 --- a/STATUS.md +++ b/STATUS.md @@ -333,3 +333,48 @@ cargo test --lib stress_test_soundness -- --ignored # 5000 proptest cases Property-based testing: 780 lines of proptests + 3200-line generator covering all Jest forms. Differential testing across 4 compilation pipelines (IR, ANF, OPT, Bytecode) at 100% match rate. + +## Self-Hosted Compiler (Jestification) + +Jest pattern-matching on its own syntax. The path to self-hosting. + +### Done + +| Pass | What | File | +|------|------|------| +| Source-level constant folder | Arithmetic, if, str, type predicates, boolean logic, equality, count, dead let | `optimizer.jst` | +| Precompiled optimizer | Optimizer calls compiled to bytecode via VM fast path | `compile/mod.rs` | + +### Medium Fruit + +| Pass | What | Rust equivalent | +|------|------|-----------------| +| Constant propagation | Substitute known let-bindings into arithmetic | `opt/constant_fold.rs` (partial) | +| Strength reduction | `{"*": [x, 2]}` → `{"+": [x, x]}` | — | +| Let flattening | Merge nested let* into single let* | — | + +### Big Fruit (new Jest modules) + +| Pass | What | Rust equivalent | Lines | +|------|------|-----------------|-------| +| Pattern match compilation | Clauses → TypeSwitch/LitSwitch decision trees | `decision.rs` | ~400 | +| Operative classification | "Is this a macro? Control form? Applicative?" | `classify.rs` + `analyze.rs` | ~600 | +| ANF normalization | Flatten nested exprs to let-bindings | `anf.rs` | ~650 | +| Dead code elimination (IR) | Count uses, prune dead bindings | `opt/dce.rs` | ~500 | + +### The Big One + +| Pass | What | Rust equivalent | Lines | +|------|------|-----------------|-------| +| **Lowering** | Source Value → IR (the heart of the compiler) | `lower.rs` | **~2600** | +| **Type inference** | Constraint generation + solving | `typing/check/` | **~4000** | + +### Future: GPU Fuzzing Backend + +| Phase | What | Status | +|-------|------|--------| +| Typed term synthesis | Generate well-typed programs from learned weights | Done (`synthesize.rs`) | +| CEM weight learning | Cross-entropy method evolves generator strategy | Done (`learned_fuzzing.rs`) | +| Fuzzer CLI | `cargo run --release --bin fuzz` | Done (`bin/fuzz.rs`) | +| WGSL VM | Minimal Jest VM in WebGPU shader language | Not started | +| GPU dispatch | 10k programs/generation on GPU threads | Not started | diff --git a/src/runtime/procs/optimizer.jst b/src/runtime/procs/optimizer.jst index a810da9..222ef32 100644 --- a/src/runtime/procs/optimizer.jst +++ b/src/runtime/procs/optimizer.jst @@ -47,6 +47,47 @@ ] ]}]}, + {"defn": ["_opt-subst", [{"var": "name"}, {"var": "val"}, {"var": "expr"}], + {"match": [{"var": "expr"}, + [ + [{"guard": [{"var": "call"}, {"var": "_opt-call?"}]}, + {"let*": [[["op", {"nth": [{"keys": {"var": "call"}}, 0]}], + ["arg", {"get": [{"var": "call"}, {"var": "op"}]}]], + {"if": [{"and": [{"==": [{"var": "op"}, "var"]}, + {"==": [{"var": "arg"}, {"var": "name"}]}]}, + {"var": "val"}, + {"tag": [{"var": "op"}, + {"_opt-subst": [{"var": "name"}, {"var": "val"}, {"var": "arg"}]}]}]}]}], + [{"guard": [{"var": "arr"}, {"var": "array?"}]}, + {"map": [{"fn": [[{"var": "el"}], + {"_opt-subst": [{"var": "name"}, {"var": "val"}, {"var": "el"}]}]}, + {"var": "arr"}]}], + [{"var": "other"}, {"var": "other"}] + ] + ]}]}, + + {"defn": ["_opt-try-identity", [{"var": "op"}, {"var": "args"}], + {"if": [{"and": [{"array?": {"var": "args"}}, + {"==": [{"count": {"var": "args"}}, 2]}]}, + {"let*": [[["a", {"nth": [{"var": "args"}, 0]}], + ["b", {"nth": [{"var": "args"}, 1]}]], + {"match": [{"var": "op"}, + [["+", {"if": [{"==": [{"var": "a"}, 0]}, {"var": "b"}, + {"if": [{"==": [{"var": "b"}, 0]}, {"var": "a"}, + {"tag": ["+", {"var": "args"}]}]}]}], + ["*", {"if": [{"==": [{"var": "a"}, 1]}, {"var": "b"}, + {"if": [{"==": [{"var": "b"}, 1]}, {"var": "a"}, + {"if": [{"or": [{"==": [{"var": "a"}, 0]}, + {"==": [{"var": "b"}, 0]}]}, + 0, + {"tag": ["*", {"var": "args"}]}]}]}]}], + ["concat", {"if": [{"==": [{"var": "a"}, []]}, {"var": "b"}, + {"if": [{"==": [{"var": "b"}, []]}, {"var": "a"}, + {"tag": ["concat", {"var": "args"}]}]}]}], + [{"var": "_"}, {"tag": [{"var": "op"}, {"var": "args"}]}]] + ]}]}, + {"tag": [{"var": "op"}, {"var": "args"}]}]}]}, + {"defn": ["_opt-try-fold", [{"var": "op"}, {"var": "args"}], {"match": [{"var": "op"}, [ @@ -58,7 +99,7 @@ {"or-pattern": ["*", {"or-pattern": ["/", "%"]}]}]}]}]}, {"array?": {"var": "args"}}, - {"_opt-all-lit?": {"var": "args"}}, + {"_opt-all-lit?": [{"var": "args"}]}, {">": [{"count": {"var": "args"}}, 0]}]}]}]}, {"try": [{"eval": {"tag": [{"var": "op"}, {"var": "args"}]}}, {"fn": [[{"var": "_e"}], @@ -69,6 +110,8 @@ {"match": [{"var": "args"}, [[[true, {"var": "then"}, {"var": "_"}], {"var": "then"}], [[false, {"var": "_"}, {"var": "else"}], {"var": "else"}], + [[{"var": "c"}, true, false], {"var": "c"}], + [[{"var": "c"}, false, true], {"tag": ["not", {"var": "c"}]}], [{"var": "_"}, {"tag": ["if", {"var": "args"}]}]] ]}, {"tag": ["if", {"var": "args"}]}]}], @@ -76,7 +119,7 @@ [{"guard": ["str", {"fn": [[{"var": "_"}], {"and": [{"array?": {"var": "args"}}, - {"_opt-all-lit?": {"var": "args"}}]}]}]}, + {"_opt-all-lit?": [{"var": "args"}]}]}]}]}, {"try": [{"eval": {"str": {"var": "args"}}}, {"fn": [[{"var": "_"}], {"tag": ["str", {"var": "args"}]}]}]}], @@ -91,7 +134,10 @@ ["not", {"if": [{"==": [{"var": "args"}, true]}, false, {"if": [{"==": [{"var": "args"}, false]}, true, - {"tag": ["not", {"var": "args"}]}]}]}], + {"if": [{"and": [{"_opt-call?": {"var": "args"}}, + {"==": [{"nth": [{"keys": {"var": "args"}}, 0]}, "not"]}]}, + {"get": [{"var": "args"}, "not"]}, + {"tag": ["not", {"var": "args"}]}]}]}]}], ["and", {"if": [{"array?": {"var": "args"}}, @@ -125,7 +171,7 @@ {"fn": [[{"var": "_"}], {"and": [{"array?": {"var": "args"}}, {"==": [{"count": {"var": "args"}}, 2]}, - {"_opt-all-lit?": {"var": "args"}}]}]}]}, + {"_opt-all-lit?": [{"var": "args"}]}]}]}]}, {"==": [{"nth": [{"var": "args"}, 0]}, {"nth": [{"var": "args"}, 1]}]}], @@ -133,14 +179,73 @@ {"if": [{"array?": {"var": "args"}}, {"match": [{"var": "args"}, [[[[[[{"var": "name"}, {"var": "val"}]], {"var": "body"}]], - {"if": [{"==": [{"_opt-count-refs": [{"var": "name"}, {"var": "body"}]}, 0]}, - {"var": "body"}, - {"tag": ["let*", {"var": "args"}]}]}], + {"let*": [[["refs", {"_opt-count-refs": [{"var": "name"}, {"var": "body"}]}]], + {"if": [{"==": [{"var": "refs"}, 0]}, + {"var": "body"}, + {"if": [{"and": [{"==": [{"var": "refs"}, 1]}, + {"_opt-literal?": {"var": "val"}}]}, + {"_opt-subst": [{"var": "name"}, {"var": "val"}, {"var": "body"}]}, + {"tag": ["let*", {"var": "args"}]}]}]}]}], [{"var": "_"}, {"tag": ["let*", {"var": "args"}]}]] ]}, {"tag": ["let*", {"var": "args"}]}]}], - [{"var": "_"}, {"tag": [{"var": "op"}, {"var": "args"}]}] + ["apply", + {"if": [{"array?": {"var": "args"}}, + {"match": [{"var": "args"}, + [[[{"guard": [{"var": "f"}, {"var": "_opt-call?"}]}, [{"var": "v"}]], + {"let*": [[["fop", {"nth": [{"keys": {"var": "f"}}, 0]}], + ["farg", {"get": [{"var": "f"}, {"var": "fop"}]}]], + {"if": [{"==": [{"var": "fop"}, "fn"]}, + {"if": [{"array?": {"var": "farg"}}, + {"match": [{"var": "farg"}, + [[[[{"var": "formals"}], {"var": "body"}], + {"if": [{"array?": {"var": "formals"}}, + {"match": [{"var": "formals"}, + [[[{"var": "param"}], + {"let*": [[["parg", {"get": [{"var": "param"}, "var"]}]], + {"if": [{"string?": {"var": "parg"}}, + {"tag": ["let*", [[[{"var": "parg"}, {"var": "v"}]], {"var": "body"}]]}, + {"tag": ["apply", {"var": "args"}]}]}]}], + [{"var": "_"}, {"tag": ["apply", {"var": "args"}]}]] + ]}, + {"tag": ["apply", {"var": "args"}]}]}], + [{"var": "_"}, {"tag": ["apply", {"var": "args"}]}]] + ]}, + {"tag": ["apply", {"var": "args"}]}]}, + {"tag": ["apply", {"var": "args"}]}]}]}], + [{"var": "_"}, {"tag": ["apply", {"var": "args"}]}]] + ]}, + {"tag": ["apply", {"var": "args"}]}]}], + + + ["nth", + {"if": [{"and": [{"array?": {"var": "args"}}, + {"==": [{"count": {"var": "args"}}, 2]}, + {"array?": {"nth": [{"var": "args"}, 0]}}, + {"number?": {"nth": [{"var": "args"}, 1]}}]}, + {"try": [{"nth": [{"nth": [{"var": "args"}, 0]}, + {"nth": [{"var": "args"}, 1]}]}, + {"fn": [[{"var": "_"}], {"tag": ["nth", {"var": "args"}]}]}]}, + {"tag": ["nth", {"var": "args"}]}]}], + + ["first", + {"if": [{"and": [{"array?": {"var": "args"}}, + {"==": [{"count": {"var": "args"}}, 1]}, + {"array?": {"nth": [{"var": "args"}, 0]}}, + {">": [{"count": {"nth": [{"var": "args"}, 0]}}, 0]}]}, + {"first": {"nth": [{"var": "args"}, 0]}}, + {"tag": ["first", {"var": "args"}]}]}], + + ["rest", + {"if": [{"and": [{"array?": {"var": "args"}}, + {"==": [{"count": {"var": "args"}}, 1]}, + {"array?": {"nth": [{"var": "args"}, 0]}}, + {">": [{"count": {"nth": [{"var": "args"}, 0]}}, 0]}]}, + {"rest": {"nth": [{"var": "args"}, 0]}}, + {"tag": ["rest", {"var": "args"}]}]}], + + [{"var": "_"}, {"_opt-try-identity": [{"var": "op"}, {"var": "args"}]}] ] ]}]}, @@ -172,5 +277,6 @@ {"select": ["optimize-source", "source-fold", "_opt-literal?", "_opt-call?", "_opt-all-lit?", "_opt-try-fold", - "_opt-type-pred?", "_opt-count-refs"]} + "_opt-type-pred?", "_opt-count-refs", "_opt-subst", + "_opt-try-identity"]} ]} -- 2.51.2