go(File) :- showfacts :- load_file(File), fact(F), iterate, numbervars(F,0,_), showfacts. print(F), nl, fail ; true.
(c) using the interpreter
|
The interpreter in Figure 3 is divided conceptually into three
components. On the left (a) is the ``control'' component which
triggers iteration of an operator
until no new facts are
derived. When a new fact gets inserted into the Prolog database, a
flag
is raised. Iteration stops when
retract(flag)
fails in the second clause for
iterate
, that is, when no new facts were asserted in the
previous iteration. On the right (b), the predicate
operator
provides the ``logic'' and the inner loop of the
algorithm which for each my_clause(Head,Body)
in P proves
the Body using facts derived so far and calls the predicate
record
which adds the Head to the set of facts derived so
far, provided it is a new fact.
In this version of the interpreter, a fact F is considered new if it
is not subsumed by a fact which is already recorded (and hence
implements the c-semantics). The subsumes check for F is
implemented by application of the built-in predicate
numbervars(F,0,_)
which instantiates the variables in F (with
fresh constant symbols) and then calling fact(
F). This should
fail if F is to be considered new (and hence does not affect the
variables in the recorded fact).
The distinction between record
and cond_assert
is
unnecessary at this point, but it will prove useful when we consider
variations of the interpreter. The second clause in the definition of
prove
is for the case when unification is made explicit and
should be considered as a built-in predicate by the interpreter.
Bottom-up evaluation is initiated by the query ?- iterate
which leaves the result of the evaluation in the Prolog database. In
(c) the predicate go
facilitates the use of the
interpreter. This predicate loads the program to be interpreted,
initiates iteration and finally prints the derived facts on the
screen. Of course this interpreter will only work in case the
semantics of the program is finite.