Commit Graph

3343 Commits

Author SHA1 Message Date
0526f796f4 Merge lib/guest/quoting into architecture: quoting.sx + Kernel/Scheme migrations 2026-05-14 20:17:58 +00:00
e5d751c5fb Merge lib/guest/method-chain into architecture: class-chain.sx + Smalltalk/CLOS migrations 2026-05-14 20:17:50 +00:00
8525165594 Merge loops/minikanren into architecture: Phase 5 disequality + Phase 6 FD constraints + Phase 7 SLG tabling
Phase 5: =/= disequality with constraint store.
Phase 6: bounds-consistency for fd-plus/fd-times, send-more-money, Sudoku 4x4, N-queens FD.
Phase 7: SLG-style tabling with in-progress sentinel + fixed-point iteration (Fibonacci + Ackermann canaries green).
2026-05-14 20:11:18 +00:00
f62df8d64e Merge hs-f into architecture: JIT Phase 2/3 + native unwrap sweep + dict-eq fix
JIT Phase 2 (LRU eviction) + Phase 3 (manual reset), lib/jit.sx convenience layer,
21 host-* natives ABI-compatible with WASM kernel handles, dict-eq fix (structural
eq for plain dicts + Integer/Number in equal?), io-wait-event interceptor fix,
HS test runner unwrap shim for post-JIT-P1 value handles.

Conflicts resolved:
- tests/hs-run-filtered.js: combined arch's fake-timer block (for socket RPC tests)
  with hs-f's auto-unwrap shim
- shared/static/wasm/sx_browser.bc.js: took hs-f's regenerated bundle
2026-05-14 20:10:49 +00:00
ca8e6f4da3 Merge loops/scheme into architecture: R7RS-small port, 296 tests across 11 phases 2026-05-14 16:12:50 +00:00
885943c5ae Merge lib/smalltalk/refl-env into architecture: Smalltalk frame as third consumer for lib/guest/reflective/env.sx 2026-05-14 15:32:16 +00:00
87f503f54b Merge loops/smalltalk into architecture: briefing tweak 2026-05-14 15:32:09 +00:00
90cd0f8f6f plans: kernel-on-sx — log quoting.sx extraction + evaluator.sx decline
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 24s
Updates Phase 7 status:
- env.sx ✓ extracted (three live consumers: Kernel, Tcl, Smalltalk,
  with Scheme also using it directly)
- class-chain.sx ✓ extracted (bonus — not on the original six-file
  list but surfaced by the same chiselling discipline; Smalltalk +
  CLOS consumers)
- quoting.sx ✓ extracted (Kernel + Scheme consumers)
- evaluator.sx DECLINED — too thin to be its own kit; the shared
  content is protocol/API surface, not algorithm. Documented
  in-plan, no file created.
- combiner.sx, short-circuit.sx — still need fexpr-having
  second consumers
- hygiene.sx — still awaits Scheme Phase 6c (research-grade
  scope-set work)

Three kits live, one declined, three still gated.
2026-05-14 07:55:08 +00:00
818e68a2f8 reflective: extract quoting.sx — Kernel + Scheme share quasiquote walker
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.
2026-05-14 07:54:15 +00:00
22411f7f80 hs: port loops/hs RPC test infrastructure to architecture's test runner
Two additions from loops/hs needed for the new WebSocket socket tests:
- unhandledRejection suppressor — synchronous test harness doesn't await RPC promises
- Fake setTimeout/clearTimeout + __hsFlushTimers — drain RPC timeout tests synchronously

Plan update: mark E36 WebSocket as DONE (previously "design-done, pending review").

Skipped: loops/hs's tests/playwright/generate-sx-tests.py — architecture's version
is 1468 lines vs loops/hs's 290; arch's is the further-evolved version.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 07:26:43 +00:00
26112f1003 plans: scheme-on-sx progress log — 11 phases done, 296 tests
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 19s
Loop closer documenting what 10 feature commits landed across the
session. Phase-by-phase outcomes captured, including the SX cond
multi-expression bug found and fixed during Phase 4.

Chisel ledger:
- env.sx already EXTRACTED with Scheme as third consumer
- evaluator.sx + quoting.sx second-consumer-ready for follow-on
  kit-extraction commits
