core: start macro tier — move comment/if-not to the Clojure overlay (jolt-1j0 phase 3)

New 30-macros tier (registered after 20-coll) for user-facing macros expressed as
defmacro + syntax-quote instead of hand-built Janet form-transformers. Validated
end to end: overlay-defined macros expand in interpret, compile AND self-host
modes (conformance 228/228 x3).

Moved comment and if-not; removed their Janet core-X fns + core-macro-names
entries. Note: Jolt defmacro is single-arity, so multi-arglist macros become one
arglist with & rest / destructuring (if-not uses [test then & [else]]). Macros
used by the compiler or earlier tiers (and/or/when/cond/case/cond->/->/declare/
doseq/when-let) stay in Janet until a load-order story exists for them.

full suite green, clojure-test-suite 3930.
This commit is contained in:
Yogthos 2026-06-07 00:29:34 -04:00
parent f0e111563b
commit 330a3a23d9
4 changed files with 31 additions and 14 deletions

View file

@ -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))

View file

@ -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)

View file

@ -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]

View file

@ -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)"])