fix: catch binds unwrapped thrown value; var-set targets thread binding

Close jolt-dd5.
- catch now binds the originally-thrown value (unwrapping the :jolt/exception
  envelope), so (catch ... e (throw e)) rethrows the same exception instead of
  nesting another envelope, and (catch ... e e) on (throw 42) yields 42.
- var-set updates the innermost thread-binding frame for the var (replacing the
  stack slot) when the var is dynamically bound, matching Clojure; it falls back
  to the root otherwise.

Restored spec cases: exceptions rethrow + catch-binds-thrown-value, namespaces
var-set-in-binding. conformance 218/218, jpm test green.
This commit is contained in:
Yogthos 2026-06-05 01:23:52 -04:00
parent a681daf7b9
commit 555cd7631e
4 changed files with 27 additions and 5 deletions

View file

@ -857,7 +857,14 @@
([err]
(var new-bindings @{})
(table/setproto new-bindings bindings)
(put new-bindings (catch-sym :name) err)
# bind the originally-thrown value (unwrap the :jolt/exception
# envelope) so (catch ... e (throw e)) rethrows the same value
# rather than nesting another envelope
(def caught
(if (and (or (table? err) (struct? err)) (= :jolt/exception (get err :jolt/type)))
(get err :value)
err))
(put new-bindings (catch-sym :name) caught)
(var result nil)
(each cb catch-body
(set result (eval-form ctx new-bindings cb)))

View file

@ -120,9 +120,19 @@
(if (not (nil? result)) result (v :root)))
(defn var-set
"Set the root binding of a var."
"Set a var's value. If the var has a thread-local binding on the stack, update
the innermost frame that binds it (matching Clojure, where var-set targets the
current binding); otherwise set the root."
[v val]
(put v :root val))
(var i (dec (length binding-stack)))
(var done false)
(while (and (not done) (>= i 0))
(let [frame (in binding-stack i)]
(if (not (nil? (get frame v)))
(do (put binding-stack i (merge frame {v val})) (set done true))
(-- i))))
(unless done (put v :root val))
val)
(defn alter-var-root
"Atomically alter the root binding of v by applying f to current value plus args."