Some more interposition points.
#%datum: wraps literal data, so these:
"str"
42
Become these:
(#%datum . "str")
(#%datum . 42)
Question: what’s the meaning of the dot after #%datum?
Question: why is the code below a bad idea? How would you fix it?
(define-macro (#%datum . X)
#'(list X X))
42
#%app: wraps function applications, so this:
(+ 42 -15)
Becomes this:
(#%app + 42 -15)
Question: why is the code below a bad idea? How would you fix it?
(define-macro (#%app OP ARG ...)
#'(OP (abs ARG) ...))
(+ 42 -15)
#%top: wraps identifiers with top-level bindings, so id becomes (#%top . id). It can be used to handle unbound identifiers.
Question (hard): why is this so?
Some more macrology.
define-macro-cases lets you make a macro with several possible patterns, like cond:
(define-macro-cases m
[(m ARG1) #''one]
[(m ARG1 ARG2) #''two]
[(m . ARGS) #`#,(length (syntax->list #'ARGS))])
(m foo) ; 'one
(m foo 42) ; 'two
(m foo 42 "yeah") ; 3
Question: what’s the meaning of #' #'' and #`#,?
syntax->datum lets you peek inside a syntax object to see what’s inside. Use this with care, because you’re working at compile time, not run time.
(define-macro (m THING)
(define datum (syntax->datum #'THING))
(cond
[(number? datum) #'"wow!"]
[else #'THING]))
(m 99)
(m "foo")
(define x 42)
(m x)
Question: why is the last result 42, not "wow"? Isn’t x holding a number?
Make a language called #lang injunction that behaves the same way as #lang conjunction. This time, however, don’t reuse any code. Instead, your expander must export only these five interposition points: #%module-begin, #%app, #%datum, #%top, and #%top-interaction.
Example:
#lang injunction
"hello world"
(+ 1 (* 2 (- x)))
Result:
"whee"
'(kaboom 42 (kaboom 42 (kaboom kaboom)))
Hint: In this case, you can’t use #lang br/quicklang as the implementation language, because it already exports some of these interposition points. Just use #lang br.
Hint: use syntax/module-reader to set up the default reader and invoke your expander, like so:
#lang br
;; smop ···
(module reader syntax/module-reader
injunction)
This is an alternative to invoking the language as #lang s-exp injunction.
Level up.