[plt-scheme] Let-syntax not transparent to top-level defines
At Thu, 22 Aug 2002 17:54:46 -0400, Brian Campbell wrote:
> I am writing a macro that expands to a let-syntax expression,
> which binds #%app. This works fine when it's wrapped around most
> expressions. When you wrap it around a group of top level
> defines, however, it introduces a new lexical scope, rather than
> being transparent to them. I would like to have something like
> the following at the top level:
>
> (with-tracing
> (define (foo bar)
> (+ 1 bar))
> (define (baz quux)
> (* 10 quux)))
>
> and have those defines apply at the top level with #%app rebound
> to the right thing. I also need this to work within the top
> level of a module. Is there any way for me to do something like
> this?
I'm a little confused about the setup. `(with-tracing (+ 1 2))'
presumably doesn't expand to `(let-syntax ([#%app ...]) (+ 1 2))'. The
`#%app' binding wouldn't affect the `(+ 1 2)' part, since the binding
is introduced by the macro, right? Maybe you're using
`fluid-let-syntax'? Or maybe something else is going on and the details
don't matter.
See
http://www.cs.utah.edu/plt/mailarch/plt-scheme-2002/msg00166.html
for some information on why `let-syntax' and `fluid-let-syntax'
introduce a new scope.
I actually don't know how to solve the problem if a `define-syntax'
expression can appear inside `with-tracing'. Otherwise, probably it can
be solved using the very machinery that forces `let-syntax' to create
new scopes.
The idea is to push the `let-syntax' into the body of a definition. To
do that, use `local-expand' to partially expand each body expression
within `with-tracing', something like this:
(local-expand
one-expr
(syntax-local-context)
(kernel-form-identifier-list (quote-syntax here)))
where `kernel-form-identifier-list' comes from "kerncase.ss" in the
"syntax" collection. The result of `local-expand' will either have the
shape
(define-values (id ....) expr)
or
(define-syntaxes (id ....) expr)
or it will be an non-definition.
* In the first case, you can move the `let-syntax' inside the
definition.
* In the second case, you're stuck. Pushing `let-syntax' into the
definition would change its phase.
* In the other cases, you can wrap the entire [partially expanded]
expression with `let-syntax'.
And you really only need to do this partial expansion if
`(syntax-local-context)' isn't 'expression.
Long term, I hope the solution to these problems is to eliminate
`local-expand', but we can't do without it right now.
Hope that helps,
Matthew