BOS - The Basic Object System Version 1.2, January 1992 Sean Levy 1 Overview BOS is a C-callable library that implements a prototype-based notion of objects. It uses TCL to represent interpreted methods; C methods can be defined as well, which are, in effect, compiled methods. C methods and TCL methods can be freely intermixed within the same object. BOS is prototype-based. That is, there is no formal notion of "class", as in OOPLs like Smalltalk. Some of the ideas behind BOS have been loosely borrowed from another prototype-based OOPL called Self, which is described elsewhere. For those not familiar with Self, a class-based style of programming is quite possible (and, in fact, usually the case) in BOS, even though the formal notion of class is not imposed on the programmer by the system. BOS objects are, quite simply, named collections of slots. There are three basic varieties of slots, with some modifications . NORMAL slots, which contain values . OBJECT slots, which contain pointers to other objects . METHOD slots, which contain methods The BOS library contains calls to create and destroy objets, add, remove and modify slots in objects, and send messages to objects. It also contains a TCL interface that defines TCL primitives to manipulate objects, upon which more elaborate constructs can be created. One possible such set of constructs is the set of base objects that come with BOS, but that are written in TCL (or TCL/BOS if you like). These objects include "wrapper" objects for all Tk widgets, some graphical objects built on top of these wrappers (like an InternalEditor object and some dialog-type objects), plus a couple utility objects like Set, List, and HashTable. Those first two objects, List and HashTable, are implemented in C, but that fact is totally transparent to the user. In fact, such objects can be extended and modified in TCL with no difficulty; List is, in fact, modified in TCL to provide an additional method. The general rule has been, push into C only what needs to be there. 2 Slots and Messages As noted above, there are three basic varieties of slots. In addition to the three types listed above, there are two others that are considered modifications of the three basic types . CMETHOD slots, which are METHOD slots that point at C code . FOREIGN slots, which are NORMAL slots that point at C data Both of these types of slots require some support on the C side to work. There are calls in the API to define C functions as being possible candidates for becoming CMETHOD slots; such functions must take certain arguments, and are expected to return an int status code with certain values. In fact CMETHOD functions look an awful lot like C TCL command procedures. There are also functions in the API to define a datatype that can be put into a FOREIGN slot. Each such datatype is associated with a name (a string), and a set of functions that create, destroy, make a printable representation and parse a printable representation of an instance of this datatype. HashTables and Lists are implemented in just this way. This was done because TCL itself only provides one representation: the string. If one wants to implement things that strings might make difficult or very slot, then one has to resort to tricks such as FOREIGN slots. In TCL, BOS objects look just like commands. The syntax of all object commands is the same: [...] Syntactically, this looks a lot like Tk widgets in TCL, but there are differences. When a message is sent to an object, either via TCL or via the C Bos_Send primitive, the following process occurs: 1. If the object has a slot with the same name as the message, then that slot is used to answer the message, depending on the type of the slot: . NORMAL slots: the value is returned as the result . OBJECT slots: same as NORMAL slots . METHOD slots: the body of the method is evaluated with the arguments to the message passed as arguments to the method code. The special TCL variable self is bound to the object that the message was originally sent to before evaluating the body. 2. If the object does not have a matching slot, but it has OBJECT slots, then the objects that this object points at are tried recursively. One difference between OBJECT slots and other types of slots is that they have a priority associated with them. This allows weighting of alternatives in the case where there is more than one OBJECT slot to follow, e.g. multiple inheritance. The OBJECT slots are sorted in order of priority and tried. If this process is exhausted and no matching slots are found, an error is returned. 3 C API There is only one include file for bos, called bos.h. It, in turn, includes everything it needs from TCL and the system. It also defines certain BOS structures and constants, all of which begin with the string "Bos_". 3.1 Basic Functions Bos_Object *Bos_Find(world, obj_name) Bos_Object *Bos_CreateNewObject(world, obj_name) Bos_Object *Bos_Copy(world, obj_name, new_name) Bos_Object *Bos_Destroy(world, obj_name) 3.2 Slot Functions int Bos_AddSlot(obj, slot_name, slot_type, slot_pri, slot_value) int Bos_RemoveSlot(obj, slot_name, slot_pri) int Bos_SetSlot(obj, op_mask, slot_name, slot_type, slot_pri, slot_value) 3.3 Messages int Bos_Send(world, interp, obj_name, message) int Bos_Sendv(world, interp, obj_name, argc, argv) 3.4 C Methods and Data int Bos_HookCMethod(name, hook) _VoidPtr Bos_GetCMethodPointer(name) char *Bos_GetCMethodName(ptr) void Bos_UnhookCMethod(name) Bos_Slot_Subtype Bos_DefineCSlotType(name, print, print_arg, free, free_arg, parse, parse_arg, copy, copy_arg) Bos_Slot_Subtype Bos_GetCSlotType(name) char *Bos_GetCSlotTypeName(subtype) void Bos_UndefineCSlotType(subtype) _VoidPtr Bos_ParseCSlotString(string, subtype) char *Bos_GetCSlotString(value, subtype) void Bos_FreeCSlotValue(value, subtype) _VoidPtr Bos_CopyCSlotValue(value, subtype) 3.4 Initialization Bos_World *Bos_InitInterp(interp, local_only_p) void Bos_InitializeBuiltins() void Bos_CreateBuiltinObjects(world,interp) 4 TCL API 4.1 Built-In Objects 4.2 System Messages 4.3 Base Objects 4.3.1 Utility 4.3.2 Graphical Objects 5 Future Directions