fix: prototype-aware binding lookup for nested let

Add binding-get helper that walks Janet table prototype chain.
resolve-sym now uses two-stage lookup: direct get first,
then prototype walk as fallback. This fixes access to outer
let bindings from inner let forms without breaking fn parameter
resolution (which uses direct table keys).

All 9 test suites pass including macro-test.
This commit is contained in:
Yogthos 2026-06-02 12:02:57 -04:00
parent 33a5b7e7a4
commit 677d059c0b
4 changed files with 60 additions and 2 deletions

View file

@ -98,6 +98,18 @@
[bindings key value]
(put bindings key (if (nil? value) :jolt/nil value)))
(defn- binding-get
"Get a value from bindings, walking the prototype chain."
[bindings name]
(var result :jolt/not-found)
(var t bindings)
(while (not (nil? t))
(when (in t name)
(set result (in t name))
(break))
(set t (table/getproto t)))
result)
(defn- resolve-sym
[ctx bindings sym-s]
(let [name (sym-s :name) ns (sym-s :ns)]
@ -109,7 +121,8 @@
(let [target-ns (ctx-find-ns ctx ns) v (ns-find target-ns name)]
(if v (var-get v) (error (string "Unable to resolve symbol: " ns "/" name))))))
# Use :jolt/not-found sentinel to distinguish nil binding from absent binding
(let [local (get bindings name :jolt/not-found)]
(let [local (get bindings name :jolt/not-found-1)
local (if (= local :jolt/not-found-1) (binding-get bindings name) local)]
(if (not= local :jolt/not-found)
(if (= local :jolt/nil) nil local)
(let [current-ns (ctx-current-ns ctx) ns (ctx-find-ns ctx current-ns) v (ns-find ns name)]