Fix record field-reorder redefine (jolt-wf4) and builtin-shadowing local names (jolt-fjb1) (#124)
* Don't direct-link a var redefined earlier in the same unit (jolt-wf4) defrecord/deftype expands to (do (def R (make-deftype-ctor ...)) (def ->R R) ...), so the ->R alias references R within one compiled unit. Under direct-link a var ref embeds the cell's root as a compile-time constant, but on a redefine R's old root is still in place when that unit compiles — the (def R new) sibling hasn't run yet — so ->R sealed to the stale pre-redef ctor. (defrecord R [x a]) (defrecord R [a x]) (:a (->R 10 20)) read the old [x a] layout and returned 20. Track the vars a unit (re)defines and force their later in-unit references to the live indirect deref. The cell is registered only after its own init is emitted, so a recursive self-reference inside the init still direct-links (it runs after the def completes); only sibling references after the def go indirect. * Emit Janet's `in` as a value so a user local can't shadow it (jolt-fjb1) The back end emits `in` to deref var cells ((in cell :root)) and index shape-recs. It emitted the bare symbol, so a user local named `in` shadowed Janet's builtin in the surrounding scope and the generated cell-deref called the user's value as a function — "<table> called with 2 arguments, possibly expected 1". malli's explainer binds [value in acc], so m/explain hit this on every schema (m/validate was unaffected — its path doesn't bind `in`). Embed `in`'s function value at the emit sites (as jolt-call/core-get already are); a value in head position can't be shadowed. Fixes m/explain on malli (loaded with JOLT_FEATURES=clj so its .cljc reader-conditionals resolve). --------- Co-authored-by: Yogthos <yogthos@gmail.com>
This commit is contained in:
parent
747ac87e03
commit
8ee04eed8e
3 changed files with 58 additions and 10 deletions
|
|
@ -11,7 +11,13 @@
|
|||
["variadic with fixed" "[1 [2 3]]" "(do (defn f [a & xs] [a xs]) (f 1 2 3))"]
|
||||
["closure captures" "8" "(do (defn adder [n] (fn [x] (+ x n))) ((adder 5) 3))"]
|
||||
["recursion" "120" "(do (defn fact [n] (if (< n 2) 1 (* n (fact (dec n))))) (fact 5))"]
|
||||
["named fn self-ref" "120" "((fn fact [n] (if (< n 2) 1 (* n (fact (dec n))))) 5)"])
|
||||
["named fn self-ref" "120" "((fn fact [n] (if (< n 2) 1 (* n (fact (dec n))))) 5)"]
|
||||
# A param whose name collides with a Janet builtin the back end emits in
|
||||
# generated code (here `in`, used to deref vars / index shape-recs) must not
|
||||
# shadow it — malli's explainer binds `[value in acc]` (jolt-fjb1).
|
||||
["param named `in`" "1" "((fn [in] (first in)) [1 2 3])"]
|
||||
["param `in` via core fn" "3" "((fn [in] (count in)) [1 2 3])"]
|
||||
["local `in` in let body" "2" "(let [in [2 3]] (first in))"])
|
||||
|
||||
(defspec "functions / application"
|
||||
["apply" "6" "(apply + [1 2 3])"]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue