I wrote a small “Prolog in Prolog” interpreter based on clause/2 to fix a strange bug in my CGI in prolog. After fixing the trouble I wanted to extend a little bit the interpreter to cover the “deep cut (!)” for future use.
As once I saw an elegant and small such “prolog in prolog” in middle 1980’s, following my vague memory, I have managed to reproduce it, I hope. As far as the running the following typical sample queries, it seems to work correctly.
?- solve(false -> true). % Prolog behaviour.
?- solve(1=2 -> 1=2; 2=2).
?- solve(((X=1, X=2) -> (Y = 1; Y=2)); Y =3; Y=4).
?- solve(((X=1; X=2) -> (Y = 1; Y=2)); Y =3; Y=4).
?- solve(solve(((X=1, X=2) -> (Y = 1; Y=2)); Y =3; Y=4)). % idempotency.
?- solve(solve(((X=1; X=2) -> (Y = 1; Y=2)); Y =3; Y=4)).
?- solve(solve((member(X, [1,2,3]), !,
member(Y, [a,b,c]), !,
The following were useful for the interpreter going down only to user-defined predicates:
predicate_property(_, built_in) predicate_property(_, imported_from(_)) predicate_property(_, interpreted)
Also, now I “qcompile” every my codes, but the builtin clause/2 works as if it traces on source codes in text. Very impressive !
After the success, I tried to improve further the interpreter to avoid using the “deep cut” (in solve/1), because the code itself I saw might have not used “deep cut.”
After several “try and error”, although I could not find a way for “pure prolog” codes, now I have another solve/1 which behaves equally to the first one.
The both codes have almost the same structure, but the second one uses nb_setarg/3 term arguments in stead to keep track the cut (!) occurrences to cut alternatves. The nb_setarg is not “pure”, but the effect was drastic and the impureness was very local, I hope. This is the reason why I uploaded also the nb_setarg version. Of course, it is not my intention to recommend to use impure primitives.
I have uploaded both codes in my pack library(pac) pac-v1.5.1.
library(pac)/misc/prolog-in-prolog.pl % deep cut version. library(pac)/misc/prolog-in-prolog2.pl % nb_setarg version.
?- [misc(‘prolog-in-prolog’)]. % “deep cut” version.
?- [misc(‘prolog-in-prolog2’)]. % nb_setarg version.
(the same queries above)