Re: [Scheme-reports] 5.3 Syntax Definitions Andre van Tonder (04 Jun 2011 00:52 UTC)
|
Re: [Scheme-reports] 5.3 Syntax Definitions
Alex Shinn
(04 Jun 2011 07:02 UTC)
|
Re: [Scheme-reports] 5.3 Syntax Definitions
Andre van Tonder
(04 Jun 2011 14:08 UTC)
|
Re: [Scheme-reports] 5.3 Syntax Definitions
Alex Shinn
(05 Jun 2011 09:41 UTC)
|
Re: [Scheme-reports] 5.3 Syntax Definitions
John Cowan
(05 Jun 2011 20:19 UTC)
|
On Fri, 3 Jun 2011, Arthur A. Gleckler wrote: >> > It looks like there's a word missing here. Perhaps add "in" after > "undeferred?" > > I still find it confusing. Sorry, I shot that off too quickly. Better: An internal (syntax-)definition must not shadow any identifier whose binding (or lack of binding) in surrounding code has already affected the expansion of preceding portions of the body or of the (syntax-)definition itself. If this constraint is violated, it means that one identifier is used with two different meanings (bindings) in the same scope, which should be an error. If this is confusing, it is probably because it depends on knowledge of the expansion algorithm, which is not described in the WG1 document. R6RS requires a specific two-pass expansion. The first pass discovers definitions and expands and evaluates macros and the second pass expands deferred right hand sides of variable definitions. This allows uses of macros before they are defined: (let () (define (even n) .....odd....) ; this is a procedure! (define-syntax odd ..........) .....) This style seems to be somewhat unpopular, to say the least. (Note that if both EVEN and ODD were syntax-rules macros, there would be no problem.) A single-pass left to right expansion is possible if we don't care to allow this kind of forward use of macros. Here is a bunch of examples of the kind of things that should be errors, from my test suite: ;; This must give an error: ;; (let () ;; (define-syntax foo (lambda (e) (+ 1 2))) ;; (define + 2) ;; (foo)) ; Syntax violation: Definition of identifier that may have ;; ; already affected meaning of undeferred portions of body: + ;; This gives no error: (let () (define-syntax foo (lambda (e) (let ((+ -)) (+ 1 2)))) (define + 2) (foo)) ;==> -1 ;;(let ((x #f)) ;; (let-syntax ((foo (syntax-rules (x) ;; ((_ x y) (define y 'outer)) ;; ((_ _ y) (define y 'inner))))) ;; (let () ;; (foo x p) ;; (define x #f) ;; p))) ; Syntax violation: Definition of identifier that may have ;; ; already affected meaning of undeferred portions of body: x ;;(let ((x #f)) ;; (let-syntax ((foo (syntax-rules (x) ;; ((_ x y) (define y 'outer)) ;; ((_ _ y) 1)))) ;; (let () ;; (foo x p) ;; (define x #f) ;; p))) ; Syntax violation: Definition of identifier that may have ;; ; already affected meaning of undeferred portions of body: x ;;(let-syntax ((def0 (syntax-rules () ;; ((_ x) (define x 0))))) ;; (let () ;; (def0 z) ;; (define def0 '(def 0)) ;; (list z def0))) ; Syntax violation: Definition of identifier that may have ;; ; already affected meaning of undeferred portions of body: def0 ;;(let () ;; (define define 17) ;; define) ; Syntax violation: Definition of identifier that may have ;; ; already affected meaning of undeferred portions of body: define ;; (define-syntax foo (syntax-rules () ((_ x) (define x 1)))) ;; (let ((b 2)) ;; (foo a) ;; (define (foo x) 2) ;; (foo b) ;; (values a b)) ; Syntax violation: Definition of identifier that may have ;; ; already affected meaning of undeferred portions of body: foo ;; (define-syntax foo (syntax-rules () ((_ x) (define x 1)))) ;; (let () ;; (foo a) ;; (define-syntax foo (syntax-rules () ((_ x) (define x 2)))) ;; (foo b) ;; (values a b)) ; Syntax violation: Definition of identifier that may have ;; ; already affected meaning of undeferred portions of body: foo ;; This should still be valid. (let () (define-syntax foo (syntax-rules () ((_ def0) (def0 define 17)))) (foo define) 0) ;; Distinguishing literals from non-literal data: (let () (define-syntax list-macro (syntax-rules () ((_ x ...) (list x ...)))) ;; This must give violation: ;;(define ... 1) ; Syntax violation: Definition of identifier that may have already ;; ; affected meaning of undeferred portions of body: ... ;; But this must not: (define list cons) (list-macro 1 2)) ;==> (1 . 2) ;;(let () ;; (define-syntax macro ;; (let ((x `(1 ,2))) ;; (lambda (form) x))) ;; (define unquote 2) ;; (macro)) ; Syntax violation: Definition of identifier that may have already ;; ; affected meaning of undeferred portions of body: unquote ;; Have to make sure that previous does give violation but this does not. (let () (define-syntax macro (let ((x `(+ ,2))) (lambda (form) (cadr x)))) (define + 2) (macro)) ;==> 2