The Prop language is fashioned as a superset of C++ and contains a number of extensions. While the extension language does not provide very high level symbolic manipulation and deductive formalisms offered in modern program transformation systems, it does provide a convenient set of constructs for many common symbolic programming tasks, features that are either impossible or hard to simulate using C++ 's classes or object oriented programming. The language provides:
The datatype compiler is responsible for generating low level classes and their member functions to implement these high level datatypes. For example, it is possible to annotate an algebraic datatype to be garbage collectible, which signals the datatype compiler to automatically generate member functions that provide type feedback to the garbage collector. Similarly, a datatype defined to be persistent will have a number of member functions generated automatically to perform the task of serialization and reconstitution.
Aspects of object oriented programming have also been integrated with the datatype specification language. For example, it is possible to attach members, member functions or destructors to variants of a datatype. A datatype or a variant of a datatype may also inherit from other classes. In general, non-virtual inheritance can be seen as a sort of cartesian product while datatype variants can be seen as its dual: the sum.
Furthermore, to provide direct control of the data structure mapping process and to provide reuse of existing classes, it is possible for the user to directly specify the datatype to class mapping using the view mechanism. Using this mechanism, existing classes can be manipulated in an algebraic form transparently in the pattern matching constructs.
Pattern matching, rewriting, and inferences are compiled into inlined or table driven code with the pattern matching compiler in the translator. Since Prop began as an experiment on efficient compilation of pattern matching constructs, pattern matching code generated by the translator are very efficient, comparable to, if not surpassing, handcrafted code.
ML-style pattern matching, which is performed top-down,
is compiled into a DFA-like decision tree, then transformed into inlined
switch
and if
statements. An algorithm derived from
the work on adaptive matching[]
is used in the pattern matching optimizer.
Rewriting in Prop is currently performed in a bottom-up manner. Rewriting
rules are gathered and compiled into a bottom-up tree automaton
using algorithms described in[Cha87,].
Finally, inference rules are compiled into a table-driven RETE-network.
Design principles
Although the design and development of Prop have progressed in an ad hoc manner, mostly driven by need, and sometimes by passing interesting, certain design principles have been maintained. These are as follows:
Compromises
For a number of reasons, some unavoidable compromises have been made in the design and implementation of Prop :
For example, although it would have been a good thing to provide first class functions in Prop , for this to be possible in a general way local variables must be transformed and packaged into closures, which would have altered the calling convention of functions. Since we have to provide binary compatibility with C++ , this transformation is undesirable. Thus until a satisfactory scheme is discovered Prop cannot have first class functions.