% reduce.pl

% things we can run at load time.

% unification can happen right now.
reduce(X = X, true).

% if we have enough info to do
% a calculation, do it now
reduce(X is Y,true) :- 
	ground(Y),
	X is Y.

% lists can be appended if
% the lists are defined enoug
% at runtime
reduce(append(L1,L2,L3),true) :- 
	proper_list(L1), 
	proper_list(L2), 
	append(L1,L2,L3).

% univs can be called at
% runtime, if the list is
% well-defined and the head is
% bound
reduce(Term =.. [H|T],true) :-
	proper_list(T),
	ground(H),
	Term =.. [H|T].

% if there is only one fact
% for X, we can call it at
% compile time
reduce(X,true) :-
	singleton(X),
        clause(X,true).

% if there is only one rule
% that defines X, we can ust
% swap the head for the rule
% body.
reduce(X,Y) :-
	singleton(X),
	clause(X,Y).

singleton(X) :-
	\+ predicate_property(X,built_in),
	findall(Y,clause(X,Y),[_]).
