Scrub dangling Janet references; drop dead Janet-coupled files
Rephrase comments that pointed at deleted Janet files (emit.janet, the seed
sources, 'the Janet back end punts ...') to present-tense descriptions of the
Chez behavior. Comment/docstring-only; the self-host fixpoint is unchanged
(comments don't affect the compiled seed).
Delete five files that were Janet-host shims with no Chez path: clojure.java.io
(provided natively by host/chez/io.ss), and jolt.{nrepl,png,interop,shell}
(the janet.* bridge, os/shell, janet.net — none exist on Chez).
jolt-cf1q.6
This commit is contained in:
parent
750ce05716
commit
48e2ef5910
53 changed files with 418 additions and 675 deletions
|
|
@ -1,4 +1,4 @@
|
|||
;; clojure.core — kernel tier (stage just above the Janet seed).
|
||||
;; clojure.core — kernel tier (stage just above the host primitives).
|
||||
;;
|
||||
;; These are the structural fns the self-hosted compiler itself uses
|
||||
;; (jolt.analyzer): second/peek/subvec/mapv/update. Because the compiler must be
|
||||
|
|
@ -6,12 +6,11 @@
|
|||
;; before it is built. So this tier is loaded FIRST and, in compile mode, is
|
||||
;; bootstrap-compiled directly into clojure.core (not routed through the
|
||||
;; self-hosted pipeline, which would need these to already exist — the
|
||||
;; circularity that previously forced `second` to stay in Janet). With this tier
|
||||
;; in place the analyzer is built against the Clojure definitions and the Janet
|
||||
;; primitives are gone.
|
||||
;; circularity that previously forced `second` to stay a host primitive). With this tier
|
||||
;; in place the analyzer is built against the Clojure definitions.
|
||||
;;
|
||||
;; Constraint: depend only on core-renames primitives (first/next/nth/count/conj/
|
||||
;; vec/map/apply/assoc/get/…, all hardwired to the Janet seed) and on each other.
|
||||
;; vec/map/apply/assoc/get/…, all hardwired to host primitives) and on each other.
|
||||
|
||||
(defn second [coll] (first (next coll)))
|
||||
|
||||
|
|
|
|||
|
|
@ -157,8 +157,8 @@
|
|||
(defmacro declare [& syms]
|
||||
`(do ~@(map (fn* [s] `(def ~s)) syms)))
|
||||
|
||||
;; destructure — Clojure's binding-vector expander, ported from the Janet seed
|
||||
;; (was core-destructure). Turns a binding vector that may contain destructuring
|
||||
;; destructure — Clojure's binding-vector expander.
|
||||
;; Turns a binding vector that may contain destructuring
|
||||
;; patterns into a plain binding vector (alternating symbol / init-form) built from
|
||||
;; nth/nthnext/get, so the COMPILER only ever sees plain symbols (analyze-bindings
|
||||
;; rejects patterns). `let` consumes it directly; `loop`/`fn` reuse it transitively
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
;; clojure.core — seq tier. Pure-Clojure leaf sequence fns on top of the kernel
|
||||
;; tier (00-kernel) and the Janet seed. Loaded after the kernel tier; in compile
|
||||
;; tier (00-kernel) and the host primitives. Loaded after the kernel tier; in compile
|
||||
;; mode these self-host through the now-built analyzer (interpreted otherwise).
|
||||
;;
|
||||
;; Migration rule for adding fns here: the fn must (1) NOT be in
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
;; neg? throws on non-numbers via <, as Clojure's Numbers.isNeg does.
|
||||
(defn neg? [x] (< x 0))
|
||||
|
||||
;; even?/odd? stay in the seed: (filter even? ...) is idiomatic-hot and the
|
||||
;; even?/odd? stay host primitives: (filter even? ...) is idiomatic-hot and the
|
||||
;; overlay versions cost an extra call layer per element (seq-pipe bench 4x).
|
||||
|
||||
;; Variadic bit ops — canonical Clojure arities folding the binary host op
|
||||
|
|
@ -355,9 +355,9 @@
|
|||
(make-hierarchy) (partition 2 deriv-seq))
|
||||
h))))
|
||||
|
||||
;; --- Stage 3 tier shrink: pure-over-core leaves moved off the Janet seed ----
|
||||
;; --- Stage 3 tier shrink: pure-over-core leaves moved off the host primitives ----
|
||||
|
||||
;; Representation predicates over the overlay's own predicates (no Janet reps).
|
||||
;; Representation predicates over the overlay's own predicates.
|
||||
(defn sequential? [x] (or (vector? x) (seq? x)))
|
||||
(defn associative? [x] (or (map? x) (vector? x)))
|
||||
(defn counted? [x]
|
||||
|
|
@ -381,10 +381,10 @@
|
|||
|
||||
|
||||
;; realized?: defined on the pending types only (delay/lazy-seq/future read
|
||||
;; Tagged-value predicates. The constructors (atom/volatile!/...) stay in Janet,
|
||||
;; but every tagged value carries its kind under :jolt/type (records under
|
||||
;; :jolt/deftype), reachable via get — which is nil on non-tables — so the
|
||||
;; predicates are pure over get and move out of the seed.
|
||||
;; Tagged-value predicates. The constructors (atom/volatile!/...) are host
|
||||
;; primitives, but every tagged value carries its kind under :jolt/type (records
|
||||
;; under :jolt/deftype), reachable via get — which is nil on non-tables — so the
|
||||
;; predicates are pure over get.
|
||||
(defn atom? [x] (= (get x :jolt/type) :jolt/atom))
|
||||
(defn volatile? [x] (= (get x :jolt/type) :jolt/volatile))
|
||||
(defn reader-conditional? [x] (= (get x :jolt/type) :jolt/reader-conditional))
|
||||
|
|
@ -418,7 +418,7 @@
|
|||
:else (throw (str "pop not supported on: " coll))))
|
||||
|
||||
;; doall/dorun: realization boundaries. dorun walks (optionally at most n
|
||||
;; steps — the Janet seed version ignored n); doall walks then returns coll.
|
||||
;; steps); doall walks then returns coll.
|
||||
(defn dorun
|
||||
([coll]
|
||||
(loop [s (seq coll)]
|
||||
|
|
@ -791,7 +791,7 @@
|
|||
(defn numerator [x] (throw (ex-info "numerator requires a ratio (Jolt has no ratios)" {})))
|
||||
(defn denominator [x] (throw (ex-info "denominator requires a ratio (Jolt has no ratios)" {})))
|
||||
|
||||
;; No class hierarchy on the Janet host.
|
||||
;; No class hierarchy on this host.
|
||||
(defn supers [x] #{})
|
||||
|
||||
;; Like Clojure's munge: rewrite dashes to underscores, preserving the argument's
|
||||
|
|
@ -949,7 +949,7 @@
|
|||
;; inst-ms itself.
|
||||
(defn inst-ms* [i] (inst-ms i))
|
||||
|
||||
;; Canonical comp — here rather than the seed so each stage is invoked with
|
||||
;; Canonical comp — here rather than a host primitive so each stage is invoked with
|
||||
;; jolt call semantics: (comp seq :content) works because the keyword stage
|
||||
;; goes through IFn dispatch (raw Janet keyword application does not).
|
||||
(defn comp
|
||||
|
|
@ -1078,7 +1078,7 @@
|
|||
(let [xf (xform f)]
|
||||
(xf (reduce xf init coll)))))
|
||||
|
||||
;; into stays in the seed: it's perf-wall hot (the into-vec bench pays ~11%
|
||||
;; into stays a host primitive: it's perf-wall hot (the into-vec bench pays ~11%
|
||||
;; through the overlay call layers — same lesson as even?/odd? in round 4).
|
||||
|
||||
;; eduction is EAGER on jolt (documented divergence, as before): the composed
|
||||
|
|
@ -1116,8 +1116,8 @@
|
|||
|
||||
;; print-method / print-dup are real multimethods in the io tier (50-io.clj).
|
||||
|
||||
;; JVM proxies don't exist on a Janet host: the read-only surface is inert,
|
||||
;; the constructive surface throws (matching the prior seed stubs).
|
||||
;; JVM proxies don't exist on this host: the read-only surface is inert,
|
||||
;; the constructive surface throws.
|
||||
(defn proxy-mappings [p] {})
|
||||
(defn proxy-call-with-super [f p meth] (f))
|
||||
(defn init-proxy [p mappings] p)
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
;; and the methods become functions — the algorithm is identical.
|
||||
;;
|
||||
;; A sorted-SET stores its elements as keys with a nil value; its ops project the
|
||||
;; key. ALL the semantics live here in Clojure; the Janet seed keeps only its
|
||||
;; key. ALL the semantics live here in Clojure; the host keeps only its
|
||||
;; dispatch branches (conj/assoc/get/seq/count/…), each a one-line call through
|
||||
;; the value's own :ops table, so the ops travel WITH the value (correct across
|
||||
;; contexts, forks, and AOT images). The wrapper is minted/read through the host
|
||||
|
|
@ -286,7 +286,7 @@
|
|||
|
||||
(defn- ss-disj-many [ss xs] (reduce ss-disj-1 ss xs))
|
||||
|
||||
;; --- the ops tables the Janet seed dispatches through ------------------------
|
||||
;; --- the ops tables the host dispatches through ------------------------
|
||||
|
||||
(def ^:private sm-ops
|
||||
{:count (fn [sm] (sfield sm :cnt))
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@
|
|||
;; IMPORTANT — only macros NOT used by the self-hosted compiler (jolt-core/jolt/*)
|
||||
;; or by the earlier overlay tiers belong here; those (and/or/when/when-not/
|
||||
;; when-let/cond/case/doseq/declare/cond->/->) must stay available before this
|
||||
;; tier loads, so they remain in Janet for now. Everything here is user-facing.
|
||||
;; tier loads, so they remain host primitives for now. Everything here is user-facing.
|
||||
;;
|
||||
;; Migration: remove the Janet core-X macro fn AND its core-macro-names entry when
|
||||
;; Migration: remove the host core-X macro fn AND its core-macro-names entry when
|
||||
;; moving a macro here (defmacro installs the :macro flag itself).
|
||||
|
||||
(defmacro comment [& body] nil)
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@
|
|||
()))
|
||||
|
||||
;; --- repeatedly --- ((f) throws on a non-fn; (take n …) throws on a non-number
|
||||
;; count — both now enforced in the seed (jolt-call / core-take), so the canonical
|
||||
;; count — both enforced by the host (jolt-call / take), so the canonical
|
||||
;; CLJ form matches the repeatedly.cljc exception cases.)
|
||||
(defn repeatedly
|
||||
([f] (lazy-seq (cons (f) (repeatedly f))))
|
||||
|
|
@ -105,8 +105,8 @@
|
|||
;; --- partition-all --- (transducer + [n coll] + [n step coll])
|
||||
;; The collection arities realize EXACTLY n per chunk via a first/rest loop and
|
||||
;; continue from the advanced cursor (not a re-drop / nthrest), so they realize
|
||||
;; minimally — matching the Janet pstep the §6.3 laziness counters were written
|
||||
;; against. (A take/nthrest form is correct but over-realizes.)
|
||||
;; minimally — the §6.3 laziness counters depend on this.
|
||||
;; (A take/nthrest form is correct but over-realizes.)
|
||||
(defn partition-all
|
||||
([n]
|
||||
(fn [rf]
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
bootstrap can compile this namespace via its plain :var path. ctx is an opaque
|
||||
host handle threaded to the contract fns; the analyzer never inspects it.
|
||||
|
||||
Coverage grows toward compiler.janet; unsupported forms throw :jolt/uncompilable
|
||||
Unsupported forms throw :jolt/uncompilable
|
||||
so the caller falls back to the interpreter (the hybrid contract).
|
||||
|
||||
`env` carries lexical state: {:locals #{names} :recur recur-target-name|nil}.
|
||||
|
|
@ -140,8 +140,8 @@
|
|||
;; form (the Chez data reader) wraps an arglist vector carrying a return-type hint
|
||||
;; (^bytes [b] / ^String [x y]). Unwrap to the underlying vector so fn parsing sees
|
||||
;; the params — the hint is ignored at runtime. Only the (with-meta <vec> _) shape
|
||||
;; matches, so a real arity clause (head is a vector) and the Janet reader's
|
||||
;; meta-on-tuple (already a vector) pass through unchanged.
|
||||
;; matches, so a real arity clause (head is a vector) and a
|
||||
;; meta-on-vector arglist pass through unchanged.
|
||||
(defn- strip-arglist-meta [form]
|
||||
(if (form-list? form)
|
||||
(let [es (vec (form-elements form))]
|
||||
|
|
@ -212,10 +212,10 @@
|
|||
;; letfn: (letfn [(name [params] body*)...] body*). The named local fns are
|
||||
;; MUTUALLY recursive, so bind every name into the env BEFORE analyzing any spec
|
||||
;; — each spec then resolves its siblings (and itself) as locals. Emitted as a
|
||||
;; :let flagged :letrec so the back ends know the bindings forward-reference each
|
||||
;; other: Chez lowers it to `letrec*`; the Janet back end punts to the
|
||||
;; interpreter (its shared mutable env already gives the letrec semantics that a
|
||||
;; compiled sequential let* lacks — the reason letfn was uncompilable before).
|
||||
;; :let flagged :letrec so the back end knows the bindings forward-reference each
|
||||
;; other: Chez lowers it to `letrec*`. The interpreter's shared mutable env already
|
||||
;; gives the letrec semantics that a
|
||||
;; compiled sequential let* lacks — the reason letfn was uncompilable before.
|
||||
(defn- analyze-letfn [ctx items env]
|
||||
(let [specs (vec (form-vec-items (nth items 1)))
|
||||
names (mapv #(form-sym-name (first (vec (form-elements %)))) specs)
|
||||
|
|
@ -252,9 +252,9 @@
|
|||
(uncompilable "def name with map metadata"))
|
||||
(if (< (count items) 3)
|
||||
;; (def name) with no init (declare): intern + reserve the cell so a
|
||||
;; forward reference resolves. The back ends key on :no-init — Chez
|
||||
;; def-var!s an unbound placeholder; the Janet back end punts to the
|
||||
;; interpreter, which interns a genuinely-unbound var.
|
||||
;; forward reference resolves. The back end keys on :no-init — Chez
|
||||
;; def-var!s an unbound placeholder; the interpreter interns a
|
||||
;; genuinely-unbound var.
|
||||
(let [nm (form-sym-name name-sym) cur (compile-ns ctx)]
|
||||
(host-intern! ctx cur nm)
|
||||
{:op :def :ns cur :name nm :no-init true})
|
||||
|
|
@ -297,8 +297,7 @@
|
|||
|
||||
;; Host interop method call (jolt-0kf5). `(.method target arg*)` — a head that
|
||||
;; starts with "." but not ".-" (field access stays punted). Analyzes to a
|
||||
;; :host-call node; the Janet back end punts it at emit (no interop model -> the
|
||||
;; interpreter runs it), the Chez back end lowers it to a jolt-host-call dispatch.
|
||||
;; :host-call node; the Chez back end lowers it to a jolt-host-call dispatch.
|
||||
(defn- method-head? [nm]
|
||||
(and (> (count nm) 1)
|
||||
(= "." (subs nm 0 1))
|
||||
|
|
@ -320,9 +319,8 @@
|
|||
(not (= "." (subs nm 0 1)))))
|
||||
|
||||
;; `(Class. args*)` and `(new Class args*)` -> a :host-new node carrying the class
|
||||
;; token and the analyzed args. The Janet back end punts it (the interpreter runs
|
||||
;; the constructor from its class-ctors registry); the Chez back end lowers it to
|
||||
;; a runtime constructor dispatch (jolt-avt6).
|
||||
;; token and the analyzed args. The Chez back end lowers it to a runtime
|
||||
;; constructor dispatch (jolt-avt6).
|
||||
(defn- analyze-ctor [ctx class args env]
|
||||
(host-new class (mapv #(analyze ctx % env) args)))
|
||||
|
||||
|
|
@ -330,10 +328,8 @@
|
|||
;; A symbol member whose name starts with "-" is a field read; otherwise it is a
|
||||
;; method (call with the trailing args). Both lower to a :host-call carrying the
|
||||
;; member name verbatim (the leading "-" survives so the runtime dispatcher reads
|
||||
;; it as a field). The Janet back end punts :host-call to the interpreter, which
|
||||
;; re-runs the original `.` form via eval-dot — so Janet behavior is unchanged;
|
||||
;; the Chez back end dispatches it through record-method-dispatch (jolt-kuic).
|
||||
;; A non-symbol member (e.g. a keyword) stays punted — the interpreter handles it.
|
||||
;; it as a field). The Chez back end dispatches it through record-method-dispatch
|
||||
;; (jolt-kuic).
|
||||
(defn- analyze-dot [ctx items env]
|
||||
(when (< (count items) 3)
|
||||
(throw (str "Malformed (. target member ...) form")))
|
||||
|
|
@ -367,11 +363,8 @@
|
|||
(if (= :var (:kind r))
|
||||
(var-ref (:ns r) (:name r))
|
||||
;; A non-var qualified ref `Class/member` is a host class static
|
||||
;; (Math/sqrt, Long/MAX_VALUE, System/getenv). The Janet back end
|
||||
;; punts the :host-static node (the interpreter resolves it from its
|
||||
;; class-statics registry, exactly as it did when this was an
|
||||
;; uncompilable); the Chez back end lowers it to a runtime static
|
||||
;; dispatch (jolt-avt6).
|
||||
;; (Math/sqrt, Long/MAX_VALUE, System/getenv). The Chez back end
|
||||
;; lowers it to a runtime static dispatch (jolt-avt6).
|
||||
(host-static ns nm)))
|
||||
:else (let [r (resolve-global ctx form)]
|
||||
(case (:kind r)
|
||||
|
|
@ -445,12 +438,10 @@
|
|||
(form-map-pairs form)))
|
||||
(form-set? form) (set-node (mapv #(analyze ctx % env) (form-set-items form)))
|
||||
(form-list? form) (analyze-list ctx form env)
|
||||
;; regex literal #"…" -> a :regex IR node (leaf). The Janet back end punts it
|
||||
;; (interpreter compiles via the seed PEG engine); the Chez back end emits a
|
||||
;; regex literal #"…" -> a :regex IR node (leaf). The Chez back end emits a
|
||||
;; jolt-regex value over the vendored irregex.
|
||||
(form-regex? form) {:op :regex :source (form-regex-source form)}
|
||||
;; #inst / #uuid literals -> :inst / :uuid IR leaves. Like :regex, the Janet
|
||||
;; back end punts (the interpreter's data-readers parse them); the Chez back
|
||||
;; #inst / #uuid literals -> :inst / :uuid IR leaves. The Chez back
|
||||
;; end emits a runtime inst/uuid value (host/chez/inst-time.ss).
|
||||
(form-inst? form) {:op :inst :source (form-inst-source form)}
|
||||
(form-uuid? form) {:op :uuid :source (form-uuid-source form)}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,14 @@
|
|||
(ns jolt.backend-scheme
|
||||
"Portable Clojure IR -> Chez Scheme emitter (Chez Phase 3, jolt-cf1q.4).
|
||||
|
||||
The no-Janet replacement for host/chez/emit.janet: consumes the same
|
||||
Consumes the
|
||||
host-neutral IR (jolt.ir, see jolt-core/jolt/ir.clj) the analyzer produces and
|
||||
emits Chez Scheme source TEXT. Pure jolt-core (clojure.core + clojure.string
|
||||
only) so that, once cross-compiled, it runs ON Chez and the analyzer can emit
|
||||
its own code with no Janet in the loop — the bootstrap spine.
|
||||
its own code — the bootstrap spine.
|
||||
|
||||
Output is a STRING of Scheme source; `host/compile` on Chez is `(eval (read
|
||||
...))`. Mirrors emit.janet op-for-op so the value-parity gate holds against the
|
||||
Janet emitter while the port is in flight.
|
||||
...))`. Lowers each IR op to Scheme.
|
||||
|
||||
INCREMENT 1 (jolt-hg7z): const/local/var/the-var/if/do/let/loop/recur/invoke
|
||||
(+ native-ops)/fn/def + the escaping/flonum/munge helpers.
|
||||
|
|
@ -17,7 +16,7 @@
|
|||
quote (emit-quoted, walks the raw reader form via the portable jolt.host form-*
|
||||
contract — same seam the analyzer uses, so it stays host-neutral).
|
||||
INCREMENT 3 (jolt-me6m): try/throw + host-call + regex/inst/uuid + def-meta +
|
||||
quoted-symbol-meta. With this the emitter covers every op emit.janet handles.
|
||||
quoted-symbol-meta. With this the emitter covers every IR op.
|
||||
emit-quoted now also reconstructs plain jolt VALUES (def/symbol :meta), enabled
|
||||
by making :meta a portable struct at the host seam (h-sym-meta). Program
|
||||
assembly + the prelude driver port land with compile-from-source (inc 4+)."
|
||||
|
|
@ -27,8 +26,8 @@
|
|||
form-literal? form-elements form-vec-items
|
||||
form-map-pairs form-set-items form-char-code]]))
|
||||
|
||||
;; Hot clojure.core primitives lowered to native Scheme, mirroring the Janet
|
||||
;; backend's native-ops. `=` is the exactness-aware jolt= from values.ss; inc/dec/
|
||||
;; Hot clojure.core primitives lowered to native Scheme.
|
||||
;; `=` is the exactness-aware jolt= from values.ss; inc/dec/
|
||||
;; not are rt shims; mod/rem/quot map to Scheme's (Scheme has all three).
|
||||
(def ^:private native-ops
|
||||
{"+" "+" "-" "-" "*" "*" "/" "/"
|
||||
|
|
@ -80,7 +79,7 @@
|
|||
|
||||
;; Host interop methods with a Chez RT shim (rt.ss jolt-host-call). A `.method`
|
||||
;; call on any other method routes to record-method-dispatch (a reify/record
|
||||
;; protocol method). Keep in sync with emit.janet's supported-host-methods.
|
||||
;; protocol method).
|
||||
(def ^:private supported-host-methods #{"isDirectory" "listFiles"})
|
||||
|
||||
;; Native-op Scheme procedures that return a genuine Scheme boolean (#t/#f), so an
|
||||
|
|
@ -173,8 +172,7 @@
|
|||
;; reconstruct each as the matching Chez RT constructor — the runtime value of a
|
||||
;; quote is just that literal data. The form is walked via the jolt.host form-*
|
||||
;; contract (the portable seam the analyzer uses), NOT host-native predicates, so
|
||||
;; this stays host-neutral: on Janet the contract walks Janet reader forms, on
|
||||
;; Chez it walks Chez reader forms.
|
||||
;; this stays host-neutral — the contract walks the host's reader forms.
|
||||
(declare emit-quoted)
|
||||
(defn- emit-quoted-map [pairs]
|
||||
;; pairs: a jolt vector of [k-form v-form] pairs (form-map-pairs)
|
||||
|
|
|
|||
|
|
@ -29,14 +29,13 @@
|
|||
|
||||
;; A qualified static reference to a host class member, `Class/member` (e.g.
|
||||
;; Math/sqrt, Long/MAX_VALUE, System/getenv). A leaf node carrying the class and
|
||||
;; member names. The Janet back end punts it (the interpreter resolves the static
|
||||
;; from its class-statics registry); the Chez back end lowers a value ref to
|
||||
;; host-static-ref and a call head to host-static-call (host-static.ss).
|
||||
;; member names. The Chez back end lowers a value ref to host-static-ref and a
|
||||
;; call head to host-static-call (host-static.ss).
|
||||
(defn host-static [class member] {:op :host-static :class class :member member})
|
||||
|
||||
;; A host constructor, `(Class. args*)` / `(new Class args*)`. Carries the class
|
||||
;; name and the analyzed argument nodes. Janet punts (interpreter runs the
|
||||
;; constructor); Chez lowers to host-new (host-static.ss class-ctor registry).
|
||||
;; name and the analyzed argument nodes. Chez lowers to host-new (host-static.ss
|
||||
;; class-ctor registry).
|
||||
(defn host-new [class args] {:op :host-new :class class :args args})
|
||||
|
||||
(defn if-node [test then else] {:op :if :test test :then then :else else})
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
;; :phm (persistent hash map; NOT raw-get-safe)
|
||||
;; :any (top), nil (bottom, identity for join).
|
||||
;; Compound types are small jolt maps, so they compare by value on both the
|
||||
;; Clojure and the Janet (orchestrator) side. struct/vec/set use distinct keys so
|
||||
;; Clojure and the host (orchestrator) side. struct/vec/set use distinct keys so
|
||||
;; a type is recognised by which key it carries.
|
||||
;; (get t :KEY) is nil for a keyword type and the child for a compound, so a
|
||||
;; compound is detected by some? — no map?/contains? needed.
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
(ns jolt.reader
|
||||
"Portable Clojure reader: source text -> reader forms (Chez Phase 3, jolt-cf1q.4).
|
||||
|
||||
The no-Janet replacement for src/jolt/reader.janet. All the lexing/parsing LOGIC
|
||||
All the lexing/parsing LOGIC
|
||||
is portable Clojure; form CONSTRUCTION and string->number parsing delegate to the
|
||||
jolt.host contract (form-make-symbol/char, form-char-from-name, form-scan-number)
|
||||
— a Clojure source file cannot write a {:jolt/type :symbol} literal (it parses as
|
||||
a tagged reader form), and the concrete form representation is the host's to own.
|
||||
Same split the analyzer uses for the form-* readers. Once cross-compiled this runs
|
||||
ON Chez so compile-from-source needs no Janet reader.
|
||||
ON Chez to drive compile-from-source.
|
||||
|
||||
Positions are CHARACTER indices (the Janet reader uses byte indices); for ASCII
|
||||
source they coincide, and form VALUES are identical either way — the parity gate
|
||||
Positions are CHARACTER indices; for ASCII
|
||||
source they coincide with byte indices, and form VALUES are identical either way — the parity gate
|
||||
compares values, not positions.
|
||||
|
||||
INCREMENT 5a (jolt-50xx): the ATOM layer — whitespace/comments, symbols (+ nil/
|
||||
|
|
@ -27,8 +27,8 @@
|
|||
form-elements form-vec-items form-set-items
|
||||
form-map-pairs]]))
|
||||
|
||||
;; Source access by CHARACTER codepoint, mirroring the Janet reader's byte access
|
||||
;; (identical for ASCII). cp = codepoint at i; len = character count.
|
||||
;; Source access by CHARACTER codepoint
|
||||
;; (identical to byte access for ASCII). cp = codepoint at i; len = character count.
|
||||
(defn- cp [s i] (int (nth s i)))
|
||||
(defn- len [s] (count s))
|
||||
|
||||
|
|
@ -71,8 +71,7 @@
|
|||
(if (and (< end (len s)) (symbol-char? (cp s end))) (recur s pos (inc end)) end))
|
||||
|
||||
(defn- read-keyword* [s pos]
|
||||
;; pos is at the first colon; ::foo is treated as :foo (no auto-resolution),
|
||||
;; matching the Janet reader.
|
||||
;; pos is at the first colon; ::foo is treated as :foo (no auto-resolution).
|
||||
(let [start (if (and (< (inc pos) (len s)) (= (cp s (inc pos)) 58)) (+ pos 2) (inc pos))
|
||||
end (read-keyword-name s start start)]
|
||||
[(keyword (subs s start end)) end]))
|
||||
|
|
@ -182,7 +181,7 @@
|
|||
;; :form payload=the form a real datum
|
||||
;; :skip payload=nil a comment (;) or #_ discard — produced nothing
|
||||
;; :splice payload=items-vector #?@ — contributes 0+ items to the enclosing coll
|
||||
;; Out-of-band control (vs the Janet reader's :jolt/skip / :jolt/splice sentinel
|
||||
;; Out-of-band control (rather than :jolt/skip / :jolt/splice sentinel
|
||||
;; FORMS) keeps it collision-free and host-neutral — no tagged-struct to build or
|
||||
;; recognize. Collection readers dispatch on kind; read-next-form skips :skip.
|
||||
(declare read-form)
|
||||
|
|
@ -345,7 +344,7 @@
|
|||
|
||||
(defn- read-tagged* [s pos]
|
||||
;; unknown dispatch -> a tagged literal (#inst, #uuid, #foo). The tag includes
|
||||
;; the leading # (read-symbol-name starts at #), matching the Janet reader.
|
||||
;; the leading # (read-symbol-name starts at #).
|
||||
(let [end (read-symbol-name s pos pos)
|
||||
tag (subs s pos end)
|
||||
[form np] (read-next-form s end)]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue