2018-03-26 17:51:43 +03:00
|
|
|
;; Defining the meta data macros early so that they can be used by all the other code.
|
|
|
|
|
|
|
|
(meta-set! doc "doc" "Set documentation for a binding.")
|
|
|
|
(defmacro doc [name string]
|
|
|
|
(list 'meta-set! name "doc" string))
|
|
|
|
|
|
|
|
(doc print-doc "Print the documentation for a binding.")
|
|
|
|
(defmacro print-doc [name]
|
|
|
|
(list 'macro-log (list 'meta name "doc")))
|
|
|
|
|
|
|
|
(doc sig "Annotate a binding with the desired signature.")
|
|
|
|
(defmacro sig [name signature]
|
|
|
|
(list 'meta-set! name "sig" signature))
|
|
|
|
|
|
|
|
(doc print-sig "Print the annotated signature for a binding.")
|
|
|
|
(defmacro print-sig [name]
|
|
|
|
(list 'macro-log (list 'meta name "sig")))
|
|
|
|
|
|
|
|
(doc hide "Mark a binding as hidden, this will make it not print with the 'info' command.")
|
2018-03-27 15:21:12 +03:00
|
|
|
(defmacro hidden [name]
|
|
|
|
(list 'meta-set! name "hidden" true))
|
2018-03-26 17:51:43 +03:00
|
|
|
|
|
|
|
(doc private "Mark a binding as private, this will make it inaccessible from other modules.")
|
2018-03-27 15:14:30 +03:00
|
|
|
(defmacro private [name]
|
2018-03-26 17:51:43 +03:00
|
|
|
(list 'meta-set! name "private" true))
|
|
|
|
|
2019-06-22 21:18:32 +03:00
|
|
|
(doc todo "sets the todo property for a binding.")
|
|
|
|
(defmacro todo [name value]
|
|
|
|
(list 'meta-set! name "todo" value))
|
|
|
|
|
2018-03-27 15:08:49 +03:00
|
|
|
(doc private? "Is this binding private?")
|
|
|
|
(defmacro private? [name]
|
2019-09-17 20:34:34 +03:00
|
|
|
(list 'not (list 'list? (meta name "private"))))
|
2018-03-27 15:08:49 +03:00
|
|
|
|
|
|
|
(doc hidden? "Is this binding hidden?")
|
|
|
|
(defmacro hidden? [name]
|
2019-09-17 20:34:34 +03:00
|
|
|
(list 'not (list 'list? (meta name "hidden"))))
|
2018-03-26 17:51:43 +03:00
|
|
|
|
2019-06-04 12:30:22 +03:00
|
|
|
(defndynamic annotate-helper [name annotation]
|
|
|
|
(cons annotation (meta name "annotations")))
|
|
|
|
|
|
|
|
(doc annotate "Add an annotation to this binding.")
|
|
|
|
(defmacro annotate [name annotation]
|
|
|
|
(list 'meta-set! name "annotations" (annotate-helper name annotation)))
|
2018-03-26 17:51:43 +03:00
|
|
|
|
2018-02-08 19:39:42 +03:00
|
|
|
(defmodule Dynamic
|
2019-03-13 20:49:48 +03:00
|
|
|
(defndynamic caar [pair] (car (car pair)))
|
|
|
|
(defndynamic cadr [pair] (car (cdr pair)))
|
|
|
|
(defndynamic cdar [pair] (cdr (car pair)))
|
|
|
|
(defndynamic cddr [pair] (cdr (cdr pair)))
|
|
|
|
(defndynamic caaar [pair] (car (car (car pair))))
|
|
|
|
(defndynamic caadr [pair] (car (car (cdr pair))))
|
|
|
|
(defndynamic cadar [pair] (car (cdr (car pair))))
|
|
|
|
(defndynamic cdaar [pair] (cdr (car (car pair))))
|
|
|
|
(defndynamic caddr [pair] (car (cdr (cdr pair))))
|
|
|
|
(defndynamic cdadr [pair] (cdr (car (cdr pair))))
|
|
|
|
(defndynamic cddar [pair] (cdr (cdr (car pair))))
|
|
|
|
(defndynamic cdddr [pair] (cdr (cdr (cdr pair))))
|
|
|
|
(defndynamic caaaar [pair] (car (car (car (car pair)))))
|
|
|
|
(defndynamic caaadr [pair] (car (car (car (cdr pair)))))
|
|
|
|
(defndynamic caadar [pair] (car (car (cdr (car pair)))))
|
|
|
|
(defndynamic caaddr [pair] (car (car (cdr (cdr pair)))))
|
|
|
|
(defndynamic cadaar [pair] (car (cdr (car (car pair)))))
|
|
|
|
(defndynamic cadadr [pair] (car (cdr (car (cdr pair)))))
|
|
|
|
(defndynamic caddar [pair] (car (cdr (cdr (car pair)))))
|
|
|
|
(defndynamic cadddr [pair] (car (cdr (cdr (cdr pair)))))
|
|
|
|
(defndynamic cdaaar [pair] (cdr (car (car (car pair)))))
|
|
|
|
(defndynamic cdaadr [pair] (cdr (car (car (cdr pair)))))
|
|
|
|
(defndynamic cdadar [pair] (cdr (car (cdr (car pair)))))
|
|
|
|
(defndynamic cdaddr [pair] (cdr (car (cdr (cdr pair)))))
|
|
|
|
(defndynamic cddaar [pair] (cdr (cdr (car (car pair)))))
|
|
|
|
(defndynamic cddadr [pair] (cdr (cdr (car (cdr pair)))))
|
|
|
|
(defndynamic cdddar [pair] (cdr (cdr (cdr (car pair)))))
|
|
|
|
(defndynamic cddddr [pair] (cdr (cdr (cdr (cdr pair)))))
|
|
|
|
|
2019-11-09 14:52:11 +03:00
|
|
|
(defndynamic cxr [x pair]
|
|
|
|
(if (= (length x) 0)
|
|
|
|
(list 'quote pair)
|
|
|
|
(list
|
|
|
|
(if (= 'a (cadr x))
|
|
|
|
'car
|
|
|
|
(if (= 'd (cadr x))
|
|
|
|
'cdr
|
|
|
|
(macro-error "`cxr` expects either `a` or `d` symbols, got " (cadr x))))
|
|
|
|
(if (= 1 (car x))
|
|
|
|
(cxr (cddr x) pair)
|
|
|
|
(cxr (cons (- (car x) 1) (cdr x)) pair)))))
|
|
|
|
|
|
|
|
(defndynamic nthcdr [n pair]
|
2019-11-26 09:13:14 +03:00
|
|
|
(cxr (list (+ n 1) 'd) pair))
|
2019-11-09 14:52:11 +03:00
|
|
|
|
|
|
|
(defndynamic nthcar [n pair]
|
|
|
|
(cxr (list 1 'a n 'd) pair))
|
|
|
|
|
2019-03-13 20:49:48 +03:00
|
|
|
(defndynamic eval-internal [form]
|
2018-03-04 13:41:47 +03:00
|
|
|
(list 'do
|
|
|
|
(list 'defn 'main [] (list 'IO.println* form))
|
|
|
|
(list 'build)
|
|
|
|
(list 'run)))
|
|
|
|
|
2020-03-09 17:50:52 +03:00
|
|
|
(defmacro evaluate [form]
|
2018-03-04 13:41:47 +03:00
|
|
|
(eval-internal form))
|
|
|
|
|
|
|
|
(defmacro e [form]
|
|
|
|
(eval-internal form))
|
2019-09-17 20:34:34 +03:00
|
|
|
|
2019-08-27 06:44:29 +03:00
|
|
|
(defndynamic list-to-array-internal [xs acc]
|
|
|
|
(if (= 0 (length xs))
|
|
|
|
acc
|
|
|
|
(list-to-array-internal (cdr xs) (append acc (array (car xs))))))
|
|
|
|
|
2019-09-08 21:58:30 +03:00
|
|
|
(defndynamic collect-into-internal [xs acc f]
|
|
|
|
(if (= 0 (length xs))
|
|
|
|
acc
|
|
|
|
(collect-into-internal (cdr xs) (append acc (f (car xs))) f)))
|
|
|
|
|
2020-04-10 17:04:44 +03:00
|
|
|
(doc collect-into
|
|
|
|
"Transforms a dynamic data literal into another, preserving order")
|
2019-09-08 21:58:30 +03:00
|
|
|
(defndynamic collect-into [xs f]
|
2019-09-08 21:54:29 +03:00
|
|
|
(list 'quote
|
2019-09-08 21:58:30 +03:00
|
|
|
(collect-into-internal xs (f) f)))
|
2020-03-09 17:50:52 +03:00
|
|
|
)
|
2018-01-02 20:13:52 +03:00
|
|
|
|
2019-03-13 20:49:48 +03:00
|
|
|
(defndynamic cond-internal [xs]
|
2018-05-20 10:57:51 +03:00
|
|
|
(if (= (length xs) 0)
|
2017-06-26 12:15:03 +03:00
|
|
|
(list)
|
2018-05-20 10:57:51 +03:00
|
|
|
(if (= (length xs) 2)
|
2017-12-15 19:43:06 +03:00
|
|
|
(macro-error "cond has even number of branches; add an else branch")
|
2018-05-20 10:57:51 +03:00
|
|
|
(if (= (length xs) 1)
|
2017-06-26 12:15:03 +03:00
|
|
|
(car xs)
|
|
|
|
(list
|
2017-10-17 10:02:12 +03:00
|
|
|
'if
|
2017-06-26 12:15:03 +03:00
|
|
|
(car xs)
|
2018-01-02 20:13:52 +03:00
|
|
|
(cadr xs)
|
|
|
|
(cond-internal (cddr xs)))))))
|
2017-06-26 12:15:03 +03:00
|
|
|
|
|
|
|
(defmacro cond [:rest xs]
|
|
|
|
(cond-internal xs))
|
|
|
|
|
2018-01-17 19:08:02 +03:00
|
|
|
(defmacro for [settings :rest body] ;; settings = variable, from, to, <step>
|
2018-05-20 10:57:51 +03:00
|
|
|
(if (> (length body) 1)
|
2018-01-17 18:09:34 +03:00
|
|
|
(macro-error "Warning: the body of the 'for' loop can only contain one expression")
|
2019-07-09 01:18:38 +03:00
|
|
|
(let [variable (car settings)
|
|
|
|
from (cadr settings)
|
|
|
|
to (caddr settings)
|
2020-02-13 18:02:49 +03:00
|
|
|
step (if (> (length settings) 3) (cadddr settings) 1)
|
|
|
|
comp (if (> (length settings) 4)
|
|
|
|
(cadddr (cdr settings))
|
|
|
|
(if (< step (- step step)) '> '<))
|
2019-07-09 01:18:38 +03:00
|
|
|
]
|
|
|
|
(list
|
|
|
|
'let (array variable from)
|
|
|
|
(list
|
2020-02-13 18:02:49 +03:00
|
|
|
'while (list comp variable to)
|
2019-12-18 14:10:47 +03:00
|
|
|
(list
|
2019-07-09 01:18:38 +03:00
|
|
|
'do
|
|
|
|
(if (= (length body) 0)
|
|
|
|
()
|
|
|
|
(if (list? body)
|
|
|
|
(car body)
|
|
|
|
body))
|
|
|
|
(list
|
|
|
|
'set! variable
|
|
|
|
(list '+ variable step))))))))
|
2017-06-29 18:05:34 +03:00
|
|
|
|
|
|
|
(defmacro refstr [x]
|
2017-10-17 10:02:12 +03:00
|
|
|
(list 'ref
|
|
|
|
(list 'str x)))
|
2017-10-13 14:48:40 +03:00
|
|
|
|
2020-02-14 17:32:05 +03:00
|
|
|
(defmacro doall [f xs]
|
|
|
|
(list 'for ['i 0 (list 'Array.length (list 'ref xs))]
|
|
|
|
(list f (list 'Array.unsafe-nth (list 'ref xs) 'i))))
|
2018-03-24 13:17:56 +03:00
|
|
|
|
2019-03-13 20:49:48 +03:00
|
|
|
(defndynamic foreach-internal [var xs expr]
|
2020-01-29 13:55:56 +03:00
|
|
|
(let [xsym (gensym-with 'xs)
|
2020-01-29 17:48:02 +03:00
|
|
|
len (gensym-with 'len)
|
|
|
|
i (gensym-with 'i)]
|
2020-01-29 13:55:56 +03:00
|
|
|
(list 'let [xsym xs
|
|
|
|
len (list 'Array.length xsym)]
|
2020-01-29 17:48:02 +03:00
|
|
|
(list 'for [i 0 len]
|
|
|
|
(list 'let [var (list 'Array.unsafe-nth xsym i)]
|
2020-01-29 13:55:56 +03:00
|
|
|
expr)))))
|
2018-03-24 13:17:56 +03:00
|
|
|
|
|
|
|
(defmacro foreach [binding expr]
|
|
|
|
(if (array? binding)
|
|
|
|
(foreach-internal (car binding) (cadr binding) expr)
|
|
|
|
(macro-error "Binding has to be an array.")))
|
2017-10-18 23:44:15 +03:00
|
|
|
|
2019-03-13 20:49:48 +03:00
|
|
|
(defndynamic thread-first-internal [xs]
|
2018-05-20 10:57:51 +03:00
|
|
|
(if (= (length xs) 2)
|
2017-10-18 23:44:15 +03:00
|
|
|
(if (list? (last xs))
|
2018-01-02 20:13:52 +03:00
|
|
|
(cons (caadr xs)
|
2017-10-18 23:44:15 +03:00
|
|
|
(cons (car xs)
|
2018-01-02 20:13:52 +03:00
|
|
|
(cdadr xs)))
|
|
|
|
(list (cadr xs) (car xs)))
|
2017-10-18 23:44:15 +03:00
|
|
|
(if (list? (last xs))
|
|
|
|
(append
|
|
|
|
(list
|
|
|
|
(car (last xs))
|
2017-12-01 12:36:14 +03:00
|
|
|
(thread-first-internal (all-but-last xs)))
|
2017-10-18 23:44:15 +03:00
|
|
|
(cdr (last xs)))
|
2017-12-01 12:36:14 +03:00
|
|
|
(list (last xs) (thread-first-internal (all-but-last xs))))))
|
2017-10-18 23:44:15 +03:00
|
|
|
|
2019-03-13 20:49:48 +03:00
|
|
|
(defndynamic thread-last-internal [xs]
|
2018-05-20 10:57:51 +03:00
|
|
|
(if (= (length xs) 2)
|
2017-10-18 23:44:15 +03:00
|
|
|
(if (list? (last xs))
|
|
|
|
(cons-last (car xs) (last xs))
|
2018-01-02 20:13:52 +03:00
|
|
|
(list (cadr xs) (car xs)))
|
2017-10-18 23:44:15 +03:00
|
|
|
(if (list? (last xs))
|
2017-12-01 12:36:14 +03:00
|
|
|
(cons-last (thread-last-internal (all-but-last xs)) (last xs))
|
|
|
|
(list (last xs) (thread-last-internal (all-but-last xs))))))
|
2017-10-18 23:44:15 +03:00
|
|
|
|
|
|
|
(defmacro => [:rest forms]
|
|
|
|
(thread-first-internal forms))
|
|
|
|
|
|
|
|
(defmacro ==> [:rest forms]
|
|
|
|
(thread-last-internal forms))
|
2017-11-29 17:28:21 +03:00
|
|
|
|
|
|
|
(defmacro swap! [x y]
|
2018-02-02 09:19:10 +03:00
|
|
|
(list 'let (array 'tmp y) (list 'do (list 'set! y x) (list 'set! x 'tmp))))
|
2017-11-30 15:43:58 +03:00
|
|
|
|
2018-01-02 20:13:52 +03:00
|
|
|
(defmacro update! [x f]
|
2018-02-02 09:19:10 +03:00
|
|
|
(list 'set! x (list f x)))
|
2018-01-02 20:13:52 +03:00
|
|
|
|
2017-12-07 16:59:55 +03:00
|
|
|
(defmacro mac-only [:rest forms]
|
2017-11-30 15:43:58 +03:00
|
|
|
(if (= "darwin" (os))
|
2020-04-10 18:31:51 +03:00
|
|
|
(eval (cons (quote do) forms))
|
2017-11-30 15:43:58 +03:00
|
|
|
()))
|
2017-12-04 11:29:15 +03:00
|
|
|
|
2017-12-07 16:59:55 +03:00
|
|
|
(defmacro linux-only [:rest forms]
|
2017-12-04 11:29:15 +03:00
|
|
|
(if (= "linux" (os))
|
2020-04-10 18:31:51 +03:00
|
|
|
(eval (cons (quote do) forms))
|
2017-12-04 11:29:15 +03:00
|
|
|
()))
|
|
|
|
|
2017-12-07 16:59:55 +03:00
|
|
|
(defmacro windows-only [:rest forms]
|
2019-03-07 01:44:43 +03:00
|
|
|
(if (Dynamic.or (= "windows" (os)) (= "mingw32" (os)))
|
2020-04-10 18:31:51 +03:00
|
|
|
(eval (cons (quote do) forms))
|
2017-12-04 11:29:15 +03:00
|
|
|
()))
|
2017-12-12 17:08:33 +03:00
|
|
|
|
2018-02-12 16:34:17 +03:00
|
|
|
(defmacro not-on-windows [:rest forms]
|
2019-03-07 01:44:43 +03:00
|
|
|
(if (not (Dynamic.or (= "windows" (os)) (= "mingw32" (os))))
|
2020-04-10 18:31:51 +03:00
|
|
|
(eval (cons (quote do) forms))
|
2018-02-12 16:34:17 +03:00
|
|
|
()))
|
|
|
|
|
2019-03-13 20:49:48 +03:00
|
|
|
(defndynamic use-all-fn [names]
|
2018-05-20 10:57:51 +03:00
|
|
|
(if (= (length names) 0)
|
2017-12-12 17:08:33 +03:00
|
|
|
(macro-error "Trying to call use-all without arguments")
|
2020-04-10 18:31:51 +03:00
|
|
|
(do
|
|
|
|
(eval (list 'use (car names)))
|
|
|
|
(if (= (length names) 1)
|
|
|
|
()
|
|
|
|
(use-all-fn (cdr names))))))
|
2017-12-12 17:08:33 +03:00
|
|
|
|
|
|
|
(defmacro use-all [:rest names]
|
2020-04-10 18:31:51 +03:00
|
|
|
(use-all-fn names))
|
2017-12-12 19:39:15 +03:00
|
|
|
|
2018-03-24 12:28:19 +03:00
|
|
|
(defmacro load-and-use [name]
|
2020-04-10 18:31:51 +03:00
|
|
|
(do
|
|
|
|
(eval (list 'load (str name ".carp")))
|
|
|
|
(eval (list 'use name))))
|
2018-03-24 12:28:19 +03:00
|
|
|
|
2017-12-12 19:39:15 +03:00
|
|
|
(defmacro when [condition form]
|
|
|
|
(list 'if condition form (list)))
|
2017-12-12 20:45:29 +03:00
|
|
|
|
|
|
|
(defmacro unless [condition form]
|
|
|
|
(list 'if condition (list) form))
|
2017-12-14 18:28:06 +03:00
|
|
|
|
2017-12-15 11:28:14 +03:00
|
|
|
(defmacro let-do [bindings :rest forms]
|
2017-12-14 18:28:06 +03:00
|
|
|
(list 'let bindings
|
|
|
|
(cons 'do forms)))
|
|
|
|
|
2019-04-30 22:42:34 +03:00
|
|
|
(defmacro while-do [condition :rest forms]
|
|
|
|
(list 'while condition
|
|
|
|
(cons 'do forms)))
|
|
|
|
|
2017-12-15 11:24:16 +03:00
|
|
|
(defmacro defn-do [name arguments :rest body]
|
2020-04-10 17:04:44 +03:00
|
|
|
(eval (list 'defn name arguments (cons 'do body))))
|
2017-12-14 18:28:06 +03:00
|
|
|
|
|
|
|
(defmacro comment [:rest forms]
|
|
|
|
())
|
|
|
|
|
2017-12-15 11:24:16 +03:00
|
|
|
(defmacro forever-do [:rest forms]
|
2017-12-14 18:28:06 +03:00
|
|
|
(list 'while true (cons 'do forms)))
|
|
|
|
|
2019-03-13 20:49:48 +03:00
|
|
|
(defndynamic case-internal [name xs]
|
2018-05-20 10:57:51 +03:00
|
|
|
(if (= (length xs) 0)
|
2017-12-14 18:28:06 +03:00
|
|
|
(list)
|
2018-05-20 10:57:51 +03:00
|
|
|
(if (= (length xs) 2)
|
2017-12-15 11:24:16 +03:00
|
|
|
(macro-error "case has even number of branches; add an else branch")
|
2018-05-20 10:57:51 +03:00
|
|
|
(if (= (length xs) 1)
|
2017-12-14 18:28:06 +03:00
|
|
|
(car xs)
|
|
|
|
(list 'if
|
|
|
|
(list '= name (car xs))
|
2018-01-02 20:13:52 +03:00
|
|
|
(cadr xs)
|
|
|
|
(case-internal name (cddr xs)))))))
|
2017-12-14 18:28:06 +03:00
|
|
|
|
|
|
|
(defmacro case [name :rest forms]
|
|
|
|
(case-internal name forms))
|
2017-12-29 13:49:51 +03:00
|
|
|
|
2018-09-23 10:34:38 +03:00
|
|
|
(defmacro and [x y]
|
2020-04-02 16:13:33 +03:00
|
|
|
(list 'if x y false))
|
2018-09-23 10:34:38 +03:00
|
|
|
|
|
|
|
(defmacro or [x y]
|
2020-04-02 16:13:33 +03:00
|
|
|
(list 'if x true y))
|
2018-09-23 10:34:38 +03:00
|
|
|
|
2019-03-13 20:49:48 +03:00
|
|
|
(defndynamic build-vararg [func forms]
|
2018-05-20 10:57:51 +03:00
|
|
|
(if (= (length forms) 0)
|
2017-12-29 13:49:51 +03:00
|
|
|
(macro-error "vararg macro needs at least one argument")
|
2018-05-20 10:57:51 +03:00
|
|
|
(if (= (length forms) 1)
|
2017-12-29 13:49:51 +03:00
|
|
|
(car forms)
|
2018-06-15 13:07:32 +03:00
|
|
|
(list func (car forms) (build-vararg func (cdr forms))))))
|
2017-12-29 13:49:51 +03:00
|
|
|
|
|
|
|
(defmacro and* [:rest forms]
|
|
|
|
(build-vararg 'and forms))
|
|
|
|
|
|
|
|
(defmacro or* [:rest forms]
|
|
|
|
(build-vararg 'or forms))
|
|
|
|
|
2019-03-13 20:49:48 +03:00
|
|
|
(defndynamic build-str* [forms]
|
2018-05-20 10:57:51 +03:00
|
|
|
(if (= (length forms) 0)
|
2017-12-29 13:49:51 +03:00
|
|
|
(list "")
|
2018-05-20 10:57:51 +03:00
|
|
|
(if (= (length forms) 1)
|
2019-05-27 19:05:44 +03:00
|
|
|
(list 'ref (list 'str (car forms)))
|
|
|
|
(list 'ref (list 'String.append (list 'ref (list 'str (car forms))) (build-str* (cdr forms)))))))
|
2017-12-29 13:49:51 +03:00
|
|
|
|
|
|
|
(defmacro str* [:rest forms]
|
2019-05-27 19:05:44 +03:00
|
|
|
(list 'copy (build-str* forms)))
|
2017-12-29 13:49:51 +03:00
|
|
|
|
|
|
|
(defmacro println* [:rest forms]
|
2019-05-27 19:05:44 +03:00
|
|
|
(list 'IO.println (build-str* forms)))
|
2018-01-25 19:26:20 +03:00
|
|
|
|
2018-03-11 16:53:50 +03:00
|
|
|
(defmacro print* [:rest forms]
|
2019-05-27 19:05:44 +03:00
|
|
|
(list 'IO.print (build-str* forms)))
|
2018-03-11 16:53:50 +03:00
|
|
|
|
2018-01-25 19:26:20 +03:00
|
|
|
(defmacro ignore [form]
|
2018-02-01 20:01:45 +03:00
|
|
|
(list 'let (array '_ form) (list)))
|
2018-03-12 18:30:36 +03:00
|
|
|
|
2018-03-27 11:51:16 +03:00
|
|
|
(defmacro save-docs [:rest modules]
|
2018-03-27 10:05:58 +03:00
|
|
|
;; A trick to be able to send unquoted symbols to 'save-docs'
|
2018-03-27 11:51:16 +03:00
|
|
|
(list 'save-docs-internal (list 'quote modules)))
|
2019-05-20 07:08:09 +03:00
|
|
|
|
2019-07-09 01:18:38 +03:00
|
|
|
(defndynamic project-config [bindings]
|
2019-05-20 07:08:09 +03:00
|
|
|
(if (< (length bindings) 2)
|
|
|
|
(list)
|
|
|
|
(cons-last (project-config (cdr (cdr bindings))) (list 'do (list 'Project.config
|
|
|
|
(car bindings) (car (cdr bindings)))))))
|
|
|
|
|
|
|
|
(doc defproject "Define a project configuration.")
|
2019-07-09 01:18:38 +03:00
|
|
|
(defmacro defproject [:rest bindings]
|
2019-05-20 07:08:09 +03:00
|
|
|
(project-config bindings))
|
2019-05-22 21:01:03 +03:00
|
|
|
|
|
|
|
(doc const-assert "asserts that the expression `expr` is true at compile time.
|
|
|
|
Otherwise it will fail with the message `msg`.
|
|
|
|
|
|
|
|
The expression must be evaluable at compile time.")
|
|
|
|
(defndynamic const-assert [expr msg]
|
|
|
|
(if expr () (macro-error msg)))
|
2019-09-09 10:59:22 +03:00
|
|
|
|
|
|
|
(doc *gensym-counter* "is a helper counter for `gensym`.")
|
|
|
|
(defdynamic *gensym-counter* 1000)
|
|
|
|
|
2019-09-09 23:33:56 +03:00
|
|
|
(doc gensym-with "generates symbols dynamically, based on a symbol name.")
|
|
|
|
(defndynamic gensym-with [x]
|
2019-09-09 10:59:22 +03:00
|
|
|
(do
|
2020-03-18 00:51:00 +03:00
|
|
|
(set! *gensym-counter* (inc *gensym-counter*))
|
2019-09-09 23:33:56 +03:00
|
|
|
(Symbol.join [x (Symbol.from *gensym-counter*)])))
|
|
|
|
|
|
|
|
(doc gensym "generates symbols dynamically as needed.")
|
|
|
|
(defndynamic gensym []
|
|
|
|
(gensym-with 'gensym-generated))
|
2019-11-22 15:10:36 +03:00
|
|
|
|
|
|
|
(doc until "executes `body` until the condition `cnd` is true.")
|
|
|
|
(defmacro until [cnd body]
|
|
|
|
(list 'while (list 'not cnd)
|
|
|
|
body))
|
2019-12-18 14:10:47 +03:00
|
|
|
|
|
|
|
(doc defdynamic-once "creates a dynamic variable and sets its value if it's not already defined.")
|
|
|
|
(defmacro defdynamic-once [var expr]
|
|
|
|
(list 'if (list 'defined? var)
|
|
|
|
()
|
|
|
|
(list 'defdynamic var expr)))
|
2019-11-29 17:25:27 +03:00
|
|
|
|
|
|
|
(defndynamic comp-internal [sym fns]
|
|
|
|
(if (= (length fns) 0)
|
|
|
|
sym
|
|
|
|
(list (car fns) (comp-internal sym (cdr fns)))))
|
|
|
|
|
|
|
|
(doc comp "composes the functions `fns` into one `fn`.")
|
|
|
|
(defmacro comp [:rest fns]
|
|
|
|
(let [x (gensym)]
|
|
|
|
(list 'fn [x] (comp-internal x fns))))
|