[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
need help with syntax-case/syntax/datum->syntax-object
I'm trying to grok the new syntax mechanism, but having some
difficulty.
First of all, I think there is a bug in the MzScheme Language Manual.
Section 11.1.1 says:
The syntax-rules form can be expressed as a syntax-case form wrapped
in lambda:
(syntax-rules (literal-identifier ···)
((ignored-identifier . pattern) template)
···)
=expands=>
(lambda (stx)
(syntax-case stx (literal-identifier ···)
((generated-identifier . pattern) template)
···))
My (shaky) understanding of syntax-case makes me believe this should
instead be:
(lambda (stx)
(syntax-case stx (literal-identifier ···)
((generated-identifier . pattern) (syntax template))
···))
Please correct me if I'm wrong.
Okay, here's what I'm trying to do (or rather, here's a simple example
that exhibits the same problem as what I'm trying to do does):
(define-syntax lambda-foo
(lambda (x)
(syntax-case x ()
((_ body ...)
(with-syntax ((foo (datum->syntax-object (syntax _) 'foo)))
(syntax (lambda (foo) body ...)))))))
This makes a special form in which the magic variable "foo" is available:
> (define add1 (lambda-foo (+ foo 1)))
> (add1 3)
4
All well and good. But when I make another macro that uses this, I
run into problems:
(define-syntax traced-lambda-foo-1
(lambda (x)
(syntax-case x ()
((_ body ...)
(syntax (lambda-foo (display foo) (newline) body ...))))))
> (define add1 (traced-lambda-foo-1 (+ foo 1)))
> (add1 3)
3
reference to undefined identifier: foo
Here's what it's being expanded to:
> (pretty-print (syntax-object->datum (expand '(traced-lambda-foo-1 (+ foo 1)))))
(lambda (foo)
(#%app (#%top . display) foo)
(#%app (#%top . newline))
(#%app (#%top . +) (#%top . foo) (#%datum . 1)))
The second "foo" gets tagged as a top-level-variable reference, rather
than a reference to the bound variable. Why is this happening? Why
does it work for the first foo but not the second?
Here's my attempt at fixing it:
(define-syntax traced-lambda-foo-2
(lambda (x)
(syntax-case x ()
((_ body ...)
(with-syntax ((foo (datum->syntax-object (syntax _) 'foo)))
(syntax (lambda-foo (display foo) (newline) body ...)))))))
But that just makes it worse:
> (pretty-print (syntax-object->datum (expand '(traced-lambda-foo-2 (+ foo 1)))))
(lambda (foo)
(#%app (#%top . display) (#%top . foo))
(#%app (#%top . newline))
(#%app (#%top . +) (#%top . foo) (#%datum . 1)))
Both "foo"s now turn into tlv references. Can someone walk me through
what's going on here? Is there a way to get this to work right?
Even more perplexing is when I try to step through the macro expansion
using expand-once:
> (pretty-print (syntax-object->datum (expand-once '(traced-lambda-foo-1 (+ foo 1)))))
(lambda-foo (display foo) (newline) (+ foo 1))
> (pretty-print (syntax-object->datum (expand-once (expand-once '(traced-lambda-foo-1 (+ foo 1))))))
(lambda (foo) (display foo) (newline) (+ foo 1))
> (pretty-print (syntax-object->datum (expand-once (expand-once (expand-once '(traced-lambda-foo-1 (+ foo 1)))))))
(lambda (foo)
(#%app (#%top . display) foo)
(#%app (#%top . newline))
(#%app (#%top . +) foo (#%datum . 1)))
Why does it seem to do the right thing when expanded incrementally,
but not when it's expanded all at once?
Thanks for your help.
--Doug Orleans
dougo@ccs.neu.edu