- hygiene.sx still awaits the deferred Phase 6c (scope-set work)
- combiner.sx and short-circuit.sx don't apply (Scheme has no
  fexprs and uses syntactic and/or)

Deferred phases listed: full hygiene, nested quasi-depth, R7RS
module rich features, dotted-pair syntax, full call/cc-wind
interaction.

Loop's defining feature: lib/guest CHISELLING discipline — every
commit had a chisel note, and the cumulative work satisfies the
two-consumer rule for three new kit extractions.
2026-05-14 06:53:36 +00:00
680cdf62aa scheme: Phase 11 — test.sh + scoreboard
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 33s
lib/scheme/test.sh — single-process test runner. Loads parser/eval/
runtime + lib/guest/reflective/env.sx once, then for each test
suite loads its file and calls its (*-tests-run!) function. Parses
the {:passed N :failed N ...} dict output and aggregates.

Usage:
  bash lib/scheme/test.sh        # summary
  bash lib/scheme/test.sh -v     # per-suite breakdown

Output: "ok 296/296 scheme-on-sx tests passed (9 suites)"

lib/scheme/scoreboard.md — per-suite passing counts, phase status,
deferred items, reflective-kit consumption ledger.

The scoreboard documents the chisel value of the Scheme port:
three reflective kits unlocked (env.sx — already extracted with
Scheme as third consumer; evaluator.sx + quoting.sx — second-
consumer-ready for extraction whenever a follow-up commit is run).

Loop status: 11 phases done (1, 2, 3, 3.5, 4, 5abc, 6ab, 7, 8, 9,
10, 11). Two deferred (6c hygiene, full call/cc-wind interaction).

296 tests, 1830 LoC of Scheme implementation. Zero substrate fixes
required across the loop.
2026-05-14 06:52:58 +00:00
7e795f95fc scheme: Phase 8 — define-library + import (minimal) + 7 tests
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 27s
eval.sx adds module support:

  (define-library NAME EXPR...)
    Where EXPR is one of:
      (export NAME ...)
      (import LIB-NAME ...)
      (begin BODY ...)

  (import LIB-NAME ...)
    Looks up each library by key, copies its exported names
    into the current env.

Library values: {:scm-tag :library :name :exports :env}
Stored in scheme-library-registry keyed by joined library-name
(`(my math)` → `"my/math"`).

Library body runs in a FRESH standard env (each library is its
own namespace). Only :exports are visible after import; private
internal definitions stay in the library's env. Internal calls
between library functions use the library's env, so public-facing
exports can rely on private helpers.

Multiple imports work — each library is independent.

NOT yet supported: cond-expand, include, include-library-
declarations, renaming (`(only ...)`, `(except ...)`, `(prefix ...)`,
`(rename ...)`). Standard R7RS modules use these but the core
two-operation flow (define-library / import) covers most everyday
module use.

7 tests: single export, multi-export, private-not-visible,
internal-calls-private, two-libs-both-imported, unknown-lib-error,
single-symbol library name.

296 total Scheme tests (62+23+49+78+25+20+13+10+9+7).

Phases done: 1, 2, 3, 3.5, 4, 5abc, 6ab, 7, 8, 9, 10.
Deferred: 6c (hygiene/scope-set — research-grade), 11 (conformance).
2026-05-14 06:50:58 +00:00
f927fb6515 scheme: Phase 9 — define-record-type + 9 tests
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 26s
eval.sx adds the define-record-type syntactic operator:

  (define-record-type NAME
    (CONSTRUCTOR ARG...)
    PREDICATE
    (FIELD ACCESSOR [MUTATOR])...)

Records are tagged dicts:
  {:scm-record TYPE-NAME :fields {FIELD VALUE ...}}

For each record type, the operator binds:
- Constructor: takes the listed ARGs, populates :fields, returns
  the record. Fields not in CONSTRUCTOR ARGs default to nil.
- Predicate: returns true iff its arg is a record of THIS type
  (tag-match via :scm-record).
- Accessor per field: extracts the field value; errors if not
  a record of the right type.
- Mutator per field (optional): sets the field via dict-set!;
  same type-check.

Distinct types are isolated via their tag — point? returns false
on a circle, even if both have the same shape.

9 tests cover: constructor + predicate + accessors, mutator,
distinct-types-via-tag, records as first-class values (in lists,
passed to map/filter), constructor arity errors.

