Chez Phase 2 (inc D): records + protocols

The largest remaining crash bucket: defrecord/deftype/defprotocol/extend-type/
reify. make-deftype-ctor/make-protocol/protocol-dispatch/register-method/
satisfies?/extenders/instance-check/make-reified were ctx-capturing seed natives
resolving to jolt-nil.

records.ss adds a jrec type (tag + field alist), set!-extended into every
collection dispatcher (get/=/hash/count/keys/vals/seq/assoc/conj/contains?/map?/
pr-str/pr-readable/str) via the transients.ss capture-prev pattern, plus a
protocol registry (type-tag -> proto -> method -> fn) and dispatch over record
tags / host-type candidates. (get rec :jolt/deftype) returns the tag, so the
overlay record? works unchanged. A record equals another of the same type with
equal fields, is map?/coll? not vector?, prints #ns.Name{...}, and str uses a
custom Object toString impl when defined.

emit.janet :host-call now routes a non-shimmed method to record-method-dispatch
(was an emit-fail), so (.protoMethod record args) compiles; .-field access is
still analyzer-punted (deferred).

Prelude parity 1652 -> 1701, 0 new divergences. 4 print-method-multimethod cases
moved crash->allowlist (the printer doesn't consult a custom print-method yet).
jolt-jgoc.
This commit is contained in:
Yogthos 2026-06-18 11:55:20 -04:00
parent 5101ada8e0
commit f0419b560d
4 changed files with 332 additions and 8 deletions

View file

@ -455,13 +455,18 @@
# IN the subset; any other method is out of subset (a clean emit-time reject,
# like an unimplemented stdlib fn), so it doesn't masquerade as a compiled-but-
# broken divergence. The Janet back end punts ALL :host-call to the interpreter.
:host-call (let [m (get node :method)]
(unless (get supported-host-methods m)
(errorf "emit: unsupported host method `.%s` (no Chez shim yet)" m))
(let [target (emit (get node :target))
args (map emit (vv (get node :args)))]
:host-call (let [m (get node :method)
target (emit (get node :target))
args (map emit (vv (get node :args)))]
(if (get supported-host-methods m)
(string "(jolt-host-call " (chez-str-lit m) " "
target (if (empty? args) "" (string " " (string/join args " "))) ")")))
target (if (empty? args) "" (string " " (string/join args " "))) ")")
# a non-shimmed method: dispatch at runtime by the target's type
# — a record/reify protocol method (jolt-jgoc). On a non-record
# host value this errors (was an emit-fail before, so no new
# divergence), but it lets (.protoMethod record …) compile.
(string "(record-method-dispatch " target " " (chez-str-lit m)
" (jolt-vector" (if (empty? args) "" (string " " (string/join args " "))) "))")))
:fn (emit-fn node)
# (def name) with no init (declare): reserve the var cell (declare-var!
# doesn't clobber an existing root) so a forward reference resolves.