[racket] variables within macros
Hi Tim,
Danny explains the problem well.
To accumulate a result, one must stay in the same
same dynamic extent. One way to solve the problem
is to use local-expand. In some cases one can
write expanders for the forms, that needs analysing
and call them directlye (rather than write a macro
for the subform and then let the expander
call a macro transformer).
Below is a short example, which incidently shows
an alternative solution the local-expand problem,
I had the other day
(see http://www.mail-archive.com/users@racket-lang.org/msg15937.html ).
If you need local-expand, then see Matthews answer on how
to use definition contexts with local-expand.
/Jens Axel
#lang racket
;;; Consider the following grammar where upper case
;;; symbols stand for literal identifiers (in lowercase).
; program ::= (PROGRAM var-decl-part body)
; var-decl-part ::= (VAR-DECL-PART var-decl ...)
; var-decl ::= (VAR-DECL DEF id type expr)
; body ::= (BODY expr ...)
; type ::= identifier
;;; The program
; (program
; (var-decl-part
; (var-decl (def x int 42))
; (var-decl (def y str "foo"))
; (body (list x y)))
;;; expands to
(let ()
(define x 42)
(define y "foo")
(list x y))
;;; During the expansion, type information is
;;; collected.
;;; The goal is to define one macro for each grammar rule.
;;; In the expansion of the body, type information
;;; from the expansion of the var-decl-part must be present
;;; to signal error for, say, (+ x y).
;;; The program macro thus uses local-expand to expand
;;; the var-decl-part.
(require racket/stxparam
racket/splicing
(for-syntax syntax/parse
syntax/context
racket/syntax))
(begin-for-syntax
(define *types* '())
(define (add-type id type)
(set! *types* (cons (cons (syntax->datum id)
(syntax->datum type))
*types*))))
(define-syntax (program stx)
; program ::= (PROGRAM var-decl-part body)
(syntax-parse stx
[(_ var-decl-part body)
(define expanded-var-decls
(expand-var-decl-part #'var-decl-part))
(displayln (list "Type information: " *types*))
(with-syntax
([(def ...) expanded-var-decls])
(syntax/loc stx (begin def ... body)))]))
(begin-for-syntax
(define (expand-var-decl-part stx)
; var-decl-part ::= (VAR-DECL-PART var-decl ...)
(syntax-parse stx
[(_ var-decl ...)
(define expanded-var-decls
(map expand-var-decl (syntax->list #'(var-decl ...))))
expanded-var-decls]))
(define (expand-var-decl stx)
; var-decl ::= (VAR-DECL DEF id type expr)
(displayln stx)
(syntax-parse stx
[(_ (def id type expr))
(add-type #'id #'type)
(syntax/loc stx (define id expr))])))
(define-syntax (body stx)
; body ::= (BODY expr ...)
(syntax-parse stx
[(_ expr ...)
(syntax/loc stx (begin expr ...))]))
(program
(var-decl-part
(var-decl (def x int 42))
(var-decl (def y str "foo")))
(body (list x y)))
>
> Tim
>
> ===================================================================================
> "counted-defines.rkt" (similar to what's on the 17.1.2 Using #lang s-exp
> Guide Page)
> ===================================================================================
> #lang racket
> (provide (except-out (all-from-out racket) #%module-begin define)
> (rename-out (module-begin #%module-begin) (my-define define)))
>
> (require (for-syntax syntax/parse))
> (define-for-syntax counter 0)
>
> (define-syntax (my-define stx)
> (syntax-parse
> stx
> [(_ i v) (set! counter (add1 counter)) #`(define i v)]
> [(_ (i args ...) v ...+) (set! counter (add1 counter))
> #`(define (i args ...) v ...)]))
>
> (define-syntax (module-begin stx)
> (syntax-parse
> stx
> [(_ expr ...)
> #`(#%module-begin expr ...
> (define defines-count #,counter)
> (provide defines-count))]))
>
>
> ==========================
> "test-counted-defines.rkt"
> ==========================
> #lang s-exp "counted-defines.rkt"
> (define woo 2) ; should have pushed counter up by one?
>
>
> ==========================
> I then run: racket -e '(require "test-counted-defines.rkt") defines-count'
> Which returns me "0"
>
>
>
> --
> Tim Brown <tim.brown at cityc.co.uk> | City Computing Limited |
> T: +44 20 8770 2110 | City House, Sutton Park Road |
> F: +44 20 8770 2130 | Sutton, Surrey, SM1 2AE, GB |
> -----------------------------------------------------------------------|
> BEAUTY: What's in your eye when you have a bee in your hand |
> -----------------------------------------------------------------------'
> City Computing Limited registered in London No. 1767817.
> Registered Office: City House, Sutton Park Road, Sutton, Surrey, SM1 2AE
> VAT number 372 8290 34.
> ____________________
> Racket Users list:
> http://lists.racket-lang.org/users
--
--
Jens Axel Søgaard