Meta-Interpreters
Because programs are terms, writing a Prolog interpreter in Prolog takes a few lines — the basis for explanation facilities, alternative search, and debugging tools.
32.1 The vanilla meta-interpreter
clause/2 retrieves clauses of (dynamic or accessible) predicates. In SWI, declare user predicates dynamic or use :- set_prolog_flag(access_level, system) for inspection.
solve(true) :- !.
solve((A, B)) :- !, solve(A), solve(B).
solve((A ; B)) :- !, ( solve(A) ; solve(B) ).
solve(H) :- predicate_property(H, built_in), !, call(H).
solve(H) :- clause(H, Body), solve(Body).32.2 Proof trees (explanations)
prove(true, true) :- !.
prove((A, B), (PA, PB)) :- !, prove(A, PA), prove(B, PB).
prove(H, H-builtin) :- predicate_property(H, built_in), !, call(H).
prove(H, H-Proof) :- clause(H, Body), prove(Body, Proof).
?- prove(grandparent(tom, X), P).32.3 Depth-limited meta-interpreter
Iterative deepening: between(1, inf, D), solve_d(Goal, D).
solve_d(true, _) :- !.
solve_d((A, B), D) :- !, solve_d(A, D), solve_d(B, D).
solve_d(H, D) :- predicate_property(H, built_in), !, call(H).
solve_d(H, D) :- D > 0, D1 is D - 1, clause(H, B), solve_d(B, D1).32.4 A pure meta-interpreter with clause/2 representation
Variants: counting inferences, collecting statistics, tracing, breadth-first or fair search, probabilistic reasoning, abductive reasoning, uncertainty (certainty factors in expert systems).
mi([]).
mi([G|Gs]) :- head_body(G, Gs, Body), mi(Body).
head_body(natnum(0), Rs, Rs).
head_body(natnum(s(X)), Rs, [natnum(X)|Rs]).