289 total Scheme tests (62+23+49+78+25+20+13+10+9).
2026-05-14 06:49:24 +00:00
e200935698 scheme: Phase 10 — quasiquote runtime + 10 tests [shapes-reflective]
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 26s
eval.sx adds quasiquote / unquote / unquote-splicing as syntactic
operators with the canonical R7RS walker:

- (quasiquote X) — top-level entry to scm-quasi-walk
- (unquote X) — at depth-0, evaluates X in env
- (unquote-splicing X) — inside a list, splices X's list value
- Reader-macro sugar: `X / ,X / ,@X work via Phase 1 parser

Algorithm identical to lib/kernel/runtime.sx's knl-quasi-walk:
- Walk template recursively
- Non-list: pass through
- ($unquote/unquote X) head form: eval X
- Inside a list, ($unquote-splicing/unquote-splicing X) head:
  eval X, splice list into surrounding context
- Otherwise: recurse on each element

No depth-tracking yet — nested quasiquotes are not properly
handled (matches Kernel's deferred state).

10 tests: plain atom/list, unquote substitution, splicing at
start/middle/end, nested list with unquote, unquote evaluates
expression, error on non-list splice, error on bare unquote.

**Second consumer for lib/guest/reflective/quoting.sx unlocked.**
Both Kernel and Scheme have structurally identical walkers; the
extraction would parameterise just the unquote/splicing keyword
names (Kernel uses $unquote / $unquote-splicing; Scheme uses
unquote / unquote-splicing — pure cfg, no algorithmic change).

280 total Scheme tests (62+23+49+78+25+20+13+10).

Three reflective-kit extractions unlocked in this Scheme port:
- env.sx        — Phase 2 (consumed directly, third overall consumer)
- evaluator.sx  — Phase 7 (second consumer via eval/interaction-env)
- quoting.sx    — Phase 10 (second consumer via scm-quasi-walk)

The kit extractions themselves remain follow-on commits when
desired. hygiene.sx still awaits a real second consumer
(Scheme phase 6c with scope-set algorithm).
2026-05-14 06:47:51 +00:00
342e1a2ccf 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
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).
2026-05-14 06:45:39 +00:00
9a7ca54902 scheme: Phase 6b — syntax-rules ellipsis (tail-rest) + 8 tests
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 29s
scm-match-list now detects `<pat> ...` at the END of a pattern list
and binds <pat> (must be a symbol — single-variable rest) to the
remaining forms as a list. Nested-list patterns under ellipsis and
middle-of-list ellipses are NOT supported yet (rare in practice;
deferred).

scm-instantiate-list mirrors: when it encounters `<var> ... `
inside a list template, it splices the list-valued binding of <var>
in place. Internal list-append-all helper for the splice.

Removes the `(length pat) = (length form)` strict-equality check
in scm-match-step's list case — that gate blocked ellipsis. The
length-1-or-more relaxed check now lives in scm-match-list itself.

8 ellipsis tests cover:
- Empty rest (my-list)
- Non-empty rest (my-list 1 2 3 4)
- my-when with multi-body
- Variadic sum-em via fold-left
- Recursive my-and pattern (short-circuit AND defined as macro)

257 total Scheme tests (62 + 23 + 49 + 78 + 25 + 20).

Phase 6c (proper hygiene) is the next step and will be the
**second consumer for lib/guest/reflective/hygiene.sx** — the
deferred research-grade kit from the kernel-on-sx loop.
2026-05-14 06:43:20 +00:00
eb14a7576b scheme: Phase 6a — define-syntax + syntax-rules (no ellipsis) + 12 tests
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 28s
eval.sx adds macro infrastructure:
- {:scm-tag :macro :literals (LIT...) :rules ((PAT TMPL)...) :env E}
- scheme-macro? predicate
- scm-match / scm-match-list — pattern matching against literals,
  pattern variables, and structural list shapes
- scm-instantiate — template substitution with bindings
- scm-expand-rules — try each rule in order
- (syntax-rules (LITS) (PAT TMPL)...) → macro value
- (define-syntax NAME FORM) → bind macro in env
- scheme-eval: when head looks up to a macro, expand and re-eval

Pattern matching supports:
- _ → match anything, no bind
- literal symbols from the LITERALS list → must equal-match
- other symbols → pattern variables, bind to matched form
- list patterns → must be same length, each element matches

NO ellipsis (`...`) support yet — that's Phase 6b. NO hygiene
yet (introduced symbols can shadow caller bindings) — that's
Phase 6c, which will be the second consumer for
lib/guest/reflective/hygiene.sx.

12 tests cover: simple substitution, multi-rule selection,
nested macro use, swap-idiom (state mutation via set!), control-
flow wrappers, literal-keyword pattern matching, macros inside
lambdas.

249 total Scheme tests now (62 + 23 + 49 + 78 + 25 + 12).
2026-05-14 06:41:11 +00:00
a90f56e3f3 scheme: Phase 5c — dynamic-wind (basic, no call/cc tracking) + 5 tests
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 29s
(dynamic-wind BEFORE THUNK AFTER)
  - Calls BEFORE; runs THUNK; calls AFTER; returns THUNK's value.
  - If THUNK raises, AFTER still runs before the raise propagates.
  - Implementation: outcome-sentinel pattern (same trick as guard
    and with-exception-handler) — catch THUNK's raise inside a
    host guard, run AFTER unconditionally, then either return the
    value or re-raise outside the catch.

Not implemented: call/cc-escape tracking. R7RS specifies that
dynamic-wind's BEFORE and AFTER thunks should re-run when control
re-enters or exits the dynamic extent via continuations. That
requires explicit dynamic-extent stack tracking, deferred until
a consumer needs it (probably never needed for pure-eval Scheme
programs; matters for first-class-continuation-heavy code).

5 tests: success ordering, return value, after-on-raise,
raise propagation, nested wind.

237 total Scheme tests now (62 + 23 + 49 + 78 + 25).
2026-05-14 06:37:51 +00:00
55c376f559 scheme: Phase 5b — R7RS exceptions (raise/guard/with-exception-handler) + 12 tests
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 31s
eval.sx adds the `guard` syntactic operator with R7RS-compliant
clause dispatch: var binds to raised value in a fresh child env;
clauses tried in order; `else` is catch-all; no match re-raises.

Implementation uses a "catch-once-then-handle-outside" pattern to
avoid the handler self-raise loop:
  outcome = host-guard {body}            ;; tag raise vs success
  if outcome was raise:
    try clauses → either result or sentinel
    if sentinel: re-raise OUTSIDE the host-guard scope

runtime.sx binds R7RS exception primitives:
- raise V
- error MSG IRRITANT...  → {:scm-error MSG :irritants LIST}
- error-object?, error-object-message, error-object-irritants
- with-exception-handler HANDLER THUNK
  (same outcome-sentinel pattern — handler's own raises propagate
  outward instead of re-entering)

12 tests cover: catch on raise, predicate dispatch, else catch-all,
no-error pass-through, first-clause-wins, re-raise-on-no-match,
error-object construction and accessors.

232 total Scheme tests now (62 + 23 + 49 + 78 + 20).
2026-05-14 06:36:50 +00:00
e3e5d3e888 scheme: Phase 5a — call/cc + 8 tests
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 38s
scheme-standard-env binds:
- call/cc                            — primary
- call-with-current-continuation     — alias

Implementation wraps SX's host call/cc, presenting the captured
continuation k as a Scheme procedure that accepts a single value
(or a list of values for multi-arg invocation). Single-shot
escape semantics: when k is invoked, control jumps out of the
surrounding call/cc form. Multi-shot re-entry isn't safely
testable without delimited-continuation infrastructure (the
captured continuation re-enters indefinitely if invoked after
the call/cc returns) — deferred to a follow-up commit if needed.

Tests cover:
- No-escape return value
- Escape past arithmetic frames
- Detect/early-exit idiom over for-each
- Procedure? on the captured k

220 total Scheme tests now (62 + 23 + 49 + 78 + 8).
2026-05-14 06:27:03 +00:00
c560f3d70d hs: port loops/hs WebSocket runtime + test suite (replaces arch's underscore-prefixed API)
Adopts loops/hs's cleaner WebSocket API on top of arch's hyperscript:
- Runtime: replace 5 arch socket functions (hs-try-json-parse, hs-socket-normalise-url,
  hs-socket-bind-name!, hs-socket-resolve-rpc!, hs-socket-register!) with loops/hs's
  versions. Wrapper fields now use external-style names (url, timeout, pending, handler,
  json?, closedFlag, dispatchEvent) instead of internal-style underscores (_url,
  _timeout, _pending, _hsSetupSocket).
- Tests: replace arch's 257-line hs-upstream-socket suite (which probed _pending,
  _hsSetupSocket etc.) with loops/hs's 162-line suite that checks the new field names.
  Both suites cover the same 16 E36 behavioral cases.

Parser/compiler unchanged: both branches emit (hs-socket-register! name-path url
timeout handler json?) so the call signature is compatible with either runtime.
Arch's parse-socket-feat / emit-socket are preserved.

Local hs test.sh: 23/25 (the 2 failures are pre-existing hide/show cmd compiler
issues, not socket-related).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 21:16:09 +00:00
5e7d431f15 Merge loops/lua into architecture: features (coroutine, math, string.format, pattern char sets, byte-level chars). GUEST-lex refactor + delay/force to be re-applied in follow-up.
# Conflicts:
#	lib/lua/runtime.sx
#	lib/lua/test.sh
#	lib/lua/tokenizer.sx
2026-05-13 20:59:49 +00:00
88c7ce4068 Merge loops/apl into architecture: Phase 10 runtime gaps (⍸ ∪ ∩ ⊥ ⊤ ⊆ ⍎), life.apl + quicksort.apl run as-written 2026-05-13 20:38:17 +00:00
c19bcc51cb Merge loops/forth into architecture: Hayes conformance 99% (632/638), JIT cooperation, full Forth-2012 core 2026-05-13 20:37:26 +00:00
129f11fdbc Merge lib/tcl/uplevel into architecture: kernel + reflective env extraction (Phase 1-7 kernel, 322+427 tests) 2026-05-13 20:34:07 +00:00
cf933f0ece scheme: Phase 4 standard env + set! bugfix + 78 tests
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 25s
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.
2026-05-13 20:29:37 +00:00
0fccd1b353 scheme: Phase 3.5 — let/let*/cond/when/unless/and/or + 21 tests
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 27s
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.
2026-05-13 20:04:44 +00:00
23a53a2ccb scheme: Phase 3 — if/define/set!/begin/lambda/closures + 24 tests
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 28s
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).
2026-05-13 20:02:46 +00:00
e222e8b0aa scheme: Phase 2 evaluator — env.sx third consumer + 23 tests [consumes-env]
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 25s
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).
2026-05-13 20:00:36 +00:00
c919d9a0d7 scheme: Phase 1 parser — R7RS lexical reader + 62 tests [consumes-lex]
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 21s
lib/scheme/parser.sx — reader for R7RS-small lexical syntax:
- numbers (int/float/exp)
- booleans #t / #f / #true / #false
- strings with standard escapes
- symbols (permissive — any non-delimiter)
- characters #\c, #\space, #\newline, #\tab, etc.
- vectors #(...)
- proper lists (dotted-pair deferred to Phase 3 with lambda rest-args)
- reader macros: 'X `X ,X ,@X → (quote X) (quasiquote X) etc.
  (Scheme conventions — lowercase, no $ prefix)
