core: move and/or/cond/when-not to the overlay (enabled by expand-once cache)

The hot control macros now live in the Clojure syntax tier. This was blocked
before: as interpreted overlay macros they re-expanded on every eval, timing out
a battery file (3930->3911). With the expand-once macro cache (prior commit) they
expand a single time with zero runtime cost, so moving them is free.

conformance 228/228 x3, clojure-test-suite 3930 (9 timeouts, not 10), full suite
green, bench flat (overlay vs janet macros within noise).
This commit is contained in:
Yogthos 2026-06-07 10:08:10 -04:00
parent 29a79f34f4
commit 613aaa5451
2 changed files with 25 additions and 54 deletions

View file

@ -11,3 +11,27 @@
(defmacro when [test & body]
`(if ~test (do ~@body)))
(defmacro when-not [test & body]
`(if (not ~test) (do ~@body)))
(defmacro and [& exprs]
(if (empty? exprs)
true
(if (empty? (rest exprs))
(first exprs)
`(let* [and# ~(first exprs)] (if and# (and ~@(rest exprs)) and#)))))
(defmacro or [& exprs]
(if (empty? exprs)
nil
(if (empty? (rest exprs))
(first exprs)
`(let* [or# ~(first exprs)] (if or# or# (or ~@(rest exprs)))))))
;; :else (any truthy value) is just a test, so no special case — (if :else e ...)
;; takes e.
(defmacro cond [& clauses]
(if (empty? clauses)
nil
`(if ~(first clauses) ~(nth clauses 1) (cond ~@(drop 2 clauses)))))

View file

@ -2062,24 +2062,6 @@
(put gensym_counter :val (+ n 1))
{:jolt/type :symbol :ns nil :name (string prefix-string n)})
(defn core-cond
"Macro: (cond test1 expr1 test2 expr2 ... :else default)
-> (if test1 expr1 (if test2 expr2 ...))"
[& clauses]
(defn build [cls]
(if (= 0 (length cls))
nil
(let [t (first cls)]
(if (= :else t)
(if (> (length cls) 1) (in cls 1) nil)
(if (< (length cls) 2)
(error "cond requires an even number of forms")
(let [e (in cls 1)]
@[{:jolt/type :symbol :ns nil :name "if"}
t e
(build (tuple/slice cls 2))]))))))
(build clauses))
(defn core-case
"Macro: (case expr val1 result1 ... default)
Supports single values, lists of values (one-of-many), and symbols."
@ -2113,37 +2095,6 @@
@[{:jolt/type :symbol :ns nil :name "let*"} @[g expr] (build clauses)])
(defn core-when-not
"Macro: (when-not test & body) -> (when (not test) & body)"
[test & body]
(def not-form @[{:jolt/type :symbol :ns nil :name "not"} test])
@[{:jolt/type :symbol :ns nil :name "if"} not-form
@[{:jolt/type :symbol :ns nil :name "do"} ;body]])
(defn core-and
"Macro: (and) -> true, (and x) -> x, (and x y ...) -> (if x (and y ...) x)"
[& exprs]
(if (= 0 (length exprs)) true
(if (= 1 (length exprs)) (first exprs)
@[{:jolt/type :symbol :ns nil :name "let*"}
@[{:jolt/type :symbol :ns nil :name "and__x"} (first exprs)]
@[{:jolt/type :symbol :ns nil :name "if"}
{:jolt/type :symbol :ns nil :name "and__x"}
@[{:jolt/type :symbol :ns nil :name "and"} ;(tuple/slice exprs 1)]
{:jolt/type :symbol :ns nil :name "and__x"}]])))
(defn core-or
"Macro: (or) -> nil, (or x) -> x, (or x y ...) -> (let [or__x x] (if or__x or__x (or y ...)))"
[& exprs]
(if (= 0 (length exprs)) nil
(if (= 1 (length exprs)) (first exprs)
@[{:jolt/type :symbol :ns nil :name "let*"}
@[{:jolt/type :symbol :ns nil :name "or__x"} (first exprs)]
@[{:jolt/type :symbol :ns nil :name "if"}
{:jolt/type :symbol :ns nil :name "or__x"}
{:jolt/type :symbol :ns nil :name "or__x"}
@[{:jolt/type :symbol :ns nil :name "or"} ;(tuple/slice exprs 1)]]])))
# if-let / when-let / if-some / when-some bind the name ONLY in the then/body
# branch — the else branch must see the surrounding scope, not the binding (so
# (let [x 5] (if-let [x nil] x x)) returns 5, like Clojure). Achieved with a fresh
@ -3609,12 +3560,8 @@
"add-watch" core-add-watch
"remove-watch" core-remove-watch
"not" core-not
"and" core-and
"or" core-or
"cond" core-cond
"case" core-case
"for" core-for
"when-not" core-when-not
"when-let" core-when-let
"->" core-thread-first
"->>" core-thread-last
@ -3699,7 +3646,7 @@
(defn core-macro-names
"Set of core binding names that are macros."
[]
@{"and" true "or" true "cond" true "case" true "for" true "when-not" true "when-let" 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 "lazy-seq" true "lazy-cat" true "cond->" true "->" true "->>" true "doseq" true})
@{"case" true "for" true "when-let" 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 "lazy-seq" true "lazy-cat" true "cond->" true "->" true "->>" true "doseq" true})
(def init-core!
(fn [& args]