diff --git a/lib/tcl/conformance.sh b/lib/tcl/conformance.sh index 23ce41fb..b6f057e4 100755 --- a/lib/tcl/conformance.sh +++ b/lib/tcl/conformance.sh @@ -69,6 +69,7 @@ for tcl_file in "${TCL_FILES[@]}"; do (epoch 2) (load "lib/tcl/parser.sx") (epoch 3) +(load "lib/guest/reflective/env.sx") (load "lib/tcl/runtime.sx") (epoch 4) (load "$helper") diff --git a/lib/tcl/runtime.sx b/lib/tcl/runtime.sx index 4bb268af..7c761c51 100644 --- a/lib/tcl/runtime.sx +++ b/lib/tcl/runtime.sx @@ -1,25 +1,33 @@ ; Tcl-on-SX runtime evaluator ; State: {:frame frame :commands cmd-table :result last-result :output accumulated-output} -; Requires lib/fiber.sx to be loaded first (provides make-fiber, fiber-resume, fiber-done?) +; Requires lib/fiber.sx and lib/guest/reflective/env.sx to be loaded first. +; +; Frames keep their Tcl-specific shape ({:level :locals :parent}) but +; route lookup/bind through the shared reflective env kit via the +; adapter cfg below — second consumer for that kit alongside Kernel. (define make-frame (fn (level parent) {:level level :locals {} :parent parent})) -(define - frame-lookup - (fn - (frame name) - (if - (nil? frame) - nil - (let - ((val (get (get frame :locals) name))) - (if (nil? val) (frame-lookup (get frame :parent) name) val))))) +; Tcl-side adapter for lib/guest/reflective/env.sx. Frames are +; functionally updated (assoc returns a fresh dict), and lookup-miss +; returns nil (Tcl convention) — the *-with kit honours both. +(define tcl-frame-cfg + {:bindings-of (fn (f) (get f :locals)) + :parent-of (fn (f) (get f :parent)) + :extend (fn (f) (make-frame (+ (get f :level) 1) f)) + :bind! (fn (f n v) (assoc f :locals (assoc (get f :locals) n v))) + :env? (fn (v) + (and (dict? v) + (number? (get v :level)) + (dict? (get v :locals))))}) -(define - frame-set-top - (fn - (frame name val) - (assoc frame :locals (assoc (get frame :locals) name val)))) +(define frame-lookup + (fn (frame name) + (refl-env-lookup-or-nil-with tcl-frame-cfg frame name))) + +(define frame-set-top + (fn (frame name val) + (refl-env-bind!-with tcl-frame-cfg frame name val))) (define make-tcl-interp (fn () {:result "" :output "" :code 0 :errorinfo "" :errorcode "" :frame (make-frame 0 nil) :frame-stack (list) :procs {} :commands {} :current-ns "::" :coro-yield-fn nil})) diff --git a/lib/tcl/test.sh b/lib/tcl/test.sh index 3bf15b1f..667b8181 100755 --- a/lib/tcl/test.sh +++ b/lib/tcl/test.sh @@ -42,6 +42,7 @@ cat > "$TMPFILE" << EPOCHS (load "lib/tcl/tests/parse.sx") (epoch 4) (load "lib/fiber.sx") +(load "lib/guest/reflective/env.sx") (load "lib/tcl/runtime.sx") (epoch 5) (load "lib/tcl/tests/eval.sx")