compiler: IFn collections held in a var/local are callable (jolt-vh5)

The back end emitted a direct Janet call (f args) for every :var/:local callee,
but Janet calling a pvec-table does get (no integer key -> nil), a keyword does
the wrong thing, etc. — so (let [v [1 2 3]] (v 0)), a keyword/meta-vector in a
binding, all returned nil in compile mode (interpret was fine). Now a direct call
is emitted only when the callee is provably a function: :fn / :host always, and a
:var whose current root is a function; everything else routes through jolt-call,
which dispatches IFn correctly (function fast-path first). User/core fn calls stay
direct, so no hot-path regression — fixpoint stage1==stage2==stage3 holds.
Conformance 218/218 all modes; full suite green. Spec cases added.
This commit is contained in:
Yogthos 2026-06-06 20:03:49 -04:00
parent d189ee2ded
commit 0878c803d7
2 changed files with 22 additions and 4 deletions

View file

@ -24,7 +24,12 @@
["count" "3" "(count [1 2 3])"]
["contains? index" "true" "(contains? [:a :b] 1)"]
["contains? past end" "false" "(contains? [:a] 3)"]
["vector as fn" ":b" "([:a :b :c] 1)"])
["vector as fn" ":b" "([:a :b :c] 1)"]
# An IFn collection held in a binding (not just a literal) must dispatch as IFn,
# not as a host call: applies to vectors, keywords, and meta-bearing vectors.
["vector-in-local as fn" "20" "(let [v [10 20 30]] (v 1))"]
["keyword-in-local as fn" "7" "(let [k :a] (k {:a 7}))"]
["meta vector as fn" "10" "((with-meta [10 20] {:k 1}) 0)"])
(defspec "vector / update (persistent)"
["conj appends" "[1 2 3]" "(conj [1 2] 3)"]