Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 31s
lib/guest/reflective/quoting.sx — quasiquote walker with adapter cfg.
Three forms:
- refl-quasi-walk-with CFG FORM ENV (top-level)
- refl-quasi-walk-list-with CFG FORMS ENV (list walker, splice-aware)
- refl-quasi-list-concat XS YS (pure-SX helper)
Adapter cfg keys:
- :unquote-name — string keyword ("$unquote" or "unquote")
- :unquote-splicing-name — string keyword
- :eval — fn (form env) → value
The shared algorithm is identical in Kernel and Scheme; the only
divergences are the keyword names (`$unquote` vs `unquote`) and
which host evaluator runs at unquote points (`kernel-eval` vs
`scheme-eval`). Both surface through the cfg.
Migrations:
- lib/kernel/runtime.sx: knl-quasi-walk reduces to a 3-line wrapper
that builds knl-quasi-cfg and delegates. Removed knl-quasi-walk-
list + knl-list-concat (~40 LoC) — now provided by the kit.
- lib/scheme/eval.sx: scm-quasi-walk reduces to a 3-line wrapper
around scm-quasi-cfg. Removed scm-quasi-walk-list + scm-list-
concat. scm-collect-exports (module impl) was a hidden consumer
of scm-list-concat — rewired to refl-quasi-list-concat.
lib/scheme/test.sh — loads lib/guest/reflective/quoting.sx before
lib/scheme/parser.sx so the kit is available when eval.sx loads.
Both consumers' tests green:
- Kernel: 322 tests across 7 suites
- Scheme: 296 tests across 9 suites
**Second reflective-kit extraction landed.** The kit-extraction
playbook from env.sx and class-chain.sx — adapter-cfg pattern from
lib/guest/match.sx, same algorithm bridges different keyword names —
works again on a third structurally different problem (quasiquote
walking). The cumulative extraction story: env.sx → class-chain.sx
→ quoting.sx, three independent kits, all using the same pattern.
`evaluator.sx` (the other deferred candidate the Scheme port
unlocked) is NOT extracted — the genuinely shared content is too
thin (one helper for closure-capturing interaction-environment).
The eval-protocol is more about API surface than algorithm.
Documented as a non-extraction.
78 lines
2.6 KiB
Plaintext
78 lines
2.6 KiB
Plaintext
;; lib/guest/reflective/quoting.sx — quasiquote walker.
|
|
;;
|
|
;; Extracted from Kernel's `knl-quasi-walk` and Scheme's `scm-quasi-walk`,
|
|
;; which differ only in:
|
|
;; - the unquote keyword name (Kernel: "$unquote" / "$unquote-splicing";
|
|
;; Scheme: "unquote" / "unquote-splicing")
|
|
;; - the host evaluator function (`kernel-eval` vs `scheme-eval`)
|
|
;;
|
|
;; Algorithm is identical. Adapter cfg parameterises the two
|
|
;; language-specific knobs.
|
|
;;
|
|
;; Adapter cfg keys
|
|
;; ----------------
|
|
;; :unquote-name — string, name of the unquote keyword
|
|
;; :unquote-splicing-name — string, name of the splice keyword
|
|
;; :eval — fn (form env) → value
|
|
;;
|
|
;; Public API
|
|
;; (refl-quasi-walk-with CFG FORM ENV)
|
|
;; Top-level walker. Returns FORM with unquotes evaluated in ENV.
|
|
;;
|
|
;; (refl-quasi-walk-list-with CFG FORMS ENV)
|
|
;; Walks a list of forms, splicing unquote-splicing results inline.
|
|
;;
|
|
;; (refl-quasi-list-concat XS YS)
|
|
;; Pure-SX list append (no host append/append! needed).
|
|
|
|
(define
|
|
refl-quasi-list-concat
|
|
(fn
|
|
(xs ys)
|
|
(cond
|
|
((or (nil? xs) (= (length xs) 0)) ys)
|
|
(:else (cons (first xs) (refl-quasi-list-concat (rest xs) ys))))))
|
|
|
|
(define
|
|
refl-quasi-walk-with
|
|
(fn
|
|
(cfg form env)
|
|
(cond
|
|
((not (list? form)) form)
|
|
((= (length form) 0) form)
|
|
((and (string? (first form)) (= (first form) (get cfg :unquote-name)))
|
|
(cond
|
|
((not (= (length form) 2))
|
|
(error
|
|
(str (get cfg :unquote-name) ": expects exactly 1 argument")))
|
|
(:else ((get cfg :eval) (nth form 1) env))))
|
|
(:else (refl-quasi-walk-list-with cfg form env)))))
|
|
|
|
(define
|
|
refl-quasi-walk-list-with
|
|
(fn
|
|
(cfg forms env)
|
|
(cond
|
|
((or (nil? forms) (= (length forms) 0)) (list))
|
|
(:else
|
|
(let
|
|
((head (first forms)))
|
|
(cond
|
|
((and (list? head) (= (length head) 2) (string? (first head)) (= (first head) (get cfg :unquote-splicing-name)))
|
|
(let
|
|
((spliced ((get cfg :eval) (nth head 1) env)))
|
|
(cond
|
|
((not (list? spliced))
|
|
(error
|
|
(str
|
|
(get cfg :unquote-splicing-name)
|
|
": value must be a list")))
|
|
(:else
|
|
(refl-quasi-list-concat
|
|
spliced
|
|
(refl-quasi-walk-list-with cfg (rest forms) env))))))
|
|
(:else
|
|
(cons
|
|
(refl-quasi-walk-with cfg head env)
|
|
(refl-quasi-walk-list-with cfg (rest forms) env)))))))))
|