Object functions typically follow this pattern:
uint32 result = 0;
AN672
// meta:{{si32SomeObject}do_something}
si32Assert(is_si32SomeObject(self));
si32SomeObject *my = self;
result = my->someObjectContext.variable;
// meta:{{si32SomeObject}do_something}
return result;
The first line declares a variable for the function result and initializes it. The comment marks the end of the function
entry and the start of the body. si32Assert is an assertion that halts in the debugger if the expression is false.
is_si32SomeObject performs the runtime type check. Next, a variable of the appropriate type is declared and
bound to self. Note that this is 'safe' because the runtime type check succeeded. The symbol my is just chosen to
reinforce that referenced attributes belong to the object bound to self. Next, the contents of the object's variables
(i.e., its attributes) are accessed through the typed pointer. The second comment marks the end of the body and
starts the function exit.
Logging and assertions only have a code footprint in debug builds. They are intended for use during development
and debugging, not for final production code. Therefore, build options exist to cause these constructs to compile
away to nothing for release builds.
Calling the functions of an object (i.e., invoking its operations) is accomplished in a similar fashion. However, it is
not necessary to employ a type* my = self statement in order to invoke an operation on an object. The following is
sufficient:
uint32 result = si32SomeObject_do_something(&my_object, arg);
Macros are employed to access the object's function tables in order to determine the correct implementation of the
operation to invoke. This is how runtime function overloading is implemented by the si32ObjectComponent and,
therefore, all of the si32Library. For example:
uint32 _si32ListObject_get_capacity(obj* /*self*/);
#define si32ListObject_get_capacity(self)
as_si32ListObject(get_capacity, (self))
The first line provides the function prototype for the early binding. Calling this directly invokes that specific function,
bypassing the function table and thus preventing polymorphism. Early bindings are preceded by an underscore.
The second line provides the late binding, which calls through the function table, enabling polymorphism.
Rev. 0.1
9