[racket-dev] generalized `begin-for-syntax'
This is great!
Vincent
At Thu, 8 Sep 2011 14:56:18 -0600,
Matthew Flatt wrote:
>
> The `begin-for-syntax' form in v5.1.3.7 supports variable and macro
> definitions within a module for all phases N >= 0 (finally!).
>
>
> As a simple example, you can use `struct' for-syntax without having to
> add `#:omit-define-syntaxes':
>
> #lang racket
>
> (begin-for-syntax
> (require racket/match)
>
> (struct posn (x y)) ; binds `posn' as syntax
>
> (match (posn 1 2)
> [(posn x y) ; uses `posn' as syntax
> (displayln (list x y))]))
>
>
> You can also define macros at the top level of a module to
> be used by macro implementations within the module:
>
> #lang racket
>
> (begin-for-syntax
> ;; like `syntax-rules', but quasiquotes the template:
> (define-syntax-rule (syntax-rules~ () [pat tmpl] ...)
> (lambda (stx)
> (syntax-case stx ()
> [pat #`tmpl]
> ...)))
> ;; plain old compile-time helper:
> (define (check-id stx)
> (unless (identifier? stx)
> (raise-syntax-error #f "not an identifier" stx))
> stx))
>
> (define-syntax define-five
> (syntax-rules~ ()
> [(_ id) (define #,(check-id #'id) 5)]
> [(_ id 5) (define-five id)]))
>
> (define-five V)
> (define-five wu 5)
> (+ V wu)
>
>
> Perhaps most usefully, you can define a syntax class in the same module
> as a macro that uses `syntax-parse':
>
> #lang racket
> (require (for-syntax syntax/parse))
>
> (begin-for-syntax
> (define-syntax-class two
> (pattern [x y])))
>
> (define-syntax (ark stx)
> (syntax-parse stx
> [(_ a:two ...)
> #'(list '(a ...))]))
>
> (ark [snake snake] [tiger tiger] [ant ant])
>
>
> A `begin-for-syntax' form can contain `begin-for-syntax' forms with
> phase-2 definitions, and so on.
>
> ----------------------------------------
>
> As part of this change, the grammar of fully expanded expressions has
> changed. It no longer includes `define-values-for-syntax', but
> `begin-with-syntax' is a core form, and `begin-with-syntax' forms can
> be nested.
>
> Code that uses `kernel-syntax-case' with a `define-values-for-syntax'
> case needs to be changed to one with a `begin-with-syntax' case. (I've
> changed the ones in the main code repo.) Fortunately, most code that
> uses `kernel-syntax-case' only handles expressions, in which case there
> is no `define-values-for-syntax' case.
>
> The `syntax-local-module-defined-identifiers' function now returns a
> hash table mapping phase levels to lists, instead of two lists.
>
> Some structs from `compiler/zo-structs' have changed: `def-for-syntax'
> is gone, `seq-for-syntax' is added, some `mod' fields have changed
> (such as a `syntax-bodies' instead of `syntax-body'), and
> `def-syntaxes' has a new field.
>
> The order of expansion for a module body has changed slightly. A
> `begin-for-syntax' form is expanded with the same two-pass algorithm as
> a module body overall, which means that partial expansion is used to
> expose definitions and meta-forms before expanding expressions. All
> `provide' (or, more precisely, `#%provide') forms across all phases are
> delayed until the module is otherwise expanded, and then the
> `#%provide' forms are expanded in the order that they appear within the
> module (independent of phase).
>
> _________________________________________________
> For list-related administrative tasks:
> http://lists.racket-lang.org/listinfo/dev