BOOL Model objects are like classes in most object-oriented languages. The define the Native and Standard data objects and allow the user to define new data types.
A BOOL Model has a name, a data definition and a set of Model Actions that implement the behaviors for the new data type. BOOL Models are typically composite objects that use existing Models to create a new abstraction. BOOL Models can inherit designs from existing Models.
Model Actions can be added to a Model after the Model is defined. Users can add new, or override existing, behaviors, although Models are allowed to block such attempts. Models can also block attempts to inherit from them.
The model-data-definition part is a list of Instance objects that comprise the new type.
The model-actions part is a list of Actions that implement the behaviors of the new type.
The example below shows a very simple Model just to illustrate the basic syntax. The *point Model is defined as comprised of two
*float Instances, named ‘
x‘ and ‘
y‘. There is only one Model Action defined, and it defines the
move: Message for
**point #public . *float x = 0.0 . *float y = 0.0 . @@move:: . >> *point p . << ! . . set:[x]! [x]p . . set:[y]! [y]p
The exclamation point symbol refers to the “self” or “this” object. The
@move Action is bound to the
move: message because of the double-colon after the name. Without it, the Action is private to the Model.
An Action can be bound to a Model after the Model is defined using the binding brackets (<object>):
@@delta:: >> *point p << ! . set:[x]! add:[x]! [x]p . set:[y]! add:[y]! [y]p
Model Actions can only be invoked outside the Model if they are bound to messages. Model Actions themselves can invoke other Model Actions. (Restricted to only those not bound to messages?)
Models don’t respond to messages (other than
W:), so they don’t really have much in their HandleMessage() method. But Instance objects call their dispatch() method when handling messages. The Models do the heavy lifting (nearly all the lifting, actually) for the Instances.
Model::dispatch (obj, message): action = FindAction(message) if not action: Exception('Unknown Message!', message) cplist = [action.name, obj] if has_parameters(message): cplist.append(PStack.pop()) action.invoke(cplist)
The invoked Model Action presumably pushes some result to the stack. That result is really the result of applying the message to the Instance, so it is left to whoever sent that message to the Instance to consume the object on the stack.
(MOD, name, data-list, action-list, object-table, name-table)
The data-list is a list of Instance objects defining the data type. For Native Models, the list is empty. The action-list is a chain list of Action objects implementing the data type behaviors.
The object-table is a dictionary of name-offset pairs that index the list of Instance objects defined in the data-list. The name-table is a name-address dictionary of the Model Actions.