Clean up codebase: rename stdlib layer, strip porting residue, fix tooling
Rename src/jolt -> stdlib (the runtime-loaded layer; jolt-core stays the seed-baked layer) and update the loader / emit-image / doc paths. Drop dead code: the spike/ experiments, the duplicate clojuredocs-export.edn (json moves to tools/), the Janet-era jolt.http binding, and the orphaned persistent_vector.clj whose ns/path didn't even match. Strip porting residue from comments and docstrings across host/chez, jolt-core, stdlib, tests, and docs: internal issue ids, "Phase N" markers, and the "vs Janet" historical exposition, leaving present-tense descriptions and the real JVM-Clojure semantic contrasts. Same pass over the corpus suite labels. The seed is unchanged (docstrings/comments aren't emitted), so the self-host fixpoint and corpus are untouched. Port tools/spec_coverage.py off the dead janet probe to bin/joltc and regenerate coverage.md; drop the dead :host/janet rule from certify.clj and regenerate the conformance profile. Add docs/host-interop.md (the JVM shims and how to register your own host class from a library) and a writing-style note in CLAUDE.md. Stabilize the four racy concurrency corpus cases (future-cancel and agent send/send-off): give the future a sleeping body and the agent a slow action, so cancel reliably catches an in-flight future and deref reliably reads the pre-update snapshot. They certify deterministically now, so drop their :flaky allowlist entries and the orphaned legend.
This commit is contained in:
parent
c18f8087f0
commit
33eff7c7d8
112 changed files with 970 additions and 1621 deletions
|
|
@ -1,12 +1,10 @@
|
|||
;; async.ss (jolt-byjr) — clojure.core.async on real OS threads for the Chez host.
|
||||
;; async.ss — clojure.core.async on real OS threads for the Chez host.
|
||||
;;
|
||||
;; 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
|
||||
;; A `go` block is an OS thread and a channel is a mutex+condition blocking
|
||||
;; queue: <! / >! are the blocking <!! / >!! (they "park" by blocking the thread).
|
||||
;; <! / >! 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).
|
||||
;; <! / >! work ANYWHERE — no CPS transform — because they are ordinary blocking
|
||||
;; calls. Real parallelism, shared heap. Trade-off: one OS thread per go block
|
||||
;; (fine for typical use, not for thousands of simultaneous go blocks).
|
||||
;;
|
||||
;; Channel: an unbuffered channel is a rendezvous (the putter blocks until its
|
||||
;; value is taken); a buffered (chan n) put blocks only when full; dropping/sliding
|
||||
|
|
|
|||
|
|
@ -1,26 +1,24 @@
|
|||
;; atoms (jolt-9ziu) — host-coupled mutable reference cells for the Chez host.
|
||||
;; atoms — host-coupled mutable reference cells for the Chez host.
|
||||
;;
|
||||
;; 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
|
||||
;; so the 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.
|
||||
;;
|
||||
;; compare-and-set!/swap-vals!/reset-vals! are overlay fns over the native kernel
|
||||
;; in the live system; provided here natively too so the Chez host is
|
||||
;; self-sufficient for atoms without the full prelude (the overlay versions, when
|
||||
;; the full prelude loads, override these but compose the same native kernel).
|
||||
;; in the live system; provided here natively too so the host is self-sufficient
|
||||
;; for atoms without the full prelude (the overlay versions, when the full prelude
|
||||
;; loads, override these but compose the same native kernel).
|
||||
|
||||
;; watches is an alist of (key . watch-fn); validator is a jolt fn or jolt-nil.
|
||||
;; The overlay's add-watch/set-validator! drive these via jolt.host/ref-put! on a
|
||||
;; Janet table, which a Chez atom record is not — so the peripheral ops + the
|
||||
;; notify/validate behaviour live natively here, and post-prelude.ss re-asserts
|
||||
;; them over the overlay's def-var! (jolt-mn9o).
|
||||
;; `lock` (jolt-byjr) is a per-atom mutex guarding the read-modify-write critical
|
||||
;; sections, so swap!/reset!/compare-and-set! are atomic under real OS threads
|
||||
;; (futures/go blocks share the heap on Chez). The user fn in swap! runs OUTSIDE
|
||||
;; the lock (a CAS retry loop, like the JVM) so it never deadlocks on re-entrant
|
||||
;; access and a watch/validator can deref the same atom.
|
||||
;; The peripheral ops + the notify/validate behaviour live natively here, and
|
||||
;; post-prelude.ss re-asserts them over the overlay's def-var!.
|
||||
;; `lock` is a per-atom mutex guarding the read-modify-write critical sections,
|
||||
;; so swap!/reset!/compare-and-set! are atomic under real OS threads
|
||||
;; (futures/go blocks share the heap). The user fn in swap! runs OUTSIDE the lock
|
||||
;; (a CAS retry loop, like the JVM) so it never deadlocks on re-entrant access and
|
||||
;; a watch/validator can deref the same atom.
|
||||
(define-record-type jolt-atom
|
||||
(fields (mutable val) (mutable watches) (mutable validator) lock)
|
||||
(nongenerative jolt-atom-v3))
|
||||
|
|
@ -108,7 +106,7 @@
|
|||
(jolt-atom-notify a old v)
|
||||
(jolt-vector old v)))
|
||||
|
||||
;; --- watches / validators (jolt-mn9o) ---------------------------------------
|
||||
;; --- watches / validators ---------------------------------------------------
|
||||
;; add-watch interns (key . fn) (replacing any existing key, keeping order);
|
||||
;; remove-watch drops it; both return the atom. set-validator! installs a
|
||||
;; validator and validates the CURRENT value immediately (Clojure throws if it's
|
||||
|
|
@ -139,7 +137,7 @@
|
|||
(def-var! "clojure.core" "reset-vals!" jolt-reset-vals!)
|
||||
(def-var! "clojure.core" "atom?" jolt-atom?)
|
||||
;; peripheral ops: the overlay (20-coll) re-defs these over jolt.host/ref-put!,
|
||||
;; which fails on a Chez atom record — post-prelude.ss re-asserts the natives.
|
||||
;; which fails on an atom record — post-prelude.ss re-asserts the natives.
|
||||
(def-var! "clojure.core" "add-watch" jolt-add-watch)
|
||||
(def-var! "clojure.core" "remove-watch" jolt-remove-watch)
|
||||
(def-var! "clojure.core" "set-validator!" jolt-set-validator!)
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
;; BigDecimal (jolt-i2jm). A jbigdec is {unscaled, scale} over Chez arbitrary-
|
||||
;; precision exact integers; its value is unscaled * 10^-scale (1.5M = {15,1},
|
||||
;; 1.00M = {100,2}, 3M = {3,0}). M-suffix literals read to a :bigdec form that the
|
||||
;; back end lowers to jolt-bigdec-from-string; bigdec coerces a number/string.
|
||||
;; Equality is by value (1.0M = 1.00M), str drops the M, pr keeps it, class is
|
||||
;; java.math.BigDecimal. Arithmetic contagion is not modelled (jolt-i2jm scope).
|
||||
;; BigDecimal. A jbigdec is {unscaled, scale} over Chez arbitrary-precision exact
|
||||
;; integers; its value is unscaled * 10^-scale (1.5M = {15,1}, 1.00M = {100,2},
|
||||
;; 3M = {3,0}). M-suffix literals read to a :bigdec form that the back end lowers
|
||||
;; to jolt-bigdec-from-string; bigdec coerces a number/string. Equality is by
|
||||
;; value (1.0M = 1.00M), str drops the M, pr keeps it, class is
|
||||
;; java.math.BigDecimal. Arithmetic contagion is not modelled.
|
||||
|
||||
(define-record-type jbigdec (fields unscaled scale) (nongenerative chez-jbigdec-v1))
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
;; bootstrap.ss (jolt-9phg, Phase 3 inc9a) — the pure-Chez self-build.
|
||||
;; bootstrap.ss — the pure-Chez self-build.
|
||||
;;
|
||||
;; This is the zero-Janet build step. Given a SEED (prelude, image) pair — the
|
||||
;; bootstrap compiler, minted once via the inc8 fixpoint and checked in under
|
||||
;; Given a SEED (prelude, image) pair — the bootstrap compiler, checked in under
|
||||
;; host/chez/seed/ — it loads them, then rebuilds the clojure.core prelude AND the
|
||||
;; 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
|
||||
;; compiler image from the .clj/.ss sources using the on-Chez compiler
|
||||
;; (emit-image.ss), writing fresh artifacts: 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 (`make selfhost` checks this); when
|
||||
;; the sources change, run it twice to reconverge and re-mint the seed.
|
||||
;; 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:
|
||||
;; chez --script host/chez/bootstrap.ss SEED-PRELUDE SEED-IMAGE OUT-PRELUDE OUT-IMAGE
|
||||
|
|
@ -23,7 +22,7 @@
|
|||
(define bs-out-image (list-ref bs-args 3))
|
||||
|
||||
;; Load the runtime + the SEED compiler (prelude for macros, image for the
|
||||
;; analyzer/emitter), exactly as the zero-Janet spine assembles a program.
|
||||
;; analyzer/emitter), exactly as the spine assembles a program.
|
||||
(load "host/chez/rt.ss")
|
||||
(set-chez-ns! "clojure.core")
|
||||
(load bs-seed-prelude)
|
||||
|
|
@ -39,4 +38,4 @@
|
|||
(put-string p (jolt-emit-prelude)) (close-port p))
|
||||
(let ((p (open-output-file bs-out-image 'replace)))
|
||||
(put-string p (jolt-emit-image)) (close-port p))
|
||||
(display "bootstrap: rebuilt prelude + compiler image on Chez (no Janet)\n")
|
||||
(display "bootstrap: rebuilt prelude + compiler image on Chez\n")
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
;; cli.ss (jolt-9phg / jolt-90sp) — the pure-Chez jolt runtime. NO Janet.
|
||||
;; cli.ss — the jolt runtime.
|
||||
;;
|
||||
;; Loads the checked-in seed (host/chez/seed/{prelude,image}.ss — the bootstrap
|
||||
;; compiler) and the zero-Janet spine, then either evaluates a -e expression or
|
||||
;; dispatches a CLI command (run/-M/repl/path/task) through jolt.main. The loader
|
||||
;; compiler) and the spine, then either evaluates a -e expression or dispatches a
|
||||
;; CLI command (run/-M/repl/path/task) through jolt.main. The loader
|
||||
;; (loader.ss) turns `require` into real file loading off the source roots, so a
|
||||
;; multi-file project with deps.edn dependencies runs end to end.
|
||||
;;
|
||||
|
|
@ -23,13 +23,13 @@
|
|||
(load "host/chez/loader.ss")
|
||||
;; jolt.ffi host primitives (memory / library loading) load AFTER the loader's
|
||||
;; baked-ns snapshot, so a library's (require '[jolt.ffi]) still loads jolt.ffi's
|
||||
;; Clojure side (the foreign-fn / defcfn macros, src/jolt/jolt/ffi.clj).
|
||||
;; Clojure side (the foreign-fn / defcfn macros, stdlib/jolt/ffi.clj).
|
||||
(load "host/chez/ffi.ss") ; jolt.ffi (FFI: a library binds native code)
|
||||
|
||||
;; jolt.main + jolt.deps live under jolt-core; keep them (and src/jolt) on the
|
||||
;; jolt.main + jolt.deps live under jolt-core; keep them (and stdlib) on the
|
||||
;; roots so the CLI's own namespaces — and any jolt.* an app pulls in — resolve.
|
||||
;; A project's resolved deps roots are prepended to these by jolt.main.
|
||||
(set-source-roots! (list "jolt-core" "src/jolt"))
|
||||
(set-source-roots! (list "jolt-core" "stdlib"))
|
||||
|
||||
;; Render an uncaught jolt throw (any value, not just a Chez condition) to stderr
|
||||
;; and exit non-zero, instead of Chez's opaque "non-condition value" dump. An
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;; Phase 1 (jolt-cf1q.2, inc 3a) — persistent collections on the Chez RT.
|
||||
;; persistent collections on the Chez RT.
|
||||
;;
|
||||
;; The vector / map / set the emitted programs construct from literals and
|
||||
;; operate on via the lowered leaf ops (conj/get/nth/count/assoc/...). Loaded by
|
||||
|
|
@ -6,11 +6,8 @@
|
|||
;; jolt-coll? / jolt-coll=? / jolt-coll-hash hooks defined here (forward refs,
|
||||
;; resolved at run time — nothing is CALLED during load).
|
||||
;;
|
||||
;; Phase note: the persistent vector is a copy-on-write Scheme vector and the
|
||||
;; map/set are a bitmap HAMT (the structure 0c measured self-hostable). They live
|
||||
;; in Scheme for the Phase-1 bootstrap; the 0c decision is to SELF-HOST them in
|
||||
;; Clojure once core is up on Chez (Phase 3 shim shrink). Correctness, not perf,
|
||||
;; is the Phase-1 gate.
|
||||
;; The persistent vector is a copy-on-write Scheme vector and the map/set are a
|
||||
;; bitmap HAMT. They live in Scheme; correctness, not perf, is the gate.
|
||||
|
||||
;; ============================================================================
|
||||
;; small immutable-vector helpers (manual; avoid stdlib arg-order ambiguity)
|
||||
|
|
@ -40,7 +37,7 @@
|
|||
;; A pvec carries an `ent` flag: #t marks a MAP ENTRY (the [k v] pair seq'd out
|
||||
;; of a map). A map entry equals its [k v] vector and walks like one (nth/count/
|
||||
;; seq/=/hash/print all read only `v`), but is NOT `vector?` and IS `map-entry?`
|
||||
;; — matching Clojure's MapEntry (jolt-agw6). The flag defaults #f, so every
|
||||
;; — matching Clojure's MapEntry. The flag defaults #f, so every
|
||||
;; existing `(make-pvec v)` builds a plain vector; modifying an entry (conj/assoc)
|
||||
;; likewise yields a plain vector.
|
||||
(define-record-type pvec
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
;; compile-eval.ss (jolt-hs9n, Phase 3 inc6) — the zero-Janet compile spine.
|
||||
;; compile-eval.ss — the compile spine.
|
||||
;;
|
||||
;; Ties together the cross-compiled compiler image (jolt.ir + jolt.analyzer +
|
||||
;; jolt.backend-scheme, loaded as def-var! forms) and the host contract
|
||||
;; (host-contract.ss) into a runtime entry: a Clojure source string is read by the
|
||||
;; Chez data reader, analyzed by the ON-CHEZ analyzer to IR, emitted to Scheme by
|
||||
;; the ON-CHEZ emitter, and eval'd — no Janet in the loop. This is the spine the
|
||||
;; stage2==stage3 bootstrap fixpoint (later increments) closes over.
|
||||
;; Chez data reader, analyzed by the analyzer to IR, emitted to Scheme by the
|
||||
;; emitter, and eval'd. This is the spine the stage2==stage3 bootstrap fixpoint
|
||||
;; closes over.
|
||||
;;
|
||||
;; Loaded after host-contract.ss + the compiler image.
|
||||
|
||||
|
|
@ -13,11 +13,11 @@
|
|||
(define jolt-ce-emit (var-deref "jolt.backend-scheme" "emit"))
|
||||
(define jolt-ce-read (var-deref "clojure.core" "read-string"))
|
||||
|
||||
;; The zero-Janet spine ALWAYS runs with the full clojure.core prelude loaded, so a
|
||||
;; clojure.* ref must lower to var-deref (resolved from the prelude), not trip the
|
||||
;; emitter's "unsupported stdlib fn (no core on Chez yet)" out-of-subset guard —
|
||||
;; that guard is only for the bare -e subset with no prelude. Turn prelude mode on
|
||||
;; once, here, so every analyze->emit on this spine sees the full core (jolt-qjr0).
|
||||
;; The spine ALWAYS runs with the full clojure.core prelude loaded, so a clojure.*
|
||||
;; ref must lower to var-deref (resolved from the prelude), not trip the emitter's
|
||||
;; "unsupported stdlib fn (no core on Chez yet)" out-of-subset guard — that guard
|
||||
;; is only for the bare -e subset with no prelude. Turn prelude mode on once, here,
|
||||
;; so every analyze->emit on this spine sees the full core.
|
||||
((var-deref "jolt.backend-scheme" "set-prelude-mode!") #t)
|
||||
|
||||
;; (quote X) -> X, else x — unwraps a quoted require spec.
|
||||
|
|
@ -31,7 +31,7 @@
|
|||
|
||||
;; Pre-register any (require ...)/(use ...) :as aliases under `ns` BEFORE analysis,
|
||||
;; so a qualified s/foo resolves while compiling (analysis precedes the runtime
|
||||
;; require). Walks the whole form (a require may be nested in a do/let). jolt-qjr0.
|
||||
;; require). Walks the whole form (a require may be nested in a do/let).
|
||||
(define (ce-clause-require? cl) ; (:require ...) / (:use ...) ns clause
|
||||
(and (pair? cl) (keyword? (car cl))
|
||||
(let ((kn (keyword-t-name (car cl)))) (or (string=? kn "require") (string=? kn "use")))))
|
||||
|
|
@ -66,7 +66,7 @@
|
|||
(define (jolt-analyze-emit src ns)
|
||||
(jolt-analyze-emit-form (jolt-ce-read src) ns))
|
||||
|
||||
;; --- runtime defmacro (jolt-r8ku) -------------------------------------------
|
||||
;; --- runtime defmacro -------------------------------------------------------
|
||||
;; Shared with emit-image.ss (loaded after this). A defmacro lowers to a def of
|
||||
;; its expander fn + a macro flag, exactly as the prelude emits build-time macros.
|
||||
|
||||
|
|
@ -82,7 +82,7 @@
|
|||
;; Strips a leading docstring (native string) + attr-map (a non-symbol pmap), then
|
||||
;; re-heads the rest with `fn` so a destructured macro arglist desugars. Emits the
|
||||
;; BARE fn (the caller wraps it in def-var! + mark-macro!), never a (def NAME ...) —
|
||||
;; interning NAME would make require skip the real macro (jolt-r9lm).
|
||||
;; interning NAME would make require skip the real macro.
|
||||
(define (ce-defmacro->fn f)
|
||||
(let* ((items (seq->list f))
|
||||
(name-sym (cadr items))
|
||||
|
|
@ -131,7 +131,6 @@
|
|||
|
||||
;; 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).
|
||||
;; jolt-r8ku.
|
||||
(define (jolt-load-string s)
|
||||
(let loop ((src s) (result jolt-nil))
|
||||
(let ((pn (jolt-parse-next src)))
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
;; concurrency.ss (jolt-byjr) — real OS-thread futures + promises for the Chez host.
|
||||
;; concurrency.ss — real OS-thread futures + promises for the Chez host.
|
||||
;;
|
||||
;; SHARED-HEAP semantics (JVM Clojure), NOT Janet's isolated-heap snapshot: a
|
||||
;; future body runs on a native thread (fork-thread) over the SAME heap, so a
|
||||
;; captured atom is shared and the body's mutations are visible to the parent —
|
||||
;; matching `clojure.core` on the JVM. deref blocks on a mutex+condition latch.
|
||||
;; SHARED-HEAP semantics, like JVM Clojure: a future body runs on a native thread
|
||||
;; (fork-thread) over the SAME heap, so a captured atom is shared and the body's
|
||||
;; mutations are visible to the parent. deref blocks on a mutex+condition latch.
|
||||
;;
|
||||
;; future / future-call / future-cancel / future? / future-done? / future-cancelled?
|
||||
;; promise / deliver, and the deref extension for both, are bound here (some
|
||||
;; re-asserted in post-prelude.ss over the overlay's Janet-shaped versions).
|
||||
;; re-asserted in post-prelude.ss over the overlay's versions).
|
||||
;;
|
||||
;; pmap / pcalls / pvalues live in the clojure.core overlay (40-lazy) expressed
|
||||
;; over `future`, so they light up for free once future-call exists.
|
||||
|
|
@ -105,8 +104,8 @@
|
|||
(and (jolt-future? x) (jolt-future-cancelled? x)))
|
||||
|
||||
;; --- promises ---------------------------------------------------------------
|
||||
;; A blocking promise (JVM), not Janet's non-blocking atom shim: deref parks until
|
||||
;; deliver, then caches the value. deliver wins once; later delivers return nil.
|
||||
;; A blocking promise (like the JVM): deref parks until deliver, then caches the
|
||||
;; value. deliver wins once; later delivers return nil.
|
||||
(define-record-type jolt-promise
|
||||
(fields (mutable delivered?) (mutable value) mu cv)
|
||||
(nongenerative jolt-promise-v1))
|
||||
|
|
@ -144,8 +143,8 @@
|
|||
(if got (jolt-promise-value p) timeout-val)))
|
||||
|
||||
;; --- agents (async, per-agent serialized dispatch) --------------------------
|
||||
;; JVM semantics, not Janet's synchronous shim: send/send-off enqueue an action
|
||||
;; and a single worker thread applies them to the state IN ORDER; deref reads the
|
||||
;; JVM semantics: send/send-off enqueue an action and a single worker thread
|
||||
;; applies them to the state IN ORDER; deref reads the
|
||||
;; (possibly not-yet-updated) state without blocking; await blocks until the queue
|
||||
;; drains. An action error is captured (agent-error) and stops the queue.
|
||||
(define-record-type jolt-agent
|
||||
|
|
@ -246,8 +245,8 @@
|
|||
((jolt-delay? x) (jolt-delay-force x))
|
||||
(else (apply %pre-conc-deref x opts)))))
|
||||
|
||||
;; realized? for a Chez future/promise/delay (the overlay reads Janet map keys).
|
||||
;; Wrapped over the overlay version in post-prelude.ss.
|
||||
;; realized? for a future/promise/delay. Wrapped over the overlay version in
|
||||
;; post-prelude.ss.
|
||||
(define (jolt-conc-realized? x)
|
||||
(cond ((jolt-future? x) (jolt-future-done? x))
|
||||
((jolt-promise? x) (jolt-promise-delivered? x))
|
||||
|
|
@ -273,7 +272,7 @@
|
|||
(def-var! "clojure.core" "delay?" jolt-delay?)
|
||||
(def-var! "clojure.core" "deref" jolt-deref)
|
||||
|
||||
;; --- cooperative thread interrupt (jolt-amzy) -------------------------------
|
||||
;; --- cooperative thread interrupt -------------------------------------------
|
||||
;; Chez has no force-kill, but its engine timer (set-timer + timer-interrupt-
|
||||
;; handler, thread-local) is polled at procedure-call / loop back-edges — so a
|
||||
;; running computation, even a tight Scheme loop, can be aborted from another
|
||||
|
|
|
|||
|
|
@ -143,8 +143,8 @@
|
|||
(def-var! "clojure.core" "gensym" jolt-gensym)
|
||||
(def-var! "clojure.core" "int" jolt-int)
|
||||
;; char: coerce a code point (jolt's all-flonum number) to a Chez char; pass a
|
||||
;; char through. Inverse of int on chars. (Missing on Chez before jolt-hs9n — the
|
||||
;; cross-compiled emitter's chez-str-lit needs it for printable-ASCII escaping.)
|
||||
;; char through. Inverse of int on chars. The cross-compiled emitter's
|
||||
;; chez-str-lit needs it for printable-ASCII escaping.
|
||||
(define (jolt-char x) (if (char? x) x (integer->char (exact (round x)))))
|
||||
(def-var! "clojure.core" "char" jolt-char)
|
||||
;; long: same truncation as int in jolt's all-flonum model (seed core-long =
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
;; dot-forms.ss — generic dispatch for the `.` special-form / `.-field` desugar
|
||||
;; (jolt-kuic). The analyzer lowers (. target member arg*) and (.-field target)
|
||||
;; dot-forms.ss — generic dispatch for the `.` special-form / `.-field` desugar.
|
||||
;; The analyzer lowers (. target member arg*) and (.-field target)
|
||||
;; 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
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
;; dynamic var binding (jolt-2o7x, Phase 2) — binding / with-bindings* / var-set /
|
||||
;; thread-bound? / with-local-vars / with-redefs / bound-fn* / get-thread-bindings.
|
||||
;; dynamic var binding — binding / with-bindings* / var-set / thread-bound? /
|
||||
;; with-local-vars / with-redefs / bound-fn* / get-thread-bindings.
|
||||
;;
|
||||
;; A per-thread dynamic-binding stack: a list of frames, innermost (most recently
|
||||
;; pushed) at the HEAD. Each frame is an alist of (var-cell . value) MUTABLE pairs
|
||||
|
|
@ -15,8 +15,8 @@
|
|||
;; the stack before falling back to the cell root. Loaded LAST (after vars.ss and
|
||||
;; ns.ss) so it chains the fully-extended jolt-var-get and overrides rt.ss var-deref.
|
||||
|
||||
;; THREAD-LOCAL (jolt-byjr): a Chez thread parameter, so each OS thread (a future
|
||||
;; / go block) has its own binding stack. Chez initializes a new thread's parameter
|
||||
;; THREAD-LOCAL: a Chez thread parameter, so each OS thread (a future / go block)
|
||||
;; has its own binding stack. Chez initializes a new thread's parameter
|
||||
;; to the spawning thread's value at fork time, giving Clojure binding conveyance
|
||||
;; for free (the future shim also installs an explicit snapshot, belt-and-suspenders).
|
||||
(define dyn-binding-stack (make-thread-parameter '()))
|
||||
|
|
@ -104,8 +104,8 @@
|
|||
;; jolt-var-get's unbound-error path) so undefined-var reads keep prior behaviour.
|
||||
;; The *ns* var cell — its reads are thread-local: with no thread-binding they
|
||||
;; derive from chez-current-ns (a thread-parameter), so *ns* tracks in-ns per
|
||||
;; thread and a (binding [*ns* ..]) drives resolution (jolt-6rld). Captured now
|
||||
;; that *ns* is defined (ns.ss loaded earlier); chez-current-ns consults it too.
|
||||
;; thread and a (binding [*ns* ..]) drives resolution. Captured now that *ns* is
|
||||
;; defined (ns.ss loaded earlier); chez-current-ns consults it too.
|
||||
(set! star-ns-cell (jolt-var "clojure.core" "*ns*"))
|
||||
|
||||
(define %dyn-rt-var-deref var-deref)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;; emit-image.ss (jolt-cf1q.4 inc8) — the on-Chez compiler-image emitter.
|
||||
;; emit-image.ss — the on-Chez compiler-image emitter.
|
||||
;;
|
||||
;; 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
|
||||
|
|
@ -34,7 +34,7 @@
|
|||
;; 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>) +
|
||||
;; (mark-macro! ns name) so the on-Chez analyzer can expand it (jolt-r9lm).
|
||||
;; (mark-macro! ns name) so the on-Chez analyzer can expand it.
|
||||
(define (ei-emit-ns ns-name src)
|
||||
(let loop ((forms (ei-read-all src)) (acc '()))
|
||||
(if (null? forms)
|
||||
|
|
@ -82,12 +82,12 @@
|
|||
(append
|
||||
(map (lambda (tf) (cons "clojure.core" (string-append "jolt-core/clojure/core/" tf ".clj")))
|
||||
'("00-syntax" "00-kernel" "10-seq" "20-coll" "25-sorted" "30-macros" "40-lazy" "50-io"))
|
||||
(list (cons "clojure.string" "src/jolt/clojure/string.clj")
|
||||
(cons "clojure.walk" "src/jolt/clojure/walk.clj")
|
||||
(cons "clojure.template" "src/jolt/clojure/template.clj")
|
||||
(cons "clojure.edn" "src/jolt/clojure/edn.clj")
|
||||
(cons "clojure.set" "src/jolt/clojure/set.clj")
|
||||
(cons "clojure.pprint" "src/jolt/clojure/pprint.clj"))))
|
||||
(list (cons "clojure.string" "stdlib/clojure/string.clj")
|
||||
(cons "clojure.walk" "stdlib/clojure/walk.clj")
|
||||
(cons "clojure.template" "stdlib/clojure/template.clj")
|
||||
(cons "clojure.edn" "stdlib/clojure/edn.clj")
|
||||
(cons "clojure.set" "stdlib/clojure/set.clj")
|
||||
(cons "clojure.pprint" "stdlib/clojure/pprint.clj"))))
|
||||
|
||||
;; Join a list of form strings with "\n", no trailing newline.
|
||||
(define (ei-join forms)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;; host class tokens (jolt-13zk) — a bare class name (String, Keyword, File...)
|
||||
;; host class tokens — 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).
|
||||
|
|
@ -81,8 +81,8 @@
|
|||
(lambda (pair) (def-var! "clojure.core" (car pair) (cdr pair)))
|
||||
class-token-alist)
|
||||
|
||||
;; resolve a ^Type hint symbol-name to its canonical class name at def time
|
||||
;; (jolt-a1ir): "String" -> "java.lang.String", matching the JVM compiler. An
|
||||
;; resolve a ^Type hint symbol-name to its canonical class name at def time:
|
||||
;; "String" -> "java.lang.String", matching the JVM compiler. An
|
||||
;; already-canonical name maps to itself; an unknown name yields #f (left as-is).
|
||||
(define class-hint-table (make-hashtable string-hash string=?))
|
||||
(for-each (lambda (p) (hashtable-set! class-hint-table (car p) (cdr p))) class-token-alist)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;; host-contract.ss (jolt-hs9n, Phase 3 inc6) — the jolt.host contract on Chez.
|
||||
;; host-contract.ss — the jolt.host contract on Chez.
|
||||
;;
|
||||
;; The portable seam between jolt-core (analyzer/IR/emitter, cross-compiled to
|
||||
;; Scheme) and the host. Every
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
;; jolt.analyzer / jolt.backend-scheme — whose unqualified form-*/resolve-global/
|
||||
;; ... refs lower to (var-deref "jolt.host" ...) — resolve here at runtime.
|
||||
;;
|
||||
;; This is what puts analyze->IR->emit ON CHEZ (the zero-Janet spine). It runs
|
||||
;; This is what puts analyze->IR->emit ON CHEZ. It runs
|
||||
;; over the Chez data reader's forms (reader.ss): symbols are symbol-t, lists are
|
||||
;; cseq (list?), () is empty-list-t, vectors/maps are pvec/pmap, sets and #tag/
|
||||
;; regex/inst/uuid are pmaps tagged :jolt/type, chars are NATIVE Chez chars.
|
||||
|
|
@ -41,13 +41,13 @@
|
|||
(define (hc-sym? x) (symbol-t? x))
|
||||
;; ANY non-empty seq is a list form for analysis (a macro/eval form built via
|
||||
;; concat/map/cons is a lazy cseq with list?=#f, but evaluating it still means
|
||||
;; calling its head) — not just reader-built lists (jolt-cf1q.7).
|
||||
;; calling its head) — not just reader-built lists.
|
||||
(define (hc-list? x) (or (empty-list-t? x) (cseq? x)))
|
||||
(define (hc-vec? x) (pvec? x))
|
||||
(define (hc-map? x) (and (pmap? x) (jolt-nil? (jolt-get x hc-kw-jolt-type))))
|
||||
;; A set form is the reader's tagged map {:jolt/type :jolt/set :value <pvec>} OR a
|
||||
;; real pset value — a macro template's #{...} expansion (syntax-quote.ss jolt-sqset)
|
||||
;; produces a pset, which the analyzer must still read as a set literal (jolt-r9lm).
|
||||
;; produces a pset, which the analyzer must still read as a set literal.
|
||||
(define (hc-set? x)
|
||||
(or (pset? x)
|
||||
(and (pmap? x) (eq? (jolt-get x hc-kw-jolt-type) hc-kw-jolt-set))))
|
||||
|
|
@ -67,7 +67,7 @@
|
|||
(define (hc-bigdec-source x) (jolt-get x hc-kw-form))
|
||||
;; A live namespace value spliced into a form (e.g. `(str ~*ns*) in a macro):
|
||||
;; the analyzer can't carry an opaque runtime value, so recognize a jns and
|
||||
;; reconstruct it by name at the call site (jolt-8sha).
|
||||
;; reconstruct it by name at the call site.
|
||||
(define (hc-ns-value? x) (jns? x))
|
||||
(define (hc-ns-value-name x) (jns-name x))
|
||||
|
||||
|
|
@ -98,7 +98,7 @@
|
|||
(let ((kv (hashtable-ref rdr-map-order x #f)))
|
||||
(if kv
|
||||
;; reader-built map literal: emit pairs in SOURCE order (kv = k1 v1 k2 v2 …)
|
||||
;; so the analyzer evaluates the values left-to-right (jolt-qjr0).
|
||||
;; so the analyzer evaluates the values left-to-right.
|
||||
(let loop ((kv kv) (acc '()))
|
||||
(if (null? kv) (apply jolt-vector (reverse acc))
|
||||
(loop (cddr kv) (cons (jolt-vector (car kv) (cadr kv)) acc))))
|
||||
|
|
@ -111,14 +111,14 @@
|
|||
(define (hc-inst-source x) (jolt-get x hc-kw-form))
|
||||
(define (hc-uuid-source x) (jolt-get x hc-kw-form))
|
||||
|
||||
;; The Chez reader does not record source offsets yet (jolt-q2kg).
|
||||
;; The Chez reader does not record source offsets yet.
|
||||
(define (hc-form-position x) jolt-nil)
|
||||
|
||||
;; --- special forms ----------------------------------------------------------
|
||||
;; Mirrors host_iface special-names + interop-head? — forms the analyzer marks
|
||||
;; uncompilable (the handled specials are dispatched in analyze-list BEFORE this).
|
||||
;; `eval` is NOT here: it is a clojure.core FUNCTION on the spine (compile-eval.ss
|
||||
;; def-var!s it), so it must resolve as an ordinary var, not punt (jolt-r8ku).
|
||||
;; def-var!s it), so it must resolve as an ordinary var, not punt.
|
||||
;; `defmacro` stays special — the spine intercepts it before analysis.
|
||||
(define hc-special-names
|
||||
'("quote" "syntax-quote" "unquote" "unquote-splicing" "do" "if" "def"
|
||||
|
|
@ -155,7 +155,7 @@
|
|||
(and ref (var-cell-lookup ref nm)))
|
||||
(var-cell-lookup "clojure.core" nm)))))
|
||||
|
||||
;; Runtime macros (jolt-r9lm, inc6b): a defmacro is emitted into the prelude as a
|
||||
;; Runtime macros: a defmacro is emitted into the prelude as a
|
||||
;; 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
|
||||
|
|
@ -173,7 +173,7 @@
|
|||
;; {:kind :var :ns NS :name NAME} — a defined var (compile ns / clojure.core)
|
||||
;; {:kind :unresolved :name NAME} — not found (late-bind -> var-ref @ compile ns;
|
||||
;; a qualified one -> host-static in the analyzer)
|
||||
;; No :host branch: there is no Janet-style native-op env on Chez — the hot
|
||||
;; No :host branch: there is no separate native-op env — the hot
|
||||
;; clojure.core primitives (+,-,map,...) are declared in clojure.core below so
|
||||
;; they classify as :var and the emitter's native-op path lowers them.
|
||||
(define (hc-resolve-global ctx sym)
|
||||
|
|
@ -187,7 +187,7 @@
|
|||
|
||||
(define (hc-intern! ctx ns-name nm) (declare-var! ns-name nm) jolt-nil)
|
||||
|
||||
;; --- syntax-quote lowering (jolt-qjr0, inc7) ---------------------------------
|
||||
;; --- syntax-quote lowering ---------------------------------------------------
|
||||
;; 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
|
||||
|
|
@ -236,7 +236,7 @@
|
|||
;; to the target namespace — Clojure resolves the alias part of a qualified
|
||||
;; symbol in syntax-quote, so a macro's `impl/foo` expands to its real
|
||||
;; (clojure.tools.logging.impl/foo) name and stays unambiguous even when
|
||||
;; another loaded ns shares the alias's short name (jolt-qjr0). Otherwise
|
||||
;; another loaded ns shares the alias's short name. Otherwise
|
||||
;; leave it as written (a real ns or an interop class token).
|
||||
(let ((target (chez-resolve-alias (chez-actx-cns ctx) sns)))
|
||||
(if target (jolt-symbol target nm) form)))))
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;; host-static.ss (jolt-avt6) — host class statics + constructors on Chez.
|
||||
;; host-static.ss — host class statics + constructors on Chez.
|
||||
;;
|
||||
;; 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
|
||||
|
|
@ -99,7 +99,7 @@
|
|||
(let ((ctor (lookup-class class-ctors-tbl class)))
|
||||
(cond
|
||||
(ctor (apply ctor args))
|
||||
;; deftype/defrecord (jolt-499t): the type name is bound as a VAR (the
|
||||
;; deftype/defrecord: the type name is bound as a VAR (the
|
||||
;; make-deftype-ctor closure) in its defining ns, not a registered host class.
|
||||
;; Resolve it in the current ns / clojure.core and invoke it — so (P. args)
|
||||
;; works the same as the ->P factory.
|
||||
|
|
@ -111,7 +111,7 @@
|
|||
(error #f (string-append "No constructor for class " class))))))))
|
||||
|
||||
;; ---- coercion helpers -------------------------------------------------------
|
||||
;; numeric tower (jolt-n6al): currentTimeMillis/nanoTime are exact longs (JVM).
|
||||
;; numeric tower: 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
|
||||
|
|
@ -161,7 +161,7 @@
|
|||
(cons "PI" (->dbl (* 4 (atan 1)))) (cons "E" (->dbl (exp 1)))
|
||||
(cons "random" (lambda args (random 1.0)))))
|
||||
|
||||
;; Thread: real OS threads back futures/promises (jolt-byjr), so sleep genuinely
|
||||
;; Thread: real OS threads back futures/promises, so sleep genuinely
|
||||
;; parks the calling thread for `ms` milliseconds (a worker sleeping doesn't block
|
||||
;; the parent). yield hands off the scheduler.
|
||||
(register-class-statics! "Thread"
|
||||
|
|
@ -178,7 +178,7 @@
|
|||
(list (cons "getContextClassLoader" (lambda (self) (make-jhost "classloader" '())))))
|
||||
|
||||
;; clojure.lang.LockingTransaction: jolt has no STM (no refs/dosync), so a
|
||||
;; transaction is never running. isRunning -> false (jolt-0obq).
|
||||
;; transaction is never running. isRunning -> false.
|
||||
(register-class-statics! "LockingTransaction" (list (cons "isRunning" (lambda () #f))))
|
||||
(register-class-statics! "clojure.lang.LockingTransaction" (list (cons "isRunning" (lambda () #f))))
|
||||
|
||||
|
|
@ -267,7 +267,7 @@
|
|||
(apply jolt-format (car rest) (cdr rest))
|
||||
(apply jolt-format a rest))))))
|
||||
|
||||
;; ---- java.text.NumberFormat (jolt-1nnn) -------------------------------------
|
||||
;; ---- java.text.NumberFormat -------------------------------------------------
|
||||
;; A grouping decimal formatter (selmer number-format / cuerdas). state:
|
||||
;; #(grouping? min-frac max-frac). .format groups the integer part with commas.
|
||||
(define (nf-make grouping? minf maxf) (make-jhost "numberformat" (vector grouping? minf maxf)))
|
||||
|
|
@ -371,7 +371,7 @@
|
|||
((char=? (string-ref l i) #\=) i)
|
||||
(else (scan (+ i 1)))))))
|
||||
(loop (if eq (cons (cons (substring l 0 eq) (substring l (+ eq 1) (string-length l))) acc) acc)))))))))
|
||||
;; JOLT_BAKE_ENV_ALLOWLIST (jolt-s3j): when set, only the listed comma-separated
|
||||
;; JOLT_BAKE_ENV_ALLOWLIST: when set, only the listed comma-separated
|
||||
;; names are served; unset (the normal case) reads are live and unfiltered.
|
||||
(define (env-allowlist)
|
||||
(let ((a (getenv "JOLT_BAKE_ENV_ALLOWLIST")))
|
||||
|
|
@ -399,7 +399,7 @@
|
|||
;; or a unique sentinel). Each call returns a new jhost so identical?/= separate.
|
||||
(register-class-ctor! "Object" (lambda _ (make-jhost "object" (vector))))
|
||||
|
||||
;; ---- java.util.ArrayList (jolt-1nnn) ----------------------------------------
|
||||
;; ---- java.util.ArrayList ----------------------------------------------------
|
||||
;; A mutable list backed by a Scheme list in a box. medley's stateful transducers
|
||||
;; (window / partition-between) build one with .add / .size / .toArray / .clear /
|
||||
;; .remove. (ArrayList.) | (ArrayList. n) | (ArrayList. coll).
|
||||
|
|
@ -899,5 +899,5 @@
|
|||
(def-var! "clojure.core" "__register-instance-check!"
|
||||
(lambda (f) (set! user-instance-checks (append user-instance-checks (list f))) jolt-nil))
|
||||
|
||||
;; (jolt.host/table? x) — is x a host tagged-table (the Janet-table replacement)?
|
||||
;; (jolt.host/table? x) — is x a host tagged-table?
|
||||
(def-var! "jolt.host" "table?" (lambda (x) (if (htable? x) #t #f)))
|
||||
|
|
@ -1,10 +1,9 @@
|
|||
;; host tables + sorted collections (jolt-cf1q.3, jolt-0zoy) — the jolt.host
|
||||
;; value primitives and the 25-sorted tier's runtime.
|
||||
;; host tables + sorted collections — the jolt.host value primitives and the
|
||||
;; 25-sorted tier's runtime.
|
||||
;;
|
||||
;; jolt.host/tagged-table + ref-put! + ref-get resolved to jolt-nil on the Chez
|
||||
;; prelude, so the whole sorted tier (sorted-map/sorted-set/subseq/rsubseq) AND
|
||||
;; every overlay fn that calls (sorted? x) — empty, ifn?, reversible?, map?, set?,
|
||||
;; coll? — hit the apply-jolt-nil crash bucket. This provides:
|
||||
;; jolt.host/tagged-table + ref-put! + ref-get back the whole sorted tier
|
||||
;; (sorted-map/sorted-set/subseq/rsubseq) AND every overlay fn that calls
|
||||
;; (sorted? x) — empty, ifn?, reversible?, map?, set?, coll?. This provides:
|
||||
;; 1. tagged-table / ref-put! / ref-get over a Chez mutable tagged-table type
|
||||
;; (a string-keyed hashtable wrapped in an `htable` record), def-var!'d into
|
||||
;; the jolt.host ns. The sorted tier (25-sorted.clj) mints its wrapper with
|
||||
|
|
@ -28,10 +27,9 @@
|
|||
(let ((h (make-hashtable string-hash string=?)))
|
||||
(hashtable-set! h "jolt/type" tag)
|
||||
(make-htable h)))
|
||||
;; ref-put! threads the table back; a nil value REMOVES the key (Janet table
|
||||
;; semantics — h-ref-put!). Errors on a non-htable so the atom-watch / volatile
|
||||
;; uses (which pass a different ref type and have no Chez table yet) stay a crash
|
||||
;; rather than silently diverging.
|
||||
;; ref-put! threads the table back; a nil value REMOVES the key. Errors on a
|
||||
;; non-htable so the atom-watch / volatile uses (which pass a different ref type
|
||||
;; and have no table yet) stay a crash rather than silently diverging.
|
||||
(define (jolt-ref-put! t k v)
|
||||
(unless (htable? t) (error #f "ref-put!: not a host table" t))
|
||||
(if (jolt-nil? v)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;; #inst values + a java.time formatting shim (jolt-at0a, inc X).
|
||||
;; #inst values + a java.time formatting shim.
|
||||
;;
|
||||
;; 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
|
||||
|
|
@ -356,7 +356,7 @@
|
|||
|
||||
;; java.util.Date / java.sql.Timestamp: #inst's classes. (Date.) = now, (Date. ms)
|
||||
;; or (Date. another-date) -> a jinst (ms-of accepts a number / jinst / instant), so
|
||||
;; .getTime / inst? / instance? Date|Timestamp work. (jolt-dcmm)
|
||||
;; .getTime / inst? / instance? Date|Timestamp work.
|
||||
(define (date-ctor . args)
|
||||
(make-jinst (if (null? args) (now-ms) (ms->exact (ms-of (car args))))))
|
||||
(register-class-ctor! "Date" date-ctor)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
;; java.io.File + host file I/O (jolt-yyud). A
|
||||
;; Chez-native implementation over Chez's filesystem primitives. A File is a
|
||||
;; java.io.File + host file I/O, implemented 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.
|
||||
|
|
@ -8,8 +8,7 @@
|
|||
;; 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,
|
||||
;; slurp over a reader) is deferred to jolt-at0a. Loaded LAST in rt.ss, after
|
||||
;; Loaded LAST in rt.ss, after
|
||||
;; dot-forms.ss (so the jfile method arm wraps the fully-built dispatch) and
|
||||
;; natives-meta.ss / records.ss / printing.ss (jolt-type / instance-check /
|
||||
;; jolt-str-render-one, which it extends).
|
||||
|
|
@ -109,8 +108,8 @@
|
|||
(%io-rmd obj method-name rest-args))))
|
||||
|
||||
;; .isDirectory / .listFiles emit to jolt-host-call (rt.ss), not record-method-
|
||||
;; dispatch — the Phase-1 shims there assume a
|
||||
;; path STRING target. Make them jfile-aware so file-seq's File branch works.
|
||||
;; dispatch — the 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
|
||||
(lambda (method target . args)
|
||||
|
|
@ -156,17 +155,15 @@
|
|||
(begin (reader-refill! r "") (values jolt-nil #f))
|
||||
(begin (reader-refill! r (jolt-nth pr 1)) (values (jolt-nth pr 0) #t)))))
|
||||
|
||||
;; clojure.edn/read over a reader (jolt-uicd): the overlay edn.clj's drain-reader is
|
||||
;; janet/type-coupled, so on Chez we drain the jhost reader to a string and read the
|
||||
;; clojure.edn/read over a reader: drain the jhost reader to a string and read the
|
||||
;; first EDN form (read-string). Re-asserted over the prelude in post-prelude.ss.
|
||||
(define (chez-edn-read reader)
|
||||
(jolt-invoke (var-deref "clojure.core" "read-string")
|
||||
(if (reader-jhost? reader) (drain-reader reader) (jolt-str-render-one reader))))
|
||||
|
||||
;; line-seq (jolt-0obq): the overlay line-seq reads via a Janet map-reader's
|
||||
;; :read-line-fn, but a Chez io/reader is a jhost StringReader. Drain it (or take a
|
||||
;; string) and split on newline; a trailing newline does NOT yield a final empty
|
||||
;; line (like readLine -> nil at EOF). Re-asserted in post-prelude.ss.
|
||||
;; line-seq: an io/reader is a jhost StringReader. Drain it (or take a string)
|
||||
;; and split on newline; a trailing newline does NOT yield a final empty line
|
||||
;; (like readLine -> nil at EOF). Re-asserted in post-prelude.ss.
|
||||
(define (chez-lines s)
|
||||
(let loop ((cs (string->list s)) (cur '()) (acc '()))
|
||||
(cond ((null? cs) (reverse (if (null? cur) acc (cons (list->string (reverse cur)) acc))))
|
||||
|
|
@ -350,7 +347,7 @@
|
|||
(else (let ((ctor (lookup-class class-ctors-tbl "URL")))
|
||||
(if ctor (ctor (jolt-str-render-one x)) (make-url (jolt-str-render-one x))))))))
|
||||
|
||||
;; --- java.lang.ClassLoader (jolt-1nnn) --------------------------------------
|
||||
;; --- java.lang.ClassLoader --------------------------------------------------
|
||||
;; jolt has no classpath; a "classloader" resolves a named resource against the
|
||||
;; loader's source roots (the same model as clojure.java.io/resource), returning a
|
||||
;; file: URL or nil. getSystemClassLoader / a thread's contextClassLoader both hand
|
||||
|
|
@ -380,7 +377,7 @@
|
|||
(register-class-statics! "Thread" (list (cons "currentThread" (lambda () the-thread))))
|
||||
(register-class-statics! "java.lang.Thread" (list (cons "currentThread" (lambda () the-thread))))
|
||||
|
||||
;; --- java.io.File / java.util.UUID constructors (jolt-1nnn) ------------------
|
||||
;; --- java.io.File / java.util.UUID constructors -----------------------------
|
||||
;; (java.io.File. parent child) joins with "/"; (File. path) wraps the path.
|
||||
(register-class-ctor! "File"
|
||||
(lambda (a . rest)
|
||||
|
|
@ -396,7 +393,7 @@
|
|||
(cons "fromString" (lambda (s) (jolt-parse-uuid (jolt-str-render-one s))))))
|
||||
(register-class-ctor! "UUID" (lambda (s) (jolt-parse-uuid (jolt-str-render-one s))))
|
||||
|
||||
;; --- java.net.URI (jolt-1nnn) -----------------------------------------------
|
||||
;; --- java.net.URI -----------------------------------------------------------
|
||||
;; A minimal RFC-3986 split into scheme/authority/host/port/path/query/fragment,
|
||||
;; kept in a jhost "uri" carrying the original string. (str u)/(.toString u) give
|
||||
;; the original; getHost is nil for a relative URI (hiccup.util/to-str branches on
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
;; lazy-seq bridge (jolt-cf1q.3, jolt-dmw9) — make-lazy-seq / coll->cells.
|
||||
;; lazy-seq bridge — make-lazy-seq / coll->cells.
|
||||
;;
|
||||
;; 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 had
|
||||
;; no Chez shim, so EVERY overlay fn
|
||||
;; and `lazy-cat` to (concat (lazy-seq c) ...). These back 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.
|
||||
;; interpose / reductions / tree-seq (-> flatten) / lazy-cat.
|
||||
;;
|
||||
;; Bridge to the cseq model (seq.ss): a `jolt-lazyseq` is a deferred seq — a 0-arg
|
||||
;; thunk that, when forced once, yields a seq (cseq | nil). coll->cells coerces the
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
;; loader.ss (jolt-90sp) — file-based namespace loading + a shell primitive.
|
||||
;; loader.ss — file-based namespace loading + a shell primitive.
|
||||
;;
|
||||
;; The corpus/CLI spine compiles one program at a time; namespaces declared in
|
||||
;; that program see each other because a top-level (do …) unrolls. A real project
|
||||
;; spans many FILES, so `require` must locate a namespace's source on the search
|
||||
;; roots and load it — transitively, once each. This is the piece the Phase-3
|
||||
;; "cross-ns load is deferred" note left open (ns.ss).
|
||||
;; roots and load it — transitively, once each.
|
||||
;;
|
||||
;; Loaded by cli.ss AFTER compile-eval.ss (it calls jolt-compile-eval-form). The
|
||||
;; gates load compile-eval.ss but NOT this file, so the corpus/unit/sci runners
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
;; clojure.math (jolt-22vo) — Chez host shim over native flonum math.
|
||||
;; clojure.math — host shim over native flonum math.
|
||||
;;
|
||||
;; 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.
|
||||
;; clojure.math is registered as native bindings, NOT a .clj file — so there's no
|
||||
;; source tier to emit. The def-var! shims here back each 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
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;; multimethods (jolt-9ls5) — the multimethod dispatch runtime on the Chez host.
|
||||
;; multimethods — the multimethod dispatch runtime on the Chez host.
|
||||
;;
|
||||
;; defmulti/defmethod are macros that expand to ctx-capturing setup CALLS
|
||||
;; (defmulti-setup / defmethod-setup, + the table ops get-method/methods/
|
||||
|
|
@ -21,7 +21,7 @@
|
|||
;; so they agree with defmulti. Loaded from rt.ss after seq.ss (jolt-invoke),
|
||||
;; collections.ss (jolt=/key-hash/jolt-hash-map) and the var-cell machinery.
|
||||
|
||||
;; THREAD-LOCAL (jolt-6rld): a Chez thread-parameter, so each OS thread (an nREPL
|
||||
;; THREAD-LOCAL: a Chez thread-parameter, so each OS thread (an nREPL
|
||||
;; session worker / future) has its own current ns — vars stay global, only the
|
||||
;; "current ns" pointer is per-thread, matching Clojure's thread-local *ns*. A new
|
||||
;; thread inherits the forking thread's value. `star-ns-cell` (the *ns* var cell,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;; natives-array.ss (jolt-cf1q.7) — Java-style mutable arrays for the Chez host.
|
||||
;; natives-array.ss — Java-style mutable arrays for the Chez host.
|
||||
;;
|
||||
;; 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
|
||||
|
|
@ -24,7 +24,7 @@
|
|||
(make-jolt-array (make-vector (exact (na-idx a)) (if (pair? rest) (car rest) init)) kind)
|
||||
(na-from-seq a kind)))
|
||||
|
||||
;; numeric tower (jolt-n6al): array element defaults / masked bytes / count are
|
||||
;; numeric tower: array element defaults / masked bytes / count are
|
||||
;; EXACT integers (= JVM byte/short/int), matching exact integer literals.
|
||||
(define (na-byte-of v) (bitwise-and (exact (floor v)) #xff))
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,8 @@
|
|||
;; 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. hash-map/array-map/hash-set/set/rand semantics.
|
||||
;; Collection constructors + rand — host-coupled natives the overlay assumes as
|
||||
;; bare clojure.core vars. 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. 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
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;; metadata (jolt-cf1q.3 Phase 2 inc E) — meta / with-meta. Chez values don't
|
||||
;; metadata — meta / with-meta. Chez values don't
|
||||
;; carry metadata, so collections use an identity-keyed side-table: with-meta
|
||||
;; returns a fresh COPY of the value (new identity) and records its meta there, so
|
||||
;; the original is unchanged (Clojure's immutable-with-meta) and a copy made by a
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
(cond
|
||||
((symbol-t? x) (let ((m (symbol-t-meta x))) (if (jolt-nil? m) jolt-nil m)))
|
||||
;; a var's meta is {:ns :name} (derived from the cell) + any def-time user
|
||||
;; meta from rt.ss's var-meta-table (jolt-zikh).
|
||||
;; meta from rt.ss's var-meta-table.
|
||||
((var-cell? x)
|
||||
(let ((user (hashtable-ref var-meta-table x #f)))
|
||||
(jolt-assoc (if user user (jolt-hash-map))
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
;; misc scalar natives (jolt-cf1q.3) — UUID, format/printf, tagged-literal,
|
||||
;; bigint. Seed natives that were jolt-nil on the prelude.
|
||||
;; misc scalar natives — UUID, format/printf, tagged-literal, bigint.
|
||||
;;
|
||||
;; Loaded after the printers (pr-str of a uuid is #uuid "…") and converters
|
||||
;; (jolt-str-render-one for %s / str of a uuid).
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
;; bit ops + string->number parsers (jolt-cf1q.3 Phase 2 inc C) — host-coupled
|
||||
;; 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-* use
|
||||
;; strict shapes (Clojure 1.11: nil on malformed, throw on a non-string).
|
||||
;; bit ops + string->number parsers — host-coupled natives (bit family,
|
||||
;; parse-long/double). jolt models every number as a double, so bit ops coerce
|
||||
;; 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.
|
||||
(define (->int x) (exact (truncate x)))
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
;; natives-parity.ss (jolt-cf1q.7) — native Chez shims for clojure.core fns that
|
||||
;; had no Chez shim, so they resolved to nil ("not a fn"). Pure-Chez, JVM-matching.
|
||||
;; natives-parity.ss — native Chez shims for clojure.core fns. 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).
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;; natives-queue.ss (jolt-b8he) — clojure.lang.PersistentQueue for the Chez host.
|
||||
;; natives-queue.ss — clojure.lang.PersistentQueue for the Chez host.
|
||||
;;
|
||||
;; A functional queue: a `front` Scheme list (the dequeue end, head = front of the
|
||||
;; queue) + a reversed `rear` Scheme list (the enqueue end, head = most recent).
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
;; 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
|
||||
;; seq-native shims — native seq fns the overlay assumes are clojure.core
|
||||
;; natives. Each is a pure fn over the existing seq layer (seq.ss) — collection
|
||||
;; arities only; the 1-arg transducer arities follow below. Loaded last (after
|
||||
;; converters.ss for jolt-compare and seq.ss for the reduced record).
|
||||
|
||||
;; reduced / reduced? — the box itself is the jolt-reduced record from seq.ss
|
||||
|
|
@ -14,7 +11,7 @@
|
|||
(define (ensure-reduced x) (if (jolt-reduced? x) x (make-jolt-reduced x)))
|
||||
|
||||
;; ============================================================================
|
||||
;; transducers (jolt-kxsr) — the 1-arg arity of map/filter/take/... returns a
|
||||
;; transducers — 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. rf and the mapping/predicate fns are jolt values, so every
|
||||
;; call routes through jolt-invoke. A `reduced` step stops the fold — reduce-seq
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;; natives-str.ss (jolt-nfca) — java.lang.String method interop on Chez.
|
||||
;; natives-str.ss — java.lang.String method interop on Chez.
|
||||
;;
|
||||
;; (.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.
|
||||
|
|
@ -316,10 +316,9 @@
|
|||
|
||||
;; (require ...) / (use ...) at runtime: register each spec's :as alias + :refer
|
||||
;; names into the runtime ns tables (chez-register-spec!, ns.ss), keyed by the
|
||||
;; current ns. The zero-Janet spine also pre-registers these at analyze time
|
||||
;; (idempotent); but when the JANET analyzer compiled the form (the prelude path)
|
||||
;; the Chez tables were never populated, so ns-aliases/ns-resolve over an :as alias
|
||||
;; need this runtime registration (jolt-cf1q.7). Specs arrive evaluated (quoted).
|
||||
;; current ns. The spine also pre-registers these at analyze time (idempotent),
|
||||
;; so ns-aliases/ns-resolve over an :as alias resolve. Specs arrive evaluated
|
||||
;; (quoted).
|
||||
(define (chez-runtime-require . specs)
|
||||
(for-each (lambda (s) (chez-register-spec! (chez-current-ns) s)) specs)
|
||||
jolt-nil)
|
||||
|
|
|
|||
|
|
@ -1,10 +1,8 @@
|
|||
;; volatiles + sequence / transduce (jolt-cf1q.3, jolt-xjx6) — the transducer
|
||||
;; application surface.
|
||||
;; volatiles + sequence / transduce — the transducer application surface.
|
||||
;;
|
||||
;; `sequence` and `transduce` are seed natives that were jolt-nil on the prelude.
|
||||
;; The stateful transducer arities (take-nth/map-indexed/partition-by/dedupe/
|
||||
;; distinct, all overlay) use volatile!/vswap!/vreset!/deref, also unshimmed — so
|
||||
;; the whole (sequence xform coll) / (transduce xform f coll) surface crashed.
|
||||
;; `sequence` and `transduce` are seed natives. The stateful transducer arities
|
||||
;; (take-nth/map-indexed/partition-by/dedupe/distinct, all overlay) use
|
||||
;; volatile!/vswap!/vreset!/deref, shimmed here.
|
||||
;;
|
||||
;; Volatiles are a native mutable box (jvol) — the overlay vreset!/vswap! drive a
|
||||
;; volatile through jolt.host/ref-put!+get, but a Chez volatile is a record, not a
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
;; namespaces (jolt-yxqm, Phase 2) — the namespace value model.
|
||||
;; namespaces — the namespace value model.
|
||||
;;
|
||||
;; Chez has no ctx, so the ctx-coupled seed natives (find-ns/resolve/in-ns/…) are
|
||||
;; reimplemented over the rt.ss var-table (cells carry ns + name + defined?) and
|
||||
;; the multimethods.ss chez-current-ns box. A namespace VALUE is a `jns` record
|
||||
;; carrying its name string — distinct from a map/record so (map? ns) is #f, but
|
||||
;; the overlay's `ns-name` reads (get ns :name); that's overridden natively in
|
||||
;; post-prelude.ss (loads after the overlay clobbers it).
|
||||
;; The namespace ops (find-ns/resolve/in-ns/…) work over the rt.ss var-table
|
||||
;; (cells carry ns + name + defined?) and the multimethods.ss chez-current-ns
|
||||
;; box. A namespace VALUE is a `jns` record carrying its name string — distinct
|
||||
;; from a map/record so (map? ns) is #f, but the overlay's `ns-name` reads
|
||||
;; (get ns :name); that's overridden natively in post-prelude.ss (loads after
|
||||
;; the overlay clobbers it).
|
||||
;;
|
||||
;; Loaded LAST from rt.ss. SCOPE (jolt-yxqm): the read/resolve/in-ns/*ns* ops.
|
||||
;; use/require cross-ns SWITCHING is deferred (Phase 3) — the analyzer bakes a
|
||||
;; def's target ns at compile time, so a runtime in-ns can't redirect later defs.
|
||||
;; Loaded LAST from rt.ss. The analyzer bakes a def's target ns at compile time,
|
||||
;; so a runtime in-ns redirects only *ns* / str-of-ns, not later defs in the
|
||||
;; same program.
|
||||
|
||||
(define-record-type jns (fields name) (nongenerative chez-jns-v1))
|
||||
|
||||
|
|
@ -24,11 +24,11 @@
|
|||
(intern-ns! "user")
|
||||
(intern-ns! "clojure.core")
|
||||
|
||||
;; --- namespace aliases (jolt-qjr0) -----------------------------------------
|
||||
;; --- namespace aliases ------------------------------------------------------
|
||||
;; (require '[ns :as a]) registers a -> ns so the analyzer can resolve a/foo to
|
||||
;; ns/foo. Keyed by (compile-ns . alias). On the zero-Janet spine the requires are
|
||||
;; pre-registered at analyze time (compile-eval.ss) — analysis precedes eval, so a
|
||||
;; runtime require no-op is fine. Also drives jolt-ns-aliases below.
|
||||
;; ns/foo. Keyed by (compile-ns . alias). The requires are pre-registered at
|
||||
;; analyze time (compile-eval.ss) — analysis precedes eval, so a runtime require
|
||||
;; no-op is fine. Also drives jolt-ns-aliases below.
|
||||
(define ns-alias-table (make-hashtable equal-hash equal?))
|
||||
(define (chez-register-alias! cns alias target)
|
||||
(hashtable-set! ns-alias-table (cons cns alias) target))
|
||||
|
|
@ -105,10 +105,10 @@
|
|||
|
||||
(define (jolt-create-ns desig) (intern-ns! (ns-desig->name desig)))
|
||||
|
||||
;; in-ns: register + switch the current ns + re-bind *ns* + return the jns. NOTE
|
||||
;; (Phase-3 deferral): this updates only the RUNTIME current ns — subsequent defs
|
||||
;; in the same program were already ns-baked by the analyzer, so it does not
|
||||
;; redirect them. It is enough for *ns* / str-of-ns to track the switch.
|
||||
;; in-ns: register + switch the current ns + re-bind *ns* + return the jns. This
|
||||
;; updates only the RUNTIME current ns — subsequent defs in the same program were
|
||||
;; already ns-baked by the analyzer, so it does not redirect them. It is enough
|
||||
;; for *ns* / str-of-ns to track the switch.
|
||||
(define (jolt-in-ns desig)
|
||||
(let* ((nm (ns-desig->name desig)) (n (intern-ns! nm)))
|
||||
;; set the THREAD-LOCAL current ns; *ns* reads derive from it (dyn-binding.ss),
|
||||
|
|
@ -140,7 +140,7 @@
|
|||
m))
|
||||
(define (jolt-ns-publics desig) (ns-vars-pmap (ns-desig->name desig)))
|
||||
|
||||
;; ns-aliases (jolt-cf1q.7): the {alias-sym -> ns-value} registered under `desig`
|
||||
;; ns-aliases: the {alias-sym -> ns-value} registered under `desig`
|
||||
;; (default the current ns) via require :as / alias. Reads ns-alias-table.
|
||||
(define (jolt-ns-aliases . desig)
|
||||
(let ((cns (if (pair? desig) (ns-desig->name (car desig)) (chez-current-ns)))
|
||||
|
|
@ -153,7 +153,7 @@
|
|||
(hashtable-keys ns-alias-table))
|
||||
m))
|
||||
|
||||
;; ns-refers (jolt-cf1q.7): the {sym -> var} referred into `desig` via refer/use.
|
||||
;; ns-refers: the {sym -> var} referred into `desig` via refer/use.
|
||||
(define (jolt-ns-refers desig)
|
||||
(let ((cns (ns-desig->name desig)) (m (jolt-hash-map)))
|
||||
(vector-for-each
|
||||
|
|
@ -225,7 +225,7 @@
|
|||
(when c (var-cell-defined?-set! c #f) (var-cell-root-set! c jolt-unbound)))
|
||||
jolt-nil)
|
||||
|
||||
;; --- ns runtime fns (jolt-cf1q.7) -------------------------------------------
|
||||
;; --- ns runtime fns ---------------------------------------------------------
|
||||
;; ns-resolve: resolve `sym` as if reading it in namespace `ns-desig`. Qualified
|
||||
;; syms consult that ns's :as aliases; unqualified resolve in the ns, its :refers,
|
||||
;; then clojure.core. Returns the var or nil (never interns).
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;; png.ss (jolt-90sp) — jolt.png: a minimal PNG writer, the built-in the
|
||||
;; png.ss — jolt.png: a minimal PNG writer, the built-in the
|
||||
;; ray-tracer-multi example renders through. Truecolor (8-bit RGB), no
|
||||
;; compression: the IDAT zlib stream uses DEFLATE "stored" (uncompressed) blocks,
|
||||
;; so there is no compressor to carry — just CRC-32 / Adler-32 framing over Chez
|
||||
|
|
|
|||
|
|
@ -1,20 +1,16 @@
|
|||
;; post-prelude overrides (jolt-9ziu) — loaded AFTER the assembled clojure.core
|
||||
;; post-prelude overrides — loaded AFTER the assembled clojure.core
|
||||
;; prelude, so these win over the overlay's own def-var!.
|
||||
;;
|
||||
;; A few clojure.core predicates are implemented in the overlay by inspecting a
|
||||
;; Janet-host tagged value's :jolt/type key (e.g. (get x :jolt/type)). That key
|
||||
;; doesn't exist for Chez-native representations: a jolt char is a Scheme char,
|
||||
;; an atom is a Chez record. The overlay's def-var! loads after rt.ss, so it
|
||||
;; clobbers the correct native shims (predicates.ss / atoms.ss) with versions
|
||||
;; that return false on every Chez value. Re-assert the native versions here.
|
||||
;;
|
||||
;; (Long-term these predicates want a host-neutral implementation that calls a
|
||||
;; host primitive instead of reading :jolt/type; until then this is the Chez-host
|
||||
;; override.)
|
||||
;; tagged value's :jolt/type key (e.g. (get x :jolt/type)). That key doesn't
|
||||
;; exist for native representations: a jolt char is a Scheme char, an atom is a
|
||||
;; Chez record. The overlay's def-var! loads after rt.ss, so it clobbers the
|
||||
;; correct native shims (predicates.ss / atoms.ss) with versions that return
|
||||
;; false on every Chez value. Re-assert the native versions here.
|
||||
(def-var! "clojure.core" "char?" jolt-char-pred?)
|
||||
(def-var! "clojure.core" "atom?" jolt-atom?)
|
||||
;; atom watches/validators: the overlay drives these via jolt.host/ref-put! on a
|
||||
;; Janet table (get a :watches), which a Chez atom record is not — re-assert the
|
||||
;; tagged table (get a :watches), which a Chez atom record is not — re-assert the
|
||||
;; native versions (defined in atoms.ss), and swap!/reset! notify+validate there.
|
||||
(def-var! "clojure.core" "add-watch" jolt-add-watch)
|
||||
(def-var! "clojure.core" "remove-watch" jolt-remove-watch)
|
||||
|
|
@ -30,7 +26,7 @@
|
|||
;; would wrongly report every var unbound. Native version (defined in vars.ss).
|
||||
(def-var! "clojure.core" "bound?" jolt-bound?)
|
||||
;; uuid?/random-uuid/parse-uuid/tagged-literal? are overlay (read :jolt/type or
|
||||
;; build tagged tables) — re-assert the native versions (defined in natives-misc.ss).
|
||||
;; build tagged tables) — re-assert the native versions (natives-misc.ss).
|
||||
(def-var! "clojure.core" "uuid?" jolt-uuid-pred?)
|
||||
(def-var! "clojure.core" "random-uuid" jolt-random-uuid)
|
||||
(def-var! "clojure.core" "parse-uuid" jolt-parse-uuid)
|
||||
|
|
@ -38,10 +34,10 @@
|
|||
;; ns-name: the overlay reads (get ns :name) — nil on a jns namespace record.
|
||||
;; Native version (defined in ns.ss) returns the namespace's name symbol.
|
||||
(def-var! "clojure.core" "ns-name" jolt-ns-name)
|
||||
;; concurrency (jolt-byjr): the overlay's future-done?/future-cancelled?/realized?
|
||||
;; read a Janet future-map's :cached/:cancelled keys, and promise/deliver are a
|
||||
;; non-blocking atom shim. A Chez future/promise is a record, and we want JVM
|
||||
;; (blocking, shared-heap) semantics — re-assert the native versions. realized?
|
||||
;; concurrency: the overlay's future-done?/future-cancelled?/realized? read a
|
||||
;; future-map's :cached/:cancelled keys, and promise/deliver are a non-blocking
|
||||
;; atom shim. A Chez future/promise is a record, and we want JVM (blocking,
|
||||
;; shared-heap) semantics — re-assert the native versions. realized?
|
||||
;; wraps the overlay (which still handles delay/lazy-seq/atom) for non-futures.
|
||||
(def-var! "clojure.core" "future-done?" jolt-native-future-done?)
|
||||
(def-var! "clojure.core" "future-cancelled?" jolt-native-future-cancelled?)
|
||||
|
|
@ -68,8 +64,8 @@
|
|||
;; realized? reads :jolt/type and throws on a jolt-lazyseq record.
|
||||
((jolt-lazyseq? x) (jolt-lazyseq-realized? x))
|
||||
(else (jolt-invoke overlay-realized? x))))))
|
||||
;; clojure.edn/read over a reader: the overlay edn.clj drain-reader uses janet/type;
|
||||
;; the native Chez version (io.ss) drains the jhost reader instead (jolt-uicd/jolt-7t3l).
|
||||
;; clojure.edn/read over a reader: the overlay edn.clj drain-reader reads
|
||||
;; :jolt/type; the native version (io.ss) drains the jhost reader instead.
|
||||
(def-var! "clojure.edn" "read"
|
||||
(case-lambda
|
||||
((reader) (chez-edn-read reader))
|
||||
|
|
@ -80,7 +76,7 @@
|
|||
(def-var! "clojure.core" "line-seq"
|
||||
(lambda (rdr)
|
||||
(if (reader-jhost? rdr) (chez-line-seq rdr) (jolt-invoke overlay-line-seq rdr)))))
|
||||
;; JVM-parity numeric tower (jolt-n6al): the overlay (20-coll.clj) carries an
|
||||
;; JVM-parity numeric tower: the overlay (20-coll.clj) carries an
|
||||
;; all-flonum number-predicate web with no Ratio concept (ratio? -> false,
|
||||
;; double? -> not-integer, float? -> double?, rational? -> int?), which
|
||||
;; misclassifies exact rationals on the Chez tower (e.g. (double? 1/2) -> true).
|
||||
|
|
@ -95,11 +91,11 @@
|
|||
(def-var! "clojure.core" "decimal?" jolt-decimal?)
|
||||
(def-var! "clojure.core" "==" jolt-num-equiv)
|
||||
;; chunked-seq? is true for a vector's seq (a real chunked-seq); the overlay's
|
||||
;; always-false stub loaded over the host fn, so re-assert it (jolt-hs5q).
|
||||
;; always-false stub loaded over the host fn, so re-assert it.
|
||||
(def-var! "clojure.core" "chunked-seq?" na-chunked-seq?)
|
||||
;; record? is a host type check (jrec?), not the overlay's (some? (get x
|
||||
;; :jolt/deftype)) — the get-trick invokes a sorted-map's comparator on
|
||||
;; :jolt/deftype and throws (jolt-3bbj). Matches the JVM (instance? IRecord).
|
||||
;; :jolt/deftype and throws. Matches the JVM (instance? IRecord).
|
||||
(def-var! "clojure.core" "record?" (lambda (x) (jrec? x)))
|
||||
|
||||
;; read / read+string over a HOST reader jhost (java.io StringReader/PushbackReader):
|
||||
|
|
|
|||
|
|
@ -1,21 +1,19 @@
|
|||
;; type predicates + simple accessors (jolt-9ziu) — host-coupled natives.
|
||||
;; type predicates + simple accessors — host-coupled natives.
|
||||
;;
|
||||
;; 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
|
||||
;; predicates are simply absent here for now.
|
||||
;; map?/vector?/set? are STRICT over the persistent-collection records, seq? is
|
||||
;; true only for real sequences, coll? is the union. Record arms are added by
|
||||
;; records.ss, which extends these dispatchers.
|
||||
|
||||
(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
|
||||
;; (jolt-75sv corrected the earlier exclusion).
|
||||
;; implements IPersistentVector, so (vector? (first {:a 1})) is true.
|
||||
(define (jolt-vector? x) (pvec? x))
|
||||
(define (jolt-set? x) (pset? x))
|
||||
(define (jolt-seq? x) (or (cseq? x) (empty-list-t? x)))
|
||||
;; (list? x): a list-marked cseq node or the empty list (). A lazy/vector-backed
|
||||
;; seq, (rest list), (seq coll), (map …) are seqs but not lists (jolt-75sv).
|
||||
;; seq, (rest list), (seq coll), (map …) are seqs but not lists.
|
||||
(define (jolt-list-pred? x) (or (and (cseq? x) (cseq-list? x)) (empty-list-t? x)))
|
||||
(define (jolt-coll-pred? x)
|
||||
(or (pvec? x) (pmap? x) (pset? x) (cseq? x) (empty-list-t? x)))
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
;; readable printer + output seams (jolt-cf1q.3 Phase 2 inc B) — the __pr-str1 /
|
||||
;; __write / __with-out-str host seams the overlay's pr-str/pr/prn/print/println/
|
||||
;; *-str family is built on (jolt-core/clojure/core/20-coll.clj). They resolved to
|
||||
;; jolt-nil, so the whole print family hit the apply-jolt-nil crash bucket.
|
||||
;; readable printer + output seams — the __pr-str1 / __write / __with-out-str
|
||||
;; host seams the overlay's pr-str/pr/prn/print/println/*-str family is built on
|
||||
;; (jolt-core/clojure/core/20-coll.clj).
|
||||
;;
|
||||
;; jolt-pr-str (rt.ss) is STR-style: strings render raw. pr-str needs READABLE
|
||||
;; (pr) style: strings quoted+escaped at every nesting level. This adds the
|
||||
|
|
|
|||
|
|
@ -1,14 +1,12 @@
|
|||
;; Chez-side Clojure data reader (jolt-r8ku, inc Y).
|
||||
;; Chez-side Clojure data reader.
|
||||
;;
|
||||
;; The data half of runtime read/eval: a recursive-descent reader that parses
|
||||
;; 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
|
||||
;; ONE Clojure form off a string and produces jolt runtime values. Two host
|
||||
;; 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).
|
||||
;; these (jolt-core/clojure/core/50-io.clj, stdlib/clojure/edn.clj).
|
||||
;;
|
||||
;; Form shapes:
|
||||
;; sets -> {:jolt/type :jolt/set :value [...]} (a FORM, not a set)
|
||||
|
|
@ -74,9 +72,6 @@
|
|||
((char=? (string-ref str i) c) i)
|
||||
(else (loop (+ i 1)))))))
|
||||
|
||||
;; jolt models EVERY number as a double (emit-const lowers integer literals to
|
||||
;; flonums too), so the reader coerces every parsed number to inexact — else a
|
||||
;; read int (exact) is not jolt= to a source int literal (flonum).
|
||||
;; Numeric tower (JVM parity): integer literals read as exact integers (= Long/
|
||||
;; BigInt, arbitrary precision), a/b ratios as exact rationals (= Ratio), and
|
||||
;; decimal/exponent literals as flonums (= double).
|
||||
|
|
@ -139,7 +134,7 @@
|
|||
(let ((n (string->number (substring body 0 (- blen 1)))))
|
||||
(and n (integer? n) (* sign n))))
|
||||
;; bigdecimal suffix M -> a :bigdec form carrying the numeric text; the back
|
||||
;; end lowers it to a runtime jbigdec (jolt-i2jm).
|
||||
;; end lowers it to a runtime jbigdec.
|
||||
((and (> blen 1) (char=? (string-ref body (- blen 1)) #\M))
|
||||
(let ((n (string->number (substring body 0 (- blen 1)))))
|
||||
(and n (real? n)
|
||||
|
|
@ -311,7 +306,7 @@
|
|||
(else (jolt-list (jolt-symbol #f "with-meta") target meta))))
|
||||
|
||||
;; --- # dispatch -------------------------------------------------------------
|
||||
;; #(...) anonymous fn shorthand (jolt-qjr0): % -> p1, %N -> pN, %& -> rest. The
|
||||
;; #(...) anonymous fn shorthand: % -> 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.
|
||||
|
|
@ -366,7 +361,7 @@
|
|||
(if rest-sym (list (jolt-symbol #f "&") rest-sym) '()))))
|
||||
(values (jolt-list (jolt-symbol #f "fn*") (apply jolt-vector params) body) j))))))
|
||||
|
||||
;; reader conditionals (jolt-qjr0): jolt's feature set is {:jolt :clj :default};
|
||||
;; reader conditionals: jolt's feature set is {:jolt :clj :default};
|
||||
;; the FIRST clause whose feature key is in the set wins (clause order, like
|
||||
;; Clojure). jolt is a Clojure/JVM-compatible host — it emulates clojure.lang.*
|
||||
;; and java.* interop — so it reads the :clj branch of a .cljc library (the JVM
|
||||
|
|
@ -537,7 +532,7 @@
|
|||
(jolt-vector form (substring s j end))))))
|
||||
|
||||
;; __read-tagged: apply a built-in data reader to an already-read form. The tag
|
||||
;; is the :#name keyword the reader produced; #uuid/#inst reuse the inc X ctors.
|
||||
;; is the :#name keyword the reader produced; #uuid/#inst reuse the inst-time ctors.
|
||||
(define (jolt-read-tagged tag form)
|
||||
(cond
|
||||
((eq? tag (keyword #f "#uuid")) (jolt-uuid-from-string form))
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
;; records + protocols (jolt-cf1q.3 Phase 2 inc D) — the deftype/defrecord +
|
||||
;; 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.
|
||||
;; records + protocols — the deftype/defrecord + defprotocol/extend-type
|
||||
;; subsystem.
|
||||
;;
|
||||
;; A record is a `jrec`: a type tag ("ns.Name") + an alist of (kw . val) in
|
||||
;; declared field order. It is map?/coll?, equal to another jrec of the same tag
|
||||
|
|
@ -28,8 +26,8 @@
|
|||
(define (jrec-has? r k)
|
||||
(let loop ((ps (jrec-pairs r)))
|
||||
(cond ((null? ps) #f) ((jolt=2 (caar ps) k) #t) (else (loop (cdr ps))))))
|
||||
;; mutate a deftype's mutable field in place (jolt-c3q): the pairs are runtime
|
||||
;; cons cells, so set-cdr! updates the field. (set! field v) inside a method
|
||||
;; mutate a deftype's mutable field in place: the pairs are runtime cons cells,
|
||||
;; so set-cdr! updates the field. (set! field v) inside a method
|
||||
;; lowers to this; returns v, as set! does.
|
||||
(define (jolt-set-field! inst k v)
|
||||
(if (jrec? inst)
|
||||
|
|
@ -97,8 +95,6 @@
|
|||
(define %r-jolt-pr-readable jolt-pr-readable)
|
||||
(set! jolt-pr-readable (lambda (x) (if (jrec? x) (jrec-pr x) (%r-jolt-pr-readable x))))
|
||||
|
||||
;; records are map? and coll? (Clojure: a record IS an associative map). Override
|
||||
;; the public predicates to include jrec.
|
||||
;; records are map? and coll? (Clojure: a record IS an associative map). The
|
||||
;; predicates.ss vars hold a snapshot, so re-def-var! after extending. record? is
|
||||
;; the overlay's (some? (get x :jolt/deftype)) — works for free since the get
|
||||
|
|
@ -244,7 +240,7 @@
|
|||
;; protocol's extended impls over the reify's host tags
|
||||
;; (e.g. an Object/default extension). malli reifies some
|
||||
;; protocols and relies on a protocol's default for the
|
||||
;; rest (jolt-az9a).
|
||||
;; rest.
|
||||
(let loop ((tags (value-host-tags obj)))
|
||||
(cond ((null? tags) (error #f (string-append "No reified method " method-name)))
|
||||
((find-protocol-method (car tags) proto-name method-name)
|
||||
|
|
@ -290,7 +286,7 @@
|
|||
((reified-methods obj)
|
||||
=> (lambda (rm) (let ((f (hashtable-ref rm method-name #f)))
|
||||
(if f (apply jolt-invoke f obj rest) (error #f (string-append "No method " method-name))))))
|
||||
;; java.lang.String interop (jolt-nfca): defined in natives-str.ss, loaded
|
||||
;; java.lang.String interop: defined in natives-str.ss, loaded
|
||||
;; after this file (free reference, resolved at call time).
|
||||
((string? obj) (jolt-string-method method-name obj rest))
|
||||
((jiterator? obj)
|
||||
|
|
@ -505,7 +501,7 @@
|
|||
(let ((s (jrec-pr v))) (substring s 1 (string-length s)))))
|
||||
(%r-str-render-one v))))
|
||||
|
||||
;; `type` lives in natives-meta.ss (jolt-fmm4): it needs jolt-meta for the :type
|
||||
;; `type` lives in natives-meta.ss: it needs jolt-meta for the :type
|
||||
;; override and a total value->taxonomy mapping, so it sits with meta — a record
|
||||
;; yields (jolt-symbol #f (jrec-tag x)), the ns.Name class-name symbol.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;; Phase 1 (jolt-cf1q.2) — regex on Chez via vendored irregex (jolt-i0s3).
|
||||
;; regex on Chez via vendored irregex.
|
||||
;;
|
||||
;; Chez has no regex at all. We vendor
|
||||
;; Alex Shinn's irregex (vendor/irregex, BSD) — a portable Scheme regex with
|
||||
|
|
@ -33,7 +33,7 @@
|
|||
(apply %chez-error args)))
|
||||
(load "vendor/irregex/irregex.scm")
|
||||
|
||||
;; Unicode property classes \p{...} (jolt-y1zq): irregex's string syntax has no
|
||||
;; Unicode property classes \p{...}: irregex's string syntax has no
|
||||
;; \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
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;; Phase 1 (jolt-cf1q.2) — the minimal Chez RT the emitted Scheme rests on.
|
||||
;; The minimal Chez RT the emitted Scheme rests on.
|
||||
;;
|
||||
;; Sits above the value model (values.ss) and below an emitted program. Adds the
|
||||
;; two things the back end's output references that aren't in the value layer:
|
||||
|
|
@ -20,7 +20,7 @@
|
|||
;; jolt `not`: only nil and false are falsey.
|
||||
(define (jolt-not x) (if (jolt-truthy? x) #f #t))
|
||||
|
||||
;; --- exceptions (jolt-vcsl) --------------------------------------------------
|
||||
;; --- exceptions --------------------------------------------------------------
|
||||
;; 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.
|
||||
|
|
@ -50,7 +50,7 @@
|
|||
jolt-kw-data jolt-nil
|
||||
jolt-kw-cause (if (null? more) jolt-nil (car more))))
|
||||
|
||||
;; --- host interop (jolt-0kf5) ------------------------------------------------
|
||||
;; --- host interop ------------------------------------------------------------
|
||||
;; (.method target arg*) lowers to (jolt-host-call "method" target arg*). JVM
|
||||
;; interop has no general Chez analog, but the few methods jolt-core's io tier
|
||||
;; calls map onto Chez equivalents: a writer's .write is a port display; a File's
|
||||
|
|
@ -74,7 +74,7 @@
|
|||
(define jolt-unbound (string->symbol "#<jolt-unbound>"))
|
||||
;; `defined?` distinguishes a genuinely interned var (def / declare / a native-op
|
||||
;; cell) from a cell lazily materialised by a forward `var-deref` / `(var x)` on a
|
||||
;; not-yet-defined name — `resolve` returns the cell iff defined? (jolt-yxqm).
|
||||
;; not-yet-defined name — `resolve` returns the cell iff defined?.
|
||||
;; ns-unmap clears it. Avoids the (def x nil) edge of probing the root.
|
||||
(define-record-type var-cell (fields ns name (mutable root) (mutable defined?)) (nongenerative var-cell-v2))
|
||||
(define var-table (make-hashtable string-hash string=?))
|
||||
|
|
@ -93,7 +93,7 @@
|
|||
;; (pr-str (def x 1)) is "#'ns/x". The prelude's def-var! forms discard the
|
||||
;; return, so this is transparent there.
|
||||
(define (def-var! ns name v) (let ((c (jolt-var ns name))) (var-cell-root-set! c v) (var-cell-defined?-set! c #t) c))
|
||||
;; var def-time metadata (jolt-zikh): the :def emit passes the def's reader meta
|
||||
;; var def-time metadata: the :def emit passes the def's reader meta
|
||||
;; (^:private / ^Type tag / docstring -> {:doc}) here, stored in an eq side-table
|
||||
;; keyed by the cell. jolt-meta (natives-meta.ss) merges it onto {:ns :name},
|
||||
;; which it derives from the cell — so EVERY var (plain def, native-op, declare)
|
||||
|
|
@ -103,7 +103,7 @@
|
|||
(define jolt-kw-var-name (keyword #f "name"))
|
||||
(define (def-var-with-meta! ns name v m)
|
||||
(let ((c (def-var! ns name v))) (hashtable-set! var-meta-table c m) c))
|
||||
;; runtime-macro registry (jolt-r9lm, inc6b): a var whose root holds a macro
|
||||
;; runtime-macro registry: a var whose root holds a macro
|
||||
;; expander fn is flagged here, so the ON-CHEZ analyzer's form-macro?/form-expand-1
|
||||
;; (host-contract.ss) expand it. The prelude emits each core/stdlib defmacro as a
|
||||
;; def-var! of its (cross-compiled) expander followed by (mark-macro! ns name).
|
||||
|
|
@ -124,17 +124,17 @@
|
|||
(hashtable-set! var-table k c)
|
||||
c))))
|
||||
|
||||
;; regex (jolt-i0s3): defines regex-t + the re-* fns (def-var!'d into
|
||||
;; regex: defines regex-t + the re-* fns (def-var!'d into
|
||||
;; clojure.core), so it loads after def-var! and before the printer below (which
|
||||
;; renders a regex-t as #"source").
|
||||
(load "host/chez/regex.ss")
|
||||
|
||||
;; atoms (jolt-9ziu): host-coupled mutable cells; def-var!'d into clojure.core
|
||||
;; atoms: host-coupled mutable cells; def-var!'d into clojure.core
|
||||
;; (atom/deref/swap!/reset! + the compare/vals kernel). Loads after def-var! and
|
||||
;; jolt-invoke (seq.ss) / jolt= (values.ss) / jolt-vector (collections.ss).
|
||||
(load "host/chez/atoms.ss")
|
||||
|
||||
;; type predicates + simple accessors (jolt-9ziu): seed natives the overlay
|
||||
;; type predicates + simple accessors: seed natives the overlay
|
||||
;; assumes (map?/vector?/nil?/number?/.../name/namespace), def-var!'d into
|
||||
;; clojure.core. Loads after the value-model record predicates they wrap.
|
||||
(load "host/chez/predicates.ss")
|
||||
|
|
@ -158,7 +158,6 @@
|
|||
;; quotes), chars as `\c`/`\newline`, collections recursively. NOTE: maps/sets
|
||||
;; 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)
|
||||
(cond ((null? strs) "") ((null? (cdr strs)) (car strs))
|
||||
(else (string-append (car strs) " " (jolt-str-join (cdr strs))))))
|
||||
|
|
@ -197,174 +196,174 @@
|
|||
(loop (jolt-seq (seq-more s)) (cons (jolt-pr-str (seq-first s)) acc))))) ")"))
|
||||
(else (format "~a" x))))
|
||||
|
||||
;; converters + string ops (jolt-t6cr): str/subs/vec/keyword/symbol/compare/int/
|
||||
;; converters + string ops: str/subs/vec/keyword/symbol/compare/int/
|
||||
;; double/gensym — host-coupled seed natives def-var!'d into clojure.core. Loaded
|
||||
;; LAST because `str` reuses jolt-pr-str (defined just above).
|
||||
(load "host/chez/converters.ss")
|
||||
|
||||
;; transients (jolt-kl2l): copy-on-write transient collections + persistent disj;
|
||||
;; transients: copy-on-write transient collections + persistent disj;
|
||||
;; extends get/count/contains? to see through a transient. After collections.ss
|
||||
;; (the persistent ops it delegates to).
|
||||
(load "host/chez/transients.ss")
|
||||
|
||||
;; seq-native shims (jolt-y6mv): mapcat/take-while/drop-while/partition/sort +
|
||||
;; seq-native shims: mapcat/take-while/drop-while/partition/sort +
|
||||
;; reduced/reduced?/identical? — seed-native fns the overlay assumes are core
|
||||
;; natives. Over the seq layer + jolt-compare, so loaded after converters.ss.
|
||||
(load "host/chez/natives-seq.ss")
|
||||
|
||||
;; readable printer + output seams (jolt-9zhh, Phase 2 inc B): __pr-str1/__write/
|
||||
;; readable printer + output seams: __pr-str1/__write/
|
||||
;; __with-out-str/__eprint/__eprintf — the host seams the overlay print family
|
||||
;; (pr-str/pr/prn/print/println/*-str) is built on. After converters.ss (uses
|
||||
;; jolt-pr-str/jolt-str-join) + seq.ss (jolt-invoke).
|
||||
(load "host/chez/printing.ss")
|
||||
|
||||
;; collection constructors + rand (jolt-agw6, Phase 2 inc A): bind the public
|
||||
;; collection constructors + rand: bind the public
|
||||
;; clojure.core names hash-map/hash-set/array-map/set/rand to the existing
|
||||
;; pmap/pset ctors. After collections.ss (the ctors) + seq.ss (seq->list).
|
||||
(load "host/chez/natives-coll.ss")
|
||||
|
||||
;; bit ops + parse-long/parse-double (jolt-cf1q.3 inc C): host-coupled scalar
|
||||
;; bit ops + parse-long/parse-double: host-coupled scalar
|
||||
;; seed natives over the all-flonum number model.
|
||||
(load "host/chez/natives-num.ss")
|
||||
|
||||
;; multimethods (jolt-9ls5): defmulti/defmethod dispatch runtime. Needs jolt-invoke
|
||||
;; multimethods: defmulti/defmethod dispatch runtime. Needs jolt-invoke
|
||||
;; (seq.ss), jolt=/key-hash/jolt-hash-map (collections.ss), jolt-atom? (atoms.ss),
|
||||
;; jolt-pr-str (above), and the var-cell machinery — so loaded last.
|
||||
(load "host/chez/multimethods.ss")
|
||||
|
||||
;; records + protocols (jolt-jgoc, Phase 2 inc D): defrecord/deftype/defprotocol/
|
||||
;; records + protocols: defrecord/deftype/defprotocol/
|
||||
;; extend-type/reify. A jrec record type set!-extended into the collection
|
||||
;; dispatchers + a protocol registry. After multimethods.ss (chez-current-ns) and
|
||||
;; the dispatchers/printers it wraps (collections/seq/values/converters/printing/
|
||||
;; transients).
|
||||
(load "host/chez/records.ss")
|
||||
|
||||
;; metadata (jolt-rkbc, Phase 2 inc E): meta / with-meta over an identity-keyed
|
||||
;; metadata: meta / with-meta over an identity-keyed
|
||||
;; side-table. After records.ss (jrec) + the collection ctors it copies.
|
||||
(load "host/chez/natives-meta.ss")
|
||||
|
||||
;; host class tokens (jolt-13zk): bare class names (String/Keyword/File...) ->
|
||||
;; host class tokens: bare class names (String/Keyword/File...) ->
|
||||
;; canonical JVM class-name strings + (class x). After natives-meta.ss (jolt-type)
|
||||
;; and the printer (jolt-str-render-one).
|
||||
(load "host/chez/host-class.ss")
|
||||
|
||||
;; dynamic vars (jolt-9ls5): *clojure-version* / *unchecked-math* constants the host
|
||||
;; dynamic vars: *clojure-version* / *unchecked-math* constants the host
|
||||
;; binds natively. After collections.ss (jolt-hash-map) + def-var!.
|
||||
(load "host/chez/dynamic-vars.ss")
|
||||
|
||||
;; host tables + sorted collections (jolt-0zoy, Phase 2): jolt.host/tagged-table/
|
||||
;; host tables + sorted collections: jolt.host/tagged-table/
|
||||
;; ref-put!/ref-get + the 25-sorted tier's runtime (sorted-map/sorted-set routed
|
||||
;; through their :ops table). Loaded LAST — wraps the jrec-extended dispatchers
|
||||
;; (records.ss), jolt-disj (transients.ss), and value-host-tags (records.ss).
|
||||
(load "host/chez/host-table.ss")
|
||||
|
||||
;; lazy-seq bridge (jolt-dmw9, Phase 2): make-lazy-seq / coll->cells over the
|
||||
;; lazy-seq bridge: make-lazy-seq / coll->cells over the
|
||||
;; cseq model — unblocks every overlay fn built on the lazy-seq macro (repeat/
|
||||
;; iterate/cycle/dedupe/take-nth/keep/interpose/reductions/tree-seq/lazy-cat).
|
||||
;; Loaded LAST so %ls-seq captures the fully-extended (sorted-aware) jolt-seq.
|
||||
(load "host/chez/lazy-bridge.ss")
|
||||
|
||||
;; volatiles + sequence / transduce (jolt-xjx6, Phase 2): native volatile boxes +
|
||||
;; volatiles + sequence / transduce: native volatile boxes +
|
||||
;; the transduce/sequence entry points over into-xform/reduce-seq. After
|
||||
;; natives-seq.ss (into-xform), seq.ss (reduce-seq) + atoms.ss (deref).
|
||||
(load "host/chez/natives-xform.ss")
|
||||
|
||||
;; vars as first-class objects (jolt-n7rz, Phase 2): var?/var-get/deref/invoke/=/
|
||||
;; vars as first-class objects: var?/var-get/deref/invoke/=/
|
||||
;; pr-str over the rt.ss var-cell. After natives-xform.ss (chains deref) + the
|
||||
;; printers. emit lowers :the-var to (jolt-var ns name).
|
||||
(load "host/chez/vars.ss")
|
||||
|
||||
;; misc scalar natives (jolt-cf1q.3): UUID (random-uuid/parse-uuid/uuid?), format/
|
||||
;; misc scalar natives: UUID (random-uuid/parse-uuid/uuid?), format/
|
||||
;; printf, tagged-literal, bigint. After the printers + converters (str/pr-str of
|
||||
;; a uuid). Overlay names (uuid?/random-uuid/parse-uuid/tagged-literal?) re-asserted
|
||||
;; in post-prelude.ss.
|
||||
(load "host/chez/natives-misc.ss")
|
||||
|
||||
;; namespaces (jolt-yxqm, Phase 2): the namespace value model — find-ns/ns-name/
|
||||
;; namespaces: the namespace value model — find-ns/ns-name/
|
||||
;; all-ns/the-ns/create-ns/in-ns/ns-publics/ns-map/ns-interns/ns-aliases/resolve/
|
||||
;; find-var/ns-unmap/*ns*, over the var-table + chez-current-ns. Loaded LAST: needs
|
||||
;; var-cell + var-cell-defined?, jolt-symbol/jolt-hash-map/jolt-assoc, chez-current-ns
|
||||
;; (multimethods.ss), list->cseq (seq.ss), and the fully-patched printers (vars.ss).
|
||||
(load "host/chez/ns.ss")
|
||||
|
||||
;; dynamic var binding (jolt-2o7x, Phase 2): the per-thread binding stack +
|
||||
;; dynamic var binding: the per-thread binding stack +
|
||||
;; push/pop/get-thread-bindings/__thread-bound?/var-set/alter-var-root/__local-var.
|
||||
;; Chains var-deref (rt.ss) and jolt-var-get (vars.ss) onto the stack, so a `binding`
|
||||
;; frame is seen by every var read. Loaded LAST: needs the fully-extended var-read
|
||||
;; paths + jolt-hash-map/pmap-fold/pmap-assoc (collections.ss).
|
||||
(load "host/chez/dyn-binding.ss")
|
||||
|
||||
;; java.lang.String method interop (jolt-nfca, Phase 2): jolt-string-method, the
|
||||
;; java.lang.String method interop: jolt-string-method, the
|
||||
;; portable String/CharSequence surface record-method-dispatch falls through to on
|
||||
;; a string target. After regex.ss (jolt-re-pattern/regex-t-irx) + records.ss
|
||||
;; (which references jolt-string-method).
|
||||
(load "host/chez/natives-str.ss")
|
||||
|
||||
;; host class statics + constructors (jolt-avt6, Phase 2): host-static-ref/
|
||||
;; host class statics + constructors: host-static-ref/
|
||||
;; host-static-call/host-new + the jhost method registry. Loads LAST — it extends
|
||||
;; record-method-dispatch (records.ss) and reuses natives-str helpers (str-trim,
|
||||
;; ascii-string-down, re-split, str-split-drop-trailing) + the regex-t accessors.
|
||||
(load "host/chez/host-static.ss")
|
||||
|
||||
;; generic dot-form dispatch (jolt-kuic): field access + map/vector member access
|
||||
;; generic dot-form dispatch: field access + map/vector member access
|
||||
;; for the `.` / `.-field` desugar. Loads after host-static.ss so it wraps every
|
||||
;; record-method-dispatch arm (jhost/number/regex/jrec/string) and falls through.
|
||||
(load "host/chez/dot-forms.ss")
|
||||
|
||||
;; java.io.File + host file I/O (jolt-yyud): path-backed jfile record, slurp/spit/
|
||||
;; java.io.File + host file I/O: path-backed jfile record, slurp/spit/
|
||||
;; flush, file-seq dir primitives, clojure.java.io/file. Loads LAST so its jfile
|
||||
;; arm wraps the fully-built record-method-dispatch and the str/type/instance-check
|
||||
;; extensions sit over every prior shim.
|
||||
(load "host/chez/io.ss")
|
||||
|
||||
;; #inst values + java.time formatting (jolt-at0a inc X): jinst (RFC3339 ms) +
|
||||
;; #inst values + java.time formatting: jinst (RFC3339 ms) +
|
||||
;; DateTimeFormatter/Instant/ZoneId/LocalDateTime/FormatStyle/Locale/Date. Loads
|
||||
;; LAST — it extends record-method-dispatch / jolt-get / jolt= / jolt-hash /
|
||||
;; jolt-pr-str / jolt-type / instance-check and uses host-static.ss's registries.
|
||||
(load "host/chez/inst-time.ss")
|
||||
|
||||
;; Chez-side data reader (jolt-r8ku inc Y): read-string / __parse-next /
|
||||
;; Chez-side data reader: read-string / __parse-next /
|
||||
;; __read-tagged. Loads after inst-time.ss — __read-tagged reuses its #uuid/#inst
|
||||
;; constructors, and the reader needs the full value/collection layer above.
|
||||
(load "host/chez/reader.ss")
|
||||
|
||||
;; clojure.math (jolt-22vo): native flonum-math shims def-var!'d into the
|
||||
;; clojure.math: native flonum-math shims def-var!'d into the
|
||||
;; clojure.math ns. Self-contained (only def-var! + Chez math), order-independent.
|
||||
(load "host/chez/math.ss")
|
||||
|
||||
;; parity shims (jolt-cf1q.7): native clojure.core fns missing on the zero-Janet
|
||||
;; spine (hash family / rseq / cat / transient?). After host-table.ss (sorted),
|
||||
;; parity shims: native clojure.core fns not covered by the overlay
|
||||
;; (hash family / rseq / cat / transient?). After host-table.ss (sorted),
|
||||
;; transients.ss, values.ss (jolt-hash), seq.ss.
|
||||
(load "host/chez/natives-parity.ss")
|
||||
|
||||
;; Java-style arrays (jolt-cf1q.7): object/typed array constructors + a jolt-array
|
||||
;; Java-style arrays: object/typed array constructors + a jolt-array
|
||||
;; backing; extends count/nth/seq/get/ref-put! so the overlay aget/aset/alength see
|
||||
;; it. After the dispatchers it chains.
|
||||
(load "host/chez/natives-array.ss")
|
||||
|
||||
;; clojure.lang.PersistentQueue (jolt-b8he): a functional queue + EMPTY static.
|
||||
;; clojure.lang.PersistentQueue: a functional queue + EMPTY static.
|
||||
;; Chains seq/count/empty?/peek/pop/conj/sequential?/class/instance?/printer, so
|
||||
;; load after natives-array (the dispatchers it extends).
|
||||
(load "host/chez/natives-queue.ss")
|
||||
|
||||
;; syntax-quote form builders (jolt-r9lm, inc6b): __sqcat/__sqvec/__sqmap/__sqset/
|
||||
;; syntax-quote form builders: __sqcat/__sqvec/__sqmap/__sqset/
|
||||
;; __sq1, def-var!'d into clojure.core. A cross-compiled macro expander (analyzer
|
||||
;; on Chez, inc6b) calls these to build its expansion as reader forms. Needs the
|
||||
;; on Chez) calls these to build its expansion as reader forms. Needs the
|
||||
;; collection/seq layer + def-var!; order-independent past those.
|
||||
(load "host/chez/syntax-quote.ss")
|
||||
|
||||
;; concurrency (jolt-byjr): real OS-thread futures + blocking promises, shared-heap
|
||||
;; concurrency: real OS-thread futures + blocking promises, shared-heap
|
||||
;; (JVM) semantics. Loaded LAST — chains the fully-built jolt-deref and conveys the
|
||||
;; thread-local binding stack (dyn-binding.ss) into workers. pmap/pcalls/pvalues
|
||||
;; (overlay, over `future`) light up once future-call exists here.
|
||||
(load "host/chez/concurrency.ss")
|
||||
|
||||
;; clojure.core.async (jolt-byjr): real-thread blocking channels + go/go-loop/
|
||||
;; clojure.core.async: real-thread blocking channels + go/go-loop/
|
||||
;; thread macros, def-var!'d into clojure.core.async. After concurrency.ss (reuses
|
||||
;; ms->duration) and the collection/seq layer.
|
||||
(load "host/chez/async.ss")
|
||||
|
||||
;; BigDecimal (jolt-i2jm): the jbigdec value type + bigdec/decimal?/class/equality/
|
||||
;; BigDecimal: the jbigdec value type + bigdec/decimal?/class/equality/
|
||||
;; printing. Loads LAST so its set!-wraps of jolt-class/jolt=2/the printers sit
|
||||
;; outermost over every earlier extension.
|
||||
(load "host/chez/bigdec.ss")
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
;; run-corpus.ss — the standing correctness gate, pure Chez. NO Janet.
|
||||
;; run-corpus.ss — the standing correctness gate.
|
||||
;;
|
||||
;; Loads the checked-in seed (host/chez/seed/{prelude,image}.ss) + the zero-Janet
|
||||
;; spine, reads test/chez/corpus.edn, and for each row evaluates :actual and
|
||||
;; Loads the checked-in seed (host/chez/seed/{prelude,image}.ss) + the spine,
|
||||
;; reads test/chez/corpus.edn, and for each row evaluates :actual and
|
||||
;; :expected through jolt-compile-eval and compares by value-equality (jolt=). The
|
||||
;; corpus :expected is JVM-sourced (test/conformance/regen-corpus.clj), so this
|
||||
;; measures jolt-on-Chez against reference Clojure.
|
||||
|
|
@ -170,7 +170,7 @@
|
|||
(define n-eval (+ pass (length crashes) (length diverged) (length known-hit)))
|
||||
(define secs (let ((d (time-difference (current-time) t0)))
|
||||
(+ (time-second d) (/ (time-nanosecond d) 1e9))))
|
||||
(printf "\nZero-Janet corpus parity: ~a/~a evaluated cases pass (~as)\n"
|
||||
(printf "\nCorpus parity: ~a/~a evaluated cases pass (~as)\n"
|
||||
pass n-eval (/ (round (* secs 10)) 10.0))
|
||||
(printf " crash: ~a NEW divergence: ~a known: ~a (throws skipped: ~a)\n"
|
||||
(length crashes) (length diverged) (length known-hit) throws)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
;; run-sci.ss — SCI conformance: load borkdude/sci's own source (vendor/sci) through
|
||||
;; joltc and require its forms to compile+eval. A real-world Clojure-compatibility
|
||||
;; stress test. Pure Chez, no Janet. Floor-gated like the corpus: a regression below
|
||||
;; stress test. Floor-gated like the corpus: a regression below
|
||||
;; the floor (or the count today, 205/218) fails. Raise the floor as host gaps close
|
||||
;; (the tail is genuine gaps — set! on vars, some macro/def shapes).
|
||||
;;
|
||||
|
|
@ -54,7 +54,7 @@
|
|||
(define verbose (and (getenv "SCI_VERBOSE") #t))
|
||||
|
||||
;; stubs first (host shims SCI's source expects)
|
||||
(for-each (lambda (f) (load-forms (string-append "src/jolt/clojure/sci/" f) verbose))
|
||||
(for-each (lambda (f) (load-forms (string-append "stdlib/clojure/sci/" f) verbose))
|
||||
'("lang_stubs.clj" "io_stubs.clj" "host_stubs.clj"))
|
||||
|
||||
(define sci-base "vendor/sci/src/sci/")
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;; run-unit.ss — host-specific unit gate, pure Chez. NO Janet.
|
||||
;; run-unit.ss — host-specific unit gate.
|
||||
;;
|
||||
;; Loads the checked-in seed + spine, reads test/chez/unit.edn, and for each case
|
||||
;; evaluates :expr (wrapped in (do ...), as `joltc -e` does) and compares its PRINTED
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;; Phase 1 (jolt-cf1q.2, inc 3b) — the seq tier on the Chez RT.
|
||||
;; The seq tier on the Chez RT.
|
||||
;;
|
||||
;; One lazy-capable node (cseq) models Clojure's list, cons, and lazy seq — all
|
||||
;; print as (...), all sequential-= to each other AND to vectors. `jolt-seq`
|
||||
|
|
@ -21,13 +21,13 @@
|
|||
;; list? : #t when this cell is a PersistentList node (list literal / (list ...)
|
||||
;; / cons / reverse / conj-onto-list) vs a lazy or vector-backed seq cell — the
|
||||
;; 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
|
||||
;; since one record type backs both (clojure.core/list?). The marker
|
||||
;; lives on the cell, so (rest a-list) / (seq a-vector) / (map …) yield plain seq
|
||||
;; cells and are not list?.
|
||||
;; cvec/ci: for a vector-backed seq cell, the backing vector and this cell's
|
||||
;; element index — so it is a real chunked-seq (chunked-seq? true, chunk-first
|
||||
;; hands out a 32-element block, chunk-rest is the seq at the next block) and
|
||||
;; reduce iterates the vector directly with no per-element cells (jolt-hs5q).
|
||||
;; reduce iterates the vector directly with no per-element cells.
|
||||
;; cvec is #f for every other seq; stored as two fields (not a cons) so a vector
|
||||
;; seq cell costs no extra allocation. The rest of the seq layer ignores them, so
|
||||
;; first/rest/count/printing are unchanged.
|
||||
|
|
@ -45,7 +45,7 @@
|
|||
(define-record-type empty-list-t (fields) (nongenerative empty-list-v1))
|
||||
(define jolt-empty-list (make-empty-list-t))
|
||||
|
||||
;; reduced (jolt-y6mv): a box a reducing fn returns to stop reduce early. The
|
||||
;; reduced: a box a reducing fn returns to stop reduce early. The
|
||||
;; reduce machinery below unwraps it; (deref a-reduced) / unreduced also read it.
|
||||
;; reduced?/reduced are def-var!'d into clojure.core in natives-seq.ss.
|
||||
(define-record-type jolt-reduced (fields val) (nongenerative jolt-reduced-v1))
|
||||
|
|
@ -213,7 +213,7 @@
|
|||
(if (if (> step 0.0) (< n end) (> n end))
|
||||
(cseq-lazy n (lambda () (range-bounded (+ n step) end step)))
|
||||
jolt-nil))
|
||||
;; numeric tower (jolt-n6al): exact 0/1 defaults so (range 3) yields exact ints
|
||||
;; numeric tower: exact 0/1 defaults so (range 3) yields exact ints
|
||||
;; (= JVM longs); flonum args still produce flonums (Scheme arithmetic preserves).
|
||||
(define jolt-range
|
||||
(case-lambda
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
;; 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
|
||||
;; syntax-quote form builders. A macro expander whose body was a syntax-quote
|
||||
;; template (lowered by jolt.host/form-syntax-quote-lower) calls these at RUNTIME
|
||||
;; to build the EXPANSION as READER forms (cseq list / pvec / pmap / tagged-set
|
||||
;; pmap) so the on-Chez analyzer can re-analyze it. def-var!'d into clojure.core,
|
||||
;; so the lowered body's
|
||||
;; unqualified __sqcat/__sqvec/__sqmap/__sqset/__sq1 refs (which lower to var-deref
|
||||
;; in prelude mode) resolve here.
|
||||
;;
|
||||
|
|
@ -36,7 +36,7 @@
|
|||
;; pmap that __sqcat/__sqvec/__sqmap build double as their own form rep — but a set
|
||||
;; value (pset) differs from the reader's set FORM ({:jolt/type :jolt/set :value
|
||||
;; <pvec>}), so building the tagged form here would make a runtime `#{~@xs} a map,
|
||||
;; not a set (jolt-r9lm regression). Build the value; the analyzer's form-set?
|
||||
;; not a set. Build the value; the analyzer's form-set?
|
||||
;; (host-contract.ss) additionally recognizes a pset, so a macro template's #{...}
|
||||
;; expansion still re-analyzes as a set literal.
|
||||
(define (jolt-sqset . parts) (apply jolt-hash-set (sq-flatten parts)))
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
;; transients (jolt-kl2l) — mutable backing per collection kind, snapshotted to
|
||||
;; the immutable collection on persistent!. A faithful port of the Janet host's
|
||||
;; mutable transients: conj!/assoc!/dissoc!/disj!/pop! mutate in place (amortized
|
||||
;; O(1)); persistent! converts back to a pvec / pmap / pset once.
|
||||
;; transients — mutable backing per collection kind, snapshotted to the immutable
|
||||
;; collection on persistent!. conj!/assoc!/dissoc!/disj!/pop! mutate in place
|
||||
;; (amortized O(1)); persistent! converts back to a pvec / pmap / pset once.
|
||||
;;
|
||||
;; vec : a growable Scheme vector (capacity) + a fill count `n`. conj!/pop! are
|
||||
;; O(1) amortized — the old copy-on-write rebuilt the whole vector per op,
|
||||
;; so building an N-vector was O(N^2).
|
||||
;; map : a Chez hashtable keyed by key-hash / jolt= (value-equality, nil-safe —
|
||||
;; a jolt-nil key stores fine here, unlike a Janet table).
|
||||
;; a jolt-nil key stores fine here).
|
||||
;; set : a Chez hashtable of elements.
|
||||
;; cow : fallback for anything else (e.g. a sorted coll) — copy-on-write over
|
||||
;; the persistent ops, preserving jolt's superset of Clojure's transients.
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
;; Jolt value model on Chez Scheme — Phase 0a (jolt-cf1q.1).
|
||||
;; Jolt value model on Chez Scheme.
|
||||
;;
|
||||
;; The irreducible value layer the self-hosted RT rests on. Maps Clojure's value
|
||||
;; types onto Chez natives where possible, and adds records only where Chez lacks
|
||||
;; a distinct type (nil sentinel, keywords, ns-bearing symbols). Loaded into an
|
||||
;; env that has already (import (chezscheme)); becomes a real library in Phase 1.
|
||||
;; env that has already (import (chezscheme)).
|
||||
;;
|
||||
;; Design notes:
|
||||
;; - nil is a UNIQUE sentinel, distinct from #f and '() (the classic Lisp-on-Lisp
|
||||
;; trap). jolt false -> Chez #f, jolt true -> #t.
|
||||
;; - Chez's numeric tower IS Clojure's: long->exact integer, double->flonum,
|
||||
;; ratio->exact rational, bigint->bignum. A windfall vs Janet (ratios/bignums
|
||||
;; for free). Clojure `=` is exactness-aware: (= 1 1.0) is FALSE.
|
||||
;; ratio->exact rational, bigint->bignum. Clojure `=` is exactness-aware:
|
||||
;; (= 1 1.0) is FALSE.
|
||||
|
||||
;; --- nil ---------------------------------------------------------------------
|
||||
(define-record-type jolt-nil-t (fields) (nongenerative jolt-nil-v1))
|
||||
|
|
@ -42,7 +42,7 @@
|
|||
|
||||
;; chars/strings: Chez natives (strings treated immutable).
|
||||
|
||||
;; --- jolt equality (Clojure =) — scalars; collections land in Phase 2 --------
|
||||
;; --- jolt equality (Clojure =) — scalars + collections ----------------------
|
||||
(define (jolt=2 a b)
|
||||
(cond
|
||||
((and (jolt-nil? a) (jolt-nil? b)) #t)
|
||||
|
|
@ -69,7 +69,7 @@
|
|||
((jolt=2 a (car rest)) (loop (car rest) (cdr rest)))
|
||||
(else #f))))
|
||||
|
||||
;; --- jolt hash — consistent with jolt= (for the HAMT in 0c / Phase 2) ---------
|
||||
;; --- jolt hash — consistent with jolt= (for the HAMT) -----------------------
|
||||
(define (jolt-hash x)
|
||||
(cond
|
||||
((jolt-nil? x) 0)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;; vars as first-class objects (jolt-cf1q.3, jolt-n7rz) — (var x) / #'x.
|
||||
;; vars as first-class objects — (var x) / #'x.
|
||||
;;
|
||||
;; The emitter lowers :the-var to (jolt-var ns name) — the rt.ss var-cell, which
|
||||
;; is now also a Clojure VAR value. var? / var-get / deref-of-var / var-as-IFn /
|
||||
|
|
@ -6,8 +6,8 @@
|
|||
;; in post-prelude.ss (the overlay reads (get v :root), nil on a record).
|
||||
;;
|
||||
;; Dynamic binding (binding / with-bindings* / var-set / thread-bound? /
|
||||
;; with-redefs) is a separate follow-up — those crash on nil host primitives,
|
||||
;; which is safe (a crash stays a crash, not a divergence).
|
||||
;; with-redefs) lives in dyn-binding.ss, which chains the var-read paths set up
|
||||
;; here.
|
||||
;;
|
||||
;; Loaded LAST (after natives-xform.ss): chains jolt-deref (atom/volatile arms)
|
||||
;; and the printers.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue