flan/test/programs/macro-writing.flan

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)