[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Scheme-reports] 5.3 Syntax Definitions



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



_______________________________________________
Scheme-reports mailing list
Scheme-reports@x
http://lists.scheme-reports.org/cgi-bin/mailman/listinfo/scheme-reports