Having pored over Robin Popplestone's report on static type-checking
I have to admit that I am impressed. Although it is not (yet) integrated
into Pop11 in a satisfactory way, his results show that it is surprisingly
effective.
To turn this work into a product, I think there are several points for
improvement. Here are the points I think are important:
(1) Types must become values rather than names. Otherwise this work
will be impossible to extend to sections and lexical types.
However, this raises the problem of how type-names in declarations
get translated into type-values. (I met this problem in method
declarations in the ObjectClass work.) I think that the right
resolution is to have a separate name space for values and types.
This suggestion may seem like heresy to those of us who have
grown up with Pop11 having a single name space. But there is an
established and (to my mind) reasonable convention that the
dataword is a valid variable name i.e. The local variable -vector-
is a perfectly sensible name for a typical vector.
define revv( vector ); .... enddefine;
There are many parts of Pop11 that would benefit from the ability
to create new name spaces. The best examples to date are
-p_typespecs-, -l_typespecs-, and the Prolog subsystem. There are
three obvious implementation techniques:
(a) Use a special prefix/suffix for names that are conceptually
in the "other" namespace. This is the solution adopted
currently.
(b) Implement a way of creating new, unpopulated top-level
sections. (This is an especially clean solution, in my view.)
(c) Simply create a hash table from idents to values i.e.
adds a virtual field to idents.
(2) The scheme for introducing type variables is too clumsy. I would
prefer a syntactic marker for type variables, such as ?x for monologs
and ??x for polylogs. e.g.
Instead of
All a, b; List of {<a>} * (<a> -> <b>) -> List of {<b>}
one would write
list of { ?a } * ( ?a -> ?b ) -> list of { ?b }
(3) Instead of using an unfamiliar infix syntax ( "of" ) for type
parameterisation I would prefer simple brackets. This makes the extent
of the parameter much clearer. In the above example, the type could
be read in (at least) two ways
( List of {<a>} ) * (<a> -> <b>) -> List of {<b>}
or
List of ( {<a>} * (<a> -> <b>) -> List of {<b>} )
Using brackets for type parameterisation, it might look like
this
list( ?a ) * ( ?a -> ?b ) -> list( ?b )
or, to distinguish the brackets,
list[ ?a ] * ( ?a -> ?b ) -> list[ ?b ]
(4) Some of the limitations in the system would be overcome by employing
the "high-level" code-planting instructions that I have previously
described. For example, instead of writing the "#| ... |#" syntax
in terms of explicit labels, variables, and arithmetic, one would
create the instructions sysCOUNT( dummy ) ... sysENDCOUNT( dummy ).
Defining these high level instructions is reasonably straightforward
provided sysCOMPILE (and friends) are defined to localise a state
variable. This state variable allows the high-level instructions
to keep a stack of the ``expected'' instructions. Other examples
would be high-level loop instructions (sysWHILE/DO/ENDWHILE) and
conditinals (sysIF/THEN/ELSEIF/ELSE/ENDIF). These are not especially
difficult to define -- see the pop9x demo code for an example.
This would mean that the type-system would be able to reason much
more effectively about a variety of common constructs.
Alternatively, adding parse tree creation to Pop11 would be a
rather superior approach.
|