:- module(_,_,[sr/bfall]).

% Trees example: polynomials

% polynomial(T,X): `T` is a polynomial in `X`.
% E.g.: a * x ^ s(s(0)) + b

polynomial(X,X).
polynomial(Term,_X)  :- 
    pconstant(Term).
polynomial(Term1+Term2,X)  :- 
    polynomial(Term1,X),
    polynomial(Term2,X). 
polynomial(Term1-Term2,X)  :- 
    polynomial(Term1,X), 
    polynomial(Term2,X).
polynomial(Term1*Term2,X)  :- 
    polynomial(Term1,X), 
    polynomial(Term2,X).
polynomial(Term1/Term2,X)  :- 
    polynomial(Term1,X), 
    pconstant(Term2).
polynomial(Term1^N,X)  :- 
    polynomial(Term1,X), 
    nat_num(N).

pconstant(X) :- 
    nat_num(X).
pconstant(a).
pconstant(b).
pconstant(c).


% Try:
% ?- polynomial(a * x ^ s(s(0)) + b, x).
% ?- polynomial(P, x).
% ?- polynomial(    a * x ^ x + b,         x).

% Version using functional notation: 
% Note that arguments are reversed in this case!
:- use_package(fsyntax).
poly_f(X) := X
    | ~pconst_f
    | ~poly_f(X) + ~poly_f(X)
    | ~poly_f(X) - ~poly_f(X)
    | ~poly_f(X) * ~poly_f(X)
    | ~poly_f(X) / ~pconst_f
    | ~poly_f(X) ^ ~nat_num. 

pconst_f := ~nat_num | a | b | c.

% Try:
% ?- poly_f(x, a * x ^ s(s(0)) + b).
% ?- poly_f(x, P).
% ?- poly_f(x, a * x ^ x + b ).


% Auxiliary predicates: 
nat_num(0).
nat_num(s(X)) :- 
    nat_num(X).
