LibAST Object Subsystem Design ------------------------------ - All functions, data types, and other symbols will begin with "spif_" in the appropriate case. "Spif," of course, is short for "Spiffy," which in turn is represented by the 'S' in "LibAST." - All macros will be named using uppercase ASCII characters. - Macros will be used for all typecasting operations. Typecasting macros will be named SPIF_type(), where "type" is the capitalized base type name (e.g., SPIF_OBJ()). They will take exactly one parameter, a variable of that type or that can be cast to that type. The result will be that same parameter with the proper typecast applied and can subsequently be used as if it were a native pointer of that type. - Object types will be named by enclosing the base type name between "spif_" and "_t" (e.g., spif_obj_t). "spif_obj_t" is actually a pointer to an object. There is a corresponding type for each object class (e.g., spif_const_obj_t) which is the actual structure type. In other words, spif_const_XXX_t is the typedef for a struct which contains all the member variables. spif_XXX_t is a pointer to a spif_const_XXX_t. - Object member functions will always begin with "spif_" and the base type name followed by what the function does (e.g. spif_obj_new). All functions except for the *_new() functions will take an object of that type as their first parameter. Additional parameters may be required for different types of functions. Each member function which operates on an existing object instance will refer to that instance (its first parameter) as "self." - There are two basic object types. The first one is "spif_nullobj_t." In the strictest sense, it isn't an object at all. It is merely a placeholder for objects which are space-sensitive. It may not even be used. - The primary object type is, of course, "spif_obj_t." This is a very basic type which has only those properties common to all types. - All objects should have basic methods to accomplish the following: - new Allocate memory for an object (also calls init) - init Initialize the object members - del Deallocate memory for the object (also calls done) - done Free and re-initialize object members - show Convert object to a string representation - comp Compare two objects of the same type - dup Create an independent copy of the object - type Return the string representation of the object type - All objects will have a corresponding "class" object which will contain the string representation of the class name (as specified by the SPIF_DECL_CNVALUE() macro) followed by a series of pointers to the functions above. This externally-visible class object allows for basic operations to be carried out on objects of arbitrary/unknown type. - Object subclasses will be derived from their parent classes by declaring the first member of their structure as "parent" with the same type as the parent class const type. For example, to declare a child class of the "obj" type, you would have "spif_const_obj_t parent;" as the first data member. - To operate on properties of the parent class, simply use the appropriate typecast macro (see above) to cast the pointer to the parent type (e.g., SPIF_OBJ(str)). - Some object types will not actually be defined per se, but rather will define abstract methods of manipulating data whose implementation is unimportant. As with Java, these are referred to as "interface" classes. Interface classes have a single header file for the interface along with a .c/.h set for each implementation. - The following should be defined for all objects (the "obj" type is being used as a reference): - SPIF_OBJ(obj) Typecast macro - SPIF_OBJ_IS_OBJ(obj) Check for type (the second OBJ) - SPIF_OBJ_ISNULL(obj) Check for NULL value of instance