- line comments ;
- nestable block comments #| ... |#
- datum comments #;<datum>

AST shape mirrors Kernel: numbers/booleans/lists pass through;
strings wrapped as {:scm-string ...} to distinguish from symbols
(bare SX strings); chars as {:scm-char ...}; vectors as
{:scm-vector (list ...)}.

62 tests in lib/scheme/tests/parse.sx cover atom kinds, escape
sequences, quote/quasiquote/unquote/unquote-splicing, all three
comment flavours, and classic Scheme idioms (lambda, define, let,
if-cond).

Note: SX cond branches evaluate only the LAST expression, so
multi-mutation branches need explicit (do ...) or (begin ...)
wrappers — caught during block-comment debugging.

chisel: consumes-lex (lex-digit?, lex-whitespace? from
lib/guest/lex.sx); pratt not consumed (no operator precedence
in Scheme).
2026-05-13 19:58:30 +00:00
a75b4cbc57 plans: scheme-on-sx — R7RS-small port, second consumer for 3 reflective kits
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 47s
11-phase plan from parser through R7RS conformance. Explicitly maps
which reflective kits Scheme consumes:

- env.sx (Phase 2)        — third consumer, no cfg needed
- evaluator.sx (Phase 7)  — second consumer, unblocks extraction
- hygiene.sx (Phase 6)    — second consumer, drives the deferred
                            scope-set / lifted-symbol work
