Class object is the root of the class hierarchy. It defines common behaviour, mainly to do with object management:
Creating objects object ->initialiseDestroying objects object ->free, object->doneCloning objects object <-cloneSaving objects on file object ->save_in_fileAdding attributes object ->attributeProgramming object ->send_method, object->get_method
Any class in PCE must be a sub-class of class object and therefore any object listens to the methods defined on this class.
It is allowed to create instances of class object and extend the instance using object-level programming to realise a single object meeting some specification. See:
object ->attributeDefine object-level attributes object ->send_methodAdd object-level sendmethodobject ->get_methodAdd object-level getmethod
Normally invoked through the Prolog predicate checkpce/0.
Diagnostics: See related error objects
<-_class
<-_class
<-_class->initialise
and hyper->unlink.
These methods should never be called directly by the user. It is
however possible to redefine these methods to intercept the creation and
destruction of hyper-links. A redefinition should
always call this method.
|name,
value=[any]An error is raised if the class already defines an instance variable with the same name.
<-object if the
current save version is not the same as save version when the file was
loaded. The two arguments are the old and the new save versions. See pce<-save_version.
|attribute->attribute.
Fails silently if the attribute is not present.
Diagnostics: Fails (silently) if the attribute is not defined.
<-find_hyper
for the interpretation of the name and condition arguments...... get(Area, size, Size), .... send(Size, done).
The receiving object will be deleted from the object base as with object->free
if the receiver has no object<-references, object<-lock_object
is @off and
object<-protect
is @off.
In the example above object->done
is equivalent to object->free
as the size object
returned by area<-size
is created by this method (provided the .... computation does not lock,
protect or make the size an attribute of some other object. In the
example below, using object->free
will corrupt PCE's database:
.... get(Graphical, area, Area), .... free(Area). % ==> ERROR!!!
The area object will
be deleted and the slot graphical<-area
will be pointing in the dark (checkpce/0
will find such problems).
Using object->done
is often not necessary. After a user-event has been processed all
unreferenced and unlocked objects will be deleted from the object base
automatically. Unreferenced objects created during the execution of a
user-defined method for a PCE class are also deleted automatically. object->done
is useful when a lot of garbage objects are created in a loop.
->same_reference.
Bugs: The notion of equality is not very clear in PCE.
<-id
and converted by error<-convert)
is the error to be raised. The remaining context arguments provide
context information about this error. Performs the following steps:
<-kind
equals ignored, silently fail.
<-last_error.
->catched),
it invokes
error->display
on the error object.
See also class error
and object->report.
Diagnostics: Diagnostics depend on the error object invoked.
For each slot-reference, code is executed with the following bindings:
@arg1 The instance @arg2 Type of slot reference @arg3 The slot @arg4 The value of the slot
The Type of slot reference is one of:
->free
performs the following steps:
->unlink.
This allows a class to unlink the object from the environment.
<-references.
Otherwise reclaim is delayed. See pce<-deferred_unalloced.
object->unlink
is often defined on objects that need to inform some other object that
they are destroyed. For example, graphical
objects inform their device to allow the device to remove the object
from the display and update their book-keeping.
The method object->unlinking
is provided as a test whether or not object->free
is in progress on the receiver.
See also visual->destroy
to destroy entire hierarchies of (visual) objects.
Diagnostics: Fails silently if object<->protect
equals @on.
Bugs: Window object->free
should just delete the window from it's object<-frame.
In new code, please delete frames using object->free.
|chain->get_class.
<-get_method, object<-send_method}
returns a value but avoids the creation of a tuple. See also
class<-send_method
and class<-get_method.<-name returns @off.<-name returns @on.<-name not-equal 2nd
argument.<-Name and
compare the result to the argument. Succeed if they are equal (have same
reference), fail otherwise.
This method is intended to test on attribute values. Similar and more
powerful results can be obtained using class ==.. It's usage is to be
preferred. The following code
objects and Prolog fragments all test whether the point<-x
of the point object @p
equals 3:
Prolog:
get(@p, x, 3) % Uses Prolog unification send(@p, has_value, x, 3)
Code fragments:
message(@p, has_value, x, 3) @p?x == 3
object->not_has_value
is equivalent to object->has_value,
but returns the inverse result. object->is_on
is equivalent to object->has_value: @on
and object->is_off
is equivalent to object->has_value: @off.
send_super(Self, initialise).
Any class should have a method object->initialise.
This method is invoked from PCE's virtual machine to initialise an
object from the parameters given to the object creation operation (new/2.
class create,
class<-instance.
The creation of objects is discussed in detail with class<-instance.
<-object).
Called when -while loading an instance from a file-, the current
definition of the class has a new instance variable (compared to when
the instance was saved to file using object->save_in_file).
The argument is the new variable
object from the class. May be used to initialise the new slot to some
sensible value.
<-convert
converts class-names to
class objects:
send(Obj, instance_of, graphical)
is the advised way to verify that Obj is a graphical.
The method pce<-convert
may be used to combine testing with possible type conversion. See also type->validate
and type<-check.
If one wants to test whether an object is a graphical
object, a node object
or @nil, the
following two test are equivalent:
( send(Obj, instance_of, graphical) ; send(Obj, instance_of, node) ; Obj == @nil )
or
send(type('graphical|node*'), validate, Obj)
<-lock_object
<-object_reference.
Diagnostics:
Bugs: Unlike with the predicate new/2, no exception is raised if the object already exists.
->free
or one of the other objects destruction methods. The global PCE
objects @pce,
@prolog, etc.
are protected this way.
There is no way to unprotect protected objects or to destroy them.
<-receiver and invokes visual->report
on this object.
If @event
is unbound the error is caused by a query from the
host-language
interaction window and PCE thus prints the message using pce->format.
Some classes redefine this method because they know they are
related to some visual
object. See also object<-report_to.
Obj1?class == Obj2?class.
and
message(Obj1, same_class, Obj2)
->equal
performs the same test, but is refined by various classes to test for same properties.
See -for example- point->equal.<-object. When the object is
reloaded in this PCE process, the combined functionality is similar to object<-clone.
When the data, manipulated by the application is stored in PCE, the
normal way is to attach all this information to a single object
(normally a hash_table, sheet or chain) and save this object to a file.
All attached objects (i.e. all data needed by
the application to save its persistent data) are then saved
in the file.
PCE's save and load functionality has a limited way to deal with
versions. The conversion activities are described with source_sink<-object.
Diagnostics:
.g. windows, cursors,
etc.).
Diagnostics related to opening, writing and closing a file are applicable as well.
Bugs:
<-get_class
for details..
<-hypered
objects. Similar to object<-get_hyper,
but does not stop if the method is received successfully. Succeeds if
there was at least one hypered object accepting the message, fails
otherwise.|chain->send_class.
<-get_sub.->send_super
and object->send_vector,
creating an argument vector from the leading arguments and vector and
invoking behaviour defined at the super-class. See object->send_super
and object->send_vector
for details.
->send_vector
supports the implementation of methods with variable argument list. Its
format is:
unchecked..., Vector, [shift]
First, a list is created containing the following arguments:
unchecked...
Next, the first element of this list is used as the selector and the remaining arguments as the arguments to the message. Examples:
vector(write_ln, 'Hello World')).
vector('Hello World')).
Defaults: Shift defaults to 0.
Diagnostics: Fails silently if the selector cannot be created,
|int,
uncheckedThe slot specification (first argument) is either the slot-name, or the offset in the object (1-based). The latter possibility is for very specific (internal) use.
This method should only be used from a send-method that has the same
name (selector) as the slot and serves as a wrapper around
the slot to deal with side-effects:
:- pce_begin_class(person, object).
variable(date_of_birth, date, get, "When person was born").
...
date_of_birth(Person, Date:date) :->
( send(Date, after, new(date))
-> send(Person, report, error,
'Cannot be born in the future!'),
fail
; send(Person, slot, date_of_birth, Date)
).
Bugs: This message should also apply to object-level defined
attributes (see
object->attribute.
->unlink
is called by object->free.
Its task is to unlink the instance from its environment. The object->unlink
method may not be called directly by the user. The user should provide
an unlink method when writing a user-defined class that requires
specialised unlink behaviour.
Some examples:
<-graphicals
and update the display.
NOTE: Unlink should never be called directly by the user. Any
user-defined object->unlink
method should invoke the method of the super-class (see object->send_super).
See also object->free, object->done, visual->destroy
and object->unlinking
->unlink’ed.
Intended as a test in object->unlink
methods to avoid unnecessary computation.
get(Obj, ?(Obj?class?term_names, element, N), Arg).
This behaviour is intended to remain reserved for system usage. Do not rely on its definition.
|int -> unchecked?- new(O, @display?size), get(O, '_class_name', C1), get(O, class_name, C2). C1 = ? C2 = size
Bugs: It is probably more elegant to introduce a separate send- and get- operation that does not evaluate the receiver.
create equals @on,
this call will always succeed, possibly returning an empty chain.
Otherwise the call might fail.
The following extensions are defined:
object ->attributeObject-level instance variable constraintBinary constraint between two objects hyperBinary relation (two-way attribute) object ->recogniserHandler for event objects (class graphical) object ->send_methodObject-level method (send) object ->get_methodObject-level method (get)
See also class constraint and class hyper.
->attribute.
The attribute may also me requested using a plain get operation:
?- new(@o, object), send(@o, attribute, gnus, 4). ?- get(@o, attribute, gnus, G). ?- get(@o, gnus, G).
The two are equivalent, except that the latter gives an error if no such attribute is defined.
->instance_of
or object<-class_name.
In most situations the first is to be preferred.
get(Object?class, name, ClassName).
<-Name
is equivalent.<-clone
creates a clone of an object. The semantics of cloning objects in
general are difficult to define. Which related objects are to be cloned
and which are to be shared between the clone and the original object?
The approach taken by PCE is not particularly neat. We do not recommend heavy use of this facility.
Object are cloned recursively. This implies all objects
that can be reached from this object are cloned as well. The algorithm
deals correctly with cyclic structures.
While executing a recursive clone, two flags may influence the result:
variable <-clone_styleDefines the type of relation class <-clone_styleDefines the type of object
Please consult the documentation of these for details.
Bugs: The semantics are ill defined. Be very carefull
with plain cloning and study this description carefully
before going ahead. When in doubt, use the inspector tool
from the main menu to find out about the result.
|char_array -> object<-convert
is called by type<-translate,
part of the generic type-checking and type conversion system. It is not
a normal method not the receiver, but the result is an
instance of the class on which the method is defined. The receiver is
normally the class.
The task of the object<-convert
method is to translate the argument into an instance of the requested
type.
For class object
itself no translation is necessary as anything in PCE already is an
instance of class object.
This method will therefore never be called directly by the PCE type
conversion system. This method translates a text (char_array
object) of the form @<name> into an object if <name>
is a valid object reference. This method is useful for defining other
conversion functions.
->initialise,
scan the goal stack searching for a receiver higher in the goal stack
for which condition succeeds. Condition is executed with the following
arguments:
@receiver receiving object @arg1 receiver of message of parent goal @arg2 implementation of message of parent goal
This method is intended to find the context in which an object (often
a graphical) is created, allowing it to query the context for additional
information. See also visual<-contained_in.
hyper_name is the
name of the hyper, seen from the receiver of this message. If hyper_name
is @default,
all hypers are considered. test is a code
object. If it is not @default,
it is executed using the following arguments:
@arg1 Receiver of this message @arg2 Hyper object @arg3 Object at other end of the hyper.
See also object<-hypered.
<-class_name.
->get_method.
This method serves a similar purpose as object->get_super
when using class-level programming.
broadcast get operation on objects object<-hypered
to this object. If a hyper_name is given only hypers with this name are
considered. Otherwise all hypers are considered. As soon as one of the
hypered objects returns a value, this method returns with this value.
Otherwise the method fails. Example:
?- new(@o, object),
new(_, hyper(@o, bitmap('pce.bm'), bitmap)),
new(_, hyper(@o, text(hello), text)).
?- pce_catch_error(no_behaviour,
get(@o, get_hyper,
@default, string, S).
S = hello
?- pce_catch_error(no_behaviour,
get(@o, get_hyper,
@default, pixel, 3, 5, P).
P = @off
The first query is answered by the text
object, while the latter is answered by the bitmap
object (delegated to the bitmap<-image).
Note the use of pce_catch_error/2 to avoid
an error while broadcasting to objects that do not understand the
method.
->attribute).
<-send_method
<-delegate
The tuple<-first contains the receiver,
which is either the object itself or the object the message will be
delegated to. The
tuple<-second contains the behaviour
object that implements the method.
Examples:
?- new(@p, point), get(@p, send_method, mirror, tuple(Object, Impl)). Object = @p/point Impl = @632241/send_method ?- new(@v, view), get(@v, send_method, append, tuple(Object, Impl)). Object = @833889/editor Impl = @749374/send_method
The second example indicates that, when a message object->append
is sent to
@v it will be delegated to the editor @833889.
See also object->has_get_method, object->has_send_method
and object<-all_send_methods.
->get_method
for further details.
Bugs: Actually, a normal get operation executed in a method
already performs a
object<-get_sub.
Reserved fro future extension.
.e. object<-get_super
is always to it self).
See also object<-slot.
.g.
get(@prolog, get_vector, vector(plus, 1, 1), X).
Is a very complicated way to add 1 and 1.
This behaviour is intended to deal with delegating messages trapped
via the object->get_catch_all behaviour.
@arg1 This object @arg2 The hyper object @arg3 The object at the other end of the hyper
The first matching object is returned. See also object<-all_hypers.
->inspect
A locked object is destroyed by object->free.
To protect an object against
object->free,
use object->protect.
When @off,
the lock is removed from the object. If the object has no references, it
will be object->free’d.
If this is not desirable, use object<-unlock.
|int->name_reference)
or integer reference for objects that have no named reference. See also
pce<-object_from_reference.
<-print_name
is intended to convert an object into a textual representation. It
serves two purposes:
->format
<-print_name_of_value.
This method is redefined by various subclasses. object<-print_name
itself performs the following steps:
<-name and
the return value can be converted into a char_array
object, return this converted value.
->protect
Note that PCE does not know which objects have references to an object; slot-relations are uni-directional.
->report.
The default for non-visual
objects is the receiver of the current event (@event).
See also
visual<-report_to.|int -> uncheckedThis method is used in the implementation of get_method
objects if the get method wants to access a slot with the same name
without interaction from the method. See also class->get_method.
->save_in_file
to handle shared object resources (colours, fonts, etc.). If this method
is executed successfully, object->save_in_file
stores the classname of the the object and the returned object.
source_sink<-object loads the
classname, converts the classname to a type
object, loads the returned reference object and attempts type<-check
to produce an object of the requested type.
See colour<-storage_reference
for an example.
<-self.
If, after unlocking, the object has no references, it will be pushed on
the‘anser stack’, making it visible to the incremental
garbage collector.
In combination with object->lock_object,
this method may be used to disconnect an object from its environment,
handing it back to the incremental garbage collector. An example can be
found in emacs_window<-prompt, a part of
PceEmacs.
Assume we have a chain
object holding a point and we want to delete the object from the chain
without deleting the point. Direct usage of chain->delete
may destroy the point. The following code avoids this:
send(Point, lock_object, @on), send(Chain, delete, Point), get(Point, unlock, _).