From: Matthew Flatt <mflatt@cs.utah.edu> To: plt-scheme@po.cs.brown.edu Subject: [plt-scheme] 299.11 Date: Fri, 2 Jul 2004 14:09:51 -0600 The v299-tagged code in CVS for MzScheme and MrEd is now version 299.11. (The exp-tagged code is still version 207.1.) I’ve finally added `begin-for-syntax’ and `require-for-template’, which let you modularize macro implementations more nicely. Here’s an example (adapted from the manual) showing a problem that macro implementors often encounter: (module et mzscheme (define (mx) #’700) (provide mx)) (module m mzscheme (require-for-syntax et) (define-syntax (onem stx) (mx)) (printf "~a~n" (onem))) ; prints 700 when run? No, ... The use of `onem’ doesn’t work, because the `et’ module has no bindings that correspond to the run time of `m’. As a result, the compiler can’t make sense of the expression `700’ that is generated by expanding `(onem)’. Before 299.10, the solution was to pass identifiers or other context into `mx’. Now, the problem can be solved by simply adding a `require-for-template’ in `et’: (module et mzscheme (require-for-template mzscheme) ; introduces a binding for the `#%datum’ ; that lives in the future (relative to ; this module’s run time) (define (mx) #’700) (provide mx)) (module m mzscheme (require-for-syntax et) (define-syntax (onem stx) (mx)) (printf "~a~n" (onem))) ; prints 700 when run Alternatively, the implementor of `m’ might not want another module. Maybe the implementor merely wanted a helper `mx’ to use in several macros within `m’. In that case, the `begin-for-syntax’ form offers a better solution: (module m mzscheme (begin-for-syntax (define (mx) #’700)) (define-syntax (onem stx) (mx)) (printf "~a~n" (onem))) ; prints 700 when run Technically, `begin-for-syntax’ is a macro that turns `define-values’ declarations into `define-values-for-syntax’, and the latter is a core form. The `begin-for-syntax’ form also turns `require’ into `require-for-syntax’ and `require-for-template’ into `require’. To complete the set, `define-for-syntax’ expands into `define-values-for-syntaxes’. So the above can also be written (module m mzscheme (define-for-syntax (mx) #’700) (define-syntax (onem stx) (mx)) (printf "~a~n" (onem))) ; prints 700 when run There’s no `provide-for-syntax’ or `require-for-syntax-for-syntax’, so there’s also no `define-syntax-for-syntax’ (which wouldn’t be useful without at least one of the other two). Similarly, it’s no use to put `begin-for-syntax’ inside `begin-for-syntax’. In the future, I may change MzScheme so that the core forms are `begin-for-syntax’ and `begin-for-template’, and so they can be nested arbitrarily. Then, a single module could contain definitions for arbitrarily many different phases ("past" and "future"). But I think that we’ll get pretty far with just `require-for-template’ and a restrictive `begin-for-syntax’. In any case, the current system is a convenient stop on the way to the most general one. ---------------------------------------- Changes: * New forms: `require-for-template’ [core form] `define-values-for-syntax’ [core form] `define-for-syntax’ `begin-for-syntax’ * New procedures: `local-transformer-expand’ `syntax-transforming?’ * `module-compiled-imports’ now returns 3 values * `identifier-binding’ and `identifier-transformer-binding’ return a list of five items instead of four, in the case of a module-bound identifier. * Added an optional argument to `make-input-port’ to support custom line counting. Temporary docs are in the usual place: http://www.cs.utah.edu/~mflatt/tmp/mzscheme-doc.plt http://www.cs.utah.edu/~mflatt/tmp/mzlib-doc.plt http://www.cs.utah.edu/~mflatt/tmp/mred-doc.plt Matthew