ludus/janet/clj-loop.janet

50 lines
1.3 KiB
Plaintext
Raw Normal View History

2024-01-11 19:26:22 +00:00
(defmacro clj-loop
``A drop-in replacement for Clojure's loop form. Useful for the current project of converting Clojure code to Janet.
``
[bindings & body]
(assert (even? (length bindings)) "Binding tuple must have an even number of terms")
2024-01-11 19:26:22 +00:00
(def names @[])
(def args @[])
(loop [i :range [0 (length bindings)]]
(if (even? i)
(array/push names (get bindings i))
(array/push args (get bindings i))))
~(do (defn recur [,;names] ,;body) (recur ,;args)))
(defmacro defn+
[name & clauses]
~(defn ,name [& args]
(print "before do")
(do
(def arities @{})
(def clauses ,clauses)
(def bindingses (map first clauses))
(def bodies (map |(slice $ 1) clauses))
(print "before loop")
(loop [i :range [0 (length clauses)]]
(def bindings (get bindingses i))
(def arity (length bindings))
(assert (not (get arities i)) "Clauses must have different arities")
(def body (get bodies i))
(def clause ~(fn ,name ,bindings ,;body))
(put $arities arity clause))
(print "before quasiquote")
(fn [& args]
(def arity (length args))
(def clause (get arities arity))
(assert clause "No clause with that arity")
(clause ;args)))))
(defn+ add
([] 0)
([x] x)
([x y] (+ x y)))
(macex1
'(defn+ add
([] 0)
([x] x)
([x y] (+ x y))))