scheme: Phase 7 — eval/interaction-environment/null-env + 13 tests [shapes-reflective]
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 31s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 31s
runtime.sx binds R7RS reflective primitives: - eval EXPR ENV - interaction-environment — returns env captured by closure - null-environment VERSION — fresh empty env (ignores version) - scheme-report-environment N — fresh full standard env - environment? V interaction-environment closes over the standard env being built; each invocation of scheme-standard-env produces a distinct interaction env that returns ITSELF when queried — so user-side (define name expr) inside (eval ... (interaction-environment)) persists for subsequent (eval 'name ...) lookups. 13 tests cover: - eval over quoted forms (literal + constructed via list) - define-then-lookup through interaction-environment - eqv? identity of interaction-environment across calls - sandbox semantics: eval in null-environment errors on + - scheme-report-environment is fresh and distinct from interaction **Second consumer for lib/guest/reflective/evaluator.sx unlocked.** Scheme's eval/interaction-environment/null-environment triple is the same protocol Kernel exposes via eval-applicative / get-current-environment / make-environment. Extraction now satisfies the two-consumer rule — same playbook as env.sx and class-chain.sx, awaits a follow-up commit to actually extract the kit. 270 total Scheme tests (62 + 23 + 49 + 78 + 25 + 20 + 13).
This commit is contained in:
@@ -586,6 +586,40 @@
|
||||
((and (dict? outcome) (get outcome :scm-weh-raised))
|
||||
(scheme-apply handler (list (get outcome :value))))
|
||||
(:else outcome))))))))
|
||||
;; ── R7RS reflection: eval / environment accessors ───────
|
||||
;; eval EXPR ENV — apply the evaluator to a user-supplied AST.
|
||||
(scheme-env-bind! env "eval"
|
||||
(fn (args)
|
||||
(cond
|
||||
((not (= (length args) 2))
|
||||
(error "eval: expects (eval expr env)"))
|
||||
(:else (scheme-eval (first args) (nth args 1))))))
|
||||
;; interaction-environment — the env we're currently building.
|
||||
;; The closure captures `env`, so each invocation of
|
||||
;; scheme-standard-env produces a distinct interaction env
|
||||
;; whose interaction-environment fn returns itself.
|
||||
(scheme-env-bind! env "interaction-environment"
|
||||
(fn (args)
|
||||
(cond
|
||||
((not (= (length args) 0))
|
||||
(error "interaction-environment: expects 0 args"))
|
||||
(:else env))))
|
||||
;; null-environment — fresh empty env. R7RS ignores version arg.
|
||||
(scheme-env-bind! env "null-environment"
|
||||
(fn (args)
|
||||
(cond
|
||||
((not (= (length args) 1))
|
||||
(error "null-environment: expects (version)"))
|
||||
(:else (scheme-make-env)))))
|
||||
;; scheme-report-environment — fresh full standard env.
|
||||
(scheme-env-bind! env "scheme-report-environment"
|
||||
(fn (args)
|
||||
(cond
|
||||
((not (= (length args) 1))
|
||||
(error "scheme-report-environment: expects (version)"))
|
||||
(:else (scheme-standard-env)))))
|
||||
(scheme-env-bind! env "environment?"
|
||||
(scm-unary "environment?" (fn (v) (scheme-env? v))))
|
||||
;; dynamic-wind BEFORE THUNK AFTER — runs BEFORE, then THUNK,
|
||||
;; then AFTER. If THUNK raises, AFTER still runs before the
|
||||
;; raise propagates. This is the basic-correctness version;
|
||||
|
||||
100
lib/scheme/tests/reflection.sx
Normal file
100
lib/scheme/tests/reflection.sx
Normal file
@@ -0,0 +1,100 @@
|
||||
;; lib/scheme/tests/reflection.sx — Phase 7 reflective primitives.
|
||||
|
||||
(define scm-ref-pass 0)
|
||||
(define scm-ref-fail 0)
|
||||
(define scm-ref-fails (list))
|
||||
|
||||
(define
|
||||
scm-ref-test
|
||||
(fn
|
||||
(name actual expected)
|
||||
(if
|
||||
(= actual expected)
|
||||
(set! scm-ref-pass (+ scm-ref-pass 1))
|
||||
(begin
|
||||
(set! scm-ref-fail (+ scm-ref-fail 1))
|
||||
(append! scm-ref-fails {:name name :actual actual :expected expected})))))
|
||||
|
||||
(define
|
||||
scm-ref
|
||||
(fn (src) (scheme-eval (scheme-parse src) (scheme-standard-env))))
|
||||
|
||||
(define
|
||||
scm-ref-all
|
||||
(fn
|
||||
(src)
|
||||
(scheme-eval-program (scheme-parse-all src) (scheme-standard-env))))
|
||||
|
||||
;; ── eval ─────────────────────────────────────────────────────────
|
||||
|
||||
(scm-ref-test
|
||||
"eval: arithmetic"
|
||||
(scm-ref "(eval '(+ 1 2 3) (interaction-environment))")
|
||||
6)
|
||||
(scm-ref-test
|
||||
"eval: nested"
|
||||
(scm-ref "(eval '(* (+ 1 2) (- 5 1)) (interaction-environment))")
|
||||
12)
|
||||
(scm-ref-test
|
||||
"eval: constructed form"
|
||||
(scm-ref "(eval (list '+ 10 20) (interaction-environment))")
|
||||
30)
|
||||
(scm-ref-test
|
||||
"eval: variable reference"
|
||||
(scm-ref-all "(define x 42) (eval 'x (interaction-environment))")
|
||||
42)
|
||||
|
||||
;; ── interaction-environment ─────────────────────────────────────
|
||||
|
||||
(scm-ref-test
|
||||
"interaction-environment: is an env"
|
||||
(scm-ref "(environment? (interaction-environment))")
|
||||
true)
|
||||
(scm-ref-test
|
||||
"interaction-environment: define persists"
|
||||
(scm-ref-all
|
||||
"(define ie (interaction-environment))\n (eval '(define stashed 99) ie)\n (eval 'stashed ie)")
|
||||
99)
|
||||
(scm-ref-test
|
||||
"interaction-environment: same env across calls"
|
||||
(scm-ref-all
|
||||
"(define a (interaction-environment))\n (define b (interaction-environment))\n (eqv? a b)")
|
||||
true)
|
||||
|
||||
;; ── null-environment ────────────────────────────────────────────
|
||||
|
||||
(scm-ref-test
|
||||
"null-environment: is an env"
|
||||
(scm-ref "(environment? (null-environment 7))")
|
||||
true)
|
||||
(scm-ref-test
|
||||
"null-environment: has no + binding"
|
||||
(scm-ref-all
|
||||
"(define ne (null-environment 7))\n (guard (e (else 'unbound)) (eval '+ ne))")
|
||||
"unbound")
|
||||
|
||||
;; ── scheme-report-environment ───────────────────────────────────
|
||||
|
||||
(scm-ref-test
|
||||
"scheme-report-environment: is an env"
|
||||
(scm-ref "(environment? (scheme-report-environment 7))")
|
||||
true)
|
||||
(scm-ref-test
|
||||
"scheme-report-environment: has +"
|
||||
(scm-ref "(eval '(+ 1 2) (scheme-report-environment 7))")
|
||||
3)
|
||||
(scm-ref-test
|
||||
"scheme-report-environment: distinct from interaction"
|
||||
(scm-ref-all
|
||||
"(define ie (interaction-environment))\n (define re (scheme-report-environment 7))\n (eval '(define only-in-ie 1) ie)\n (guard (e (else 'unbound)) (eval 'only-in-ie re))")
|
||||
"unbound")
|
||||
|
||||
;; ── eval with explicit env for sandboxing ──────────────────────
|
||||
|
||||
(scm-ref-test
|
||||
"eval: sandbox with null-environment"
|
||||
(scm-ref-all
|
||||
"(define sandbox (null-environment 7))\n (guard (e (else 'unbound))\n (eval '(+ 1 1) sandbox))")
|
||||
"unbound")
|
||||
|
||||
(define scm-ref-tests-run! (fn () {:total (+ scm-ref-pass scm-ref-fail) :passed scm-ref-pass :failed scm-ref-fail :fails scm-ref-fails}))
|
||||
Reference in New Issue
Block a user