If Prolog encounters a foreign predicate at run time it will call a
function specified in the predicate definition of the foreign predicate.
The arguments 1, ... , <arity> pass the
Prolog arguments to the goal as Prolog terms. Foreign functions should
be declared of type
foreign_t. Deterministic foreign functions have two
alternatives to return control back to Prolog:
return TRUE.
return FALSE.
By default foreign predicates are deterministic. Using the
PL_FA_NONDETERMINISTIC attribute (see PL_register_foreign())
it is possible to register a predicate as a non-deterministic predicate.
Writing non-deterministic foreign predicates is slightly more
complicated as the foreign function needs context information for
generating the next solution. Note that the same foreign function should
be prepared to be simultaneously active in more than one goal. Suppose
the natural_number_below_n/2 is a non-deterministic foreign predicate,
backtracking over all natural numbers lower than the first argument. Now
consider the following predicate:
quotient_below_n(Q, N) :-
natural_number_below_n(N, N1),
natural_number_below_n(N, N2),
Q =:= N1 / N2, !.
|
In this predicate the function natural_number_below_n/2 simultaneously generates solutions for both its invocations.
Non-deterministic foreign functions should be prepared to handle three different calls from Prolog:
PL_FIRST_CALL)PL_REDO)PL_CUTTED)Both the context information and the type of call is provided by an
argument of type control_t appended to the argument list
for deterministic foreign functions. The macro PL_foreign_control()
extracts the type of call from the control argument. The foreign
function can pass a context handle using the PL_retry*() macros
and extract the handle from the extra argument using the
PL_foreign_context*() macro.
PL_CUTTED case and should be aware that the other
arguments are not valid in this case.
PL_FIRST_CALL the context value is 0L. Otherwise it is the
value returned by the last PL_retry()
associated with this goal (both if the call type is PL_REDO
as PL_CUTTED).
Note: If a non-deterministic foreign function returns using
PL_succeed or PL_fail, Prolog assumes the foreign function has cleaned
its environment. No call with control argument PL_CUTTED
will follow.
The code of figure 6 shows a skeleton for a non-deterministic foreign predicate definition.
typedef struct /* define a context structure */
{ ...
} context;ninclude.html#PL_open_foreign_frame()">PL_open_foreign_frame()/PL_close_foreign_frame().
|