[racket] define-syntax-class
On Wed, Apr 27, 2011 at 11:25 PM, Carl Eastlund <cce at ccs.neu.edu> wrote:
> Modules currently can't define syntax for syntax. However, you can
> use define-syntax-set from mzlib/etc to define multiple macros at once
> that share local bindings, such as syntax classes. Since they're
> lexical bindings rather than module bindings, they work just fine. If
> you want to export them and share them between files, however, you'll
> need to use Sam's suggestion.
That's what I was looking for. Thank you. Here's a complete example
for posterity:
#lang racket/base
(require syntax/parse mzlib/etc
(for-syntax syntax/parse
racket/base)
)
(define-syntax-set (let let1)
(define-syntax-class binding
#:description "binding pair"
(pattern [var:identifier rhs:expr]))
(define-syntax-class distinct-bindings
#:description "sequence of binding pairs"
(pattern (b:binding ...)
#:with (var ...) #'(b.var ...)
#:with (rhs ...) #'(b.rhs ...)
#:fail-when (check-duplicate-identifier (syntax->list #'(var ...)))
"duplicate variable name"
))
(define (let/proc stx)
(syntax-parse stx
[(let bs:distinct-bindings body:expr)
#'((λ (bs.var ...) body) bs.rhs ...)]
[(let)
(raise-syntax-error #f
"expected a sequence of binding pairs and
a body expression"
stx #'let)]
))
(define (let1/proc stx)
(syntax-parse stx
[(let1 b:binding body:expr)
#'((λ (b.var) body) b.rhs)]
[(let1)
(raise-syntax-error #f
"expected a binding pair and a body expression"
stx #'let1)]
))
)
(let ([x 1] [y 2]) (+ x y))
(let ((x 4)) (sub1 x))
(let1 (y 2) (add1 y))
#|
All cause errors:
(let1)
(let)
(let x (add1 x))
(let ([x 1]) )
(let ([x 1] [x 2]) (+ x x))
(let ([(x) (f 7)]) (g x x))
(let ([x 1] [y 2]) (+ x x) 4)
|#