In file prolog_walk_code examples
.
:- module(prolog_walk_code_examples,[
assert_call_graph/0,
list_called_by/2
]).
% -----------------------------------------------------------------------------
:- working_directory(_,'C:/Users/Groot').
% ['prolog_walk_code examples'].
% -----------------------------------------------------------------------------
:- dynamic
calls/2.
assert_call_graph :-
retractall(calls(_, _)),
prolog_walk_code([ trace_reference(_),
on_trace(assert_edge),
source(false)
]),
predicate_property(calls(_,_), number_of_clauses(N)),
format('Got ~D edges~n', [N]).
assert_edge(Callee, Caller, _Where) :-
calls(Caller, Callee), !.
assert_edge(Callee, Caller, _Where) :-
assertz(calls(Caller, Callee)).
% NB This has to come after assert_call_graph/0
%
% If there are no calls/2 facts, the goals will return nothing,
% so this will assert the facts into the Prolog database.
:- if(\+ prolog_walk_code_examples:calls(_,_)).
:- assert_call_graph.
:- endif.
% queries
list_called_by((M1:Name1/Arity1),M:Name/Arity) :-
ground(M),
ground(Name),
ground(Arity), !,
compound_name_arity(Head,Name,Arity),
prolog_walk_code_examples:calls(M1:Head1,_:Head),
functor(Head1,Name1,Arity1).
list_called_by(M:Name/Arity,Called_by) :-
var(Called_by), !,
setof(pi(M:Name/Arity),local_predicate_generator(Name,M:Name/Arity),PI_set),
member(pi(M:Name/Arity),PI_set),
setof(Call,list_called_by(Call,M:Name/Arity),Called_by).
local_predicate_generator(Name,M:Name/Arity) :-
current_predicate(M:Name/Arity),
local_predicate(M:Name/Arity).
local_predicate(M:Name/Arity) :-
compound_name_arity(Head,Name,Arity),
\+ predicate_property(M:Head,imported_from(_)).
Example run:
Welcome to SWI-Prolog (threaded, 64 bits, version 8.3.5-8-ge14460a94)
?- working_directory(_,'C:/Users/Groot').
true.
?- ['prolog_walk_code examples'].
Got 6,462 edges
true.
?- list_called_by(M:append/Arity,Called_by).
M = lists,
Arity = 2,
Called_by = [ansi_term:ansi_get_color_/2] ;
M = lists,
Arity = 3,
Called_by = [ansi_term:read_pattern/3, arithmetic:do_expand_function/3, pce_goal_expansion:expand/2, predicate_options:extend/3, predopts_analysis:attr_unify_hook/2, prolog_codewalk:extend/6, prolog_codewalk:extend_term_pos/3, prolog_debug:debug_message_context/1, prolog_debug:update_debug/6, prolog_edit:substitute/4, prolog_metainference:annotate_meta_arg/3, prolog_stack:join_stacks/3] ;
false.
I made this a Discourse Wiki topic so that anyone with a proper trust level can edit this. If you want to improve the code, add some documentation, or other, feel free.
There will probably be a few more topics in this category related to Prolog code analysis that I might pull together into a Wiki, but for now having the code in a more prominent place is better than being buried in a Wiki discussion topic.
Also see: List the properties for predicate(s)