[plt-scheme] require-for-syntax issues

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Thu Jul 10 11:26:00 EDT 2003

At Wed, 9 Jul 2003 23:09:44 -0400, "Felix Klock's PLT scheme proxy" wrote:
> My thought process was something like: mod2:opaque-2 declares a 
> particular syntax transformer.  The RHS for the DEFINE-SYNTAX command 
> uses the transformer environment to lookup free identifiers.  

Variables and syntax objects that appear literally in the RHS of
`define-syntax' get bindings from the transformer environment.

But if the RHS calls another function, the variables and syntax objects
that appear in the called function's body get bindings from their own
lexical environment.

> My goal is to generate new syntax transformers through various 
> compile-time combinators that produce functions of type Syntax -> 
> Syntax.  But my methodology is obviously flawed.   What is wrong with 
> my reasoning above?  What would you do to achieve an effect like this?

The short answer is that MzScheme doesn't provide a piece that it
probably should.

Simplified example:

 (module utils mzscheme
   (provide helper)
   (define (helper) #'id)
           ;; #'id has run-time bindings (phase 0) from mzscheme and utils
           ;; and elaboration-time bindings (phase 1) from mzscheme
   )

 (module m mzscheme
   (require-for-syntax utils)
   ;; This require-for-syntax instantiates utils at elaboration time,
   ;;  shifting its bindings by +1 phase. So the #'id in utils has
   ;;  elaboration-time bindings (phase 1) from mzscheme and utils
   ;;  and elaboration-elaboration-time bindings (phase 2) from mzscheme.
   ;;  It has no run-time bindings.

   (require more-utils)

   (define-syntax (s stx)
     ... #'id
          ;; #'id has run-time bindings from mzscheme and more-utils
          ;; and elaboration-time bindings from mzscheme and utils
     ... (helper) ...
          ;; Resulting #'id has no run-time bindings, so using it
          ;; unquoted in a result expression will lead to an error.

     ) ...)

Suppose that you want the #'id produced by `helper' when called by `s'
to have run-time bindings from more-utils. It would be best if you
could write something like this:

 (module utils mzscheme
   (require-for-next more-utils) ;; imports phase -1 bindings
   (provide helper)
   (define (helper) #'id)
           ;; #'id has run-time bindings (phase 0) from mzscheme and utils,
           ;; elaboration-time bindings (phase 1) from mzscheme
           ;; and next-time bindings (phase -1) from more-utils.
	   ;; Shifting by +1 puts more-utils bindings in phase 0
   )

But `require-for-next' doesn't exist. We're trying to add it.

Meanwhile, the options are to not use a helper module, or to write code
like this:

 (module utils mzscheme
   (provide helper)
   (define (helper ctx) (datum->syntax-object ctx 'id))
   )

 (module m mzscheme
   (require-for-syntax utils)
   (require more-utils)

   (define-syntax (s stx)
     ... (helper #'here) ...
          ;; #'here has run-time bindings from mzscheme and more-utils,
          ;; which is what we want for helper's result
     ) ...)


Matthew



Posted on the users mailing list.