compiler: compile set?/disj as plain fns (close the last Stage-1 fallback gap)

Stage 1 jolt-g3h. set? and disj were special-cased in all three "can't compile"
lists (host_iface special-names, compiler.janet uncompilable-heads, evaluator
special-symbol? + handlers) — but they're pure value-production with callable
core vars (core-set?/core-disj), and those vars are byte-for-byte equivalent to
the evaluator handlers. Removed them from all three lists + dropped the now-dead
evaluator handler arms, so they're ordinary clojure.core fns everywhere: the
analyzer compiles (set? x)/(disj s x) as normal var calls instead of punting to
the interpreter.

Verified identical results in default AND JOLT_MUTABLE builds (no representation
sensitivity — sets are phs in both, unlike vector?/list? which collapse).

With this, the self-hosted analyzer's compile-path fallback set equals the frozen
intentional stateful set (Task 2) — it's now a strict superset of the bootstrap
compiler's compilable surface, so the Janet bootstrap is retireable (Stage 2).

fallback-zero: set?/disj moved to must-compile (31 now), set! into must-punt.
Gate: conformance 267x3 (+5 set?/disj cases), lazy-infinite 44/44, suite 4034/67,
fixpoint, self-host, sci, specs+unit green.
This commit is contained in:
Yogthos 2026-06-09 00:04:11 -04:00
parent 3da5a5fcfa
commit 1804b3011e
5 changed files with 13 additions and 11 deletions

View file

@ -56,6 +56,12 @@
["empty set literal" "true" "(empty? #{})"]
["set literal count" "3" "(count #{1 2 3})"]
["set literal in let" "true" "(let [x 5] (= #{5 6} #{x (inc x)}))"]
# set?/disj compile as plain fns now (jolt-g3h), not special forms
["set? true" "true" "(set? #{1 2 3})"]
["set? false" "false" "(set? [1 2])"]
["disj one" "#{1 3}" "(disj #{1 2 3} 2)"]
["disj many" "#{1}" "(disj #{1 2 3} 2 3)"]
["disj absent" "#{1 2}" "(disj #{1 2} 5)"]
["keyword as fn" "1" "(:a {:a 1})"]
["map fn over coll" "(quote (1 3))" "(map {:a 1 :b 3} [:a :b])"]

View file

@ -40,14 +40,16 @@
"(try (inc 1) (catch :default e e))"
# def + calls into core
"(def answer 42)" "(map inc [1 2 3])" "(reduce + 0 [1 2 3])"
"(get {:a 1} :a)" "(vec (range 5))"])
"(get {:a 1} :a)" "(vec (range 5))"
# set?/disj are plain fns now, not special forms (jolt-g3h)
"(set? #{1 2})" "(disj #{1 2 3} 2)"])
# --- Intentional fallback (sanity sample): these SHOULD punt to the interpreter.
# Not the frozen set (that's Task 2) — just a few to confirm the boundary holds
# in the punt direction so the harness can't pass by compiling everything.
(def must-punt
["(ns foo.bar)" "(defmacro m [x] x)" "(require (quote [clojure.string]))"
"(set? #{1 2})" "(letfn [(f [n] (g n)) (g [n] (f n))] (f 1))"])
"(set! *warn-on-reflection* true)" "(letfn [(f [n] (g n)) (g [n] (f n))] (f 1))"])
(var fails @[])
(each s must-compile