Reject a malformed catch clause with a clean error in both modes

jolt's catch is (catch class binding body*); the binding (3rd element) must be
a symbol. Neither the analyzer nor the interpreter validated it, so a non-symbol
binding crashed with an internal Janet error (expected integer key for array...)
and, in the interpreter, a malformed clause whose body never threw was silently
swallowed (returned the try value). Clojure rejects a non-class/non-symbol catch
clause; match that with an up-front error in analyze-try and eval-try.

Surfaced building the Chez try/throw emit. Regression rows in exceptions-spec
(runs x3 modes) plus a unit test asserting the clean message in interpret and
compile. jolt-kg6p.
This commit is contained in:
Yogthos 2026-06-17 17:25:14 -04:00
parent ffa122440a
commit d35783bf1b
4 changed files with 67 additions and 1 deletions

View file

@ -162,6 +162,12 @@
(cond
(= hname "catch")
(let [cl (vec (form-elements c))]
;; (catch class binding body*) — binding (3rd elem) MUST be a symbol.
;; Validate eagerly (plain throw, NOT uncompilable, so it's a real
;; error rather than a compile->interpret punt) instead of letting
;; form-sym-name crash on a non-symbol.
(when (or (< (count cl) 3) (not (form-sym? (nth cl 2))))
(throw "Unable to parse catch clause; expected (catch class binding body*)"))
(reset! catch-sym (form-sym-name (nth cl 2)))
(reset! catch-body (drop 3 cl)))
(= hname "finally")