Files
rose-ash/plans/lib-guest-method-chain.md
giles 4563a7ae97
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 40s
method-chain: plan — current status + future-consumer notes
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

3.9 KiB

lib/guest/reflective/class-chain.sx — extraction plan

Status

  • Kit landedlib/guest/reflective/class-chain.sx (7 forms, ~120 LoC).
  • First consumer migratedlib/smalltalk/runtime.sx st-method-lookup-walk. 20 lines → 9 lines. Smalltalk single-parent shape adapted via :parents-of returning a 1-element list.
  • Second consumer migratedlib/common-lisp/clos.sx clos-specificity. 28 lines → 4 lines. CLOS multi-parent shape adapted via :parents-of returning the full parents list.
  • Both consumers' test counts unchanged. Smalltalk 847/847. CL 222/240 (18 pre-existing failures unrelated to CLOS dispatch).

API surface

(refl-class-chain-find-with CFG CLASS-NAME PROBE)
  ;; DFS through parent chain. Returns first non-nil probe result.
  ;; Smalltalk method lookup uses this.

(refl-class-chain-depth-with CFG CLASS-NAME ANCESTOR-NAME)
  ;; Minimum hop count via any parent path. nil if unreachable.
  ;; CLOS method specificity uses this.

(refl-class-chain-ancestors-with CFG CLASS-NAME)
  ;; Flat DFS-ordered list of all reachable ancestor names.

Adapter cfg keys:

  • :parents-of — fn (class-name) → list of parent class names. Empty list = root. Single-parent guests wrap into a 1-element list.
  • :class? — predicate; short-circuits walk on non-existent class names.

Why two consumers were enough

Smalltalk and CLOS have structurally different class hierarchies — single inheritance with one :superclass field versus multiple inheritance with a :parents list. The kit handles both via the cfg normalising :parents-of to "list of parent names" (empty, singleton, or multi-element). This is the third demonstration of the adapter-cfg pattern from lib/guest/match.sx and lib/guest/reflective/env.sx.

Future consumers

A third consumer would validate the kit further but isn't blocked by the two-consumer rule. Plausible candidates that already have class chains in the codebase or could acquire them:

  • JavaScript prototype chains — if lib/js/ builds an evaluator that walks __proto__. :parents-of returns a 1-element list (the proto, if any). Probably the cleanest third consumer.
  • Ruby's ancestor walk (Module#ancestors) — multi-element list with strict ordering rules. Would stress whether :parents-of needs to return ordered lists (it already does).
  • Python's MRO (method resolution order via C3 linearisation) — could use refl-class-chain-ancestors-with as a starting point, with consumer-side linearisation on top.

Non-goals

  • Method-cache invalidation protocol — Smalltalk has st-method-cache with class-change invalidation; CLOS has per-generic method lists with clos-defmethod updates. Currently only one consumer per cache shape; defer.

  • Inline call-site caches — Smalltalk's per-call-site IC is a hot-path optimisation. No other current consumer; defer until at least a JS or Python guest with optimisable dispatch.

  • combiner.sx, evaluator.sx, hygiene.sx, quoting.sx, short-circuit.sx — these still wait for a Scheme/Maru port. CLOS doesn't have fexprs, so it can't be the second consumer for combiner.sx. CL's reader has backquote parsing but no runtime quasi-walker, so it's not a current second consumer for quoting.sx either. The Scheme port is the unlock.

Cumulative session output

Branch Kit Consumers
loops/kernel (proposal docs) 1
lib/tcl/uplevel reflective/env.sx 2 (Kernel, Tcl)
lib/smalltalk/refl-env + refl-env-find-frame-with 3 (+ Smalltalk)
lib/guest/test-runner test-runner.sx 1 (Kernel POC)
lib/guest/method-chain reflective/class-chain.sx 2 (Smalltalk, CLOS)

Two complete reflective kits live with multiple consumers; one infrastructure kit at proof-of-concept; one extraction (the Scheme port that would unlock four more reflective kits) is the next natural strategic move but is a substantial undertaking.