[R6RS] SYNTAX-CASE

dyb at cs.indiana.edu dyb
Mon Apr 11 15:52:54 EDT 2005


> > This means we can still discuss changes to the proposal, but gives
> > Kent enough license to write down the bulk of it.  Right?
>
> That's my understanding.  Kent, will you write up a formal proposal
> that we can put up for vote (I prefer you do it so that we have a
> clear wording of what you have in mind.)

I propose that we accept syntax-case as proposed below and direct me to
produce a more precisely worded description, with input from Matthew
and anyone else who cares to contribute, but that we leave open the
possibility that we would reconsider the pattern language if a replacement
is proposed.  What this does is insure that we have something in the
r6rs by default if efforts to produce something better falter.

Kent

--------

Syntax objects:
  Syntax objects are opaque datatypes.  Syntax objects may be created
  by the expander or by the programmer via the syntax form or
  datum->syntax-object (see below).  Syntax objects represent program
  fragments and sufficient information to place identifiers contained
  within those fragments in their proper lexical context.

  Syntax objects may be coerced to data via syntax-object->datum
  (see below).

  Terminology note: a syntax-object representing an identifier is
  referred to as an identifier.

  note: we may want to add syntax->list, especially for use in fenders
  that want to map predicates, like identifier?, over lists of syntax
  objects.

Transformers:
  define-syntax, let-syntax, or letrec-syntax right-hand-sides are
  transformers.  A transformer is an expression that evaluates (at
  expansion time) to a procedure of one argument.  The expander
  applies a transformer to a syntax object representing the input
  form.

  note: we may want the transformer to take two arguments: a syntax object
  and a compile-time environment, provide a mechanism for extracting
  bindings from the environment, and specify abstractly what the bindings
  look like.  We would presumably also want to extend define-syntax and
  company right-hand sides to allow extended bindings to be placed into
  the compile-time environment.

define-syntax:
  No change in syntax, but allow define-syntax to appear wherever other
  definitions can appear

indirect-export:
  (indirect-export keyword identifier ...) is a declaration to the
  module system that the transformer associated with keyword may
  insert references to one or more of identifier ....  If keyword is
  directly or indirectly exported by a module, then identifier ...
  are indirectly exported.  Identifiers that are indirectly exported
  and not separately directly exported can be referenced or assigned
  only by the code produced by an exported transformer.

  note: this can go away if we don't agree on module system.  if we do
  agree on a module system, it may be better to describe this form
  with the module system.

syntax-rules
  syntax-rules evaluates to a procedure of one argument.

  syntax-rules is as in r5rs with the following extensions:

  - Patterns are generalized slightly to allow a fixed number of
    subpatterns to appear after an ellipsis, e.g., (x ... y z).

  - Underscores are anonymous pattern variables that match anything
    but are not bound to anything.

    note: should also allow underscore in place of macro keyword in
    'car' of syntax-rules pattern

  - An optional fender may appear between the pattern and
    template of any clause.  the clause is chosen only if the
    pattern matches the input and (if present) the fender
    evaluates to a non-false value.  within the fender, the
    pattern variables appearing within the pattern are bound
    to the corresponding pieces of the input.

  syntax-rules may be defined as a macro in terms of syntax-case.

syntax-case
  syntax-case has the following syntax:

  (syntax-case expr (literal ...) clause ...)

  where clause takes one of the two forms below.

    (pattern output-expr)
    (pattern fender output-expr)

  (literal ...) and fenders are as in syntax-rules.

  syntax-case evaluates expr, which must evaluate to a syntax object,
  then attempts to find a matching clause by trying each pattern
  and, for patterns that match, fender in turn.

  The pattern variables of the matching clause are bound to the
  corresponding pieces of the input within output-expr.

  Patterns are similar to syntax-rules patterns except that the
  pattern need not be list structured and, if list structured,
  the first subform is not treated specially.

  The following transformers for or are equivalent:

      (syntax-rules ()
        ((_) #f)
        ((_ e) e)
        ((_ e1 e2 ...) (let ((t e1)) (if t t (or e2 ...)))))

      (lambda (x)
        (syntax-case x ()
          ((_) #'#f)
          ((_ e) #'e)
          ((_ e1 e2 ...) #'(let ((t e1)) (if t t (or e2 ...))))))

syntax
  A syntax form, written as (syntax datum) or #'datum, evaluates to a
  syntax object representing datum, with embedded pattern variables
  lexically visible where the syntax form appears replaced by their
  values.  Ellipses are used as in syntax-rules templates.  Information
  necessary to place each identifier (except pattern variables replaced
  as described above) in the lexical context of the syntax form is
  incorporated into the syntax object.

syntax-object?
  is bound to a procedure that takes a single argument.  If the argument
  is a syntax-object, it returns #t, otherwise it returns #f.

syntax-object->datum
  is bound to a procedure that takes a single argument, which must be
  a syntax-object.  It returns a datum representing the syntax object.
  All lexical-context information associated with embedded identifiers
  is lost.

datum->syntax-object
  is bound to a procedure of two arguments.  The first is a template
  identifier and the second is an arbitrary value.  datum->syntax-object
  converts the value into a syntax object with all of the information
  necessary to make the object appear to the expander as if it appeared
  in the source or macro output where and when the template identifier
  first appeared.

generate-temporaries
  is bound to a procedure of one argument.  The argument must be a
  proper list, the contents of which is of no consequence.
  generate-temporaries returns a list of unique identifiers as long
  as the input list.

identifier?
  is bound to a procedure of one argument.  It returns true if the
  argument is an identifier (syntax object representing an identifier),
  otherwise false.

bound-identifier=?
  is bound to a procedure of two arguments, which must both be
  identifiers.  It returns true if a binding for either in the output
  of a macro would capture references to the other.

free-identifier=?
  is bound to a procedure of two arguments, which must both be
  identifiers.  It returns true if the two identifiers would refer
  to the same binding if inserted into the output of a macro as
  free identifiers. 

  note: we may also need literal-identifier=? if we add modules

identifier-syntax
  identifier-syntax is an additional way to define transformers for
  simulated variables.  It takes one of the following two forms:

    (identifier-syntax template)

    (identifier-syntax
      [id template]
      [(set! id expr) template])

  note: we probably want a lower-level version of this as supported
        by both Chez Scheme and MzScheme.

with-syntax
  with-syntax is a local binding construct (like let) for pattern
  variables.  It takes the following form:

     (with-syntax ((pattern expr) ...) expr)

  e.g.,

     (with-syntax ((a 1) ((b ...) '(2 3 4))) #'(a b ...)) => (1 2 3 4)

  it is may be defined as a macro in terms of syntax-case.

Note:
  We may also want to consider adding fluid-let-syntax


More information about the R6RS mailing list