Querying Prolog from Foreign Predicates

#1

I would like to ask about querying SWI-Prolog from foreign predicates and non-deterministic foreign predicates. I was looking at unifying parameter variables with values returned from a nested query iterated across invocations of a non-deterministic foreign predicate. I was looking at calling PL_next_solution for a nested query opened in a foreign non-deterministic predicate each time that the non-deterministic foreign predicate was invoked. I’m wondering whether such nested queries are currently possible with SWI-Prolog?

I reviewed the documentation. I wonder why it is the case that “a foreign context can have at most one active query. This implies that it is allowed to make strictly nested calls between C and Prolog (Prolog calls C, calls Prolog, calls C, etc.), but it is not allowed to open multiple queries and start generating solutions for each of them by calling PL_next_solution(). Be sure to call PL_cut_query() or PL_close_query() on any query you opened before opening the next or returning control back to Prolog.” (http://www.swi-prolog.org/pldoc/man?section=foreign-create-query)

Are there any examples of querying SWI-Prolog from deterministic and non-deterministic foreign predicates?

#2

The reason for this limitation is bound to be the nature of the SWI engine. It has a single call stack and a single trail stack, and having two open queries would require two stacks. I bet you could get there by having two threads or two engines running, bu I have not tried this.

#3

I found this: “The SWI-Prolog engine uses three stacks. The local stack (also called environment stack) stores the environment frames used to call predicates as well as choice points. The global stack (also called heap) contains terms, floats, strings and large integers. Finally, the trail stack records variable bindings and assignments to support backtracking.” (http://www.swi-prolog.org/pldoc/man?section=limits)

I would be interested in some new functionality to save and restore state from non-deterministic foreign predicates. In theory, one could open a foreign frame during an invocation of a non-deterministic foreign predicate and then, just prior to returning, clone or copy the contents of the stack(s) atop or after that mark. In theory, a non-deterministic foreign predicate could, if/when subsequently invoked, open a foreign frame and restore state to the stack(s) atop or after it.

Also, the PL_open_foreign_frame() documentation says that the SWI-Prolog kernel creates a foreign frame prior to calling a foreign predicate and the PL_close_foreign_frame documentation states that the kernel closes the foreign frame after returning from the foreign predicate.

Does it make sense to save and restore portions of the stack(s) for non-deterministic foreign predicate invocations? Any other ideas regarding whether or how it might be possible to achieve nested queries?

#4

Using the C++ wrapper to the C api I would write

PlEngine a;
PlEngine b;

start query on a
start query on b

while (neither query is done)
{
    next the query on a
    next the query on b
}

I have not tested this.

#5

Roughly that can work. You do need to ensure the right engine is active at the right time in the computation. Notably not only queries are engine specific, but also term_t handles. Trying to access any of these with the wrong engine being active will cause a crash.