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.