[R6RS] library proposal(s)

dyb at cs.indiana.edu dyb at cs.indiana.edu
Tue Jun 13 11:43:17 EDT 2006


I've included below some proposals for updating the library syntax to
accommodate the features we've discussed.  The SRFI 83 syntax is
given first, followed by three proposal variants, followed by some
orthogonal options.

Kent

--------

Review---SRFI 83 syntax:

  (library <lib-path> <language> <body>)

  <body> --> <impexp-form>* <comdef-form>*

  <impexp-form> --> (import <import-spec>*)
      | (export <export-spec>*)
 
  <comdef-form> --> <command or definition>
      | (indirect-export <indirect-spec>*)
      | (begin <comdef-form>*)
      | <derived-comdef>
   
  <import-spec> --> <import-set>
      | (for <import-set> <import-phase>*)

  <import-phase> --> run
      | expand

  <export-spec> --> <export-set>

  <indirect-spec> --> (<identifier> <identifier>*)

  <import-set> --> <lib-path>
      | (only <X-set> <identifier>*)
      | (except <X-set> <identifier>*)
      | (add-prefix <X-set> <identifier>)
      | (rename <X-set> (<identifier> <identifier>)*)

  <export-set> --> <identifier>
      | (rename (<identifier> <identifier>)*)

Proposed syntax, Variant I:

  (library <lib-path>
    (import <import-spec>*)
    (export <import-spec>*)
    <library body>)

  <library body> --> <command or definition>*

  <command or definition> --> <command>
      | <definition>
      | (begin <command or definition>*)
      | <derived command or definition>

  <definition> --> <variable definition>
      | <syntax definition>
      | (indirect-export <indirect-spec>*)

  <variable definition> --> (define <variable> <expression>)
      | (define (<variable> <def formals>) <body>)

  <syntax definition> --> (define-syntax <keyword> <transformer spec>)

  <lambda expression> --> (lambda <formals> <body>)

  <body> --> <command or definition>* <expression>

  [ all else remains as in the SRFI 83 ]

  Scoping: all imports and definitions occupy a single scope within
    the library <body>.

  Rationale: This variant eliminates <language>, thereby allowing
    us to use the subsetting and renaming features of <import-spec>
    for all imported libraries.

    It also allows indirect-export in any definition context, so that
    macros that expand into macro definitions can also produce any
    necessary indirect-export forms.  indirect-export forms would be
    ignored except within a library <body>.

    It also allows lambda bodies to contain interleaved commands and
    definitions.  I didn't allow this in the syntax srfi because I thought
    that the library srfi required all of the definitions to appear before
    all of the commands/expressions.

  Example:

    (library sane-if
      (import (rename "scheme://r6rs" (r6rs:if if)))
      (export if)
      (define-syntax if
        (syntax-rules ()
          [(_ e1 e2 e3) (r6rs:if e1 e2 e3)])))

Proposed syntax, Variant II:

  (library <lib-path> <language>
    (import <import-spec>*)
    (export <import-spec>*)
    <body>)

  <language> -> <import-spec>

  [ all else remains as in Variant I ]

  Scoping: the language and all imports and definitions occupy a single
    scope within the library <body>.

  Rationale: This variant keeps <language>, allowing an implementation
    or future report more lattitude in changing the library syntax.  (With
    language r7rs, for example, the syntax of a library body might
    differ.) As with Variant I, it still allows the use of the subsetting
    and renaming features of <import-spec> for all imported libraries,
    including the language library.

  Example:

    (library sane-if (rename "scheme://r6rs" (r6rs:if if))
      (import)
      (export if)
      (define-syntax if
        (syntax-rules ()
          [(_ e1 e2 e3) (r6rs:if e1 e2 e3)])))

Proposed syntax, Variant III:

  (library <lib-path> <language>
    (import <import-spec>*)
    (export <import-spec>*)
    <body>)

  <language> -> <lib-path>

  [ all else remains as in Variant I ]

  Scoping: the language occupies a single outer contour, and the imports
    and definitions occupy a single outer contour.

  Rationale: As with Variant II, this variant keeps <language>, allowing
    an implementation or future report more lattitude in changing the
    library syntax.  While the language imports cannot be subject to
    subsetting or renaming, the language bindings can be shadowed by
    the imported bindings and definitions in the library body.  This
    allows an implementation or future report even more lattitude in
    changing the library syntax, since it doesn't tie down the
    <import-spec> syntax.

  Example:

    (library sane-if "scheme://r6rs"
      (import (rename (only "scheme://r6rs" if) (r6rs:if if)))
      (export if)
      (define-syntax if
        (syntax-rules ()
          [(_ e1 e2 e3) (r6rs:if e1 e2 e3)])))

Orthogonal options:

  * Instead of allowing definitions and commands to be interleaved in
    a lambda body, we might want to go the other way and require
    definitions to appear before commands in both library and lambda
    bodies.

  * Instead of tying down the import syntax and requiring imports to
    appear only at the head of a library form, we might want to allow
    import forms to be derived and/or appear anywhere a definition can
    appear.  (Allowing them to appear anywhere a definition appears
    implies allowing them to be derived, but the converse is not
    true.)

  * Instead of tying down the export syntax, we might want to allow
    export forms to be derived and/or appear anywhere amongst the
    definitions in a language body.  (Allowing them to appear anywhere a
    definition appears implies allowing them to be derived, but the
    converse is not true.)

  * With variants II and III we may want for the language to be
    imported "for expand" as well as "for run".  (I'm not sure whether
    this is true in SRFI 83.)  With Variant I we may want for
    all imports to be imported "for expand" as well as "for run"
    unless the import-spec says otherwise.  But see the next option
    below.

  * Instead of requiring the user to specify "for expand" or
    "for run", the expander could automatically invoke (or cause to be
    invoked) an imported module at the appropriate meta level if an
    attempt is made to reference an identifier at that level.

  * Another way to avoid "for expand" and "for run" is to allow local
    imports.  A local import within a transformer expression is
    implicitly "for expand".  This only works if the language and/or
    all imports are implicitly imported "for expand" as well as "for
    syntax".



More information about the R6RS mailing list