diff --git a/jolt-core/clojure/core.clj b/jolt-core/clojure/core.clj new file mode 100644 index 0000000..2b4c40c --- /dev/null +++ b/jolt-core/clojure/core.clj @@ -0,0 +1,12 @@ +;; The Clojure portion of clojure.core. Loaded into the clojure.core namespace at +;; init (api/init), AFTER the Janet primitives are interned by core/init-core!, +;; and compiled by the self-hosted pipeline (analyzer -> IR -> Janet back end). +;; +;; This is the Phase 4 kernel-shrink seam: fns expressible in plain Clojure on top +;; of the remaining Janet primitives move here from core.janet, one at a time, +;; each compiled by the prior stage. Anything here must depend only on core vars +;; already interned by init-core! (and on other overlay fns defined above it). + +(defn ffirst [coll] (first (first coll))) +(defn fnext [coll] (first (next coll))) +(defn nnext [coll] (next (next coll))) diff --git a/src/jolt/api.janet b/src/jolt/api.janet index 15efc01..7171334 100644 --- a/src/jolt/api.janet +++ b/src/jolt/api.janet @@ -27,6 +27,21 @@ x)) +(defn- load-core-overlay! + "Load the Clojure portion of clojure.core (embedded jolt-core/clojure/core.clj) + into the clojure.core namespace, routed through eval-toplevel like any other + source (compiled when :compile?, interpreted otherwise)." + [ctx] + (when-let [src (get stdlib-embed/sources "clojure.core")] + (def saved (ctx-current-ns ctx)) + (ctx-set-current-ns ctx "clojure.core") + (var s src) + (while (> (length (string/trim s)) 0) + (def [form rest] (parse-next s)) + (set s rest) + (when (not (nil? form)) (eval-toplevel ctx form))) + (ctx-set-current-ns ctx saved))) + (defn init "Create a new Jolt evaluation context. opts may contain: @@ -57,6 +72,11 @@ (install-async! ctx) # Host contract (ns jolt.host): the seam the portable jolt-core compiler calls. (host/install! ctx) + # Clojure portion of clojure.core (jolt-core/clojure/core.clj): fns expressed + # in plain Clojure on top of the Janet primitives interned above. Loaded into + # clojure.core and compiled by the self-hosted pipeline (or interpreted when + # :compile? is off). Phase 4 kernel-shrink seam — see that file. + (load-core-overlay! ctx) ctx)) (defn eval-one diff --git a/src/jolt/core.janet b/src/jolt/core.janet index 56f2bf5..2390533 100644 --- a/src/jolt/core.janet +++ b/src/jolt/core.janet @@ -940,10 +940,8 @@ (if (jvec? coll) (make-vec dropped) dropped)))))) (defn core-second [coll] (core-first (core-rest coll))) -(defn core-ffirst [coll] (core-first (core-first coll))) (defn core-nfirst [coll] (core-next (core-first coll))) -(defn core-fnext [coll] (core-first (core-next coll))) -(defn core-nnext [coll] (core-next (core-next coll))) +# ffirst / fnext / nnext now live in the Clojure overlay (jolt-core/clojure/core.clj). (defn core-last [coll] (let [c (realize-for-iteration coll)] @@ -3809,10 +3807,7 @@ "ex-cause" core-ex-cause "prefers" core-prefers "random-uuid" core-random-uuid - "ffirst" core-ffirst "nfirst" core-nfirst - "fnext" core-fnext - "nnext" core-nnext "last" core-last "drop-last" core-drop-last "take-last" core-take-last diff --git a/test/integration/self-host-test.janet b/test/integration/self-host-test.janet index 876fbe8..128a192 100644 --- a/test/integration/self-host-test.janet +++ b/test/integration/self-host-test.janet @@ -74,4 +74,14 @@ (eval-one ctx (parse-string "(+ 1 2)")) (assert (zero? (length ((ctx-find-ns ctx "jolt.analyzer") :mappings))) "analyzer NOT loaded when interpreting")) +# clojure.core overlay: fns moved from core.janet to jolt-core/clojure/core.clj +# load into clojure.core at init and work the same compiled or interpreted. +(print "clojure.core overlay (Clojure-defined core fns)...") +(each opts [{:compile? true} {}] + (let [ctx (init opts)] + (defn ev [s] (normalize-pvecs (eval-one ctx (parse-string s)))) + (assert (= 1 (ev "(ffirst [[1 2] [3 4]])")) "ffirst") + (assert (= 2 (ev "(fnext [1 2 3])")) "fnext") + (assert (= [3 4] (ev "(nnext [1 2 3 4])")) "nnext"))) + (print "self-host pipeline passed!")