- quoting.sx (Phase 10)   — second consumer, unblocks extraction
- combiner.sx             — N/A (Scheme has no fexprs)

Correction to earlier session claim: a Scheme port unlocks THREE
more reflective kits, not four. combiner.sx stays Kernel-only.
2026-05-13 19:53:29 +00:00
4fd376a348 Merge loops/datalog into architecture: tokenizer/parser, magic sets, negation, semi-naive (259/259 tests) 2026-05-13 19:52:11 +00:00
a7665a7b25 js-on-sx: js-display filter to format JS values without leaking internals
The OCaml epoch-protocol printer serializes raw SX dicts. JS object literals
now carry __proto__ / __js_order__ bookkeeping that points into Object.prototype,
a complex dict containing lambdas that close over Object — the printer
recurses indefinitely and hangs.

js-display walks the value once, dropping any dict key that matches the
__name__ dunder convention. js-eval calls it on its return value so the
output is the user-facing shape only. Restores 587/593 passing (up from
191/593 post-merge and 492/585 pre-merge) — the surviving 6 failures are
legitimate pre-existing test mismatches (illegal return/break/continue,
parseFloat float vs rational, escaped backtick).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 08:38:47 +00:00
95c2d0b64a HS scoreboard: io-wait-event fix landed — both wait regressions cleared
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 43s
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 21:33:50 +00:00
cfbab3b2f9 HS test runner: unwrap value handles in io-wait-event interceptor
Some checks are pending
Test, Build, and Deploy / test-build-deploy (push) Waiting to run
The new WASM ABI wraps numbers, strings, and other atoms as opaque
value-handles ({_type, __sx_handle}) inside the perform request args.
The io-wait-event mock checks typeof against 'number' and 'string'
directly, so under the new ABI:

  - typeof timeout === 'number'  →  false  (timeout is a handle)
  - typeof items[2] === 'string' →  false  (event name is a handle)

