1/***************************************************************************** 2 * This file is part of the Prolog Development Tool (PDT) 3 * 4 * Author: G�nter Kniesel, Tobias Rho (among others) 5 * WWW: http://sewiki.iai.uni-bonn.de/research/pdt/start 6 * Mail: pdt@lists.iai.uni-bonn.de 7 * Copyright (C): 2004-2012, CS Dept. III, University of Bonn 8 * 9 * All rights reserved. This program is made available under the terms 10 * of the Eclipse Public License v1.0 which accompanies this distribution, 11 * and is available at http://www.eclipse.org/legal/epl-v10.html 12 * 13 ****************************************************************************/ 14 15% Author: G�nter Kniesel & Tobias Rho 16% Date: 5. April 2012 17% Licence: EPL
USE:
Invoke
?- gen_call_graph.
Then use the clauses generated in this module:
?- xref(CallingClauseRef,CallLiteral,ProgramPoint,CalledClauseRef)
.
For many applications call resolution at clause level granularity
might be too detailed. Predicate-level granularity can be easily
obtained by calling the internal predicate get_clause/2 via once/1.
and asserting the
xref(CallingRef,Literal,ProgramPoint,CalledRef)
just for the first referenced clause.
38:- module( pdt_xref_v3, 39 [ gen_call_graph/0 40 , xref/4 % (CallingRef,Literal,ProgramPoint,CalledRef) 41 ] 42 ). 43 44% Folgendes Pr�dikat nutzen wir gar nicht mehr. 45% Eigentlich m�ssten wir es in der vorletzten Klausel 46% von process_body__/3 aufrufen. Wir tun es aber nicht. 47resolve_call(Call,DeclaringModule,ClauseRef) :- 48 strip_module(Call,Module,Literal), 49 functor(Literal,Name,Arity), 50 defined_in(Module,Name,Arity,DeclaringModule), 51 clause(DeclaringModule:,_Body,ClauseRef). 52% Das heisst: Entweder ist dort ein Fehler, oder es 53% funktioniert auch ohne den Aufruf von defined_in/3 54% also so: 55% 56%resolve_call(Call,DeclaringModule,ClauseRef) :- 57% strip_module(Call,Module,Literal), 58% %defined_in(Module,Name,Arity,DeclaringModule), 59% clause(Module:Literal,_Body,ClauseRef). 60% 61%Das ist tats�chlich der Fall: 62% 63%?- clause(sub:c(X),_Body,ClauseRef). 64%X = 1, 65%_Body = true, 66%ClauseRef = <clause>(08A640F0) ; 67%X = 2, 68%_Body = true, 69%ClauseRef = <clause>(08A64080) ; 70%X = 3, 71%_Body = true, 72%ClauseRef = <clause>(08A640B8). 73% FAZIT: Wenn man nur die referenzierten Klauseln will, reicht clause/3. 74% Wenn man hingegen auch das Modul wissen will, aus dem die Klauseln 75% stammen braucht man defined_in. Das (bzw. resolve_call) 76% ist also noch einzbauen in unsere Implementierung. 77 78 79 80 81gen_call_graph :- 82 retractall(xref(_,_,_,_)), 83 defined_in_module(Module,Name,Arity), 84 functor(Head,Name,Arity), 85 \+ predicate_property(Module:Head, foreign), 86 clause_xref(Module,Head,Xref), 87 assert(Xref), 88 fail. 89gen_call_graph.
93clause_xref(Module,Head,Xref):- 94 clause(Module:,Body,CallingRef), 95 process_body(Module,Body,Arc), 96 Arc = arc( Literal,ProgramPoint,CalledRef), 97 Xref = xref(CallingRef,Literal,ProgramPoint,CalledRef). 98 99process_body(Module,Body,Arc) :- 100 nb_setval(program_point, 0), 101 process_body__(Module,Body,Arc). 102 103%process_body__(Module,(A,B),Arc):- 104% !, 105% ( process_body__(Module,A,Arc) 106% ; process_body__(Module,B,Arc) 107% ). 108% 109%process_body__(Module,(A;B),Arc):- 110% !, 111% ( process_body__(Module,A,Arc) 112% ; process_body__(Module,B,Arc) 113% ). 114% 115process_body__(Module,Term,_Arc):- 116 ( var(Module) 117 ; var(Term) 118 ), 119 !, 120 fail. 121 122 123process_body__(_,Module:Term,Arc):- 124 !, 125 process_body__(Module,Term,Arc). 126 127process_body__(Module,Meta,Arc):- 128 is_meta_call(Module:Meta), 129 !, 130 peel_meta(Module:Meta,Literal), 131 process_body__(Module,Literal,Arc). 132 133 134process_body__(Module,Literal,Arc):- 135 callable(Literal), 136 !, 137 inc_program_point, 138 get_program_point(Pt), 139 get_clause(Module:Literal,Ref), % refer to each called clause 140% once(get_clause(Module:Literal,Ref), % refer just to first clause 141 Arc=arc(Module:Literal, Pt, Ref). 142 143 144process_body__(_,Literal, arc(Literal, -1, failed)). 145 146 147is_meta_call(Call):- 148 predicate_property(Call, meta_predicate(_)). 149 150 151get_clause(_:'$_variable'(Term,Number),variable(Term,Number)):- 152 !. 153get_clause(Module:Literal,Ref):- 154 predicate_property(Module:Literal, foreign), 155 !, 156 Ref=foreign. 157get_clause(Module:Literal,Ref):- 158 \+ clause(Module:,_,_), 159 !, 160 Ref=undefined. 161get_clause(Module:Literal,Ref):- 162 clause(Module:,_Body,Ref).
167peel_meta(Module:Meta,Literal):-
168 predicate_property(Module:Meta, meta_predicate(Pattern)),
169 inc_program_point,
170 meta_argument(Meta,Pattern,Literal).
174meta_argument(Meta,Pattern,Literal):- 175 arg(Nr,Pattern,MetaIndicator), 176 number(MetaIndicator), 177 arg(Nr,Meta,Argument), 178 add_arguments(Argument,MetaIndicator,Literal). 179 180%peel_meta(Literal,Literal). 181 182 183add_arguments(Term,Number,Result) :- 184 var(Term), 185 !, 186 Result = '$_variable'(Term,Number). 187add_arguments(Term,0,Term) :- !. 188add_arguments(Term,Number,BiggerTerm) :- 189 callable(Term), 190 Number > 0, 191 Term =.. List, 192 length(Postfix,Number), 193 append(List,Postfix,BiggerList), 194 BiggerTerm =.. BiggerList. 195 196 197inc_program_point :- 198 nb_getval(program_point, Value), 199 Next is Value+1, 200 nb_setval(program_point, Next). 201 202get_program_point(Value):- 203 nb_getval(program_point, Value)