Chez Phase 2 (inc Q): Java class statics + constructors (jolt-avt6)

Lower host class interop on the Chez back end. The analyzer now turns a
non-var qualified ref `Class/member` into a :host-static node and a
`(Class. ...)` / `(new Class ...)` form into a :host-new node (ir.clj
gains both, with walker support). The Janet back end punts both to the
interpreter, so its behavior is unchanged (verified: dot-form, `..`
threading, shadowed `new`, and all interop still resolve via fallback).

The Chez emit lowers a value ref to host-static-ref, a call head to
host-static-call, and a constructor to host-new. host/chez/host-static.ss
is the runtime registry these resolve against — the Chez port of the
seed's class-statics / class-ctors / tagged-methods (java_base.janet +
host_io.janet), restricted to the java.lang/util/net/io surface portable
cljc code calls: Math, System (getenv/getProperty/exit/currentTimeMillis),
Long, Integer, Boolean, Character, String, Thread, Class, Pattern
(compile/quote/MULTILINE), URLEncoder/Decoder, Base64, the Number method
surface (byteValue/intValue/...), plus the StringBuilder, StringWriter,
StringReader, PushbackReader, HashMap, StringTokenizer, BigInteger,
String, MapEntry, and exception constructors. Constructed objects are
jhost records dispatched through record-method-dispatch.

Also: emit now evaluates collection-literal elements left-to-right
(emit-ordered) — Chez evaluates call args right-to-left, which had been
swapping side-effecting elements in [(read r) (read r)] and map literals.
This un-allowlisted the 6 eval-order corpus cases (the read-line trio +
the three map-construction cases). Removed `.write` from the
jolt-host-call fast-path so a StringWriter routes through dispatch.

java.time formatting, edn/read-over-readers, and slurp/with-open over
readers are deferred to a follow-up.

Corpus parity 2078 -> 2134 (floor raised), 0 new divergences; the
print-method builtin-override case is allowlisted (same multimethod gap,
newly reachable now that StringWriter constructs). emit-test 326/326,
_javastatic 51/51, conformance 355x3, full jpm test green.
This commit is contained in:
Yogthos 2026-06-18 23:24:01 -04:00
parent a706a79b90
commit c90c4cb610
10 changed files with 711 additions and 26 deletions

View file

@ -27,6 +27,18 @@
;; Janet) — the back end emits a host-appropriate reference.
(defn host-ref [name] {:op :host :name name})
;; A qualified static reference to a host class member, `Class/member` (e.g.
;; Math/sqrt, Long/MAX_VALUE, System/getenv). A leaf node carrying the class and
;; member names. The Janet back end punts it (the interpreter resolves the static
;; from its class-statics registry); the Chez back end lowers a value ref to
;; host-static-ref and a call head to host-static-call (host-static.ss).
(defn host-static [class member] {:op :host-static :class class :member member})
;; A host constructor, `(Class. args*)` / `(new Class args*)`. Carries the class
;; name and the analyzed argument nodes. Janet punts (interpreter runs the
;; constructor); Chez lowers to host-new (host-static.ss class-ctor registry).
(defn host-new [class args] {:op :host-new :class class :args args})
(defn if-node [test then else] {:op :if :test test :then then :else else})
(defn do-node [statements ret] {:op :do :statements statements :ret ret})
@ -103,6 +115,7 @@
(= op :def) (assoc node :init (f (get node :init)))
(= op :host-call) (assoc node :target (f (get node :target))
:args (mapv f (get node :args)))
(= op :host-new) (assoc node :args (mapv f (get node :args)))
;; :catch-body / :finally are optional; recurse them only when PRESENT.
;; Assoc'ing them nil-when-absent would turn the node into a phm (jolt's
;; nil-valued-key representation) and force backend densification — so we
@ -112,5 +125,5 @@
n (if (get node :catch-body) (assoc n :catch-body (f (get node :catch-body))) n)
n (if (get node :finally) (assoc n :finally (f (get node :finally))) n)]
n)
;; :const :local :var :host :the-var :rt :quote — no child nodes
;; :const :local :var :host :host-static :the-var :rt :quote — no child nodes
:else node)))