The runtime library applib provides several components for app generated programs, an 'alpha' core component, an alpha type utility component 'beta', and a few additional utility components.
Most library component symbols are namespace qualified according to the #define symbol APP_LIB_NS, which by default is defined as 'applib', and which also has by default the synonym 'alpha' - see also the applib_config.h file. This namespace must be introduced prior to using any such types from the context of app generated match statement code, by either a using directive or appropriate using declarations, as app itself knows nothing of namespaces.
Applib provides a core component called alpha, the functionality and interface of which is required by app generated programs. It defines the two alpha base classes Top & Top__, and a few auxiliary types and functions.
In addition to Top & Top__, the core component provides the type Copy, a replacement for type bool used for reference counting control purposes, and a customizable class Alpha_Control that serves primarily as a wrapper class for output and error handling. Alpha types support stream output via the << operator; the Alpha_Control class can be used to customize its behavior.
A number of functions are forwarding interfaces for members of Alpha_Control; error handling: escape, escape_output; output formatting: form_type_name, form_using_zero, form_using_rtti, form_class_part, form_param_part, form_under_part, form_final_part, show_begin, show_delim, show_end, show, showln; utilities: write_string. Additional utility functions: dup_string, new_string, raw_type_is.
It should be noted that this core component is provided as a kind of default implementation rather than as an absolute requirement. In other words you may define your own core if so desired, and in fact you are not required to use the provided runtime library at all, though if the provided core is not used, you must define a core with similar functionality and consistent interface, to the extent required to satisfy the relevant assumptions of app generated code. See the alpha.h and alpha.cpp library files for additional information.
Applib provides a component called beta that defines a number of simple and common alpha types as a standard library of sorts, and some additional related functions and classes. All of the alpha types therein have all comparison operations defined for them, and are (or should be) directly usable as STL contained types.
The alpha type declarations include the following.
The native types are base types declared via the (implied) "$user {} $user {}" construct and have no corresponding generated classes. The boxed versions are base types that do have generated handle/body classes (body object == "box"). In most cases the unboxed native versions can be used rather than the boxed versions. The boxed versions may be useful in circumstances when alpha typed objects must be uniformly represented (with the usual handle/body classes).
There is a fairly rich set of list related utility functions provided, most of which were explicitly designed to be consistent with corresponding functions of the Pizza language.
The essential List access functions are head() and tail(). List objects are constructed from Cons injectors and also null objects; the Cons itor is of form Cons(A a, List<A> b), where a is the head and b is the tail. A non-null list is a sequence of Cons objects such that the last Cons object has a null tail. The provided List<A> member functions include the following.
A head() const; // first Cons product of this list
A head(A new_head); // setter
List<A> tail() const; // second Cons product of this list
List<A> tail(List<A> new_tail); // setter
int length() const; // number of elements of this list
List<A> take(int n) const; // first n elements of this list
List<A> drop(int n) const; // all but the first n elements of this list
A at(int i) const; // i'th element of this list, i>=0
A last() const; // last element of this list
List<A> reverse() const; // elements of this list in reverse order
List<A> append(List<A> ys) const; // this list with ys appended
List<A> extend(List<A> ys); // this list with ys appended destructively
List<A> filter(bool f(A)) const; // elements x of this list s.t. f(x) is true
int index(A y) const; // least i s.t. (*this)[i] == y, -1 if no such i
List<A> diff(List<A> ys) const; // this list without the elements of ys
List<A> diff(A y) const; // this list without the element y
List< Pair<A, A> > zip(List<A> ys) const; // this list and ys pairwise
List<A> sort_insert(A e) const; // this list with e inserted ordered by <
bool contains(A y) const; // index(y) >= 0
List<A> concat(A y) const; // append(Cons<A>(y, 0))
List<A> extend(A y); // extend(Cons<A>(y, 0))
A operator [] (int i) const {return at(i);}
List<A> init() const {return take(length() - 1);}
List<A> concat(List<A> ys) const {return append(ys);}
Pair< List<A>, List<A> > split(int n) const {
return Pair< List<A>, List<A> >(take(n), drop(n));
}
There are also a number of list related template functions.
template <class A> // the concatenation of all elements of xss List<A> concatenate(List< List<A> > xss) template <class A, class B> // apply f to each element of xs void forall(B f(A), List<A> xs) template <class A, class B> // list of f applied to each element of xs List<B> map(B f(A), List<A> xs) template <class A, class B> // catenation of f applied to each element of xs List<B> bind(List<B> f(A), List<A> xs) template <class A, class B> // f applied to each element of xs from left B foldl(B f(B, A), B z, List<A> xs) template <class A, class B> // f applied to each element of xs from right B foldr(B f(A, B), B z, List<A> xs) template <class A> // the list of n x's List<A> repeat(A x, int n)
The Single alpha type is a convenient way for example to represent in asts some kinds of optional syntactic constructs.
$data Single<class A> = 0 | Single_Element(A a) : {
bool empty() const {return null();} // true if zero constructed
bool not_empty() const {return not_null();} // false if zero constructed
A element() const; // a if Single_Element(A a) constructed
};
An ordinary C++ template class Associative_List is included that provides simple linear multimap-like services.
template <class A, class B>
class Associative_List {
public:
typedef List< Pair<A, B> > State;
Associative_List() {}
Associative_List(State list) : list(list) {}
virtual ~Associative_List() {}
virtual State state() const {return list;}
virtual State state(State new_list) {return list = new_list;}
virtual void init() {list = 0;}
virtual B get(A x) const; // the first value with key == x
virtual List<B> getall(A x) const; // the list of all such values
virtual List<B> getall(A x, List< Pair<A, B> > z) const; // prepended to z
virtual bool has(A x) const; // true if there is at least one key x
virtual void addnew(Pair<A, B> p) {init(); add(p);}
virtual void addnew(A x, B y) {addnew(Pair<A, B>(x, y));}
virtual void add(Pair<A, B> p) {list = Cons< Pair<A, B> >(p, list);}
virtual void add(A x, B y) {add(Pair<A, B>(x, y));}
protected:
State list;
};
The class also appears as an alpha type:
$base Associative_List<class A, class B>;
Another ordinary C++ template class Extending_List is included and provides for efficient repeated destructive appending list operations, with additional related functions that yield stack/queue/deque capabilities.
template <class A>
class Extending_List {
public:
Extending_List() : triple(State(0, 0, 0)) {}
Extending_List(List<A> xs) : triple(State(0, 0, 0)) {extend(xs);}
Extending_List(A x) : triple(State(0, 0, 0)) {extend(x);}
virtual ~Extending_List() {}
virtual void extend(List<A> xs); // add last elements, subsequently mutated
virtual void extend(A x) {extend(Cons<A>(x, 0));} // add last element
virtual void prepend(A x); // add first element
virtual void retract(); // remove last element
virtual void consume(); // remove first element
virtual A last(); // last element
virtual A first(); // first element
virtual length() {return triple.third();} // list length
virtual List<A> list() const {return triple.first();} // the list
protected:
typedef Triple<List<A>, List<A>, int> State;
State triple;
};
The class also appears as an alpha type ala Associative_List.
Applib also provides miscellaneous additional components, consisting of a small number of utilities and the like that may be found useful. The library can be configured in various ways, excluding certain parts, so as to make various lean versions if so desired.
To be useful as a normal null-terminated string, taking str() of an ostrstream object with a dynamic buffer first requires 'ends' then unfreezing the internal buffer frozen by str() in order for ~ostrstream to release it. The provided Str class automates this behavior.
class Str : public ostrstream {
public:
Str(bool unfreezes = true) : unfreeze(unfreezes) {}
virtual ~Str() {}
virtual const char* string(bool end = true) {
if (end) *this << ends;
const char* s = str();
if (unfreeze) rdbuf()->freeze(0);
return s;
}
protected:
bool unfreeze;
};
The Str class, in combination with alpha type Atom, serves very well for many purposes that might otherwise be done using the standard C++ string class. A typical situation might involve an auto Str object that is built up by << operations and then finally used to define an Atom via Str::string(). The app source itself makes extensive use of the combination.
Note that the default behavior for both Str and Atom is to use independent dynamic buffers - this is safe but less efficient than letting Atom reuse the Str buffer via ownership transfer, possible by constructing Str with a false 'unfreezes' argument, and Atom with a false 'clone' argument. Such sharing of course is best done only when it is clear that it is indeed safe to do so. A good practice is to construct both in close textual proximity, e.g.
Str s(false); // let Atom own the buffer do_something_with(s); Atom a = Atom(s.string(), false); // last use of s, a now owns the buffer
A class Pretty_Printer provides basic pretty printing capabilities for alpha types. The class customizes the alpha.h core class Alpha_Control. Note that it does not customize Alpha_Control by default. See the pretty.h file.
A class Flow provides simple debugging and tracing capabilities using a context stack pushed by the ctor and popped by the dtor, and which is customizable. See the flow.h and flow.cpp files.
Files shared.h & _shared.h contain classes that provide general non-intrusive reference counting capabilities. The shared.h file is an app source; the _shared.h file is the app generated version. Usage is akin to std::auto_ptr except that there is no ownership transfer mechanism - reference counted pointer ownership is a shared rather than unique relation.
For further details see the sources in the applib directory.
This is a summary list of applib symbols directly exposed via #includes. Unless otherwise indicated, all are in the applib namespace.
Symbols in alpha.h excluding overloaded operators.
Symbols in beta.h & _beta.h excluding overloaded operators & body classes e.g. Int__ etc. (Top & Top__ appear in alpha.h, not _beta.h; Top also appears in beta.h as an alpha type declaration; the bool, char etc. symbols are alpha type declarations).
Symbols in flow.h, pretty.h, shared.h, str.h, yystype.h. (YY is not in the applib namespace).
All visible #define symbols are prefixed 'APP_', except 'alpha' and 'YYSTYPE'.