45 lines
1.4 KiB
Plaintext
45 lines
1.4 KiB
Plaintext
;;;; Macros that write macros: a quasiquote inside a quasiquote.
|
|
;;;;
|
|
;;;; The outer quasiquote is desugared when the file is read, and the inner one
|
|
;;;; is data until the outer macro runs. What that macro answers is a defmacro
|
|
;;;; holding the inner quasiquote, which is desugared then, and the macro it
|
|
;;;; defines is compiled and called like one written by hand.
|
|
|
|
;; The inner ~x belongs to the inner quasiquote, so it is the generated
|
|
;; macro's own parameter and nothing the outer macro evaluates.
|
|
(defmacro defsquare [name]
|
|
`(defmacro ~name [x]
|
|
`(* ~x ~x)))
|
|
|
|
;; ~~n reaches out two levels: n is evaluated when defadder runs, and what it
|
|
;; holds is pasted into the inner template as an expression the generated
|
|
;; macro evaluates. A Form constructor is such an expression, so the literal
|
|
;; arrives as one.
|
|
(defmacro defadder [name n]
|
|
`(defmacro ~name [x]
|
|
`(+ ~x ~~n)))
|
|
|
|
;; ~@ inside the inner template is the inner macro's splice.
|
|
(defmacro defsum [name]
|
|
`(defmacro ~name [& xs]
|
|
`(+ 0 ~@xs)))
|
|
|
|
;; Two levels down: a macro that writes a macro that writes a macro.
|
|
(defmacro defsquarer [name]
|
|
`(defmacro ~name [inner]
|
|
`(defmacro ~inner [x]
|
|
`(* ~x ~x))))
|
|
|
|
(defsquare sq)
|
|
(defadder add5 (Form.Int {.i 5}))
|
|
(defsum total)
|
|
(defsquarer defsq2)
|
|
(defsq2 sq2)
|
|
|
|
(defn main [] i32
|
|
(print (sq 7)) (println "")
|
|
(print (add5 10)) (println "")
|
|
(print (total 1 2 3 4)) (println "")
|
|
(print (sq2 9)) (println "")
|
|
0)
|