so the "timeout wins" branch never triggered, and the test fell into
the "neither timeout nor event" else that resumed with nil but never
fired the post-wait `then add .bar` command.

Apply _unwrapHandle to the three args (target, evName, timeout) before
the type checks. This is the same pattern the rest of the host-* native
sweep already follows (commit 29ef89d4).

Effect: hs-upstream-wait goes from 5/7 → 7/7.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 21:33:24 +00:00
4d92eafb36 HS scoreboard: dict-eq fix entry + post-JIT-Phase-2 regression note
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 39s
Records that the 1514/1514 claim was relative to the kernel as of
92619301; the value-handle ABI + numeric tower + JIT Phase 2 commits
introduced three regressions (1 dict-eq, now fixed in 4db1f85f, and 2
event-or-timeout wait tests still pending).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 21:22:00 +00:00
4db1f85fe8 Fix dict equality: structural eq for plain dicts, Integer/Number in equal?
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 44s
Two related kernel bugs were causing the HS conformance test
"arrays containing objects work" to fail with the misleading message
"Expected ({:a 1} {:b 2}) but got ({:a 1} {:b 2})".

1. sx_primitives.ml safe_eq: Dict/Dict only returned true for DOM-wrapped
   dicts (those carrying __host_handle); all other dict pairs returned
   false unconditionally. Plain dict literals can never have been =
   to each other. Add the structural-equality fallback: when neither
   side has a host handle, compare lengths and walk keys.

2. sx_browser.ml deep_equal (the kernel binding for equal?): had a
   Number/Number branch but no Integer/Integer or cross-Integer/Number
   branches, so since the numeric tower change Integer 1 vs Integer 1
   was falling through to the catch-all and returning false. Mirror the
   cases from run_tests.ml deep_equal which already had them.

Verified via direct kernel probe:
  (= {:a 1} {:a 1})                        => true   (was false)
  (= {:a 1 :b 2} {:b 2 :a 1})              => true   (was false)
  (equal? 1 1)                             => true   (was false)
  (equal? {:a 1} {:a 1})                   => true   (was false)
  (equal? (list {:a 1}) (list {:a 1}))     => true   (was false)

