;; lib/kernel/tests/metacircular.sx — Kernel-in-Kernel demo. ;; ;; Demonstrates reflective completeness: a Kernel program implements ;; a recognisable subset of Kernel's own evaluation rules and produces ;; matching values for a battery of test programs. ;; ;; This is a SHALLOW metacircular: it dispatches on expression shape ;; itself (numbers, booleans, lists, symbols), recursively meta-evals ;; each argument of an applicative call, and delegates only to the ;; host evaluator for the leaf cases (operatives, symbol lookup). The ;; point is to show that env-as-value, first-class operatives, and ;; first-class evaluators all line up — enough so a Kernel program ;; can itself reason about Kernel programs. (define kmc-test-pass 0) (define kmc-test-fail 0) (define kmc-test-fails (list)) (define kmc-test (fn (name actual expected) (if (= actual expected) (set! kmc-test-pass (+ kmc-test-pass 1)) (begin (set! kmc-test-fail (+ kmc-test-fail 1)) (append! kmc-test-fails {:name name :actual actual :expected expected}))))) ;; Build a Kernel env with m-eval and m-apply defined. The two refer ;; to each other and to standard primitives, so we use the standard ;; env as the static-env for both. (define kmc-make-env (fn () (let ((env (kernel-standard-env))) (kernel-eval (kernel-parse "($define! m-eval\n ($lambda (expr env)\n ($cond\n ((number? expr) expr)\n ((boolean? expr) expr)\n ((null? expr) expr)\n ((symbol? expr) (eval expr env))\n ((list? expr)\n ($let ((head-val (m-eval (car expr) env)))\n ($cond\n ((applicative? head-val)\n (apply head-val\n (map ($lambda (a) (m-eval a env)) (cdr expr))))\n (else (eval expr env)))))\n (else expr))))") env) env))) (define kmc-eval (fn (src) (let ((env (kmc-make-env))) (kernel-eval (kernel-parse (str "(m-eval (quote " src ") (get-current-environment))")) env)))) ;; ── literals self-evaluate via m-eval ────────────────────────── (kmc-test "m-eval: integer literal" (kernel-eval (kernel-parse "(m-eval 42 (get-current-environment))") (kmc-make-env)) 42) (kmc-test "m-eval: boolean true" (kernel-eval (kernel-parse "(m-eval #t (get-current-environment))") (kmc-make-env)) true) (kmc-test "m-eval: boolean false" (kernel-eval (kernel-parse "(m-eval #f (get-current-environment))") (kmc-make-env)) false) (kmc-test "m-eval: empty list" (kernel-eval (kernel-parse "(m-eval () (get-current-environment))") (kmc-make-env)) (list)) ;; ── symbol lookup goes through env ───────────────────────────── (kmc-test "m-eval: symbol lookup" (let ((env (kmc-make-env))) (kernel-eval (kernel-parse "($define! shared-x 99)") env) (kernel-eval (kernel-parse "(m-eval ($quote shared-x) (get-current-environment))") env)) 99) ;; ── applicative calls are dispatched by m-eval recursively ───── (kmc-test "m-eval: addition" (kernel-eval (kernel-parse "(m-eval ($quote (+ 1 2)) (get-current-environment))") (kmc-make-env)) 3) (kmc-test "m-eval: nested arithmetic" (kernel-eval (kernel-parse "(m-eval ($quote (+ (* 2 3) (- 10 4))) (get-current-environment))") (kmc-make-env)) 12) (kmc-test "m-eval: variadic +" (kernel-eval (kernel-parse "(m-eval ($quote (+ 1 2 3 4 5)) (get-current-environment))") (kmc-make-env)) 15) (kmc-test "m-eval: list construction" (kernel-eval (kernel-parse "(m-eval ($quote (list 1 2 3)) (get-current-environment))") (kmc-make-env)) (list 1 2 3)) (kmc-test "m-eval: cons reverse-style" (kernel-eval (kernel-parse "(m-eval ($quote (cons 0 (list 1 2))) (get-current-environment))") (kmc-make-env)) (list 0 1 2)) (kmc-test "m-eval: nested apply" (kernel-eval (kernel-parse "(m-eval ($quote (apply + (list 10 20 30))) (get-current-environment))") (kmc-make-env)) 60) ;; ── operatives delegate to host eval (transparently for the caller) ─ (kmc-test "m-eval: $if true branch (via delegation)" (kernel-eval (kernel-parse "(m-eval ($quote ($if #t 1 2)) (get-current-environment))") (kmc-make-env)) 1) (kmc-test "m-eval: $if false branch" (kernel-eval (kernel-parse "(m-eval ($quote ($if #f 1 2)) (get-current-environment))") (kmc-make-env)) 2) ;; ── m-eval can call a user-defined lambda ────────────────────── (kmc-test "m-eval: user lambda call" (let ((env (kmc-make-env))) (kernel-eval (kernel-parse "($define! sq ($lambda (x) (* x x)))") env) (kernel-eval (kernel-parse "(m-eval ($quote (sq 7)) (get-current-environment))") env)) 49) (define kmc-tests-run! (fn () {:total (+ kmc-test-pass kmc-test-fail) :passed kmc-test-pass :failed kmc-test-fail :fails kmc-test-fails}))