Prolog library: ixref.pl
pereira at sri-unix.UUCP
pereira at sri-unix.UUCP
Mon Aug 15 15:55:16 AEST 1983
% File: Ixref.PL Author: R.A.O'Keefe Updated: 9 November 82
% Note: this program is completely parasitic on PP.Pl. It only provides
% a way of building the database and a few methods for accessing it; the
% general pattern-matching stuff comes from PP, and the access method is
% called from it. It also depends on Helper for try_hard_to_see.
:- op(900, fx, sf).
:- op(900, fx, sp).
:- public
ixref/1, % inspect some files
ixref_path/3, % for 'setof'
(sf)/0, (sf)/1, (sf)/2,
(sp)/1, (sp)/2.
:- mode
ixref(+), % read a list of files and update the database
get_from(+,+),
start_ixref(+,+),
ixref_process(+,+,+),
ixref_command(+),
ixref_declaration(+),
ixref_head(+,+,+,-,-),
ixref_goal(+,-,-),
ixref_Current(+, -, -),
ixref_Pattern(+),
cassert(+), % put something in DataBase if not already there
sf, sf(+), sf(+,-),
sp(+), sp(+,-),
ixref_path(+, +, -),
ixref_path(+, ?, -, +),
memberchk(+, +).
ixref(Files) :-
nofileerrors,
( call('$seen'('<prolog>ixref.def'))
| get_from('<prolog>ixref.def', +)
), !,
get_from(Files, +),
fileerrors.
get_from([Head|Tail], Flag) :-
!, get_from(Head, Flag),
!, get_from(Tail, Flag).
get_from([], Flag) :- !.
get_from(erase(File), Flag) :- !,
start_ixref(File, erase).
get_from(-File, Flag) :- !,
get_from(File, -).
get_from(File, Flag) :-
seeing(OldFile),
try_hard_to_see(File, [press,extras,mec,util,pll], [pl,def]),
seeing(NewFile),
start_ixref(NewFile, Flag),
repeat,
read(Term),
expand_term(Term, Form),
ixref_process(Form, NewFile, Flag),
Form = end_of_file,
!,
seen,
see(OldFile).
start_ixref(File, Flag) :-
retract('$seen'(File)), % File has been seen before
retract('$defn'(Fn,Ar, File)), % Fn/Ar is defined in File
retract('$call'(Fn,Ar, _,_)), % forget all its calls
retract('$call'(Fn,Ar, _)), % forget what it applies
fail. % failure-driven LOOP
start_ixref(File, erase) :- !.
start_ixref(File, Flag) :-
assertz('$seen'(File)).
ixref_process(end_of_file, File, Flag) :- !.
ixref_process((Head :- Body), File, Flag) :- !,
ixref_head(Head, File, Flag, HeadFn,HeadAr),
ixref_goal(Body, GoalFn,GoalAr),
cassert('$seen'(GoalFn,GoalAr)),
cassert('$call'(HeadFn,HeadAr, GoalFn,GoalAr)).
ixref_process((:- Commands), File, Flag) :- !,
ixref_command(Commands).
ixref_process((?- Question), File, Flag) :- !.
ixref_process(system(Head), File, Flag) :- !,
ixref_head(Head, utility, Flag, HeadFn,HeadAr).
ixref_process(known(Head, F), File, Flag) :- !,
ixref_head(Head, F, Flag, HeadFn,HeadAr).
ixref_process(op(P, T, O), File, Flag) :- !,
op(P, T, O).
ixref_process(applies(G, A), File, Flag) :-
var(A), !,
cassert('$call'(G, A, 0)).
ixref_process(applies(G, A+N),File, Flag) :- !.
cassert('$call'(G, A, N)).
ixref_process(Fact, File, Flag) :- !,
ixref_head(Fact, File, Flag, HeadFn,HeadAr).
ixref_command((A,B)) :-
ixref_command(A), !,
ixref_command(B).
ixref_command(op(P, T, O)) :- !,
op(P, T, O).
ixref_command([X|Y]) :- !,
get_from([X|Y], +).
ixref_command(consult(Files)) :- !,
get_from(Files, +).
ixref_command(reconsult(Files)) :- !,
get_from(Files, -).
ixref_command(compile(Files)) :- !,
get_from(Files, -).
ixref_command((public Public)) :- !,
ixref_declaration(Public).
ixref_command((mode Mode)) :- !,
ixref_declaration(Mode).
ixref_command(_).
% handle :- public and :- mode declarations. The information
% should be stored somewhere for the sake of MEDIC, but until
% all these tools are properly fitted together it doesn't matter.
ixref_declaration((A,B)) :-
ixref_declaration(A), !,
ixref_declaration(B).
ixref_declaration(Functor/Arity) :- !,
cassert('$seen'(Functor, Arity)).
ixref_declaration(Term) :-
functor(Term, Functor, Arity),
cassert('$seen'(Functor, Arity)).
ixref_head(Head, File, Flag, Functor, Arity) :-
functor(Head, Functor, Arity),
call('$defn'(Functor, Arity, File)), !.
ixref_head(Head, File, Flag, Functor, Arity) :-
functor(Head, Functor, Arity),
( call('$defn'(Functor, Arity, OtherFile)),
OtherFile \== File,
(Flag == - | OtherFile = utility),
display('** '), display(File),
display(' redefines '), display(Functor),
display(/), display(Arity),
display(' which belongs to '),
display(OtherFile), ttynl
| true
), !,
cassert('$seen'(Functor, Arity)),
cassert('$defn'(Functor, Arity, File)).
ixref_goal(Goal, Fn,Ar) :-
var(Goal), !,
fail.
ixref_goal((G1,G2), Fn,Ar) :-
ixref_goal(G1, Fn,Ar).
ixref_goal((G1,G2), Fn,Ar) :- !,
ixref_goal(G2, Fn,Ar).
ixref_goal((G1;G2), Fn,Ar) :-
ixref_goal(G1, Fn,Ar).
ixref_goal((G1;G2), Fn,Ar) :- !,
ixref_goal(G2, Fn,Ar).
ixref_goal(Goal, Fn,Ar) :-
call('$call'(Goal, Argument, Extra)),
nonvar(Argument),
functor(Argument, Fn, Small),
Ar is Small+Extra.
ixref_goal(Goal, Fn,Ar) :-
functor(Goal, Fn,Ar),
call('$defn'(Fn,Ar, utility)),
!, fail.
ixref_goal(Goal, Fn,Ar) :-
functor(Goal, Fn,Ar).
cassert(Fact) :-
call(Fact), !.
cassert(Fact) :-
assertz(Fact).
% The following predicate accesses the IXREF data-base.
% from(-) -- called but not defined
% from(F) -- defined in file F
% >(-) -- defined but calling nothing
% >(Pattern) -- calling something matching Pattern
% <(-) -- defined but not called
% <(Pattern) -- called by something matching Pattern
% @>(Pattern) -- calling Pattern = closure of >
% @<(Pattern) -- called by Pattern = closure of <
ixref_Pattern(from(_)).
ixref_Pattern(>(_)). ixref_Pattern(@>(_)).
ixref_Pattern(<(_)). ixref_Pattern(@<(_)).
ixref_Current(from(-), Functor, Arity) :- !,
call('$seen'(Functor, Arity)),
\+ call('$defn'(Functor, Arity, File)).
ixref_Current(from(File), Functor, Arity) :- !,
call('$defn'(Functor, Arity, File)).
ixref_Current(>(-), Functor, Arity) :- !,
call('$defn'(Functor, Arity, _)),
\+ call('$call'(Functor, Arity, _, _)).
ixref_Current(>(Pattern), Functor, Arity) :- !,
isCurrent(Pattern, sp, G/B),
call('$call'(Functor, Arity, G, B)).
ixref_Current(<(-), Functor, Arity) :- !,
call('$defn'(Functor, Arity, File)),
File \== utility,
\+ call('$call'(_, _, Functor, Arity)).
ixref_Current(<(Pattern), Functor, Arity) :- !,
isCurrent(Pattern, sp, G/B),
call('$call'(G, B, Functor, Arity)).
ixref_Current(@>(Pattern), Functor, Arity) :- !,
ixref_path(Functor/Arity, Pattern, _).
ixref_Current(@<(Pattern), Functor, Arity) :- !,
ixref_path(Pattern, Functor/Arity, _).
/*----------------------------------------------------------------------+
| |
| Seen File ? |
| |
| The predicates provided to the user are |
| sf(Pattern, Files) -- return selected filenames |
| sf(Pattern) -- display selected filenames |
| sf -- display all file names |
| |
| Once again, there are two sorts of patterns, and keeping them apart |
| is confusing. If the pattern is a string, the user is told which |
| files have been seen whose names match the pattern. Otherwise, he |
| is told which files have been seen that defined predicates matching |
| the pattern. E.g. sf "fre*" might locate a file 'fred.pl', while |
| sf ["fre*"] will locate files defining predicates fred... |
| |
+----------------------------------------------------------------------*/
sf :-
sf("*").
sf(Pattern) :-
sf(Pattern, Files),
answer_List(Files, 32).
sf([Head|Tail], Files) :-
integer(Head), !,
setof(File, ('$seen'(File), isCurrent([Head|Tail], File)), Files).
sf(Pattern, Files) :-
setof(File, ('$defn'(F,A,File), isCurrent(Pattern, cf, F/A)), Files).
/*----------------------------------------------------------------------+
| |
| Show Paths |
| |
| The predicates provided for the user are |
| sp(Limits, Paths) -- return paths |
| sp(Limits) -- display paths |
| Note that there is no sp/0, as the complete list of paths is as |
| long as it is boring. |
| A path is a list [F0/N0, ..., Fk/Nk] where each entry names |
| a predicate, and Fi/Ni calls Fi+1/Ni+1, and no entry appears more |
| than once. It describes in detail how F0/N0 may call Fk/Nk. For |
| my convenience, this is the scheme used to implement @> and @<. |
| The Limits are |
| FirstCaller - LastCalled |
| - LastCalled |
| FirstCaller |
| where FirstCaller, LastCalled are TermPatterns. |
| |
+----------------------------------------------------------------------*/
sp(Limits) :-
sp(Limits, Paths),
answer_List(Paths, 31).
sp(FirstCaller-LastCalled, Paths) :- !,
setof(Path, ixref_path(FirstCaller, LastCalled, Path), Paths).
sp(-LastCalled, Paths) :- !,
sp("*"-LastCalled, Paths).
sp(FirstCaller, Paths) :-
sp(FirstCaller-"*", Paths).
ixref_path(First, Last, [FirstSpec|Path]) :-
isCurrent(First, sp, FirstSpec),
ixref_path(FirstSpec, LastSpec, Path, [FirstSpec]),
isCurrent(Last, sp, LastSpec).
ixref_path(F/A, G/B, [H/C|Path], Forbidden) :-
call('$call'(F, A, H, C)),
\+ memberchk(H/C, Forbidden),
ixref_path(H/C, G/B, Path, [H/C|Forbidden]).
ixref_path(F/A, F/A, [], _).
memberchk(H, [H|_]) :- !.
memberchk(X, [_|T]) :- memberchk(X, T).
More information about the Comp.sources.unix
mailing list