lib/scheme/runtime.sx — full R7RS-base surface:
- Arithmetic: variadic +/-/*//, abs, min, max, modulo, quotient,
remainder. Predicates zero?/positive?/negative?.
- Comparison: chained =/</>/<=/>=.
- Type predicates: number?/boolean?/symbol?/string?/char?/vector?/
null?/pair?/procedure?/not.
- List: cons/car/cdr/list/length/reverse/append.
- Higher-order: map/filter/fold-left/fold-right/for-each/apply.
These re-enter scheme-apply to invoke user-supplied procs.
- String: string-length/string=?/string-append/substring.
- Char: char=?.
- Vector: vector/vector-length/vector-ref/vector->list/list->vector/
make-vector.
- Equality: eqv?/equal?/eq? (all = under the hood for now).
Built via small adapters: scm-unary, scm-binary, scm-fold (variadic
left-fold with identity + one-arity special), scm-chain (n-ary
chained comparison).
**Bugfix in eval.sx set! handler.** The :else branch had two
expressions `(dict-set! ...) val` — SX cond branches don't run
multiple expressions, they return nil silently (or evaluate only
the first, depending on shape). Wrapped in (begin ...) to force
sequential execution. This fix also unblocks 4 set!-dependent
tests in lib/scheme/tests/syntax.sx that were silently raising
during load (and thus not counted) — syntax test count jumps
from 45 → 49.
Classic programs verified:
- factorial 10 → 3628800
- fib 10 → 55
- recursive list reverse → working
- sum of squares via fold-left + map → 55
212 total Scheme tests: parse 62 + eval 23 + syntax 49 + runtime 78.
All green.
The env-as-value section in runtime tests demonstrates
scheme-standard-env IS a refl-env? — kit primitives operate on it
directly, confirming the third-consumer adoption with zero adapter.
Adds the rest of the standard syntactic operators, all built on the
existing eval/closure infrastructure from Phase 3:
- let — parallel bindings in fresh child env; values evaluated in
outer env (RHS sees pre-let bindings only). Multi-body via
scheme-eval-body.
- let* — sequential bindings, each in a nested child env; later
bindings see earlier ones.
- cond — clauses walked in order; first truthy test wins. `else`
symbol is the catch-all. Test-only clauses (no body) return the
test value. Scheme truthiness: only #f is false.
- when / unless — single-test conditional execution, multi-body
body via scheme-eval-body.
- and / or — short-circuit boolean. Empty `(and)` = true,
`(or)` = false. Both return the actual value at the point
of short-circuit (not coerced to bool), matching R7RS.
130 total Scheme tests (62 parse + 23 eval + 45 syntax). The
Scheme port is now self-hosting enough to write any non-stdlib
program — factorial, list operations via primitives, closures
with mutable state, all working.
Next phase: standard env (runtime.sx) with variadic +/-, list
ops as Scheme-visible applicatives.
eval.sx grows: five new syntactic operators wired via the table-
driven dispatch from Phase 2. lambda creates closures
{:scm-tag :closure :params :rest :body :env} that capture the
static env; scheme-apply-closure binds formals + rest-arg, evaluates
multi-expression body in (extend static-env), returns last value.
Supports lambda formals shapes:
() → no args
(a b c) → fixed arity
args → bare symbol; binds all call-args as a list
Dotted-pair tail (a b . rest) deferred until parser supports it.
define has both flavours:
(define name expr) — direct binding
(define (name . formals) body...) — lambda sugar
set! walks the env chain via refl-env-find-frame, mutates at the
binding's source frame (no shadowing). Raises on unbound name.
24 new tests in lib/scheme/tests/syntax.sx, including:
- Factorial 5 → 120 and 10 → 3628800 (recursion + closures)
- make-counter via closed-over set! state
- Curried (((curry+ 1) 2) 3) → 6
- (lambda args args) rest-arg binding
- Multi-body lambdas with internal define
109 total Scheme tests (62 parse + 23 eval + 24 syntax).
lib/scheme/eval.sx — R7RS evaluator skeleton:
- Self-evaluating: numbers, booleans, characters, vectors, strings
- Symbol lookup: refl-env-lookup
- Lists: syntactic-operator table dispatch, else applicative call
- Table-driven syntactic ops (Phase 2 wires `quote` only; full set
in Phase 3)
- Apply: callable host fn or scheme closure (closure stub for Phase 3)
scheme-make-env / scheme-env-bind! / etc. are THIN ALIASES for the
refl-env-* primitives from lib/guest/reflective/env.sx. No adapter
cfg needed — Scheme's lexical-scope semantics ARE the canonical
wire shape. This is the THIRD CONSUMER for env.sx after Kernel and
Tcl + Smalltalk's variant adapters; the first to use it without
any bridging code. Validates the kit handles canonical-shape
adoption with zero ceremony.
23 tests in lib/scheme/tests/eval.sx cover literals, symbol
lookup with parent-chain shadowing, quote (special form + sugar),
primitive application with nested calls, and an env-as-value
section explicitly demonstrating the kit primitives work on
Scheme envs.
85 total Scheme tests (62 parse + 23 eval).
chisel: consumes-env (third consumer for lib/guest/reflective/env.sx).