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]