diff --git a/jolt-core/clojure/core/30-macros.clj b/jolt-core/clojure/core/30-macros.clj new file mode 100644 index 0000000..08bba37 --- /dev/null +++ b/jolt-core/clojure/core/30-macros.clj @@ -0,0 +1,18 @@ +;; clojure.core — macro tier. Macros expressed in Clojure (defmacro + syntax-quote) +;; rather than as hand-built Janet form-transformers. Loaded after the fn tiers, +;; so a macro here may use any already-frozen core fn/macro. +;; +;; 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. +;; +;; Migration: remove the Janet 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) + +;; Single arglist (Jolt defmacro is single-arity); the optional else defaults nil +;; via rest-destructuring. +(defmacro if-not [test then & [else]] + `(if (not ~test) ~then ~else)) diff --git a/src/jolt/api.janet b/src/jolt/api.janet index 66d739a..0290ed0 100644 --- a/src/jolt/api.janet +++ b/src/jolt/api.janet @@ -39,7 +39,8 @@ (def- core-tiers [{:ns "clojure.core.00-kernel" :kernel true} {:ns "clojure.core.10-seq" :kernel false} - {:ns "clojure.core.20-coll" :kernel false}]) + {:ns "clojure.core.20-coll" :kernel false} + {:ns "clojure.core.30-macros" :kernel false}]) (defn- eval-overlay-source [ctx src] (var s src) diff --git a/src/jolt/core.janet b/src/jolt/core.janet index d1e681a..732c9db 100644 --- a/src/jolt/core.janet +++ b/src/jolt/core.janet @@ -2200,13 +2200,6 @@ (array/push result sym) result) -(defn core-if-not - "Macro: (if-not test then else?) -> (if (not test) then else?)" - [test then-form & else-forms] - @[{:jolt/type :symbol :ns nil :name "if"} - @[{:jolt/type :symbol :ns nil :name "not"} test] - then-form - ;else-forms]) (defn core-when-first "Macro: (when-first [sym coll] & body) -> (when-let [sym (first coll)] body...)" @@ -2626,9 +2619,6 @@ name-sym @{}]) -# comment macro — ignores body, returns nil -(defn core-comment [& body] - nil) # defrecord — creates a proper type via deftype + factory functions (defn core-defrecord [name-sym fields-vec & body] @@ -3845,7 +3835,6 @@ "for" core-for "when" core-when "when-not" core-when-not - "if-not" core-if-not "when-first" core-when-first "if-let" core-if-let "when-let" core-when-let @@ -3899,7 +3888,6 @@ "IllegalStateException" core-IllegalStateException "definterface" core-definterface "defrecord" core-defrecord - "comment" core-comment "resolve" core-resolve "ns-name" core-ns-name "update-in" core-update-in @@ -3944,7 +3932,7 @@ (defn core-macro-names "Set of core binding names that are macros." [] - @{"and" true "or" true "cond" true "case" true "for" true "when" true "when-not" true "if-let" true "when-let" true "if-some" true "when-some" true "doto" true "defn" true "defn-" true "declare" true "fn" true "let" true "loop" true "defrecord" true "defprotocol" true "extend-type" true "extend-protocol" true "extend" true "reify" true "proxy" true "definterface" true "comment" true "binding" true "lazy-seq" true "lazy-cat" true "if-not" true "when-first" true "condp" true "dotimes" true "while" true "some->" true "some->>" true "cond->" true "cond->>" true "as->" true "->" true "->>" true "letfn" true "doseq" true "delay" true "assert" true "future" true}) + @{"and" true "or" true "cond" true "case" true "for" true "when" true "when-not" true "if-let" true "when-let" true "if-some" true "when-some" true "doto" true "defn" true "defn-" true "declare" true "fn" true "let" true "loop" true "defrecord" true "defprotocol" true "extend-type" true "extend-protocol" true "extend" true "reify" true "proxy" true "definterface" true "binding" true "lazy-seq" true "lazy-cat" true "when-first" true "condp" true "dotimes" true "while" true "some->" true "some->>" true "cond->" true "cond->>" true "as->" true "->" true "->>" true "letfn" true "doseq" true "delay" true "assert" true "future" true}) (def init-core! (fn [& args] diff --git a/test/spec/macros-spec.janet b/test/spec/macros-spec.janet index cd409ad..551e51d 100644 --- a/test/spec/macros-spec.janet +++ b/test/spec/macros-spec.janet @@ -25,3 +25,13 @@ "(= (gensym) (gensym))"] ["gensym# in template" "true" "(do (defmacro m [] `(let [x# 1] x#)) (= 1 (m)))"]) + +# Core macros ported from Janet to the Clojure overlay (jolt-1j0 phase 3, +# jolt-core/clojure/core/30-macros.clj). +(defspec "macros / core-overlay" + ["if-not true branch" ":then" "(if-not false :then :else)"] + ["if-not else branch" ":else" "(if-not true :then :else)"] + ["if-not no else" "nil" "(if-not true :then)"] + ["if-not no else hit" ":then" "(if-not false :then)"] + ["comment -> nil" "nil" "(comment a b c)"] + ["comment in do" "42" "(do (comment ignored) 42)"])