[plt-scheme] Can generated lexical (syntax) bindings work?
I recommend:
1. Have `define-syntax-in-context' bind a fresh name to the
transformer using `define-syntax', and also add a mapping in the
table from the context name and definition symbol to a syntax
object for the fresh name.
Do not have the `define-syntax-in-context' macro perform the table
registration directly. Instead, have it expand to
`begin-for-syntax' to perform the registration.
2. Have `with-context' expand to a `let-syntax' that uses
`make-rename-transformer' to map the defined name to the fresh name
generated by `define-syntax-in-context'.
To generate the identifier bound by `let-syntax', use
`datum->syntax-object' with the context identifier supplied to
`with-context' and the symbol for the defined name.
Using `make-rename-transformer' is the key part of this strategy. It
only works when the context for a use is nested within the context for
a definition (where all module top levels count as the same top level
for this notion of "nesting"); my guess is that's fine for your
purposes.
If it doesn't work out, post the code for your attempt, and we can help
more from there.
Matthew
At Fri, 6 Apr 2007 13:27:22 -0700, Brian Chin wrote:
> Hey all, I have a bit of a long problem (with a possibly shorter
> answer). I'm trying to write a small module which allows you to
> define a syntax definition in a separate context, so that it isn't
> actually defined at the top level. Later when you want to use it, you
> can declare that some syntax be run in that context, thus enabling
> those syntax bindings. A quick example:
>
> (define-syntax-in-context foo my-context
> (syntax-rules () ((foo) 5)))
>
> (foo) ; Syntax error, foo is not defined
>
> (with-context my-context (foo)) ; Equivalent to just 5
>
> Now, the problem I'm having is in saving the symbol foo from the
> define-syntax-in-context call to actually bind to the "foo" in the
> with-context call. Most of the approaches I've tried hasn't allowed
> with-context to generate a new lexical binding for "foo". This is
> definitely non-hygienic, but it seems like it should still be
> possible. I've tried three things, all of which save information
> about mappings from (context, syntax-name) -> transformer in one
> fashion or another:
>
> 1. define-syntax-in-context saves the transformer syntax object in a
> hash table keyed by the context symbol and the syntax name symbol,
> both extracted using syntax-object->datum. With-context generates a
> let-syntax form, and generates new syntax objects for the syntax-name
> using datum->syntax-object. This doesn't seem to work, as (foo) is
> still being interpreted as a top-level form.
>
> The code it's generating is something like this:
>
> (let-syntax ((foo (syntax-rules () ((foo) 5)))) (foo))
>
> But it's still failing.
>
> 2. define-syntax-in-context effectively executes the transformer
> expression, creating the actual transformer function. It also
> declares a top-level macro with the same name. When that macro is
> called, it looks up the current context from a global variable with
> dynamic scope, and then applies the appropriate transformer. This
> works, but since this requires a top-level syntax declaration and
> uses dynamic scope, I find this solution unsatisfying.
>
> 3. Similar to the original, I save the transformer syntax objects in
> a hash table. Instead of making let-syntax terms, I create a syntax
> environment using syntax-local-make-definition-context and syntax-
> local-bind-syntaxes, and apply it to the body using local-expand, and
> return the result. This seems to work part of the time, as long as
> the with-context is being called in the module where the syntax was
> originally declared. However, it fails at weird times. For instance,
> in this same macro, I made another syntax object which uses with-
> context to process one set of syntax multiple times in different
> contexts. That doesn't seem to work.
>
> It seems that one of my troubles relates to the actual generated
> symbol syntax-object made from datum->syntax-object, possibly related
> to the context syntax object I have to pass. Am I making some sort of
> silly mistake, or is there something wrong with the way I'm
> approaching this problem?
>
> Thanks in advance,
> - Brian Chin