HS suite arrayLiteral: 7/8 → 8/8.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 21:20:43 +00:00
4563a7ae97 method-chain: plan — current status + future-consumer notes
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 40s
Documents the extraction (Smalltalk + CLOS migrated, kit landed,
counts unchanged), lists plausible third consumers (JS proto chain,
Ruby ancestors, Python MRO), and notes which other patterns stayed
unextracted and why (method-cache invalidation, inline cache, and
the five reflective siblings all need consumers that don't exist
yet in the codebase).

Closes the session's extraction work at five branches: env (3
consumers), class-chain (2), test-runner (POC), plus the chain
of intermediate branches. The Scheme port is the next high-leverage
move; it would unlock four more reflective kits in one stroke.
2026-05-12 21:14:28 +00:00
2981a479e8 reflective: extract class-chain.sx — Smalltalk + CLOS method dispatch share parent-walk
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 35s
lib/guest/reflective/class-chain.sx — class inheritance walker with
adapter cfg for single-parent (Smalltalk) and multi-parent (CLOS)
hierarchies. Three primitives:

- refl-class-chain-find-with CFG CN PROBE
    DFS through parents, returns first non-nil probe result.
    Smalltalk method lookup uses this.

- refl-class-chain-depth-with CFG CN ANCESTOR
    Min hop distance via any parent path, or nil if unreachable.
    CLOS method specificity uses this.

- refl-class-chain-ancestors-with CFG CN
    Flat DFS-ordered list of all reachable ancestor names.

Adapter cfg has two keys: :parents-of (CN → list of parent names,
possibly empty) and :class? (predicate; short-circuits walk on
non-existent class names mid-chain).

Migrations:
- lib/smalltalk/runtime.sx: st-method-lookup-walk now a 9-line
  thin probe through the kit (was 20 lines of inline recursion);
  st-class-cfg wraps the single-parent :superclass field into a
  1-element list for the cfg.

- lib/common-lisp/clos.sx: clos-specificity is a one-line wrapper
  around refl-class-chain-depth-with (was 28 lines); clos-class-cfg
  reads the multi-parent :parents field.

Both consumers green:
- Smalltalk: 847/847 (unchanged)
- CL: 222/240 (unchanged baseline; 18 pre-existing failures, all
  in stdlib functions like cl-set-memberp, unrelated to CLOS).

This is the second extracted reflective kit (env.sx was first).
The adapter-cfg pattern continues to bridge structurally divergent
consumers (Smalltalk single-inheritance vs CLOS multiple-inheritance
with method-precedence distance) via a uniform :parents-of callback.
2026-05-12 21:09:07 +00:00
54a890db71 HS: install Phase 2 WASM as default + fix batched total to 1514
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 50s
The shared/static/wasm/sx_browser.bc.js artifact now reflects the OCaml
kernel with JIT Phase 1 (tiered compilation), Phase 2 (LRU eviction),
and Phase 3 (manual reset) — same source as previously committed,
just the rebuilt binary so test/dev consumers pick it up without
needing a local sx_build.

tests/hs-run-batched.js: TOTAL default 1496 → 1514. The conformance
suite grew by 18 tests since the constant was last set; without this
the batched runner stops short of the final 14 tests.

Verified via batched run (75-test batches, parallelism=2):
  1436 / 1439 reported pass (3 failures, all in suites where the
  underlying parser/dict-equality gap is independent of WASM).
  Batch 150-225 didn't complete inside 15 min — 75 reactivity /
  regressions / runtime tests at 5-11s each blow past the wall; a
  per-batch deadline raise is the right knob, not a kernel change.

