(defmacro do-grid [[r rows c cols] & body] ...) — positional names, a [ ] pattern wherever an argument is a vector, and & for the tail. The reading of the list lives in Expand, below both sides that need it: Parse turns it into the bindings a macro body opens with, and Macro checks a call against the same reading before expanding it, so arity and shape are refused with the call's own location rather than with the Loc.from_macro stamp every node of an expansion carries. The breaking half: [args] used to bind the whole argument list and now binds the first argument. The whole list is [& args], and every defmacro in the tree — prelude, vendor, tests, the elisp fixtures — was migrated to it. One grammar, not a legacy mode.
51 lines
2.1 KiB
Plaintext
51 lines
2.1 KiB
Plaintext
;;;; A package that declares macros.
|
|
;;;;
|
|
;;;; Its names arrive at an importer qualified, exactly as a defn's do: the
|
|
;;;; program that imports this directory as [mac] writes (mac/twice 4), and
|
|
;;;; (twice 4) is an unknown name there. Nothing becomes globally visible by
|
|
;;;; importing a package, macros included.
|
|
;;;;
|
|
;;;; Inside the package the names are the package's own, unqualified, which is
|
|
;;;; the same rule every other declaration here follows.
|
|
|
|
(defn double [n i32] i32 (* n 2))
|
|
|
|
;; The plain case: one macro, nothing else needed to compile it.
|
|
(defmacro twice [& args]
|
|
`(+ ~(at args 0) ~(at args 0)))
|
|
|
|
;; A macro that quasiquotes a call to another macro of this package. That is
|
|
;; *output*, not a compile-order dependency -- the call is part of what this
|
|
;; macro answers and is expanded again after it returns -- so it needs nothing
|
|
;; compiled first. What it does need is the name coming out qualified, because
|
|
;; the answer lands in the importer's file, where [twice] is not a name.
|
|
(defmacro quad [& args]
|
|
`(twice (twice ~(at args 0))))
|
|
|
|
;; And one whose output names a *function* of this package, which has the same
|
|
;; problem and the same answer.
|
|
(defmacro doubled [& args]
|
|
`(double ~(at args 0)))
|
|
|
|
;; [wrap] takes a form-valued expression and answers one, so it is a macro
|
|
;; another macro's *body* can call for real.
|
|
(defmacro wrap [& args]
|
|
`(do ~(at args 0)))
|
|
|
|
;; A macro that really calls another, outside a quasiquote. This one *is* a
|
|
;; compile-order dependency: [wrap] has to be compiled and loaded before this
|
|
;; body will compile at all, which is what the rounds in [Macro] are for, and
|
|
;; it is the case a quasiquoted call deliberately is not.
|
|
(defmacro also-twice [& args]
|
|
(wrap `(+ ~(at args 0) ~(at args 0))))
|
|
|
|
;; A shadowing local named like a top-level of this package. The rename must
|
|
;; leave it alone, or the expansion would name [mac/double] where the author
|
|
;; wrote a let binding.
|
|
(defmacro shadowed [& args]
|
|
`(let [double ~(at args 0)]
|
|
(+ double 1)))
|
|
|
|
;; The package's own function, calling the package's own macro unqualified.
|
|
(defn quadruple [n i32] i32 (quad n))
|