Joseph Ferano 1898a3157d Macros come from a package now, and the refusal's reason was wrong
Load.program takes forms: it reads the import forms, resolves them with the
one resolver it always had, and parses the file with the packages' macros in
front of it. The refusal said this needed a second import resolver at the Form
level. It did not notice that the file being compiled is parsed before Load
runs too, so no shape of the feature could have left import resolution where
it was.

Names arrive qualified, as a defn's do. (mac/twice 4) is a call and (twice 4)
is an unknown name.

Stopped mid-task: dune test was never run and the acceptance wiring is
unfinished. HANDOFF-macros.md has what is left.
2026-09-13 15:40:08 +07:00

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))