The on-Chez analyzer (inc6a) skipped macros, so let/when/->/defn didn't
expand from source. Each core/stdlib defmacro now emits into the prelude as
(def-var! ns name <expander fn>) + (mark-macro! ns name); form-macro?/
form-expand-1 on Chez look up the macro flag (rt.ss var-macro-table) and
apply the expander to the unevaluated arg forms, and the analyzer re-analyzes
the result. The expander's syntax-quote template was lowered to construction
code at cross-compile time, so it builds the expansion via __sqcat/__sqvec/
__sqmap/__sqset/__sq1 (new host/chez/syntax-quote.ss) as Chez reader forms.
Emit the bare (fn ...), not (def NAME (fn ...)): analyzing a def would
host-intern! NAME as a non-macro stub in the build ctx, and that stub makes a
later (require '[stdlib-ns]) skip loading the real macro — with-pprint-dispatch
then resolved as a fn and returned its unexpanded template. Wrapping the
lambda in def-var! manually never interns NAME. Fuller build-ctx isolation
(so stdlib cases pass instead of crash) tracked in jolt-lpvi.
__sqset builds a real set VALUE, not the reader's tagged-set form — a runtime
`#{~@xs} must be a set, not a map. form-set? additionally recognizes a pset so
a macro template's #{...} expansion still re-analyzes as a set literal.
spine-test 35/35 (20 macro cases: when/when-not/let/->/->>/and/or/cond/if-not/
defn run zero-Janet from source). Prelude parity 2280->2295, 0 new divergences.
Full Janet gate green.
51 lines
2.8 KiB
Scheme
51 lines
2.8 KiB
Scheme
;; syntax-quote form builders (jolt-r9lm, inc6b) — the Chez analogs of
|
|
;; core_types.janet's core-sq*. A cross-compiled macro expander whose body was a
|
|
;; syntax-quote template (lowered by jolt.host/form-syntax-quote-lower at Janet
|
|
;; cross-compile time) calls these at RUNTIME on Chez to build the EXPANSION as
|
|
;; Chez READER forms (cseq list / pvec / pmap / tagged-set pmap) so the on-Chez
|
|
;; analyzer can re-analyze it. def-var!'d into clojure.core, so the lowered body's
|
|
;; unqualified __sqcat/__sqvec/__sqmap/__sqset/__sq1 refs (which lower to var-deref
|
|
;; in prelude mode) resolve here.
|
|
;;
|
|
;; A list/vector/set template lowers to (__sqcat part ...) where each part is
|
|
;; either (__sq1 x) — a single non-spliced item — or a ~@ expr that evaluates to a
|
|
;; seqable spliced in place. Both kinds are seqables, so __sqcat just flattens each
|
|
;; part's jolt-seq in order. A map template lowers to (__sqmap k v ...) with no
|
|
;; splicing (alternating key/value, already lowered).
|
|
;;
|
|
;; Loaded by rt.ss after collections.ss/seq.ss (jolt-list/jolt-vector/jolt-hash-map/
|
|
;; jolt-seq) and def-var!.
|
|
|
|
;; flatten the __sqcat/__sqvec/__sqset parts (each a seqable) into a Scheme list.
|
|
(define (sq-flatten parts)
|
|
(let loop ((ps parts) (acc '()))
|
|
(if (null? ps)
|
|
(reverse acc)
|
|
(loop (cdr ps)
|
|
(let inner ((s (jolt-seq (car ps))) (a acc))
|
|
(if (jolt-nil? s)
|
|
a
|
|
(inner (jolt-seq (seq-more s)) (cons (seq-first s) a))))))))
|
|
|
|
;; single non-spliced item -> a one-element seqable (__sqcat flattens it).
|
|
(define (jolt-sq1 x) (jolt-list x))
|
|
;; list FORM: cseq with list?=#t, so the analyzer's form-list? sees a list.
|
|
(define (jolt-sqcat . parts) (apply jolt-list (sq-flatten parts)))
|
|
;; vector FORM: pvec.
|
|
(define (jolt-sqvec . parts) (apply jolt-vector (sq-flatten parts)))
|
|
;; set: a REAL set value (pset). A syntax-quote builds VALUES, and the cseq/pvec/
|
|
;; pmap that __sqcat/__sqvec/__sqmap build double as their own form rep — but a set
|
|
;; value (pset) differs from the reader's set FORM ({:jolt/type :jolt/set :value
|
|
;; <pvec>}), so building the tagged form here would make a runtime `#{~@xs} a map,
|
|
;; not a set (jolt-r9lm regression). Build the value; the analyzer's form-set?
|
|
;; (host-contract.ss) additionally recognizes a pset, so a macro template's #{...}
|
|
;; expansion still re-analyzes as a set literal.
|
|
(define (jolt-sqset . parts) (apply jolt-hash-set (sq-flatten parts)))
|
|
;; map FORM: a plain pmap (the analyzer's form-map? = pmap with no :jolt/type).
|
|
(define (jolt-sqmap . parts) (apply jolt-hash-map parts))
|
|
|
|
(def-var! "clojure.core" "__sq1" jolt-sq1)
|
|
(def-var! "clojure.core" "__sqcat" jolt-sqcat)
|
|
(def-var! "clojure.core" "__sqvec" jolt-sqvec)
|
|
(def-var! "clojure.core" "__sqset" jolt-sqset)
|
|
(def-var! "clojure.core" "__sqmap" jolt-sqmap)
|