Previous: stdlib syntax-case intro more, Up: stdlib syntax-case intro [Index]
Macro transformers are ordinary Scheme functions, which are written in an R6RS–compatible Scheme language; the only difference from ordinary functions, is that: transformer definitions are evaluated at expand time, while ordinary function definitions are evaluated at run time. We take a look at how the expander works, avoiding almost all the details and focusing on the languages.
Let’s define a simple library to be used as language for run time:
#!r6rs (library (language-for-run) (export write newline quote define) (import (rnrs)))
and a simple library to be used as language for expand time:
#!r6rs (library (language-for-expand) (export lambda syntax) (import (rnrs)))
we use them in the following library, where we also import
define-syntax for run time:
#!r6rs
(library (the-library)
(export doit)
(import (for (language-for-run) run)
(for (language-for-expand) expand)
(for (only (rnrs) define-syntax) run))
(define (doit)
(write (the-macro))
(newline))
(define-syntax the-macro
(lambda (stx)
(syntax (quote (1 2 3)))))
)
we can run the code with the following program:
#!r6rs (import (the-library)) (doit)
Let’s point our attention to (the-library). After parsing the
import and export clauses, the expander scans the library
body; the define-syntax identifier is recognised as the one from
(rnrs), so the transformer expression on its right–hand side:
(lambda (stx) (syntax (quote (1 2 3))))
is extracted and (not true, but we have to start from somewhere) we can imagine it being evaluated with (notice the import levels):
(define the-transformer
(eval '(lambda (stx)
(syntax (quote (1 2 3))))
(environment
'(for (language-for-run) (meta -1))
'(for (language-for-expand) run))))
what’s left of the library’s body is:
(define (doit) (write (the-macro)) (newline))
which is scanned for uses of the-macro; the use is found and the
transformer function applied to a syntax object holding
(the-macro); the return value is a syntax object holding the
quoted list (1 2 3), which is inserted in the body:
(define (doit) (write (quote (1 2 3))) (newline))
The body can now be evaluated using bindings from
(language-for-run).
Previous: stdlib syntax-case intro more, Up: stdlib syntax-case intro [Index]