#!/usr/bin/env swipl -q -t start -f %% chmod +x pharmacon.prolog && ./pharmacon.prolog %% hello world program in stack form helloworld([ pushz,inc,inc,dup,dup,mul,mul,dup,dup,inc,mul, prc,pushz,inc,inc,inc,dup,dup,mul,mul,add,inc, inc,prc,add,dec,prc,prc,inc,inc,inc,prc,pushz, inc,inc,dup,dup,mul,dup,inc,mul,inc,mul,inc,inc, prc,pushz,inc,inc,inc,dup,inc,mul,swap,sub,prc, swap,dup,pushz,inc,inc,dup,dup,mul,mul,add,prc, swap,pushz,inc,inc,inc,add,dup,dec,dec,dec,prc, pop,prc,swap,pop,pushz,inc,inc,dup,inc,mul,swap, sub,prc,pushz,inc,inc,dup,dup,mul,mul,swap,sub, prc,pop,inc,prc,pop,pushz,inc,inc,dup,dup,dup, inc,add,mul,add,inc,prc,dec,dec,dec,prc,pop ]). %% peano arithmetic z(z). inc(S,s(S)). dec(s(S),S). add(z,S,S). add(s(S),A,O) :- add(S,s(A),O). sub(S,z,S). sub(s(S),s(A),O) :- sub(S,A,O). mul(_,z,z). mul(z,_,z). mul(S,s(z),S). mul(s(z),S,S) :- \+ S = s(z). mul(A,B,O) :- dec(A,A1), mul(A1,B,O1), add(B,O1,O). num(0,z). num(N,s(S)) :- \+ var(N), N> 0, N1 is N -1, num(N1,S). num(N,s(S)) :- \+ var(S), num(N1,S), N is N1 + 1. %% basic linked list/cons cells/ nil(nil). pair(A,B,pair(A,B)). head(pair(A,_),A). tail(pair(_,B),B). pairs([],nil). pairs([H|T],pair(H,T1)) :- pairs(T,T1). %% stack machine run(P,O) :- pairs(P,Pa), nil(S), eval(Pa,S,Oa), stackback(Oa,O),!. eval(I,S,S) :- nil(I). eval(I,S,O) :- head(I,H), exec(H,S,O1),!, tail(I,T), eval(T,O1,O). exec(pushz,S,O) :- z(Z),pair(Z,S,O). exec(pop,S,O) :- tail(S,O). exec(inc,S,O) :- pair(A,B,S), inc(A,A1), pair(A1,B,O). exec(dup,S,O) :- head(S,A), pair(A,S,O). exec(prc,S,S) :- head(S,A), num(N,A), writef('%n',[N]). exec(prn,S,S) :- head(S,A), num(N,A), writef('%w',[N]). exec(dec,S,O) :- pair(A,B,S), dec(A,A1), pair(A1,B,O). exec(add,S,O) :- pair(A,At,S), pair(B,T,At), add(A,B,AB), pair(AB,T,O). exec(swap,S,O) :- pair(A,At,S), pair(B,T,At), pair(A,T,Bt), pair(B,Bt,O). exec(sub,S,O) :- pair(A,At,S), pair(B,T,At), sub(A,B,AB), pair(AB,T,O). exec(mul,S,O) :- pair(A,At,S), pair(B,T,At), mul(A,B,AB), pair(AB,T,O). exec(A,_,_) :- writef("Unknown %w\n",[A]), !, fail. stackback(nil,[]). stackback(pair(H,T),[H1|T1]) :- num(H1,H),stackback(T,T1). start :- helloworld(H), run(H,[]).