Here is a take, replicating the “pop” instruction and only term
building and unification, and simulating a C memory
pointer as a pair I-Z:
step(atom(C), _, [I-Z|S], [J-Z|S]) :-
arg(I, Z, C),
J is I+1.
step(var(N), V, [I-Z|S], [J-Z|S]) :-
arg(N, V, W),
arg(I, Z, W),
J is I+1.
step(functor(F,A), _, [I-Z|S], [1-K,J-Z|S]) :-
arg(I, Z, K),
functor(K, F, A),
J is I+1.
step(pop, _, [_|S], S).
And then iteratively executing the steps:
exec([X|L], V, S, T) :-
step(X, V, S, H),
exec(L, V, H, T).
exec([], _, S, S).
Seems to work for term building, here f(a,g(b,W),W):
?- exec([functor(f, 3), atom(a), functor(g, 2),
atom(b), var(1), pop, var(1), pop], display(W),
[1-result(_)], L).
L = [2-result(f(a, g(b, W), W))]
Works also for unification, here f(a,g(b,W),W)=f(a,X,Y) success
and f(a,g(b,W),W)=f(X,Y) failure:
?- exec([functor(f, 3), atom(a), functor(g, 2),
atom(b), var(1), pop, var(1), pop], display(W),
[1-result(f(a,X,Y))], L).
W = Y,
X = g(b, Y),
L = [2-result(f(a, g(b, Y), Y))]
?- exec([functor(f, 3), atom(a), functor(g, 2),
atom(b), var(1), pop, var(1), pop], display(W),
[1-result(f(X,Y))], L).
No
Open source:
Modern Albufeira Prolog Interpreter
https://gist.github.com/jburse/9fd22e8c3e8de6148fbd341817538ef6#file-modern-pl