:- module(_,[expand/2],[]).
% Expansion for clp(Q).

:- use_module(library('clpq/eval_q')).

expand(Goal, Code) :-
        ( Goal = arith_eval(_)
        ; Goal = arith_eval(_,_)
        ; Goal = arith_zero(_)
        ),
        pattern(Pattern, Code),
        pm(Pattern, Goal),
        Pattern = Goal.

pm(Pattern, Data) :-
        var(Pattern), !,
        leaf(Data).
pm(Pattern, Data) :-
        nonvar(Data),
        functor(Pattern, N, A),
        functor(Data,    N, A),
        pm_args(A, Pattern, Data).

pm_args(0, _, _) :- !.
pm_args(N, P, D) :-
        arg(N, P, Pa),
        arg(N, D, Da),
        pm(Pa, Da),
        N1 is N-1,
        pm_args(N1, P, D).

leaf(V) :- var(V).
leaf(N) :- number(N).
leaf(rat(_,_)).

pattern( arith_zero(A), (A=0)).
pattern( arith_zero(A-B), 'arith_zero-1'(A,B)).
pattern( arith_zero(A*B-1), 'arith_zero-*1'(A, B)).
pattern( arith_zero(A-1), 'arith_zero-1'(A)).
pattern( arith_eval(A<0), 'arith_eval<1'(A)).
pattern( arith_eval(A>0), 'arith_eval>1'(A)).
pattern( arith_eval(A<B), 'arith_eval<1'(A,B)).
pattern( arith_eval(A>B), 'arith_eval<1'(B,A)).
pattern( arith_eval(A=<0), 'arith_eval=<1'(A)).
pattern( arith_eval(A>=0), 'arith_eval>=1'(A)).
pattern( arith_eval(B-C, A), 'arith_eval-1'(B, C, A)).
pattern( arith_eval(B*C, A), 'arith_eval*1'(B, C, A)).
pattern( arith_eval(C*D-B, A), 'arith_eval-*1'(C, D, B, A)).
pattern( arith_eval(B*C+D*E, A), 'arith_eval+*1'(B, C, D, E, A)).
pattern( arith_eval(B*C-D*E, A), 'arith_eval-*1'(B, C, D, E, A)).
pattern( arith_eval(B+C, A), 'arith_eval+1'(B, C, A)).
pattern( arith_eval(C+D+B, A), 'arith_eval++1'(C, D, B, A)).
pattern( arith_eval(D+E+C+B, A), 'arith_eval+++1'(D, E, C, B, A)).
pattern( arith_eval(-(B/C), A), 'arith_eval-/1'(B, C, A)).
pattern( arith_eval(-1/B, A), 'arith_eval/-11'(B, A)).
pattern( arith_eval(-(B/C), A), 'arith_eval-/2'(B, C, A)).
pattern( arith_eval(-(B), A), 'arith_eval-1'(B, A)).
pattern( arith_eval(B*rat(C,D), A), 'arith_eval*1'(B, C, D, A)).
pattern( arith_eval(C*D+B, A), 'arith_eval+*1'(C, D, B, A)).
pattern( arith_eval(B+C*D, A), 'arith_eval+1'(B, C, D, A)).

