I wrote a Prolog meta interpreter some years ago, taht worked well in GNU Prolog. However, I can’t make gprolog work on Linux anymore, it seems tehre is no support to it. That’s a pity.
Now I am porting it to SWI Prolog and it works well, except for a circularity issue.
When I call the meta-interpreter to execute itself, I get a fail. I traced it and what I got is:
Glad my hint was useful. Anyway, I’ve tried to install GNU Prolog (from source) on Ubuntu 16.04 without problems. Just, since I didn’t configured (for laziness) the INSTALL_DIR I had to use sudo make install as final step.
There are roughly 5 classes of predicates relevant to meta-interpretation:
With predicate property foreign. These are written in C (or have a C wrapper to Java/Python/…). You cannot do clause/2 and thus you cannot meta-interpret them.
Stuff handled by the compiler that has a clause that is exactly the same. Below is an example. You can get a clause, but this is the same as the original clause and thus you make no progress You find the full set in boot/init.pl, currently from line 318.
(G1, G2) :- call((G1, G2)).
Normal Prolog code that is part of the core system. They are reported as built_in.
Normal Prolog code from the libraries. The way to find them, as @EricGT mentioned is using the imported_from(Module) property and module_property/2, checking for class(library)
User code. This may be local to the module (or not in a module) or imported user code.
The first two cannot be meta-interpreted. The rest is a choice up to the user.
This gets really tricky. I think the only way to call ,/2 is using call/2 (or call/3), as in
?- call(','((between(1,3,X),!)),writeln(X)).
1
X = 1.
I think this is correct as the above must be the same as call((between(1,3,X),!,writeln(X))). I think all other ways to call ,/2 are handled by the compiler rather than the predicate.