Each method-clause translates to a Prolog clause with two extra arguments: Self (a variable) and Myself. The latter argument is needed to cater for passing object parameters to the method body, which is desribed further in next section.
The method body is translated to a Prolog clause body
as follows. The code is traversed, and the goals are transformed
according to the following transformation patterns and rules. In the
transformation rules, the notation Msg
(
X,
Y)
denotes the term produced by augmenting Msg by the two
arguments X and Y:
Goal
objects:call_from_body(
Goal,
Self,
Myself,
Src)
where Src is the source
module. objects:call_from_body/4
will meta-interpret Goal
at runtime.
::
Msg
Myself:
Msg(
Myself,
Myself)
if Msg is
a non variable. Otherwise, it is translated to
objects:call_object(
Myself,
Msg,
Myself)
.
<:
Msg
Myself:
Msg(
Self,
Myself)
if Msg is a non variable. Otherwise, it is translated to
objects:call_object(
Myself,
Msg,
Self)
.
super ::
Msg is translated to
objects:call_super_exp(
Myself,
Msg(
Super,
Myself),
Super)
if Msg is a non variable. call_super_exp/3
searches
the supers of Myself. Super is bound to the super
object where the method is found. If Msg is a variable, the
goal is translated to
objects:call_super(
Myself,
Msg,
Super,
Super)
,
which expands Msg and performs otherwise the same actions as
call_super_exp/3
.
super <:
Msg
objects:call_super_exp(
Myself,
Msg(
Self,
Myself),
Super)
if Msg is a non variable. call_super_exp/3
searches
the supers of Myself. Super is bound to the super
object where the method is found. If Msg is a variable, the
goal is translated to
objects:call_super(
Myself,
Msg,
Self,
Super)
,
which expands Msg and performs otherwise the same actions as
call_super_exp/3
.
Obj ::
Msg
Obj:
Msg(
Obj,
Obj)
.
objects:call_object(
Obj,
Msg,
Obj)
.
Obj <:
Msg
Obj:
Msg(
Self,
Obj)
.
functor(
Obj,
O,
_),
O:
Msg(
Self,
Obj)
.
objects:call_object(
Obj,
Msg,
Self)
.
self <:
Msg
self ::
Msg
Msg
Self ::
Msg
.
Module:
Goal
Module:
Goal
.
:
Goal
Src:
Goal
where Src is the
source module.
To illustrate the expansion, consider the object history_point
directives, all executed in the history_point
module:
:-objects:create_object(history_point, [point-[]], [attributes/3,display/3,move/4,new/4,print_history/3,super/4], [], [y(0),x(0),history([])], tree(history_point,[tree(point,[tree(object,[])])])). history_point:super(point, [], _, history_point). history_point:attributes([history([])], _, _). history_point:display(A, B, _) :- objects:call_super_exp(history_point, display(A,B,C), C), history_point:print_history(A, B, history_point). history_point:'$so_type'(history_point, static). history_point:move(A, B, C, _) :- objects:call_super_exp(history_point, move(A,B,C,E), E), prolog:'$get_module_data'(C, history, D), prolog:'$set_module_data'(C, history, [(A,B)|D]). history_point:print_history(A, B, _) :- prolog:'$get_module_data'(B, history, C), A:format('with location history ~w~n', [C], A, A). history_point:new(A, xy(D,E), B, _) :- objects:call_super_exp(history_point, new(A,xy(D,E),B,C), C), prolog:'$set_module_data'(A, history, [(D,E)]).
The directive create_object/6
creates the object, performs
the inheritance by importation, and initializes attributes. The
last argument is a tree representing the ancestor hierarchy
during compilation. It is used to check that the load time
and compile time environments are consistent.