Per-test timing (new vs old WASM, slice 170-195) is comparable
(60s vs 78s on new/threshold=4 — Phase 1+2 is NOT a perf regression
on HS code; the slow tests are slow on both kernels because the
underlying CEK path doesn't get JIT-compiled either way — HS emits
anonymous lambdas that bypass the named-only JIT gate).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 20:59:46 +00:00
480462646d Merge loops/js into architecture: var hoisting + ASI + matchAll on top of regex engine / TDZ scaffolding
Combined arch's regex platform dispatch (runtime.sx) with loops/js's var-hoisting transpiler
(transpile.sx) and matchAll string method. Plan checkboxes updated to reflect both done.
Conflicts: lib/js/runtime.sx, lib/js/transpile.sx, lib/js/test.sh, plans/js-on-sx.md.
2026-05-12 20:47:05 +00:00
decaf818fa Merge loops/ocaml into architecture: OCaml-on-SX language port (Phase 5.1 + ~200 baselines)
# Conflicts:
#	plans/ocaml-on-sx.md
2026-05-12 20:39:48 +00:00
9efbf4ad38 reflective: third consumer — Smalltalk frame adopts env.sx — 847+322+427 tests green
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 43s
lib/guest/reflective/env.sx — added refl-env-find-frame-with (returns
the scope where NAME is bound, or nil). Needed by consumers like
Smalltalk that mutate variables at the source frame rather than
shadowing at the current one. Also added refl-env-find-frame for
the canonical shape.

lib/smalltalk/eval.sx — new st-frame-cfg adapter for the kit.
st-lookup-local now delegates parent-walk to refl-env-find-frame-with
while preserving its Smalltalk-flavoured {:found :value :frame}
return shape (which is used to mutate at the binding's source
frame, not the current one).

lib/smalltalk/test.sh + compare.sh — load lib/guest/reflective/env.sx
before lib/smalltalk/eval.sx.

Three genuinely different wire shapes now share the parent-walk:
- Kernel: {:refl-tag :env :bindings :parent}      mutable bindings
- Tcl:    {:level :locals :parent}                 functional update
- Smalltalk: {:self :method-class :locals :parent  mutable bindings,
              :return-k :active-cell}              rich metadata

All three consumers' full test suites unchanged: Smalltalk 847/847,
Kernel 322/322, Tcl 427/427. The cfg adapter pattern (modelled after
lib/guest/match.sx) cleanly handles all three.
2026-05-12 15:19:19 +00:00
4e904a2782 merge: loops/smalltalk into lib/smalltalk/refl-env — bring in third consumer 2026-05-12 14:50:05 +00:00
dea2a6e390 Merge loops/haskell into architecture: Phase 17 — import decls, type annotations, typecheck 15/15 2026-05-12 14:45:44 +00:00
c27db9b78f reflective: Phase 3 docs — mark env.sx extraction DONE, others still blocked
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 19s
plans/kernel-on-sx.md — Phase 7 header updated from "partial" to
"env.sx EXTRACTED 2026-05-12"; second-consumer-found checkbox ticked
for env.sx specifically. Other five files (combiner, evaluator,
hygiene, quoting, short-circuit) stay blocked pending their own
second consumers.

plans/lib-guest-reflective.md — Phases 1-3 ticked off with date
stamps; Outcome section added summarising the three commits, file
stats (124 LoC, within 80-200 bound), and the third-consumer
adoption protocol (cfg with five keys, no changes to env.sx).
2026-05-12 07:04:17 +00:00
39381fda92 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.
2026-05-12 07:02:56 +00:00
2e7e3141d4 reflective: extract env.sx + migrate Kernel — 322 tests green
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 56s
Phase 1 of the lib-guest-reflective extraction plan.

lib/guest/reflective/env.sx — canonical wire shape
{:refl-tag :env :bindings DICT :parent ENV-OR-NIL} with mutable
defaults (dict-set!), plus *-with adapter-cfg variants for consumers
with their own shape (modelled after lib/guest/match.sx). 13 forms,
~5 KB.

lib/kernel/eval.sx — env block collapses from ~30 lines to 6 thin
wrappers (kernel-env? = refl-env?, etc.). No semantic change; envs
now carry :refl-tag :env instead of :knl-tag :env. All 322 Kernel
tests pass unchanged across 7 suites (parse 62, eval 36, vau 38,
standard 127, encap 19, hygiene 26, metacircular 14).

Next: Phase 2 — Tcl adapter cfg in lib/tcl/runtime.sx using
refl-env-lookup-with against the existing :level/:locals/:parent
frame shape.
2026-05-12 06:59:07 +00:00
edfc37636f merge: loops/kernel into lib/tcl/uplevel — bring in first consumer for extraction 2026-05-12 06:55:00 +00:00