In XSB, tables are designed so that they can be used transparently by
computations. However, it is often useful to be able to explicitly
inspect a table, or to alter its state. In the following predicates,
which are provided for this purpose, Skeleton refers to
information about the function and arity of a predicate. If p/2
is a predicate, its skeleton can be represented as
where arg1 and arg2 can be
any instantiation pattern. Thus the information derived from the
skeletons p(1,2) and p(A,B) would be the same.
- get_calls(+Skeleton,-Subgoal_Structure_Pointer,-Return_Skeleton)
- Tabling
Backtracks through the subgoal trie, unifying Skeleton with
entries in the call trie. As it does so, get_calls/3
binds Subgoal_Structure_Pointer with the pointer to the
subgoal structure and binds Return_Skeleton to a term of the
form ret/n where each of its arguments corresponds to a free variable
in the call. Example:
For the following program and table
:- table p/2.
p(1,2).
p(1,3).
p(1,X).
p(2,3).
|
|
Call |
Returns |
p(1,X) |
p(1,2) |
|
p(1,3) |
|
p(1,X) |
p(X,3) |
p(1,3) |
|
p(2,3) |
|
calls to get_calls/3 will act as follows
| ?- get_calls(p(X,Y),Cs,Ret).
X = _864816
Y = 3
Cs = 2927152
Ret = ret(_864816);
X = 1
Y = _864644
Cs = 2927104
Ret = ret(_864644);
no
| ?- get_calls(p(1,Y),Cs,Ret).
Y = 3
Cs = 2927152
Ret = ret(1);
Y = _864620
Cs = 2927104
Ret = ret(_864620);
no
| ?- get_calls(p(Y,3),Cs,Ret).
Y = _864792
Cs = 2927152
Ret = ret(_864792);
Y = 1
Cs = 2927104
Ret = ret(3);
no
| ?- get_calls(p(1,3),Cs,Ret).
Cs = 2927152
Ret = ret(1);
Cs = 2927104
Ret = ret(3);
no
- get_call(+Skeleton,-Subgoal_Structure_Pointer,-Return_Skeleton)
- Tabling
This predicate binds Subgoal_Structure_Pointer and
Return_Skeleton only if Skeleton is a variant (i.e., identical
up to variable renaming) of some entry in the subgoal table. It may
be compared to the previous predicate get_call/3 which
unifies Skeleton with entries in the subgoal trie. Repeating
the example from get_calls/3, calls to get_call/3 will
act as follows
| ?- get_call(p(X,Y),Cs,Ret).
no
| ?- get_call(p(1,Y),Cs,Ret).
Y = _864620
Cs = 2927104
Ret = ret(_864620);
no
| ?- get_call(p(Y,3),Cs,Ret).
Y = _864792
Cs = 2927152
Ret = ret(_864792);
no
| ?- get_call(p(1,3),Cs,Ret).
no
- get_calls_for_table(+Skeleton,-Call)
- Tabling
Succeeds whenever Skeleton unfies with an entry in the subgoal
table. When this predicate suceeds, it returns a variant of the call
entry with which Skeleton unifies.
This predicate does not provide any information about whether a table is
complete. Use table_state to inquire about a table's state.
Calls to get_calls_for_table/2 for the example in
get_calls/3 would act as follows
|?- get_calls_for_table(p(X,Y), Call).
X = _646608
Y = _646436
Call = p(1,_646724) ;
X = _646608
Y = _646436
Call = p(_646720,3) ;
no
| ?- get_calls_for_table(p(1,2), Call).
Call = p(1,_646676)
Call = p(_646672,3) ;
no
The second example backtracks through all entries in the table, since
only skeletal information is used from the first argument.
Exception:
- instantiation_error
- First argument is not instantiated.
- table_error
- First argument is not a tabled predicate.
- get_returns(+Subgoal_Structure_Pointer,-Return_Skeleton)
- Tabling
Backtracks through the answer trie for the subgoal whose subgoal structure
is pointed to by Subgoal_Structure_Pointer, and instantiates the
Return_Skeleton with the bindings corresponding to the return.
One way of accessing subgoals and answers of the example in in
get_calls/3 is as follows
| ?- get_calls(p(Y,3),Cs,Ret), get_returns(Cs,Ret).
Y = 2
Cs = 2561656
Ret = ret(2);
Y = 1
Cs = 2561656
Ret = ret(1);
Y = 1
Cs = 2559032
Ret = ret(3);
Y = 1
Cs = 2559032
Ret = ret(3);
no
- get_returns(+Subgoal_Structure_Pointer,-Return_Skeleton,-LeafNode)
- Tabling
Same as above, except for the fact that the third argument is bound
to the leaf node corresponding to the return in the return trie.
- get_returns_for_call(+Call,-Return)
- Tabling
Succeeds whenever there is a table entry for a variant of Call.
If this is the case, Return is instantiated with an entry for
the table corresponding to call, and successive entries are returned
by backtracking. If there are no answers in the table, or no table
entry for Call, the goal fails.
This predicate creates fresh variables for the return, rather than
unifying them with variables in the first argument. An explicit
unification of a call with its return can be done if so desired.
Example:
Let us continue from the example in get_calls_for_table/3.
| ?- get_returns_for_call(p(1,X), Return).
X = _646412
Return = p(1,_646628);
X = _646412
Return = p(1,2);
X = _646412
Return = p(1,3);
no
| ?- get_returns_for_call(p(X,Y), Return).
no
| ?- get_returns_for_call(p(1,2), Return).
no
Exception:
- instantiation_error
- First argument is not instantiated.
- table_error
- First argument is not a tabled predicate.
- get_residual(?Skeleton,?Delay_list)
- Tabling
get_residual/2 is used to backtrack through answers that unify
with a skeleton. These answers may in fact come from any call that
unifies with Skeleton. Since the Delay_list of an answer
consists of those literals whose truth value is unknown in the
well-founded model of the program (see Section 5)
get_residual/2 can be useful when extensions of the
well-founded model are desired. Consider the program
For the following program and table
:- table p/2.
p(1,2).
p(1,3):- tnot(p(2,3)).
p(2,3):- tnot(p(1,3)).
|
|
Call |
Returns |
p(1,X) |
p(1,2) |
|
p(1,3):- tnot(p(2,3)) |
|
p(2,3):- tnot(p(1,3)) |
p(1,3) |
p(1,3):- tnot(p(2,3)) |
p(2,3) |
p(2,3):- tnot(p(1,3)) |
|
calls to get_residual/3 will act as follows
| ?- get_residual(p(X,Y),List).
X = 1
Y = 2;
Z = [];
X = 1
Y = 3;
Z = [tnot(p(2,3))];
X = 2
Y = 3;
Z = [tnot(p(1,3))];
X = 1
Y = 3;
Z = [tnot(p(2,3))];
X = 2
Y = 3;
Z = [tnot(p(1,3))];
no
- delete_return(+Subgoal_Structure_Pointer,+LeafNode)
- Tabling
Deletes a return from the return trie. The LeafNode parameter should
be obtained from a call to get_returns/3.
- abolish_all_tables
- Tabling
abolish_all_tables/0 abolishes all tables presently in the
system. Predicates which have been declared tabled remain tabled, but
information about calls and returns is deleted. In Version 2.2,
abolish_all_tablesl/0 reclaims used space. The predicate always
succeeds.
Note that incomplete tables are abolished automatically by the system on
exceptions and when the interpreter level is resumed. In these cases,
the user does not need to abolish tables to maintain correctness.
- abolish_table_pred(+PredSpecification or
+Skeleton)
- Tabling
Predicate abolish_table_pred/1 abolishes tables for all calls
to the predicate denoted by PredSpecification (as in
path/2) or by Skeleton (as in path(X,Y)). The predicate
remains tabled, but information about its calls and their returns is
removed from the system. In Version 2.2, abolish_table_pred/1
reclaims the space used by the calls to this predicate (and their
answers). Note that incomplete tables are abolished automatically by
the system on exceptions and when the interpreter level is resumed.
In these cases, the user does not need to abolish tables to maintain
correctness.
Exception:
- instantiation_error
- Argument is a variable.
- type_error
- Argument is not a predicate specification of a callable term.
- table_error
- Argument is not a (specification of a) tabled predicate.
- abolish_table_call(?Call)
- Tabling
Predicate abolish_table_call/1 abolishes tables for a
particular call to a predicate denoted by Call. The predicate
remains tabled, and information about all other tables remains intact.
In Version 2.2, abolish_table_call/1 does not reclaim used space.
Note that incomplete tables are abolished automatically by the system
on exceptions and when the interpreter level is resumed. In these
cases, the user does not need to abolish tables to maintain
correctness.
Example:
Continuing the example started in the description of predicate
get_calls_for_table/3 the call
abolish_table_call(p(1,X)) would produce the table
Call |
Returns |
p(X,3) |
p(1,3) |
|
p(2,3) |
Exception:
- table_error
- Argument 1 is not a callable predicate.
- table_state(?Call,-State)
- Tabling
If the first argument is a valid Term indicator, table_state/1
unifies state with one of the set
{ not_yet_called, complete, incomplete, undef}.
The meaning of these atoms is defined as:
- not_yet_called
- iff the predicate corresponding to
Call has been declared tabled, but there is no table entry for call.
- complete
- iff the table entry for Call contains
all solutions.
- incomplete
- iff the table entry for Call may not contain
all solutions.
- undef
- iff the predicate corresponding to Call
has not been declared tabled.
Exceptions:
- type_error
- Argument 1 is not a callable predicate.