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:
parent
750ce05716
commit
48e2ef5910
53 changed files with 418 additions and 675 deletions
|
|
@ -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))))
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)))
|
||||
|
|
|
|||
|
|
@ -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))))
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)))
|
||||
|
|
|
|||
|
|
@ -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 ""))
|
||||
|
|
|
|||
|
|
@ -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"))
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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/
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)))
|
||||
|
|
|
|||
|
|
@ -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)))
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 '()))
|
||||
|
|
|
|||
|
|
@ -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)))
|
||||
|
|
|
|||
|
|
@ -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>"))
|
||||
|
|
|
|||
|
|
@ -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)))
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)))
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue