34
35:- module(record_locations,
36 [ record_location/0
37 ]). 38
39:- use_module(library(filesex)). 40:- use_module(extra_location). 41:- use_module(library(prolog_codewalk), []). 42:- use_module(library(apply)).
57:- multifile
58 system:term_expansion/4,
59 system:goal_expansion/4. 60
61:- dynamic record_location/0. 62record_location. 63
64:- thread_local rl_tmp/3. 65
67extra_location:loc_declaration(Head, M, assertion(Status, Type), From) :-
68 assertions:asr_head_prop(_, CM, Head, Status, Type, _, _, From),
69 predicate_property(CM:Head, implementation_module(M)).
70
71:- multifile skip_record_decl/1. 72
73skip_record_decl(initialization(_)) :- !.
74skip_record_decl(Decl) :-
75 nonvar(Decl),
76 '$current_source_module'(M),
77 predicate_property(M:Decl, imported_from(assertions)),
78 functor(Decl, Type, Arity),
79 memberchk(Arity, [1, 2]),
80 assertions:assrt_type(Type), !.
81
82:- public record_extra_location/4. 83
((:- Decl),
85 term_position(_, _, _, _, [DPos])) -->
86 ( {\+ skip_record_decl(Decl)}
87 ->record_extra_decl(Decl, DPos)
88 ; []
89 ).
90
(Decl, DPos) -->
92 { '$current_source_module'(SM),
93 declaration_pos(Decl, DPos, SM, M, IdL, ArgL, PosL)
94 },
95 foldl(assert_declaration(M), IdL, ArgL, PosL),
96 !.
97record_extra_decl(Goal, Pos) -->
98 { nonvar(Goal),
99 source_location(File, Line),
100 retractall(rl_tmp(File, Line, _)),
101 asserta(rl_tmp(File, Line, 1)),
102 assert_position(Goal, Pos, body)
103 }.
104
105declaration_pos(DM:Decl, term_position(_, _, _, _, [_, DPos]), _, M, ID, U, Pos) :-
106 declaration_pos(Decl, DPos, DM, M, ID, U, Pos).
107declaration_pos(module(M, L), DPos,
108 _, M, [module_2, export], [module(M, L), L], [DPos, Pos]) :-
109 DPos = term_position(_, _, _, _, [_, Pos]).
110declaration_pos(volatile(L), term_position(_, _, _, _, PosL),
111 M, M, [volatile], [L], PosL).
112declaration_pos(dynamic(L), term_position(_, _, _, _, PosL),
113 M, M, [dynamic], [L], PosL).
114declaration_pos(thread_local(L), term_position(_, _, _, _, PosL),
115 M, M, [thread_local], [L], PosL).
116declaration_pos(public(L), term_position(_, _, _, _, PosL),
117 M, M, [public], [L], PosL).
118declaration_pos(export(L), term_position(_, _, _, _, PosL),
119 M, M, [export], [L], PosL).
120declaration_pos(multifile(L), term_position(_, _, _, _, PosL),
121 M, M, [multifile], [L], PosL).
122declaration_pos(discontiguous(L), term_position(_, _, _, _, PosL),
123 M, M, [discontiguous], [L], PosL).
124declaration_pos(meta_predicate(L), term_position(_, _, _, _, PosL),
125 M, M, [meta_predicate], [L], PosL).
126declaration_pos(reexport(SM:DU), DPos, _, M, ID, U, Pos) :- !,
127 declaration_pos(reexport(DU), DPos, SM, M, ID, U, Pos).
128declaration_pos(use_module(SM:DU), DPos, _, M, ID, U, Pos) :- !,
129 declaration_pos(use_module(DU), DPos, SM, M, ID, U, Pos).
130declaration_pos(use_module(SM:DU, L), DPos, ID, _, M, U, Pos) :- !,
131 declaration_pos(use_module(DU, L), DPos, ID, SM, M, U, Pos).
132declaration_pos(reexport(SM:DU, L), DPos, ID, _, M, U, Pos) :- !,
133 declaration_pos(reexport(DU, L), DPos, ID, SM, M, U, Pos).
134declaration_pos(include(U), DPos, M, M, [include], [U], [DPos]).
135declaration_pos(use_module(U), DPos, M, M, [use_module], [U], [DPos]).
136declaration_pos(reexport(U), DPos, M, M, [reexport], [U], [DPos]).
137declaration_pos(consult(U), DPos, M, M, [consult], [U], [DPos]).
138declaration_pos(reexport(U, L), DPos, M, M,
139 [reexport_2, reexport(U)], [reexport(U, L), L], [DPos, Pos]) :-
140 DPos = term_position(_, _, _, _, [_, Pos]).
141declaration_pos(use_module(U, L), DPos, M, M,
142 [use_module_2, import(U)], [use_module(U, L), L], [DPos, Pos]) :-
143 DPos = term_position(_, _, _, _, [_, Pos]).
144
145:- meta_predicate foldsequence(4,?,?,?,?). 146
147foldsequence(G, A, B) --> foldsequence_(A, G, B).
148
149foldsequence_(A, _, _) -->
150 {var(A)},
151 !.
152 153foldsequence_([], _, _) --> !.
154foldsequence_([E|L], G, list_position(_, _, PosL, _)) -->
155 !,
156 foldl(foldsequence(G), [E|L], PosL).
157foldsequence_((A, B), G, term_position(_, _, _, _, [PA, PB])) -->
158 !,
159 foldsequence_(A, G, PA),
160 foldsequence_(B, G, PB).
161foldsequence_(A, G, PA) --> call(G, A, PA).
162
163assert_declaration(M, Declaration, Sequence, Pos) -->
164 foldsequence(assert_declaration_one(Declaration, M), Sequence, Pos).
165
166assert_declaration_one(reexport(U), M, PI, Pos) -->
167 !,
168 assert_reexport_declaration_2(PI, U, Pos, M).
169assert_declaration_one(module_2, M, H, Pos) -->
170 !,
171 172 assert_declaration_one(H, M, module_2, Pos).
173assert_declaration_one(Declaration, _, M:PI,
174 term_position(_, _, _, _, [_, Pos])) -->
175 !,
176 assert_declaration_one(Declaration, M, PI, Pos).
177assert_declaration_one(Declaration, M, F/A, Pos) -->
178 { atom(F),
179 integer(A)
180 },
181 !,
182 {functor(H, F, A)},
183 assert_position(H, M, Declaration, Pos).
184assert_declaration_one(Declaration, M, F//A1, Pos) -->
185 { atom(F),
186 integer(A1)
187 },
188 !,
189 { A is A1+2,
190 functor(H, F, A)
191 },
192 assert_position(H, M, Declaration, Pos).
193assert_declaration_one(Declaration, M, H, Pos) -->
194 assert_position(H, M, Declaration, Pos).
195
196assert_reexport_declaration_2((F/A as G), U, Pos, M) -->
197 {functor(H, G, A)},
198 assert_position(H, M, reexport(U, [F/A as G]), Pos).
199assert_reexport_declaration_2(F/A, U, Pos, M) -->
200 {functor(H, F, A)},
201 assert_position(H, M, reexport(U, [F/A]), Pos).
202assert_reexport_declaration_2(op(_, _, _), _, _, _) --> [].
203assert_reexport_declaration_2(except(_), _, _, _) --> [].
204
205assert_position(H, M, Type, TermPos) :-
206 assert_position(H, M, Type, TermPos, Clauses, []),
207 compile_aux_clauses(Clauses).
208
209assert_position(H, M, Type, TermPos) -->
210 211 212 { source_location(File, Line1),
213 ( nonvar(TermPos)
214 ->arg(1, TermPos, Chars),
215 setup_call_cleanup(
216 '$push_input_context'(rl_filepos_line),
217 (prolog_codewalk:filepos_line(File, Chars, Line, LinePos)),
218 '$pop_input_context')
219 ; Line = Line1,
220 LinePos = -1
221 )
222 },
223 assert_location(H, M, Type, File, Line, file(File, Line, LinePos, Chars)).
224
225assert_location(H, M, Type, File, Line, From) -->
226 ( {\+ extra_location(H, M, Type, From)}
227 ->['$source_location'(File, Line):extra_location:loc_declaration(H, M, Type, From)]
228 ; []
229 ).
230
231in_swipl_home(File) :-
232 current_prolog_flag(home, Dir),
233 directory_file_path(Dir, _, File).
234
235system:term_expansion(Term, Pos, [Term|Clauses], Pos) :-
236 record_location,
237 source_location(File, Line),
238 \+ in_swipl_home(File),
239 ( rl_tmp(File, Line, _)
240 ->fail
241 ; retractall(rl_tmp(_, _, _)),
242 asserta(rl_tmp(File, Line, 0 )),
243 record_extra_location(Term, Pos, Clauses, []),
244 Clauses \= []
245 ).
246
247redundant((_,_)).
248redundant((_;_)).
249redundant((_:_)).
250redundant(true).
251redundant(!).
252
253assert_position(G, Pos, T) :-
254 '$current_source_module'(M),
255 assert_position(G, M, T, Pos).
256
257:- public rl_goal_expansion/2. 258rl_goal_expansion(Goal, Pos) :-
259 callable(Goal),
260 \+ redundant(Goal),
261 source_location(File, Line),
262 \+ in_swipl_home(File),
263 ( nb_current('$term', Term)
264 ->( rl_tmp(File, Line, Flag)
265 ->Flag == 1
266 ; true
267 ),
268 memberchk(Term, [(:-_), []])
269 ; 270 true
271 ),
272 \+ clause(declaration_pos(Goal, _, _, _, _, _, _), _),
273 \+ skip_record_decl(Goal),
274 assert_position(Goal, Pos, goal),
275 !.
276
277system:goal_expansion(Goal, Pos, _, _) :-
278 record_location,
279 rl_goal_expansion(Goal, Pos),
280 fail
Record locations
Be careful since this module MUST not depend on others, otherwise such extra locations in the dependent modules will not be recorded, that is why we avoid the usage of the next two libraries:
*/