Scrub dangling Janet references; drop dead Janet-coupled files

Rephrase comments that pointed at deleted Janet files (emit.janet, the seed
sources, 'the Janet back end punts ...') to present-tense descriptions of the
Chez behavior. Comment/docstring-only; the self-host fixpoint is unchanged
(comments don't affect the compiled seed).

Delete five files that were Janet-host shims with no Chez path: clojure.java.io
(provided natively by host/chez/io.ss), and jolt.{nrepl,png,interop,shell}
(the janet.* bridge, os/shell, janet.net — none exist on Chez).

jolt-cf1q.6
This commit is contained in:
Yogthos 2026-06-21 12:01:04 -04:00
parent 750ce05716
commit 48e2ef5910
53 changed files with 418 additions and 675 deletions

View file

@ -3,7 +3,7 @@
;; No mature Chez fibers library exists, and this Chez is a threaded build, so a
;; `go` block is just an OS thread and a channel is a mutex+condition blocking
;; queue: <! / >! are the blocking <!! / >!! (they "park" by blocking the thread).
;; Like the Janet stackful-fiber model, <! / >! work ANYWHERE (no CPS transform) —
;; <! / >! work ANYWHERE (no CPS transform) —
;; here because they are ordinary blocking calls. Real parallelism, shared heap.
;; Trade-off: one OS thread per go block (fine for typical use / conformance, not
;; for thousands of simultaneous go blocks).
@ -13,7 +13,7 @@
;; buffers never block the putter. A transducer is applied on the put side.
;;
;; The fns are def-var!'d into clojure.core.async; go/go-loop/thread are macros
;; (mark-macro!) expanding to go-spawn, mirroring src/jolt/async.janet. Loaded after
;; (mark-macro!) expanding to go-spawn. Loaded after
;; concurrency.ss (reuses ms->duration). Requires a threaded Chez build.
;; --- buffers ----------------------------------------------------------------
@ -49,7 +49,7 @@
;; A transducer is a jolt fn (xform); (xform add-rf) yields the channel's reducing
;; fn. add-rf: 0-arg init, 1-arg completion, 2-arg step (enqueue the output). A
;; `reduced` step result closes the channel. Mirrors async.janet make-add-rf.
;; `reduced` step result closes the channel.
(define (ac-make-add-rf ch)
(lambda args
(cond ((null? args) ch) ; init
@ -135,8 +135,8 @@
(else ac-poll-empty))))
;; (alts! [ch ...]) — take from whichever channel is ready first; returns
;; [value channel] (value nil if that channel closed). Take-only (like the Janet
;; impl). Polls with a 1ms backoff — no cross-channel wait-set yet.
;; [value channel] (value nil if that channel closed). Take-only.
;; Polls with a 1ms backoff — no cross-channel wait-set yet.
(define ac-1ms (make-time 'time-duration 1000000 0))
(define (jolt-async-alts chans)
(let ((cs (seq->list (jolt-seq chans))))

View file

@ -1,7 +1,7 @@
;; atoms (jolt-9ziu) — host-coupled mutable reference cells for the Chez host.
;;
;; atom/deref/swap!/reset! stay in the Janet seed (not the clojure.core overlay),
;; so the Chez runtime needs native shims, def-var!'d into clojure.core. They
;; atom/deref/swap!/reset! are host primitives (not the clojure.core overlay),
;; so the Chez runtime provides native shims, def-var!'d into clojure.core. They
;; lower to var-deref in prelude mode. The hierarchy machinery
;; (global-hierarchy = (atom (make-hierarchy))) calls `atom` at the prelude's
;; LOAD time, so without this shim the whole prelude fails to load.
@ -42,7 +42,7 @@
(error #f "Invalid reference state"))))
;; notify each watch (k ref old new), in insertion order (alist is reverse-built,
;; so walk it reversed to match add order — matches the seed's :pairs iteration).
;; so walk it reversed to match add order).
(define (jolt-atom-notify a old new)
(for-each (lambda (kv) (jolt-invoke (cdr kv) (car kv) a old new))
(reverse (jolt-atom-watches a))))
@ -65,7 +65,7 @@
;; (swap! a f arg*): JVM-style CAS loop — read, compute f OUTSIDE the lock, then
;; atomically compare-and-set; retry if another thread changed it. Validate the
;; new value before storing, notify watches after (the seed order).
;; new value before storing, notify watches after.
(define (jolt-swap! a f . args)
(let retry ()
(let* ((old (jolt-atom-val a))

View file

@ -6,7 +6,7 @@
;; compiler image from the .clj/.ss sources using the ON-CHEZ compiler (emit-image.ss),
;; writing fresh artifacts. No Janet is invoked: read -> analyze -> emit all run on
;; Chez. The seed is a JOINT fixpoint, so a rebuild from an up-to-date seed
;; reproduces it byte-for-byte (test/chez/bootstrap-test.janet checks this); when
;; reproduces it byte-for-byte (`make selfhost` checks this); when
;; the sources change, run it twice to reconverge and re-mint the seed.
;;
;; Run from the repo root:

View file

@ -205,7 +205,7 @@
((pset? coll) (pset-conj coll x))
;; a list/seq conjs by PREPENDING (seq.ss: cseq / empty-list). conj onto a
;; list stays a list, conj onto a lazy/realized seq yields a seq cell (a
;; Cons) — list?-preserving, matching the seed.
;; Cons) — list?-preserving.
((cseq? coll) (if (cseq-list? coll) (cseq-list x coll) (cseq-realized x coll)))
((empty-list-t? coll) (cseq-list x jolt-nil))
((pmap? coll)

View file

@ -115,7 +115,7 @@
(loop (cdr fs) (jolt-compile-eval-form (car fs) ns)))))
;; runtime defmacro: def the expander fn + mark the var a macro so subsequent
;; forms expand it (hc-macro? reads var-macro-table). Mirrors emit-image.ss
;; ei-emit-ns and the Janet seed eval-defmacro.
;; ei-emit-ns.
((ce-macro-form? form)
(let-values (((nm fn-form) (ce-defmacro->fn form)))
(def-var! ns nm (jolt-compile-eval-form fn-form ns))
@ -132,7 +132,7 @@
;; clojure.core/load-string: read every form from the source string and compile+
;; eval each in the current ns, returning the last value (nil for blank input).
;; Mirrors src/jolt/api.janet load-string (the parse-next loop). jolt-r8ku.
;; jolt-r8ku.
(define (jolt-load-string s)
(let loop ((src s) (result jolt-nil))
(let ((pn (jolt-parse-next src)))

View file

@ -45,7 +45,7 @@
(cond
((jolt-nil? a) jolt-nil)
((keyword? a) a)
;; a 1-arg string splits on the FIRST "/" into ns/name, like the seed
;; a 1-arg string splits on the FIRST "/" into ns/name:
;; (keyword "x/y") => :x/y with ns "x" — destructure's {:keys [x/y]} builds
;; the key this way, so without the split the namespaced key never matches.
((string? a)
@ -79,7 +79,7 @@
((= (length args) 2) (jolt-symbol (car args) (cadr args)))
(else (error #f "symbol: wrong arity"))))
;; gensym: per-process counter, like the seed's gensym_counter.
;; gensym: per-process counter.
(define jolt-gensym-counter 0)
(define (jolt-gensym . prefix)
(let ((p (if (null? prefix) "G__" (car prefix))))

View file

@ -3,11 +3,11 @@
;; to a :host-call; the Chez emit routes a non-shimmed :host-call through
;; record-method-dispatch. This file extends that dispatcher with the collection
;; arms the interpreter's dispatch-member covers but the record/string base does
;; not, mirroring src/jolt/interop/collections.janet precedence exactly:
;; not, with this precedence:
;;
;; * collection interop wins first — count/seq/nth/get/valAt/containsKey on a
;; vector/map/set/seq/record (so (. {:count 9} count) is the entry count, 1,
;; like the seed, NOT the :count field).
;; NOT the :count field).
;; * field access — a "-name" member reads the field (records and maps).
;; * map member — a stored fn is a method (called with self + args); any
;; other value is returned as a field.
@ -20,7 +20,7 @@
(define %dot-rmd record-method-dispatch)
;; Vectors / maps / sets only (records are jolt-map? here). Raw seqs are excluded:
;; the seed's coll-interop accepts some seq representations and not others (a
;; coll-interop accepts some seq representations and not others (a
;; plain (seq v) returns nil from .count, a lazy-seq returns the count), an
;; inconsistency Chez's normalized cseq can't mirror — so a raw seq target falls
;; through to the base dispatcher rather than risk a divergence the corpus would
@ -40,7 +40,7 @@
((string=? name "containsKey") (list (jolt-contains? obj (car args))))
(else #f)))
;; Mirror the seed's universal object-methods (src/jolt/eval_resolve.janet): on a
;; Universal object-methods: on a
;; non-record map these win OVER a field lookup, like dispatch-member. getMessage
;; on an ex-info reads its :message (the one the corpus exercises); getCause reads
;; :cause; toString/hashCode/equals round out the set. Returns a boxed result or

View file

@ -9,7 +9,7 @@
;; The binding macro builds a frame as a jolt map (array-map of (var x) -> value);
;; push-thread-bindings folds it into the alist. Lookups walk frames by cell
;; IDENTITY (eq?) — vars are interned, so (var x) always yields the same cell, and
;; this sidesteps the seed's persistent-hash-map-can't-find-a-var-key quirk.
;; this sidesteps a persistent-hash-map-can't-find-a-var-key quirk.
;;
;; var reads (var-deref in compiled code, jolt-var-get / deref on a cell) consult
;; the stack before falling back to the cell root. Loaded LAST (after vars.ss and

View file

@ -1,9 +1,6 @@
;; emit-image.ss (jolt-cf1q.4 inc8) — the on-Chez compiler-image emitter.
;;
;; This is the stage2/stage3 half of the self-hosting fixpoint. driver.janet's
;; emit-compiler-image cross-compiles the compiler sources (jolt.ir +
;; jolt.analyzer + jolt.backend-scheme) to a Scheme def-var! image USING THE JANET
;; analyzer/emitter — that is stage1. This file does the SAME job but the
;; This is the stage2/stage3 half of the self-hosting fixpoint. The
;; analyze->emit runs ON CHEZ (jolt-ce-analyze / jolt-ce-emit, loaded from a
;; previously-built image): feed it stage1's image and it produces stage2; feed it
;; stage2 and it produces stage3. stage2 == stage3 byte-for-byte proves the
@ -12,8 +9,8 @@
;; Loaded after compile-eval.ss (needs jolt-ce-analyze/jolt-ce-emit/ce-scan-requires!,
;; make-analyze-ctx) and rt.ss (read-file-string, the reader's rdr-read-form).
;; Read every top-level form from a source string (a Chez read-all). Mirrors the
;; Janet driver's parse-all; uses the same reader the spine reads single forms with.
;; Read every top-level form from a source string (a Chez read-all).
;; Uses the same reader the spine reads single forms with.
(define (ei-read-all src)
(let ((end (string-length src)))
(let loop ((i 0) (acc '()))
@ -23,7 +20,7 @@
(loop j (cons form acc)))))))
;; Is `f` an (ns ...) form? (Its only role in the image is alias registration; we
;; never emit it — the def-var!s carry explicit ns names. Matches driver.janet.)
;; never emit it — the def-var!s carry explicit ns names.)
(define (ei-ns-form? f)
(and (cseq? f) (cseq-list? f)
(let ((items (seq->list f)))
@ -34,7 +31,6 @@
;; ce-defmacro->fn, loaded before this) — shared with the runtime defmacro spine.
;; Cross-compile one namespace's source to a list of guard-wrapped Scheme strings.
;; Mirrors driver.janet emit-ns-forms-list/emit-core-prelude + emit-form-scheme.
;; Each form is analyzed with a fresh ctx — resolution is via the runtime var-table
;; + alias tables, not ctx-accumulated state, so this matches the spine's per-form
;; analyze. A defmacro emits its expander fn as (def-var! ns name <fn>) +
@ -69,19 +65,18 @@
(cons (string-append "(guard (e (#t #f))\n " scm ")") acc)
acc)))))))))
;; Scheme string literal for a ns/name — uses the runtime's own writer so it
;; matches the Janet driver's %j (printable ASCII identifiers only here).
;; Scheme string literal for a ns/name — uses the runtime's own writer
;; (printable ASCII identifiers only here).
(define (ei-str-lit s) (with-output-to-string (lambda () (write s))))
;; The compiler namespaces, in load order — same list as driver.janet
;; compiler-ns-files.
;; The compiler namespaces, in load order.
(define ei-compiler-ns-files
(list (cons "jolt.ir" "jolt-core/jolt/ir.clj")
(cons "jolt.analyzer" "jolt-core/jolt/analyzer.clj")
(cons "jolt.backend-scheme" "jolt-core/jolt/backend_scheme.clj")))
;; The clojure.core tiers + stdlib namespaces, in load order — same lists as
;; driver.janet core-tier-files / stdlib-ns-files. Re-emitting these on Chez is the
;; The clojure.core tiers + stdlib namespaces, in load order.
;; Re-emitting these on Chez is the
;; prelude half of the fixpoint (the whole emitted system reproducing itself).
(define ei-prelude-ns-files
(append
@ -94,8 +89,7 @@
(cons "clojure.set" "src/jolt/clojure/set.clj")
(cons "clojure.pprint" "src/jolt/clojure/pprint.clj"))))
;; Join a list of form strings with "\n", no trailing newline — byte-identical
;; layout to the Janet driver's (string/join out "\n").
;; Join a list of form strings with "\n", no trailing newline.
(define (ei-join forms)
(let join ((fs forms) (out ""))
(cond

View file

@ -1,20 +1,16 @@
;; host class tokens (jolt-13zk) — a bare class name (String, Keyword, File...)
;; evaluates to its JVM canonical-name STRING, the same value (class instance)
;; returns, so (= String (class "x")) holds and a (defmethod m String ...) keys
;; against a (class …) dispatch (ring.util.request does this). Mirrors
;; src/jolt/eval_resolve.janet's class-canonical-names + core_refs.janet's
;; core-class. The analyzer already resolves these names to clojure.core vars (the
;; seed ctx interns them via setup-class-ctors), so the back end emits
;; against a (class …) dispatch (ring.util.request does this).
;; The analyzer resolves these names to clojure.core vars, so the back end emits
;; (var-deref "clojure.core" "String") — def-var!'ing the canonical strings here is
;; all that's needed at runtime. No analyzer change, so the Janet back end is
;; untouched.
;; all that's needed at runtime.
;;
;; Loaded after natives-meta.ss (jolt-type) + the printer (jolt-str-render-one).
;; (class x) — Clojure's class of a value. Scalars map to their JVM class name,
;; matching core-class. Collections/seqs have no JVM class on this host; the seed
;; leaks the Janet host type ("table"/"struct"/"tuple") there, which we don't
;; reproduce (Janet is going away) — (str (type x)) is the clean host taxonomy and
;; matching core-class. Collections/seqs have no JVM class on this host;
;; (str (type x)) is the clean host taxonomy and
;; is never compared against a class token in the corpus. Records yield their
;; ns-qualified class name (= (str (type x))). Total — never crashes.
(define (jolt-class x)

View file

@ -1,7 +1,7 @@
;; host-contract.ss (jolt-hs9n, Phase 3 inc6) — the jolt.host contract on Chez.
;;
;; The portable seam between jolt-core (analyzer/IR/emitter, cross-compiled to
;; Scheme) and the host. Mirrors src/jolt/host_iface.janet's `exports`: every
;; Scheme) and the host. Every
;; contract fn is def-var!'d into the "jolt.host" namespace so the cross-compiled
;; jolt.analyzer / jolt.backend-scheme — whose unqualified form-*/resolve-global/
;; ... refs lower to (var-deref "jolt.host" ...) — resolve here at runtime.
@ -149,8 +149,7 @@
;; def-var! of its cross-compiled expander fn plus (mark-macro! ns name), so the
;; var cell is flagged a macro (rt.ss var-macro-table). form-macro? checks the
;; flag; form-expand-1 applies the expander to the unevaluated arg forms (the rest
;; of the list), and the analyzer re-analyzes the returned form. Mirrors
;; host_iface.janet h-macro?/h-expand-1.
;; of the list), and the analyzer re-analyzes the returned form.
(define (hc-macro? ctx sym)
(macro-var? (hc-resolve-cell ctx sym)))
(define (hc-expand-1 ctx form)
@ -179,7 +178,7 @@
(define (hc-intern! ctx ns-name nm) (declare-var! ns-name nm) jolt-nil)
;; --- syntax-quote lowering (jolt-qjr0, inc7) ---------------------------------
;; Mirrors src/jolt/eval_base.janet syntax-quote-lower/sq-symbol. Lowers a `form
;; Lowers a `form
;; to CONSTRUCTION CODE — Chez reader forms calling __sqcat/__sqvec/__sqmap/
;; __sqset/__sq1 + quote — that the analyzer re-analyzes, so a backtick compiles
;; with zero runtime cost (read -> macroexpand -> compile). Symbols resolve to

View file

@ -2,11 +2,11 @@
;;
;; The analyzer lowers `Class/member` to a :host-static node and `(Class. ...)` /
;; `(new Class ...)` to a :host-new node (jolt-core/jolt/analyzer.clj); the Chez
;; emit (emit.janet) lowers a value ref to (host-static-ref "Class" "member"), a
;; emit lowers a value ref to (host-static-ref "Class" "member"), a
;; call head to (host-static-call "Class" "member" args...), and a constructor to
;; (host-new "Class" args...). This file is the runtime registry those three
;; resolve against — the Chez port of the seed's class-statics / class-ctors /
;; tagged-methods registries (src/jolt/interop/java_base.janet + host_io.janet),
;; resolve against — the class-statics / class-ctors /
;; tagged-methods registries,
;; restricted to the java.lang/util/net/io surface portable cljc code calls.
;; (java.time formatting is a separate increment.)
;;
@ -111,7 +111,7 @@
;; numeric tower (jolt-n6al): currentTimeMillis/nanoTime are exact longs (JVM).
(define (->num x) x)
(define (jnum->exact n) (exact (truncate n)))
;; parse an integer string in radix; #f on failure (matches the seed's scan-number)
;; parse an integer string in radix; #f on failure
(define (parse-int-str s radix)
(let ((n (string->number (str-trim (if (string? s) s (jolt-str-render-one s))) radix)))
(and n (integer? n) (->num n))))
@ -488,7 +488,7 @@
(if (regex-t? obj)
(let ((rest (if (jolt-nil? rest-args) '() (seq->list rest-args))))
(cond ((string=? method-name "split")
;; .split returns a String[] — a seq, like the seed's array (prints
;; .split returns a String[] — a seq (prints
;; (a b c), not a vector). re-split with no limit; drop trailing
;; empties (JVM default).
(let ((parts (re-split (regex-t-irx obj) (car rest) #f)))

View file

@ -11,7 +11,7 @@
;; these — a red-black tree + :ops table travel inside the htable.
;; 2. a sorted-coll arm on the collection dispatchers, set!-extended the same
;; way records.ss extends them for jrec: each op routes through the value's
;; own :ops table (the seed's dispatch pattern, core_coll.janet). first/rest/
;; own :ops table (the dispatch pattern). first/rest/
;; next/last fall out free once jolt-seq has a sorted arm (they seq first).
;;
;; Loaded LAST (after records.ss / transients.ss / natives-meta.ss): it wraps the
@ -118,7 +118,7 @@
(def-var! "clojure.core" "coll?" (lambda (x) (or (htable-sorted? x) (jrec? x) (jolt-coll-pred? x))))
;; --- equality / hash ---------------------------------------------------------
;; A sorted coll canonicalizes like its unordered counterpart (core_types.janet):
;; A sorted coll canonicalizes like its unordered counterpart:
;; a sorted-map equals ANY map (hash or sorted) with the same entries, a
;; sorted-set ANY set with the same elements — the comparator is irrelevant to =.
;; Convert to the plain persistent coll and delegate to the prior jolt=2 / hash.
@ -140,8 +140,8 @@
;; --- printing ----------------------------------------------------------------
;; sorted colls render in SORTED order (the value's :seq), not HAMT order — and
;; a sorted-map prints "{k v, k v}" (", " between pairs) like the seed's
;; pr-render-pairs, NOT the space-only form the unordered pmap arm uses.
;; a sorted-map prints "{k v, k v}" (", " between pairs),
;; NOT the space-only form the unordered pmap arm uses.
(define (sorted-map-render sc render)
(string-append "{"
(let loop ((es (seq->list (sc-call sc kw-op-seq))) (first #t) (acc ""))

View file

@ -3,13 +3,12 @@
;; A #inst literal lowers (analyzer :inst node -> emit) to (jolt-inst-from-string
;; "…"); this file parses the RFC3339 string to epoch-ms and models the value as a
;; `jinst` record (one flonum field, ms). Equality / map-key hashing are by the
;; INSTANT (offset-normalized), matching the seed (types_ctx.janet parse-inst /
;; inst->rfc3339). The overlay inst?/inst-ms read (get x :jolt/type)/(get x :ms),
;; INSTANT (offset-normalized). The overlay inst?/inst-ms read (get x :jolt/type)/(get x :ms),
;; so jolt-get answers those off a jinst — the overlay fns then work unchanged.
;;
;; The java.time surface (DateTimeFormatter/Instant/ZoneId/LocalDateTime/
;; FormatStyle/Locale + the .format/.atZone/.toInstant/… methods) is the Chez port
;; of java_base.janet, registered through host-static.ss's class-statics / host-
;; FormatStyle/Locale + the .format/.atZone/.toInstant/… methods) is
;; registered through host-static.ss's class-statics / host-
;; methods registries — so this loads LAST in rt.ss, after host-static.ss and io.ss.
;; --- civil <-> days since the Unix epoch (Howard Hinnant's algorithms) -------
@ -113,7 +112,7 @@
"T" (pad2 (list-ref f 3)) ":" (pad2 (list-ref f 4)) ":" (pad2 (list-ref f 5))
"." (pad3 (list-ref f 6)) "-00:00")))
;; --- DateTimeFormatter pattern engine (port of java_base.janet format-ms) -----
;; --- DateTimeFormatter pattern engine -----
(define month-names (vector "January" "February" "March" "April" "May" "June" "July"
"August" "September" "October" "November" "December"))
(define day-names (vector "Sunday" "Monday" "Tuesday" "Wednesday" "Thursday" "Friday" "Saturday"))

View file

@ -1,12 +1,11 @@
;; java.io.File + host file I/O (jolt-yyud). The seed's clojure.java.io (io.clj)
;; is a Janet-backed shim (janet.*/janet.file) — not reusable here, so this is a
;; java.io.File + host file I/O (jolt-yyud). A
;; Chez-native implementation over Chez's filesystem primitives. A File is a
;; path-backed jfile record: (instance? java.io.File f) is true, str/slurp coerce
;; it to its path, and the File method surface (getName/getPath/exists/
;; isDirectory/isFile/listFiles) dispatches through record-method-dispatch.
;;
;; Mirrors src/jolt/core_io.janet (core-make-file/file?/slurp/spit/flush/dir?/
;; list-dir) and the overlay file-seq (20-coll.clj), which calls __file?/__dir?/
;; Provides make-file/file?/slurp/spit/flush/dir?/
;; list-dir for the overlay file-seq (20-coll.clj), which calls __file?/__dir?/
;; __list-dir + the .isDirectory/.listFiles/.isFile method surface.
;;
;; Reader/StringReader-coupled io (io/reader, line-seq over a file, .toURL,
@ -47,7 +46,7 @@
;; --- java.net.URL (a jhost "url", state #(spec)) ----------------------------
;; A File.toURL value: .toString / .toExternalForm give the spec, .getPath /
;; .getFile strip the "file:" scheme. (Mirrors host_io.janet's :jolt/url.)
;; .getFile strip the "file:" scheme.
(define (make-url spec) (make-jhost "url" (vector spec)))
(define (url-spec u) (vector-ref (jhost-state u) 0))
(define (url-strip-scheme spec)
@ -91,7 +90,7 @@
(%io-rmd obj method-name rest-args))))
;; .isDirectory / .listFiles emit to jolt-host-call (rt.ss), not record-method-
;; dispatch (emit.janet supported-host-methods) — the Phase-1 shims there assume a
;; dispatch — the Phase-1 shims there assume a
;; path STRING target. Make them jfile-aware so file-seq's File branch works.
(define %io-host-call jolt-host-call)
(set! jolt-host-call
@ -171,7 +170,7 @@
(set! jolt-str-render-one
(lambda (v) (if (jfile? v) (jfile-path v) (%io-str-render v))))
;; (type f) -> :jolt/file, matching the seed's tagged-file :jolt/type. Re-def-var!
;; (type f) -> :jolt/file (the tagged-file :jolt/type). Re-def-var!
;; "type": natives-meta.ss already bound the var to the old jolt-type value, so the
;; set! alone (which updates the symbol for internal callers) wouldn't reach it.
(define io-kw-file (keyword "jolt" "file"))
@ -192,7 +191,7 @@
(%io-instance-check type-sym val)))))
(def-var! "clojure.core" "instance-check" instance-check)
;; --- def-var! the seed-native names the overlay file-seq + str/slurp use ----
;; --- def-var! the native names the overlay file-seq + str/slurp use ----
(def-var! "clojure.core" "__make-file" jolt-make-file)
(def-var! "clojure.core" "__file?" jolt-file?)
(def-var! "clojure.core" "__dir?" jolt-dir?)
@ -202,8 +201,8 @@
(def-var! "clojure.core" "flush" jolt-flush)
;; --- char-array: a seq of chars over a string (the JVM char[]). io/reader's
;; char[] branch + selmer's (char-array template) feed on this. Mirrors the seed
;; core-char-array (string -> chars). A leaf array native; lives here as io/reader
;; char[] branch + selmer's (char-array template) feed on this.
;; char-array (string -> chars). A leaf array native; lives here as io/reader
;; is its only Chez consumer so far.
(define (jolt-char-array a . rest)
(cond
@ -215,7 +214,7 @@
;; --- with-open's close seam (__close): a map-like value closes via its :close
;; fn; a jhost reader/writer/file via its .close method (a no-op here); anything
;; else is an error. Mirrors core_extra.janet core-close-resource.
;; else is an error.
(define (jolt-close x)
(cond
((jolt-nil? x) jolt-nil)

View file

@ -2,8 +2,8 @@
;;
;; The `lazy-seq` macro (00-syntax.clj) expands to
;; (make-lazy-seq (fn* [] (coll->cells (do body))))
;; and `lazy-cat` to (concat (lazy-seq c) ...). make-lazy-seq / coll->cells are
;; seed natives (src/jolt/lazyseq.janet) with no Chez shim, so EVERY overlay fn
;; and `lazy-cat` to (concat (lazy-seq c) ...). make-lazy-seq / coll->cells had
;; no Chez shim, so EVERY overlay fn
;; built on lazy-seq — repeat / iterate / cycle / dedupe / take-nth / keep /
;; interpose / reductions / tree-seq (-> flatten) / lazy-cat — resolved the call
;; to jolt-nil and hit the apply-jolt-nil crash bucket.

View file

@ -1,15 +1,14 @@
;; clojure.math (jolt-22vo) — Chez host shim over native flonum math.
;;
;; On the Janet seed clojure.math is registered as native math/ bindings
;; (api.janet install-clojure-math!, jolt-h79), NOT a .clj file — so there's no
;; source tier to emit. Chez provides its own def-var! shims here, one per
;; clojure.math fn, over Chez's native procedures. The analyzer already knows the
;; clojure.math ns exists (init interns the same fns on the Janet side), so a ref
;; clojure.math is registered as native bindings (jolt-h79), NOT a .clj file — so
;; there's no source tier to emit. Chez provides its own def-var! shims here, one per
;; clojure.math fn, over Chez's native procedures. The analyzer knows the
;; clojure.math ns exists, so a ref
;; like clojure.math/sqrt lowers to a var-deref; these cells back it at runtime.
;;
;; jolt is all-flonum, so every result is a flonum (inputs arrive as flonums; Chez
;; sqrt/sin/expt/... return flonums for flonum args). Semantics match the seed
;; (Clojure 1.11 clojure.math): round = floor(x+0.5), rint = round-half-even,
;; sqrt/sin/expt/... return flonums for flonum args). Semantics match
;; Clojure 1.11 clojure.math: round = floor(x+0.5), rint = round-half-even,
;; floor/ceil/floor-div return doubles, to-degrees/to-radians via PI.
(define jolt-math-pi (acos -1.0))

View file

@ -2,8 +2,8 @@
;;
;; defmulti/defmethod are macros that expand to ctx-capturing setup CALLS
;; (defmulti-setup / defmethod-setup, + the table ops get-method/methods/
;; remove-method/prefer-method/prefers). The Janet seed implements these against
;; the evaluator's ns/var machinery (eval_runtime.janet); this is the Chez port.
;; remove-method/prefer-method/prefers), implemented here against
;; the runtime's ns/var machinery.
;;
;; A multimethod VALUE is a jolt-multifn record carrying its dispatch fn and a
;; mutable method table (dispatch-val -> method fn, keyed with jolt= so keyword/

View file

@ -3,8 +3,7 @@
;; A jolt-array wraps a Chez mutable vector + a `kind` tag (for bytes?). The array
;; CONSTRUCTORS are native (they build the backing); the overlay's aget/aset/alength
;; are pure over count / nth / jolt.host/ref-put!, so we extend those dispatchers
;; to see a jolt-array. Mirrors src/jolt/core_refs.janet (Janet uses its mutable
;; arrays/buffers; here a Chez vector). Loaded after host-table.ss (ref-put!),
;; to see a jolt-array (backed by a Chez vector). Loaded after host-table.ss (ref-put!),
;; transients.ss, seq.ss (the dispatchers it chains).
(define-record-type jolt-array (fields (mutable vec) kind) (nongenerative jolt-array-v1))

View file

@ -1,12 +1,10 @@
;; Collection constructors + rand (jolt-cf1q.3 Phase 2 inc A) — host-coupled seed
;; Collection constructors + rand (jolt-cf1q.3 Phase 2 inc A) — host-coupled
;; natives the overlay assumes as bare clojure.core vars but which were never
;; def-var!'d, so they resolved to jolt-nil and any call hit the apply-jolt-nil
;; crash bucket. The persistent-collection constructors already exist in
;; collections.ss (jolt-hash-map / jolt-hash-set / jolt-vector); this just binds
;; the public clojure.core names to them. Loaded after def-var! (rt.ss) + the
;; collections + seq tiers. Semantics match the Janet seed (core_coll.janet
;; core-hash-map/core-array-map/core-hash-set/core-set, core_types.janet
;; core-rand).
;; collections + seq tiers. hash-map/array-map/hash-set/set/rand semantics.
;; hash-map / hash-set: variadic kvs / elems straight onto the existing ctors.
;; array-map: Clojure preserves insertion order, but jolt's `=` is structural and

View file

@ -47,8 +47,8 @@
;; (type x) — Clojure's (or (:type (meta x)) (class x)). With no JVM classes the
;; "class" is a host taxonomy: a record yields its ns-qualified class-name SYMBOL
;; (user.TyR), everything else a keyword (:number/:vector/:seq/…). Mirrors the
;; seed's core-type (src/jolt/core_io.janet). MUST be total — a non-record value
;; (user.TyR), everything else a keyword (:number/:vector/:seq/…).
;; MUST be total — a non-record value
;; falling through to a crash would read as a divergence, not the right keyword.
;; Forward refs (jolt-lazyseq?, the sorted-htable / wrapper predicates) all bind by
;; call time (every host .ss loads before any user expr runs).
@ -89,7 +89,7 @@
((keyword? x) ty-keyword)
((symbol-t? x) ty-symbol)
((char? x) ty-char)
;; host wrappers — match the seed's :jolt/* tags (checked before the
;; host wrappers — keyed by their :jolt/* tags (checked before the
;; collection arms; none of these are pvec/pmap/pset).
((jolt-atom? x) ty-atom)
((jvol? x) ty-volatile)
@ -99,7 +99,7 @@
((juuid? x) ty-uuid)
((htable-sorted-set? x) ty-sorted-set)
((htable-sorted-map? x) ty-map)
;; collections — pvec INCLUDES map entries (:vector, like the seed's jvec?).
;; collections — pvec INCLUDES map entries (:vector).
((pvec? x) ty-vector)
((pmap? x) ; a :jolt/type-tagged map (ex-info) -> its tag
(let ((t (jolt-get x ty-kw-jtype jolt-nil))) (if (jolt-nil? t) ty-map t)))

View file

@ -26,7 +26,7 @@
(loop (fx+ i 1)))))))
(define (jolt-random-uuid) (make-juuid (random-uuid-str)))
;; #uuid literal -> a uuid value (emit.janet lowers the :uuid node to this). The
;; #uuid literal -> a uuid value (the emitter lowers the :uuid node to this). The
;; reader already validated the shape; lowercase for value equality.
(define (jolt-uuid-from-string s) (make-juuid (string-downcase s)))

View file

@ -1,7 +1,7 @@
;; bit ops + string->number parsers (jolt-cf1q.3 Phase 2 inc C) — host-coupled
;; seed natives (core_refs.janet bit family, core_io.janet parse-long/double) that
;; natives (bit family, parse-long/double) that
;; resolved to jolt-nil. jolt models every number as a double, so bit ops coerce
;; to an exact integer, operate, and return a flonum. parse-* match the seed's
;; to an exact integer, operate, and return a flonum. parse-* use
;; strict shapes (Clojure 1.11: nil on malformed, throw on a non-string).
;; bit ops return EXACT integers (= JVM long). ->int coerces the operand.

View file

@ -1,11 +1,10 @@
;; natives-parity.ss (jolt-cf1q.7) — native Chez shims for clojure.core fns that
;; live in the Janet seed (src/jolt/core*.janet) but had no Chez shim, so on the
;; zero-Janet spine they resolved to nil ("not a fn"). Pure-Chez, JVM-matching.
;; had no Chez shim, so they resolved to nil ("not a fn"). Pure-Chez, JVM-matching.
;;
;; Loaded after host-table.ss (htable-sorted?), transients.ss (jolt-transient?),
;; values.ss (jolt-hash), seq.ss (jolt-seq/seq->list/list->cseq/jolt-invoke).
;; --- hash family (mirrors core_extra.janet: 24-bit masked so int? holds) ------
;; --- hash family (24-bit masked so int? holds) ------
(define (np-h24 x) (bitwise-and (jolt-hash x) #xffffff))
(define (np-hash x) (np-h24 x))
(define (np-hash-combine a b)
@ -26,7 +25,7 @@
(list->cseq (reverse (seq->list (jolt-seq coll))))
(jolt-throw (jolt-ex-info "rseq requires a vector or sorted collection" (jolt-hash-map)))))
;; --- cat transducer (mirrors core_refs.janet core-cat): each item of the input
;; --- cat transducer: each item of the input
;; is itself a collection, concatenated into the downstream reducing fn.
(define (np-cat rf)
(lambda a

View file

@ -1,6 +1,6 @@
;; seq-native shims (jolt-y6mv) — seed-native seq fns the overlay assumes are
;; clojure.core natives but which live in the Janet seed (src/jolt/core_coll.janet),
;; so they have no def-var! in the assembled prelude and resolve to jolt-nil on
;; seq-native shims (jolt-y6mv) — native seq fns the overlay assumes are
;; clojure.core natives but which have no def-var! in the assembled prelude and
;; resolve to jolt-nil on
;; Chez. This was the dominant prelude-parity crash bucket ('apply jolt-nil').
;; Each is a pure fn over the existing seq layer (seq.ss) — collection arities
;; only; the 1-arg transducer arities are jolt-kxsr. Loaded last (after
@ -16,8 +16,7 @@
;; ============================================================================
;; transducers (jolt-kxsr) — the 1-arg arity of map/filter/take/... returns a
;; transducer (fn [rf] rf') where rf' is a reducing fn with arities
;; []=init, [acc]=complete, [acc x]=step. Ported from the seed's td-* factories
;; (core_coll.janet). rf and the mapping/predicate fns are jolt values, so every
;; []=init, [acc]=complete, [acc x]=step. rf and the mapping/predicate fns are jolt values, so every
;; call routes through jolt-invoke. A `reduced` step stops the fold — reduce-seq
;; (seq.ss) already short-circuits on a jolt-reduced.
;; ============================================================================
@ -181,9 +180,8 @@
(if (jolt-nil? s) jolt-empty-list
(list->cseq (list-sort less? (seq->list s))))))
;; identical?: jolt reference identity. The seed defines it as (= a b) over its
;; value model (core_types.janet core-identical?), where interned keywords/small
;; values compare equal — so jolt= is the faithful port.
;; identical?: jolt reference identity, defined as (= a b) over the
;; value model, where interned keywords/small values compare equal.
(define (jolt-identical? a b) (jolt= a b))
;; Give the seq.ss native procedures their transducer (1-arg) arity — the emitter

View file

@ -2,7 +2,7 @@
;;
;; (.method s arg*) on a string target lowers to record-method-dispatch (emit.ss),
;; which falls through to jolt-string-method here when the target is a string.
;; Ported from the seed surface (src/jolt/eval_resolve.janet string-methods): the
;; Covers the
;; portable java.lang.String/CharSequence methods cljc libraries actually call.
;; Case mapping is ASCII (the whole engine is byte-oriented), indexOf returns -1
;; on miss as on the JVM, indices come in as flonums, char results are Scheme
@ -11,7 +11,7 @@
;; Loaded from rt.ss AFTER regex.ss (the regex methods reuse jolt-re-pattern /
;; regex-t-irx) and records.ss (which calls jolt-string-method).
;; --- ASCII case mapping (match the seed's byte-oriented string/ascii-*) -------
;; --- ASCII case mapping (byte-oriented) -------
(define (ascii-up-char c)
(if (and (char<=? #\a c) (char<=? c #\z))
(integer->char (fx- (char->integer c) 32)) c))
@ -131,9 +131,9 @@
(else (error #f (string-append "No method " method " for value")))))
;; --- clojure.core str-* primitives (the substrate clojure.string.clj calls) ---
;; clojure.string.clj (src/jolt/clojure/string.clj) is pure Clojure over these
;; seed natives (core.janet core-bindings); def-var!'d here so the emitted
;; clojure.string prelude tier's var-derefs resolve. Ported from the seed:
;; clojure.string.clj is pure Clojure over these
;; natives; def-var!'d here so the emitted
;; clojure.string prelude tier's var-derefs resolve:
;; string/ascii-* (ASCII), string/find (index or nil), core-str-* (regex|literal).
;; (string/split sep s) -> parts, splitting on each non-overlapping sep.
@ -168,8 +168,8 @@
;; (re-split irx s limit) -> parts, splitting at each match. Keeps interior AND
;; trailing empty strings (the clojure.string wrapper drops trailing for limit 0);
;; a positive limit yields at most `limit` parts (the rest kept unsplit). Mirrors
;; the seed re-split (src/jolt/regex.janet); the clojure.string.clj split wrapper
;; a positive limit yields at most `limit` parts (the rest kept unsplit).
;; The clojure.string.clj split wrapper
;; layers the trailing-empty trim on top.
(define (re-split irx s limit)
(let ((len (string-length s)))
@ -224,14 +224,14 @@
;; One match's replacement text. A string gets $N expansion; a fn (jolt closure)
;; is called with the match result (whole string, or [whole g1 ...] when grouped)
;; and its result stringified (mirrors the seed replacement-for).
;; and its result stringified.
(define (replacement-text replacement m)
(cond
((string? replacement) (expand-dollar replacement m))
((procedure? replacement) (jolt-str-render-one (jolt-invoke replacement (irx-result m))))
(else (jolt-str-render-one replacement))))
;; regex replace, first or all matches. Mirrors the seed re-replace-all/first.
;; regex replace, first or all matches.
(define (re-replace irx s replacement all?)
(let ((len (string-length s)))
(let loop ((start 0) (last 0) (acc '()))

View file

@ -1,16 +1,16 @@
;; type predicates + simple accessors (jolt-9ziu) — host-coupled seed natives.
;; type predicates + simple accessors (jolt-9ziu) — host-coupled natives.
;;
;; These are seed primitives (not clojure.core overlay fns), so they're never
;; def-var!'d by the assembled prelude; the Chez host must provide them. Semantics
;; match the Janet seed (src/jolt/core_types.janet): map?/vector?/set? are STRICT
;; These are host primitives (not clojure.core overlay fns), so they're never
;; def-var!'d by the assembled prelude; the Chez host must provide them.
;; map?/vector?/set? are STRICT
;; over the persistent-collection records, seq? is true only for real sequences,
;; coll? is the union. Records (shape-recs) are Phase 2, so the record arms of the
;; seed predicates are simply absent here for now.
;; predicates are simply absent here for now.
(define (jolt-map? x) (pmap? x))
;; a map entry is a pvec under the hood AND is vector? — Clojure's MapEntry
;; implements IPersistentVector, so (vector? (first {:a 1})) is true (the seed
;; agrees; jolt-75sv corrected the earlier exclusion).
;; implements IPersistentVector, so (vector? (first {:a 1})) is true
;; (jolt-75sv corrected the earlier exclusion).
(define (jolt-vector? x) (pvec? x))
(define (jolt-set? x) (pset? x))
(define (jolt-seq? x) (or (cseq? x) (empty-list-t? x)))

View file

@ -33,8 +33,8 @@
((and (flonum? x) (fl= x +inf.0)) "Infinity")
((and (flonum? x) (fl= x -inf.0)) "-Infinity")
((and (flonum? x) (not (fl= x x))) "NaN")
;; transients print as a cold tagged type (the seed routes this through a
;; print-method multimethod; the readable fallback renders it directly).
;; transients print as a cold tagged type (print-method routes this through a
;; multimethod; the readable fallback renders it directly).
;; forward refs to transients.ss (loaded later) — resolved at call time.
((jolt-transient? x)
(if (pvec? (jolt-transient-coll x)) "#<transient vector>" "#<transient map>"))

View file

@ -1,16 +1,16 @@
;; Chez-side Clojure data reader (jolt-r8ku, inc Y).
;;
;; The data half of runtime read/eval: a recursive-descent reader that parses
;; ONE Clojure form off a string and produces the same jolt runtime values the
;; Janet reader's parse-next yields (the analyzer/eval half — eval, load-string,
;; ONE Clojure form off a string and produces jolt runtime values
;; (the analyzer/eval half — eval, load-string,
;; runtime defmacro — stays Phase-3, it needs the compiler at runtime). Two host
;; seams hang off it, matching the Janet seed (eval_runtime.janet):
;; seams hang off it:
;; read-string : string -> first form (clojure.core seam, src 772)
;; __parse-next : string -> [form rest] | nil (the *in* family seam, src 801)
;; read / read+string / with-in-str / line-seq / clojure.edn are Clojure over
;; these (jolt-core/clojure/core/50-io.clj, src/jolt/clojure/edn.clj).
;;
;; Form shapes are pinned to the Janet reader's output (probed against build/jolt):
;; Form shapes:
;; sets -> {:jolt/type :jolt/set :value [...]} (a FORM, not a set)
;; #tag frm -> {:jolt/type :jolt/tagged :tag :#tag :form ...} (NO data reader)
;; #"src" -> {:jolt/type :jolt/tagged :tag :regex :form "src"}
@ -61,7 +61,7 @@
;; --- numbers ----------------------------------------------------------------
;; A token is a number iff it (after an optional sign) starts with a digit and
;; parses. Ratios and big-N/M decimals follow the seed's all-double rendering
;; parses. Ratios and big-N/M decimals use all-double rendering
;; for division; ints/bignums stay exact (Chez's tower IS Clojure's).
(define (rdr-string-index-char str c)
(let ((n (string-length str)))
@ -287,10 +287,10 @@
(make-symbol-t (symbol-t-ns target) (symbol-t-name target)
(rdr-merge-meta (symbol-t-meta target) meta))
;; non-symbol target (a collection): lower to a runtime (with-meta form meta)
;; the analyzer compiles like any invoke — same as the Janet reader, so e.g.
;; the analyzer compiles like any invoke, so e.g.
;; (meta ^{:tag :int} [1 2]) and ^:foo {} carry their meta at runtime. The meta
;; pmap doubles as its own map-literal form. Use the BARE `with-meta` symbol
;; (ns #f) to match the Janet reader exactly — the fn/defn macros unwrap a
;; (ns #f) — the fn/defn macros unwrap a
;; (with-meta <arglist-vec> _) return-hint by matching the unqualified head,
;; so a qualified clojure.core/with-meta would slip past them (^bytes [b]).
(jolt-list (jolt-symbol #f "with-meta") target meta)))
@ -299,7 +299,7 @@
;; #(...) anonymous fn shorthand (jolt-qjr0): % -> p1, %N -> pN, %& -> rest. The
;; fixed arity is the MAX positional used (Clojure: #(do %2 %&) -> [p1 p2 & rest]).
;; Param names carry a trailing "#" so a #() inside a syntax-quote still reads them
;; as auto-gensyms. Mirrors src/jolt/reader.janet read-anon-fn.
;; as auto-gensyms.
(define rdr-anon-counter 0)
(define (rdr-anon-gensym)
(set! rdr-anon-counter (+ rdr-anon-counter 1))
@ -427,7 +427,7 @@
;; --- keyword ----------------------------------------------------------------
(define (rdr-read-keyword s i end) ; i points just past the leading ':'
;; ::kw auto-resolves; the seed drops the ns, so skip a second ':'
;; ::kw auto-resolves; drop the ns, so skip a second ':'
(let ((i (if (and (< i end) (char=? (string-ref s i) #\:)) (+ i 1) i)))
(let-values (((tok j) (rdr-read-token s i end)))
(let-values (((ns name) (rdr-sym-parts tok)))
@ -494,7 +494,7 @@
;; --- the two host seams -----------------------------------------------------
;; clojure.core/read-string: first form, or nil for blank / comment-only input
;; (the seed's parse-string wart, matched deliberately).
;; (parse-string wart, matched deliberately).
(define (jolt-read-string s)
(let-values (((form j) (rdr-read-form s 0 (string-length s))))
(if (rdr-eof? form) jolt-nil form)))

View file

@ -1,6 +1,6 @@
;; records + protocols (jolt-cf1q.3 Phase 2 inc D) — the deftype/defrecord +
;; defprotocol/extend-type subsystem. These are ctx-capturing seed natives
;; (eval_runtime.janet) that resolved to jolt-nil on the prelude, so every record
;; defprotocol/extend-type subsystem. These are ctx-capturing natives
;; that resolved to jolt-nil on the prelude, so every record
;; case hit the apply-jolt-nil crash bucket.
;;
;; A record is a `jrec`: a type tag ("ns.Name") + an alist of (kw . val) in
@ -138,7 +138,7 @@
(define (record-tag obj) (and (jrec? obj) (jrec-tag obj)))
;; ---- the seed-native handles the analyzer/overlay call ----------------------
;; ---- the native that handles the analyzer/overlay call ----------------------
;; make-deftype-ctor: (name-sym field-kws field-tags field-muts) -> ctor closure.
;; The tag is baked at definition time in the type's ns (chez-current-ns).
(define (make-deftype-ctor name-sym field-kws . _ignored)
@ -156,7 +156,7 @@
(keyword #f "name") (jolt-symbol jolt-nil name-str)
(keyword #f "methods") methods))
;; register-protocol-methods!: devirt hint in the seed; a no-op for Chez dispatch.
;; register-protocol-methods!: a no-op for Chez dispatch.
(define (register-protocol-methods! proto-name method-names) jolt-nil)
;; register-method: extend-type/extend register an impl. Host type names keep a

View file

@ -1,7 +1,6 @@
;; Phase 1 (jolt-cf1q.2) — regex on Chez via vendored irregex (jolt-i0s3).
;;
;; jolt's seed regex (src/jolt/regex.janet) compiles patterns to Janet's PEG
;; engine; Chez has no regex at all. Rather than re-host that engine, we vendor
;; Chez has no regex at all. We vendor
;; Alex Shinn's irregex (vendor/irregex, BSD) — a portable Scheme regex with
;; PCRE/Java-style STRING patterns — and wrap jolt's re-* surface over it.
;;
@ -14,7 +13,7 @@
;;
;; The re-* fns are def-var!'d into clojure.core so prelude / -e code resolves
;; them at runtime (they're NOT subset native-ops: irregex's Unicode/property-
;; class semantics differ from the seed's byte-PEG approximation, so they stay out
;; class semantics keep them out
;; of the subset-parity corpus). Loaded from rt.ss after def-var! is defined.
;; irregex.scm is portable R[457]RS; two small adaptations for Chez's top level:
@ -35,17 +34,16 @@
(load "vendor/irregex/irregex.scm")
;; Unicode property classes \p{...} (jolt-y1zq): irregex's string syntax has no
;; \p{...}, so translate the ones the seed's byte-PEG maps (src/jolt/regex.janet
;; prop-frag) to ASCII char classes before compiling. ASCII-only — the seed counts
;; UTF-8 high bytes as letters for \p{L}, which a Unicode-char Scheme string can't
;; \p{...}, so translate a fixed set of property names
;; to ASCII char classes before compiling. ASCII-only — \p{L} would need
;; UTF-8 high bytes counted as letters, which a Unicode-char Scheme string can't
;; reproduce byte-for-byte; the corpus tests ASCII inputs, where they agree. An
;; unmapped name is left as-is (irregex errors, as before — no new behavior). The
;; ORIGINAL source is kept for printing; only the compiled pattern is translated.
(define (prop-class name)
(cond
;; L/Alpha: ASCII letters + any non-ASCII codepoint (the seed counts UTF-8 high
;; bytes as letters, so ^\p{L}+$ accepts accented words). N/Z stay ASCII-only,
;; matching the seed's byte-PEG.
;; L/Alpha: ASCII letters + any non-ASCII codepoint (UTF-8 high
;; bytes count as letters, so ^\p{L}+$ accepts accented words). N/Z stay ASCII-only.
((or (string=? name "L") (string=? name "Alpha")) "a-zA-Z\\x80-\\x{10FFFF}")
((string=? name "Lu") "A-Z")
((string=? name "Ll") "a-z")
@ -55,7 +53,7 @@
((string=? name "Pe") ")\\]}")
(else #f)))
;; Tracks whether the cursor is inside a [...] char class: a \p{X} there emits the
;; class CONTENT (the seed inlines it), standalone it emits a wrapping [X]. Escapes
;; class CONTENT (inlined), standalone it emits a wrapping [X]. Escapes
;; (\[, \]) don't toggle the class. \P (negation) only wraps when standalone.
(define (translate-prop-classes src)
(let ((len (string-length src)) (out (open-output-string)))
@ -120,7 +118,7 @@
;; All non-overlapping matches, left to right. Advance past each match end (or by
;; one on a zero-width match). nil when there are no matches (Clojure: seq-able as
;; nil, so (if-let [m (re-seq ...)] ...) works), matching the seed.
;; nil, so (if-let [m (re-seq ...)] ...) works).
(define (jolt-re-seq re s)
(let ((irx (regex-t-irx (jolt-re-pattern re)))
(len (string-length s)))

View file

@ -6,7 +6,7 @@
;; reference reads at call time, so redefinition / mutual recursion work);
;; 2. the rt primitive shims the emitter names (jolt-inc/dec/not) and jolt's
;; number printing (all jolt numbers model Clojure doubles; integer-valued
;; print without a trailing ".0", matching the Janet host).
;; print without a trailing ".0").
;;
;; Emitted programs do `(load "host/chez/rt.ss")`; this loads values.ss in turn.
@ -14,15 +14,15 @@
(load "host/chez/collections.ss")
(load "host/chez/seq.ss")
;; --- rt arithmetic / logic shims (named in emit.janet's native-ops) ----------
;; --- rt arithmetic / logic shims (named in the emitter's native-ops) ----------
(define (jolt-inc x) (+ x 1))
(define (jolt-dec x) (- x 1))
;; jolt `not`: only nil and false are falsey.
(define (jolt-not x) (if (jolt-truthy? x) #f #t))
;; --- exceptions (jolt-vcsl) --------------------------------------------------
;; throw raises the jolt value RAW (no envelope), like the Janet compiled back
;; end; catch (emitted as `guard`) binds it directly. Chez `raise` accepts any
;; throw raises the jolt value RAW (no envelope);
;; catch (emitted as `guard`) binds it directly. Chez `raise` accepts any
;; object, so a thrown number/map/ex-info all work; uncaught -> non-zero exit.
(define (jolt-throw v) (raise v))
;; ex-info builds the tagged map {:jolt/type :jolt/ex-info :message :data :cause}
@ -130,7 +130,7 @@
;; --- jolt number printing ----------------------------------------------------
;; jolt models every number as a Clojure double: integer-valued values print
;; without a ".0" (the Janet host prints (* 1.0 5) as "5", (/ 1 2) as "0.5").
;; without a ".0" ((* 1.0 5) prints as "5", (/ 1 2) as "0.5").
(define (jolt-num->string x)
(cond
;; the -e / element printer renders the infinities and NaN as inf/-inf/nan
@ -144,7 +144,7 @@
;; Program-final-value printer. jolt's `-e` prints in str-style: strings raw (no
;; quotes), chars as `\c`/`\newline`, collections recursively. NOTE: maps/sets
;; render in HAMT-iteration order, which does NOT match the Janet host's order —
;; render in HAMT-iteration order, which is not a stable insertion order —
;; so unordered values are compared via `=` (true/false), not printed form.
;; The full canonical printer is Phase 2.
(define (jolt-str-join strs)
@ -236,7 +236,7 @@
;; and the printer (jolt-str-render-one).
(load "host/chez/host-class.ss")
;; dynamic vars (jolt-9ls5): *clojure-version* / *unchecked-math* constants the seed
;; dynamic vars (jolt-9ls5): *clojure-version* / *unchecked-math* constants the host
;; binds natively. After collections.ss (jolt-hash-map) + def-var!.
(load "host/chez/dynamic-vars.ss")

View file

@ -12,28 +12,14 @@ Both are **generated**, not hand-written. They are checked in because a fresh
checkout must be able to build jolt-on-Chez using only Chez: `host/chez/bootstrap.ss`
loads this seed, then rebuilds the prelude + image from the `.clj`/`.ss` sources via
the on-Chez compiler (read → analyze → emit, all on Chez). The seed is a **joint
byte-fixpoint**: rebuilding from an up-to-date seed reproduces it exactly
(`test/chez/bootstrap-test.janet` verifies this).
Janet was used once, historically, to mint the very first seed (the Janet analyzer/
emitter cross-compiled the sources, then the on-Chez compiler iterated to the
fixpoint — see `test/chez/fixpoint-test.janet`). After that, Janet is never needed
to build or run jolt-on-Chez.
byte-fixpoint**: rebuilding from an up-to-date seed reproduces it exactly.
`make selfhost` (`host/chez/selfcheck.sh`) runs `host/chez/bootstrap.ss` and diffs
the rebuilt artifacts against the checked-in seed.
## Re-minting
When the seed sources change (the core tiers, the compiler namespaces, the host
contract, the reader, `emit-image.ss`), the seed drifts and `bootstrap-test`
fails. Re-mint it:
```janet
(import host/chez/driver :as d)
(import host/chez/jolt-chez :as jc)
(def ctx (d/make-ctx))
(d/mint-chez-seed* (jc/ensure-prelude ctx)
(d/ensure-compiler-image ctx "/tmp/stage1.ss")
"host/chez/seed/prelude.ss"
"host/chez/seed/image.ss")
```
Then commit the refreshed `prelude.ss` / `image.ss`.
contract, the reader, `emit-image.ss`), the seed drifts and `make selfhost`
fails. Re-mint it by running `host/chez/bootstrap.ss` and writing the freshly
rebuilt prelude/image back to `host/chez/seed/prelude.ss` /
`host/chez/seed/image.ss`, then commit the refreshed files.

View file

@ -23,7 +23,7 @@
;; only thing that distinguishes a list from any other realized seq on this host,
;; since one record type backs both (clojure.core/list? — jolt-75sv). The marker
;; lives on the cell, so (rest a-list) / (seq a-vector) / (map …) yield plain seq
;; cells and are not list?, matching the seed.
;; cells and are not list?.
(define-record-type cseq (fields head (mutable tail) (mutable forced?) list?) (nongenerative chez-cseq-v2))
(define (cseq-realized head tail) (make-cseq head tail #t #f)) ; tail already a seq
(define (cseq-lazy head tail-thunk) (make-cseq head tail-thunk #f #f))
@ -84,11 +84,11 @@
;; other (if (next s) ...) loops over a lazy seq ran one step too far.
(let ((s (jolt-seq x))) (if (jolt-nil? s) jolt-nil (jolt-seq (seq-more s)))))
;; Only the HEAD cell carries the list marker — (rest a-list)/(next a-list) return
;; the unmarked tail, so they are seqs and not list?, matching the seed (which
;; makes rest-of-a-list a non-list seq). cons/list/reverse/conj therefore mark
;; the unmarked tail, so they are seqs and not list? (rest-of-a-list is a non-list
;; seq). cons/list/reverse/conj therefore mark
;; just the cell they create.
;;
;; cons always yields a list — (list? (cons x anything)) is true on the seed (cons
;; cons always yields a list — (list? (cons x anything)) is true (cons
;; onto a vector/seq/nil all report list?).
(define (jolt-cons x coll) (cseq-list x (jolt-seq coll)))
;; Scheme list -> a jolt PersistentList: head is a list cell, the tail chain is

View file

@ -1,7 +1,6 @@
;; 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
;; syntax-quote form builders (jolt-r9lm, inc6b). A macro expander whose body was a
;; syntax-quote template (lowered by jolt.host/form-syntax-quote-lower) 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