Re: fundamental design issues Taylor Campbell 03 Dec 2005 16:22 UTC

   Date: Fri, 2 Dec 2005 18:21:57 -0800 (PST)
   From: bear <xxxxxx@sonic.net>

   But I want to point out some simple things that work
   in other languages, and point out that this model
   does not support them.

(I'm going to assume, since you're responding to my mail, that by
'this model' you mean my (Scheme48-based) model, not the current
SRFI's (MzScheme-based) model.)

   In static languages such as C and Pascal, a forward
   declaration is often used to state particular properties
   about a function or procedure, while leaving the body
   of the definition for later (presumably after the
   definitions of some of the things it depends on).

   In both languages, a procedure or function may have any
   number of forward declarations (or the same forward
   declaration may be imported multiple times) but only
   one definition.

   In C in particular, this turned out to facilitate a
   very useful pattern.  A "header file" with nothing but
   forward declarations allows most interdependency problems
   to be solved statically, because the forward declarations
   facilitate the separated compilation of many different
   units. The effect is that with the forward declarations
   handy, the compiler knows how to compile calls to particular
   functions, even when the definitions of those functions are
   not visible.  This is very important.

I certainly agree that this can be very important, and this is why I
am proposing a module model that allows for this kind of information
to be obtained from simple static analyses of the module language
without delving into the source code of any modules.

   So I look at the "imports" syntax, and I am thinking,
   "Here is a forward declaration.  Does it contain enough
   information to allow a compiler to create an optimized
   call to the associated function without being able to
   see the function definition?"  And the answer is a resounding
   no.  It contains only namespace control information.

No, the answer is not a resounding 'no.'  The answer depends on what
information can be obtained statically from the modules from which
bindings are being imported.  In my proposed model, this information
is *always* available to a processor of the module system, in the form
of the interface of the module.  Indeed, namespace control information
is only one of the many useful properties of the model I'm proposing,
among which this kind of easy static analysis of module descriptions
also lies.

   So I look at the "exports" syntax, and I am thinking,
   "okay, here is more namespace control information, but it
   is also a specification that, together with the file of
   source code, may be used to automatically generate
   (implicit) forward declarations usable in the compilation
   of other files."

Ignoring macros, you do not need the source file.  The interface
contains enough information to know what kind of denotation every
identifier exported by a module implementing the interface will have.
This is sufficient to compile clients of the modules (assuming, again,
that macros are not used, which inherently require static information
to be passed across module compilations).

In the simplest form, there is no more information than whether the
binding is a syntactic binding or a run-time variable binding, but the
EXPORT syntax could be extended to support more information than that
for further compiler optimization.  In Scheme48, for example, there is
a simple static type language that can be used to annotate the
identifiers listed in interfaces with their static types; the
interface of the SCHEME module, for instance, might be defined along
these lines:

 (define-interface scheme-interface
   (export ... (car (proc (:pair) :value)) ...))

(This optional static type language is documented in my unofficial
Scheme48 reference manual, which is available on the web at
<http://mumble.net/~campbell/darcs/s48-refman/> (Texinfo source; I can
supply different formats on request).)