[r6rs-discuss] Formal comment 61

From: AndrevanTonder <andre>
Date: Sun Dec 17 13:47:04 2006

I would like to register a slight disagreement with the response to formal
comment 61: "Expansion process violates lexical scoping".

  - Lexical scoping is, in my opinion, too basic a property of the
    language to permit leaving its enforcement up to the user.
    I believe it would be better if the syntactic check were mandatory and
    not optional as stated in the response.
    To support this, I would like to point out that several of the
    commented out examples below give lexical-scope-violating answers on
    MzScheme and/or Chez. The problems with these fragments are not
    always immediately obvious even to experienced people, and it may
    be asking too much to expect users to anticipate them and do the required
    alpha-renaming (for example) to avoid them. That should be the job of the
    expander, which should be reliable.

  - An algorithm that avoids these violations exists. It is trivial to
    implement. It was also, in my implementation, easier to implement
    than the r5.91rs algorithm.

  - It is not expensive. I found the slowdown, if any, over the r5.91rs
    algorithm, to be imperceptible.

  - The algorithm is single-pass left-to-right.

The algorithm is implemented in the newer version of the implementation at

    http://www.het.brown.edu/people/andre/macros/

and may be summarized as follows:

      It is a syntax violation if an identifier whose meaning is needed
      during the left-to-right expansion of definitions is subsequently
      redefined by a definition in the same body. To detect this error, the
      expander records each identifier reference occurring during
      expansion of the body.
      Before an identifier is bound, its current binding is compared
      against bindings already referenced for the same (in the sense of
      bound-identifier=?) identifier during the expansion of the definitions.
      If a match is found, the binding may have already affected the
      expansion of the body, and a syntax violation is therefore thrown.

This algorithm correctly throws an error for all the cases below where the
current draft algorithm would allow lexical violations. Several of the
commented out examples below give incorrect answers on MzScheme and/or Chez.

    ;; This must give an error:

    ;; (let ()
    ;; (define-syntax foo (lambda (e) (+ 1 2)))
    ;; (define + 2)
    ;; (foo)) ; Syntax violation: Redefinition of identifier + that
    ;; has already been referenced during expansion of body

    ;; This gives no error:

    (let ()
      (define-syntax foo (lambda (e) (let ((+ -)) (+ 1 2))))
      (define + 2)
      (foo)) ;==> -1

    ;; This must give an error:

    ;; (script
    ;; (import r6rs)
    ;; (bar x)
    ;; (define-syntax bar
    ;; (syntax-rules ()
    ;; ((bar x) (define x 1))))
    ;; x) ; Syntax violation: Redefinition of identifier bar that has
    ;; already been referenced during expansion of body

    ;;(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: Redefinition of identifier x that has
    ;; already been referenced during expansion of body

    ;; Still, the following is valid.

    (let ((x #f))
      (let-syntax ((foo (syntax-rules (x)
                          ((_ x y) (define y 'outer))
                          ((_ _ y) (define y 'inner)))))
        (let ()
          (define x #f)
          (foo x p)
          p))) ;==> inner

    ;;(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: Redefinition of identifier x that has
    ;; already been referenced during expansion of body

    ;;(let-syntax ([def0 (syntax-rules ()
    ;; [(_ x) (define x 0)])])
    ;; (let ()
    ;; (def0 z)
    ;; (define def0 '(def 0))
    ;; (list z def0))) ; Syntax violation: Redefinition of identifier def0 that has
    ;; already been referenced during expansion of body

    ;;(let ()
    ;; (define define 17)
    ;; define) ; Syntax violation: Redefinition of identifier define that has
    ;; already been referenced during expansion of body

    ;; (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: Redefinition of identifier foo that has
    ;; ; already been referenced during expansion of body

    ;; (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: Redefinition of identifier foo that has
    ;; ; already been referenced during expansion of body

    ;; This should still be valid.

    (let ()
      (define-syntax foo
        (syntax-rules ()
          ((_ def0) (def0 define 17))))
      (foo define)
      0)

Andre
Received on Sun Dec 17 2006 - 13:42:09 UTC

This archive was generated by hypermail 2.3.0 : Wed Oct 23 2024 - 09:15:00 UTC