1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
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
|