[plt-scheme] Can generated lexical (syntax) bindings work?

From: Brian Chin (naerbnic at ucla.edu)
Date: Fri Apr 6 16:27:22 EDT 2007

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

Posted on the users mailing list.