% ------------------------------------------------
% example stuff to look at
demo1(emp(tim,23,male)).
demo1([a,b,c]).
demo1(2+3).
demo1(10 - 10 * 3).
demo1(- x). 
demo1(+ y).
demo1((age(Dob,Age) :- now(Now), Age is Now - Dob)).
demo1((:- now(Now), print(Now))).

% ------------------------------------------------
% wrapping find (so we can find all solution)
finds(What,Term,Founds) :-
    findall(Found,
   	       find(What,0,Term,Found),
	    Founds).

% ------------------------------------------------
% find some part of Term at depth N that 
% satisfied predicate What
find(What,N,Term,Found) :- 
    call(What,N,Term,Found).
find(What,N,Term,Found) :-
    nonvar(Term),
    Term =.. [H1,H2|T], 
    member(Next,[H1,H2|T]),
    find(What,N+1,Next,Found).

% ------------------------------------------------
% examples of predicates that can be used in find/4

% find functor in the head of rules
headp(N,X,Y) :- nonvar(X), headp1(N,X,Y).
headp1(_,(X :- _),Y) :- X =.. [Y|_].

% find anything, and print it
blurt(N,Term,Term) :-
    tab(4*N),
    numbervars(Term,1,_),
    print(Term),nl.

% find numbers
numberp(_,N,N) :- number(N).

% find numbers and multiply them by something
mult(M,_,N,NtimesM) :- number(N), NtimesM is M * N.

% find the lhs functors of my code.
lhs(N,X,Lhs) :- nonvar(X), mine(X,Body), lhs1(N,X,Body,Lhs).

lhs1(_,Head,_,Lhs) :- Head =.. [Lhs|_].
lhs1(N,_,Body,Lhs) :- find(lhs,N+1,Body,Lhs).

% support routines for lhs
% is X something that I wrote? or is it a prolog built-in
mine(X,Body) :- mine(X,_,Body).
mine(X,F,Body) :- not(builtIn(X)), clause(X,Body), X =.. [F|_].

builtIn(X) :- predicate_property(X,built_in).

%----------------------------------
% a variant of the above finds that includes
% a working memory variable. returns all
% solutions to find/7.
finds(What,N,Term,W,Founds) :-
    findall(Found,
             find(What,N,Term,W,_,Found),
            Founds).


%----------------------------------
% a variant of the above finds that includes
% a working memory variable.
find(What,N,Term,W0,W,Found) :- 
    call(What,N,Term,W0,W,Found).
find(What,N,Term,W0,W,Found) :-
    nonvar(Term),
    Term =.. [H1,H2|T], 
    member(Next,[H1,H2|T]),
    find(What,N+1,Next,W0,W,Found).

% a variant of the above lhs that uses the
% working memory variable
lhs(N,X,W0,W,Lhs) :- 
	nonvar(X), 
	mine(X,Functor, Body),
	not(member(Functor,W0)),
	lhs1(N,X,Body,[Functor|W0],W,Lhs).

lhs1(_,Head,_,W,W,Lhs) :- Head =.. [Lhs|_].
lhs1(N,_,Body,W0,W,Lhs) :- find(lhs,N+1,Body,W0,W,Lhs).
