reflective: Tcl adapter cfg — second consumer wired, 427+322 tests green
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 24s

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.
This commit is contained in:
2026-05-12 07:02:56 +00:00
parent 2e7e3141d4
commit 39381fda92
3 changed files with 26 additions and 16 deletions

View File

@@ -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")

View File

@@ -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}))

View File

@@ -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")