From 39381fda9242d9fc5c2a542372c9b24a0d83e041 Mon Sep 17 00:00:00 2001 From: giles Date: Tue, 12 May 2026 07:02:56 +0000 Subject: [PATCH] =?UTF-8?q?reflective:=20Tcl=20adapter=20cfg=20=E2=80=94?= =?UTF-8?q?=20second=20consumer=20wired,=20427+322=20tests=20green?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 2 of the lib-guest-reflective extraction. lib/tcl/runtime.sx — frame-lookup and frame-set-top now delegate to refl-env-lookup-or-nil-with and refl-env-bind!-with via a new tcl-frame-cfg adapter. Tcl keeps its existing {:level :locals :parent} frame shape unchanged; the cfg bridges it to the kit's generic algorithms. Functional update semantics preserved (cfg's :bind! returns the new frame via assoc). lib/tcl/test.sh + conformance.sh — load lib/guest/reflective/env.sx before lib/tcl/runtime.sx. Both consumers' full test suites unchanged: - Tcl: 427/427 (parse 67, eval 169, error 39, namespace 22, coro 20, idiom 110) - Kernel: 322/322 across 7 suites The extraction is now real: two consumers, two genuinely different wire shapes (mutable canonical vs functional frame), sharing the parent-walk algorithm via cfg adapter — same pattern as lib/guest/match.sx. --- lib/tcl/conformance.sh | 1 + lib/tcl/runtime.sx | 40 ++++++++++++++++++++++++---------------- lib/tcl/test.sh | 1 + 3 files changed, 26 insertions(+), 16 deletions(-) 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")