Programming Notes
This section provides a description of some of the nitty-gritty involved
in getting the high-level interface to work. It presumes extensive
familiarity with the High-Level interface, in addition to the Low-Level
Interface and the Prolog Foreign Language Interface (FLI).
Overview
The High-Level Interface provides, in essence, a set of Java data structures
for invoking queries on a Prolog engine. By itself, the High-Level
interface makes no direct calls to the Prolog Abstract Machine (AM).
Instead, the High-Level interface rests entirely on top of the Low-LevelInterface,
a Java implementation of the FLI. The Low-Level interface is more
or less in 1-1 correspondence with the FLI (barring methods that do not
make sense in the Java environment).
The following describes a typical execution of a Prolog query using
the interfaces described in the jpl.Query class. Assume the High-Level
Interface programmer (hereafter, just 'the programmer') has constructed
a jpl.Term structure (assume, for simplicity, that the programmer is invoking
a predicate of arity 1), and is about to use the Query class to make a
query using the hasMoreSolutions/nextSolution protocol. Roughly the
following sequence of events occurs.
-
The jpl.Term is converted to a jpl.fli.term_t
-
A call to the Prolog AM is opened using the Low-Level Interface Prolog.open_query
method with the predicate name and term_t just created
-
For any jpl.Variable occurrence (i.e., instance) in the original
jpl.Term
given to the Query, convert the term_ts that are bound to
those variables o jpl.Terms, and construct a
Hashtable of
these Terms, indexed by the Variables in the Query.
-
Close the query using the Low-Level Interface Prolog.close_query
method if there are no more solutions. Otherwise, keep the query
open for subsequent calls to hasMoreSolutions.
Significantly more bookeeping is required to prevent the programmer from
opening a query while another is open, maintaining state about the status
of the query, and so forth, but the above gives a rough approximation of
what occurs in typical "successful" calls to the Prolog AM. The remainder
of this section describes these steps in some detail.
Translating Terms to term_ts
Translating jpl.Terms to jpl.fli.term_ts is relatively straightforward.
Each Term subclass knows more or less how to convert itself to a
term_t via its pack method, and the top-level Term static
method terms_to_term_ts takes an array of Terms and performs
the conversion for the Query. The following features of the
FLI, however, help explain the perhaps mysterious signature of pack.
-
The Prolog FLI requires that term_t references first be created,
and then data of an appropriate type be "put" into the term_t reference
using one of the FLI _put functions. For example, to create
an atom in the FLI, one first creates a term_t, and then "puts"
an atom_t into the term_t.
term_t t = PL_new_term_ref();
atom_t
a = PL_new_atom( "a" );
PL_put_atom(
t, a );
Translating a Term to a term_t requires mimicking this behavior.
-
In the case of Compound Terms,
-
A term_t in the Prolog FLI is, literally, an unsigned long value.
It is essentially an index into the Prolog AM. A sequence of term_ts
is a set of consecutive long values, typically created via the FLI
C funtion PL_new_term_refs(). In order to construct a compound
term_t, in the FLI, one must create such a sequence of term_ts
(as many as the arity of the compound), and then use the various FLI _put
functions to put terms into the term_ts that have just been created.
Computing Substitutions
Translating term_ts to Terms
Terms
A jpl.Term structure holds, as an element, a jpl.fli.term_t
structure, which itself is a class which holds a long value. This
long value is in fact a pointer (though not a C pointer) to Prolog term
in the Prolog Abstract Machine (AM). Unfortunately, these low-level
values are not really valid throughout the life of the jpl.Term.
Indeed, they are only valid pointers into the Prolog AM during the execution
of a Prolog query. They must, therefore, be treated with exceptional
caution, and are consequently kept well-hidden from the user of the High-Level
Interface.