[R6RS] phases and modules (was syntax-case semantics)

William D Clinger will at ccs.neu.edu
Wed Mar 22 12:10:55 EST 2006


I don't understand the phase semantics of libraries as
specified by SRFI 83.  The comments in the following
example ask questions I can't answer.

****************************************************************

(library "global-counter" "scheme://r6rs"
  (export new-integer)

  (define new-integer
    (let ((n 0))
      (lambda ()
        (set! n (+ n 1))
        n))))

(library "fresh-integer" "scheme://r6rs"
  (import "global-counter")
  (export fresh-integer)

  ; Must this library declare new-integer as
  ; an implicit export?

  (define-syntax fresh-integer
    (syntax-rules ()
      ((_) (new-integer)))))

(library "A" "scheme://r6rs"
  (import "global-counter")
  (export a1 a2 a3)

  (define a1 (new-integer))
  (define a2 (new-integer))
  (define a3 (new-integer)))

(library "B" "scheme://r6rs"
  (import (for "fresh-integer" expand))
  (export b1 b2 b3)

  (define b1 (fresh-integer))
  (define b2 (fresh-integer))
  (define b3 (fresh-integer)))

(library "C" "scheme://r6rs"
  (import "A" "B")

  ; Can this list contain duplicates?
  ; If not, why not?

  (write (list a1 a2 a3 b1 b2 b3))
  (newline))

****************************************************************

According to SRFI 83, executing library "C" is the same as
invoking library "C" at phase 0.  Assuming an interpreter as
pure as SRFI 83 allows, and a left to right, depth-first order
of evaluation of the library DAG, here's what happens:

* invoke "C" at phase 0
* invoke "A" at phase 0
* invoke "global-counter" at phase 0
* invoke "B" at phase 0
* evaluate all definitions within "B"
* et cetera

The SRFI 83 section on "Library Semantics" is leaving something
out, however, because we can't evaluate the definitions of "B"
until the "fresh-integer" library has been invoked or visited.
SRFI 83 alludes to this, but doesn't specify when it should
happen except by alluding to "compiling a library".  Our
hypothetical interpreter doesn't compile, so I don't know what
this means.

I'm guessing that the intended semantics is something like

* invoke "C" at phase 0
* invoke "A" at phase 0
* invoke "global-counter" at phase 0
* invoke "B" at phase 0
* invoke "fresh-integer" at phase 1
* invoke "global-counter" at phase 1
* evaluate all definitions within "global-counter"
* evaluate all syntax definitions within "fresh-integer"
* evaluate all definitions within "B"
    so b1=1, b2=2, b3=3
* evaluate all definitions within "global-counter"
* evaluate all definitions within "A"
    so a1=1, a2=2, a3=3, I think
* evaluate all definitions and top-level forms within "C"
    so the output is (1 2 3 1 2 3), I think

I'm hoping this is not the intended semantics.

Another question:  When a library is invoked twice, at different
phases, does it define two different copies of its variables, or
does it redefine the same copy during the second invocation?

Will




More information about the R6RS mailing list