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

a separate configuration language



In both Marc Feeley's original SRFI 0 and in the SRFI editors'
revised version, programs and their configuration (e.g. what
SRFI's they use) are intermixed.  I think that this is a mistake
for a number of reasons:

 - I have found that more than minimal use of C's #ifdef construct,
   which is similar to IF-IMPLEMENTS and COND-IMPLEMENTS, makes code
   extremely hard to read.

 - Both people and programs need to read the entire source to see
   which SRFI's might be needed.  In the revised SRFI 0, ambiguities
   can arise if an identifier appears before the IMPORT-IMPLEMENTATION
   form that defines it.  Does the entire source have to be read
   before evaluating the first form?  Does it all have to be macro
   expanded before evaluating the first form?
   
 - It may be difficult to implement either version of SRFI 0 in the
   presence of a module system.  This is certainly the case with
   Scheme 48.

I would like to propose that we have a separate configuration
language, one that is not embedded in Scheme.  Below is a suggestion
for such a language.  It is not quite as flexible as either version
of SRFI 0, in that features can be tested only at top level, and not
in nested expressions.  I doubt that this would matter much in
practice, given the ease of writing both procedural and syntactic
abstractions in Scheme.  In return we get a very simple and portable
configuration language that avoids any confusing interaction with the
underlying Scheme's syntax and semantics.

                                    -Richard Kelsey

----------------
Configuration language syntax:

 <program> --> (program <program clause>+)

 <program clause>
   --> (requires <feature-identifier>+)
   --> (reader-syntax <feature-identifier>+)
   --> (files <filename>*)
   --> (code <body>)
   --> (feature-cond <feature-cond clause>+)

  <feature-cond clause>
   --> (<implementation requirement>
        <program clause>+)

  <implementation requirement>
   --> as in the SRFI editor's version of SRFI 0

  <feature identifier>
   --> as in the SRFI editor's version of SRFI 0

----------------
Semantics:

Given a set of available features and a configurable reader,
a <program> can be read in as a list of S-expressions to be
evaluated.  No macro expansion is required to read a <program>.

Each implementation would provide some way for loading a program.
For example, it might have a (LOAD-PROGRAM <filename>) function
or a compiler that compiled a program into an executable file.

The meanings of the different clauses are given below.  The
ordering of the clauses in a <program> is significant.  It
determines both the order of the forms in the final program
and which reader is used to read different sections of the
program.

(requires <feature-identifier>+)
  The listed features are required by the program.  If one or
more is not provided by the implementation the program cannot
be run.

(reader-syntax <feature-identifier>+)
  The listed features determine the lexical syntax of the program
from this point on.  If one or more of the features is not provided
by the implementation the program cannot be read.  [Personally, I
do not think changes to the lexical syntax are a good idea.  At a
minimum they should be restricted to the #... syntax.  Scheme
programs should have something in common.]

(files <filename>*)
  The listed files are read, using the current lexical syntax,
and the forms they contain added to the program.

(code <body>)
  The forms in <body> are read, again using the current lexical
syntax, and added to the program.  (This requires that the syntax
of `)' not be changed by any SRFI).

(feature-cond <feature-cond clause>+)
  The meaning of a FEATURE-COND clause is that of the
<program-clause>s in the first <feature-cond clause> whose
<implementation-requirement> is satisfied by the implementation.
Unlike the proposed COND-IMPLEMENTS, the implementation has no
leeway in choosing which clause to use (down with ambiguity!).

----------------
Implementation:

Available on request.

The portable part of the implementation would be a READ-PROGRAM
function that took three arguments: an input port, a list of
symbols indicating the features available in the current
implementation, and a make-reader function that took a list
of symbols representing features and returned a READ-like
function that supported those features.

READ-PROGRAM would return two values: the forms of the program
as a list of S-expressions and a list of the features used by the
program.  Both this list and any lists passed to the make-reader
function would be subsets of the features list passed to
READ-PROGRAM.