Chez Phase 3 inc 3: try/throw + host-call + regex/inst/uuid + def-meta in jolt.backend-scheme

Completes the op coverage of the portable Clojure emitter — it now handles every
op emit.janet does (const/local/var/the-var/host/host-static/host-new/if/do/
invoke/vector/set/map/quote/throw/try/regex/inst/uuid/host-call/let/loop/recur/
fn/def). Adds emit-try (guard + dynamic-wind), :throw, :regex/:inst/:uuid, and
:host-call (jolt-host-call for rt-shimmed methods else record-method-dispatch).

def-meta + quoted-symbol-meta needed emit-quoted to reconstruct plain jolt VALUES
(metadata maps), not just reader forms. The blocker was that :meta arrived as a
raw Janet table embedded in the IR — jolt's count/map?/keys don't work on a table
(counter to jolt.ir's 'no host values embedded'). Fixed at the host seam:
h-sym-meta now returns the meta as an immutable struct, which is a portable jolt
map (jolt count/map?/keys work on a struct, and the Janet backend's merge/get
still do too). emit-quoted handles both reader forms (jolt.host form-* contract)
and jolt-value collections (native map?/vector?/set?/seq? branches, after the
form-* branches so reader forms win).

Gate: emit-parity 55/55 (incl try/catch/finally, ^:private def-var-with-meta!
structural check, inst/uuid eq, regex smoke, quoted-sym-meta). Full jpm gate
green after clean rebuild (seed change). jolt-me6m.
This commit is contained in:
Yogthos 2026-06-19 18:16:36 -04:00
parent 206fe94a95
commit f9a665b3c4
3 changed files with 101 additions and 11 deletions

View file

@ -157,6 +157,20 @@
(check "vector map filter" "(into [] (filter even? (map inc [1 2 3 4 5])))")
(check "map over literal" "(reduce + (vals {:a 1 :b 2 :c 3}))")
# --- inc 3 subset: try/throw + def-meta + quoted-sym-meta + inst/uuid + regex ----
(check "try catch" `(try (throw (ex-info "boom" {})) (catch Throwable e 42))`)
(check "try catch value" `(+ (try (throw (ex-info "" {})) (catch Throwable e 10)) 5)`)
(check "try no throw" `(try 7 (catch Throwable e 0))`)
(check "try finally" `(try 1 (finally 2))`)
(check "try finally side" `(try (throw (ex-info "" {})) (catch Throwable e 3) (finally 9))`)
(check "def private runs" `(do (defn ^:private secret [] 99) (secret))`)
(check "def tagged runs" `(do (def ^:dynamic *q* 5) *q*)`)
(check "quoted sym meta eq" `(do (def x (quote ^:foo bar)) (= x x))`)
(check "inst eq" `(= #inst "2020-01-01" #inst "2020-01-01")`)
(check "uuid eq" `(= #uuid "00000000-0000-0000-0000-000000000000" #uuid "00000000-0000-0000-0000-000000000000")`)
(check "regex smoke" `(do (def r #"[0-9]+") true)`)
(check "mandelbrot run(20)"
(string ``
(defn count-point [cr ci cap]
@ -178,5 +192,16 @@
acc))))
`` "\n(run 20)"))
# Structural: a ^:private def must now take the def-var-with-meta! path (the meta
# is a portable struct after the h-sym-meta fix; before, map?/count failed on the
# raw table and it silently fell back to the lean def-var!, dropping the meta).
(let [scm (emit-clj (backend/analyze-form ctx (in (r/parse-next "(def ^:private p 1)") 0)))]
(ok "def ^:private emits def-var-with-meta!"
(truthy? (string/find "def-var-with-meta!" scm)) scm))
(let [scm (emit-clj (backend/analyze-form ctx (in (r/parse-next "(def plain 1)") 0)))]
(ok "plain def stays lean def-var!"
(and (truthy? (string/find "(def-var! " scm))
(not (string/find "with-meta" scm))) scm))
(printf "\n%d/%d ok" (- total fails) total)
(when (> fails 0) (os/exit 1))