% faster.pl

% an optimizer using a meta-interpreter
% and the wrapper

:- [lib], -[demos,capsule,reduce,
	    tidyTrue,wrapper,format].
:- op(999,xfx,`), op(998,fx,`).

demof :- demos(faster2).
demo1 :- listing(d), nl, d(demo1), nl, d(demo2).

% for rules
term_expansion((C`X --> Y),Z) :-
	% C is magic context symbol
	faster(C,X,Y,Z).
% for facts
term_expansion(C`X,Z) :-
	faster(C,X,true,Z).

% as before- do the pe.
% but add in In/Out arguments for the
% term we are querying and updating.
faster(C,X,Y0,Out) :-
	pe(Y0,C,Y1,W0,W),
	Head =.. [C,X,W0,W],
	tidy((Head :- Y1),Out).

pe(X,Y,C,W0,W) :-
	% standard top-down parser.
	% block backtracking
	once(pe1(X,Y,C,W0,W)).

% standard base cases: yawn
pe1(X,   _,X,   W,W) :- var(X).
pe1(true,_,true,W,W).

% for "not", input W is not changed by the not
pe1(\+ X0,C,\+X, W,W) :-
	pe(X0,C,X,W,_).

% for "ors", have to pass the same input W into both
pe1((X0;Y0),C,(X;Y),W0,W) :-
	pe(X0,C,X,W0,W),
	pe(Y0,C,Y,W0,W).

% "|" a.k.a. ";"
pe1((X|Y),C,Z,W0,W) :-
	pe((X;Y),C,Z,W0,W).

% conjunction: input gets changed by term1 into temp,
% then passed to term2 to be changed into out
pe1((X0,Y0),C,   (X,Y),W0,W) :-
	pe(X0,C,X,W0,W1),
	pe(Y0,C,Y,W1,W).

% implication 
pe1((X0->Y0) ,C,(X->Y),W0,W) :-
	pe(X0,C,X,W0,W1),
	pe(Y0,C,Y,W1,W).

% X -> Y | Z = (X -> Y) | Z

% catch the get, set methods
pe1(!(X=Y), C,Z,  W0,W) :-
	Z0 =.. [C,X,_,Y,W0,W1],
	pe(Z0,C,Z,W1,W).
pe1(?(X=Y), C,Z,  W0,W) :-
	Z0 =.. [C,X,Y,Y,W0,W1],
	pe(Z0,C,Z,W1,W).

% catch the method sub-calls
pe1(`X,C,Z,  W0,W) :-
	Z0 =.. [C,X,W0,W1],
	pe(Z0,C,Z,W1,W).

% catch calls to other methods
% in other contexts (not tested)
pe1(C1`X,_,Z,  W,W) :-
	Z0 =.. [C1,X,W0,W1],
	pe(Z0,C1,Z,W0,W1).

% generate get, sets if we need to
pe1(X,C,Y,  W0,W) :-
	wrap(X,Z),
	pe(Z,C,Y,W0,W).

% reduce, if possible
pe1(X,C,Y,  W0,W) :-
	reduce(X,Z),
	pe(Z,C,Y,W0,W).

%else, do nothing
pe1(X,_,X,  W, W).

:- [fastereg2].