Scheme and Macro Expansion
Posted by kernelbob on November 15, 2009
I got to work on my Scheme interpreter this weekend. Real life had interfered for about three weeks straight.
I’m still working on syntax-case, the code transformation workhorse. I’ve got two separate pieces of Scheme code. There’s an expander for a subset of Scheme (no macros) that has the framework for α-substitution and is tied into my interpreter. Then there’s another expander that I wrote in Chicken Scheme which just handles the pattern matching of syntax-case. That part is debugged and uses the same syntax objects and environments as my Scheme.
Which is kind of useless. Being written in full Scheme, it won’t run in my Scheme subset. (My scheme doesn’t have cond, let, etc.) And it won’t run in Chicken Scheme, because Chicken Scheme uses a different environment format. But I can use Chicken Scheme to call the pattern match routine with some test input and see whether it finds the pattern variables and binds them correctly. Which it does, for a small set of tests.
I also puzzled out how syntax-case ties into the macro expander. Typical use is like this.
(define-syntax my-macro (lambda (x) (syntax-case x (<literal> ...) (<pattern> <output expression>) ...)))
Because syntax-case is wrapped in a lambda, it will run when the lambda is called, which is at macro use time. That’s the right time to bind the pattern variables. So no extra tricks are needed (I think) to delay its execution. syntax-case does need to be a special form, so the evaluator doesn’t try to evaluate its arguments before applying it.
So now I’m working on the syntax keyword. syntax substitutes pattern variables into template expressions, and it expands ellipses. For example, given this pattern
(my-letrec ((var init) ...) body ...)
and this input form
(my-letrec ((a 0) (b #f)) (display b) (display (+ b 3)))
and this syntax template
(syntax ((lambda (var ...) body ...) init ...))
I’m working on generating the right output, which, does to α-substition, is too unreadable to post here.
Actually, I’m not working on it. I’ve spent the day scanning the literature trying to see how others have done it. And I haven’t found any actual implementations yet. So I’m thinking about it…