34
35:- module(prolog_debug_tools,
36 [ (spy)/1, 37 (nospy)/1, 38 nospyall/0,
39 debugging/0,
40 trap/1, 41 notrap/1 42 ]). 43:- use_module(library(broadcast), [broadcast/1]). 44:- autoload(library(edinburgh), [debug/0]). 45:- autoload(library(gensym), [gensym/2]). 46
47:- multifile
48 trap_alias/2. 49
50:- set_prolog_flag(generate_debug_info, false). 51
59
65
66:- multifile
67 prolog:debug_control_hook/1. 68
69:- meta_predicate
70 spy(:),
71 nospy(:). 72
87
88spy(Spec) :-
89 '$notrace'(spy_(Spec)).
90
91spy_(_:X) :-
92 var(X),
93 throw(error(instantiation_error, _)).
94spy_(_:[]) :- !.
95spy_(M:[H|T]) :-
96 !,
97 spy(M:H),
98 spy(M:T).
99spy_(Spec) :-
100 prolog:debug_control_hook(spy(Spec)),
101 !.
102spy_(Spec) :-
103 '$find_predicate'(Spec, Preds),
104 '$member'(PI, Preds),
105 pi_to_head(PI, Head),
106 '$define_predicate'(Head),
107 '$spy'(Head),
108 fail.
109spy_(_).
110
111nospy(Spec) :-
112 '$notrace'(nospy_(Spec)).
113
114nospy_(_:X) :-
115 var(X),
116 throw(error(instantiation_error, _)).
117nospy_(_:[]) :- !.
118nospy_(M:[H|T]) :-
119 !,
120 nospy(M:H),
121 nospy(M:T).
122nospy_(Spec) :-
123 prolog:debug_control_hook(nospy(Spec)),
124 !.
125nospy_(Spec) :-
126 '$find_predicate'(Spec, Preds),
127 '$member'(PI, Preds),
128 pi_to_head(PI, Head),
129 '$nospy'(Head),
130 fail.
131nospy_(_).
132
133nospyall :-
134 '$notrace'(nospyall_).
135
136nospyall_ :-
137 prolog:debug_control_hook(nospyall),
138 fail.
139nospyall_ :-
140 spy_point(Head),
141 '$nospy'(Head),
142 fail.
143nospyall_.
144
145pi_to_head(M:PI, M:Head) :-
146 !,
147 pi_to_head(PI, Head).
148pi_to_head(Name/Arity, Head) :-
149 functor(Head, Name, Arity).
150
154
155:- '$hide'(debugging/0). 156debugging :-
157 current_prolog_flag(debug, DebugMode),
158 '$notrace'(debugging_(DebugMode)).
159
160debugging_(DebugMode) :-
161 prolog:debug_control_hook(debugging(DebugMode)),
162 !.
163debugging_(DebugMode) :-
164 print_message(informational, debugging(DebugMode)),
165 ( DebugMode == true
166 -> findall(H, spy_point(H), SpyPoints),
167 print_message(informational, spying(SpyPoints))
168 ; true
169 ),
170 trapping,
171 forall(debugging_hook(DebugMode), true).
172
173spy_point(Module:Head) :-
174 current_predicate(_, Module:Head),
175 '$get_predicate_attribute'(Module:Head, spy, 1),
176 \+ predicate_property(Module:Head, imported_from(_)).
177
183
184:- multifile debugging_hook/1. 185
186
187 190
226
227:- dynamic
228 exception/4, 229 installed/1. 230
231trap(Error) :-
232 '$notrace'(trap_(Error)).
233
234trap_(Spec) :-
235 expand_trap(Spec, Formal),
236 gensym(ex, Rule),
237 asserta(exception(Rule, error(Formal, _), true, true)),
238 print_message(informational, trap(Rule, error(Formal, _), true, true)),
239 install_exception_hook,
240 debug.
241
242notrap(Error) :-
243 '$notrace'(notrap_(Error)).
244
245notrap_(Spec) :-
246 expand_trap(Spec, Formal),
247 Exception = error(Formal, _),
248 findall(exception(Name, Exception, NotCaught, Caught),
249 retract(exception(Name, error(Formal, _), Caught, NotCaught)),
250 Trapping),
251 print_message(informational, notrap(Trapping)).
252
253expand_trap(Var, _Formal), var(Var) =>
254 true.
255expand_trap(Alias, Formal), trap_alias(Alias, For) =>
256 Formal = For.
257expand_trap(Explicit, Formal) =>
258 Formal = Explicit.
259
263
264trap_alias(det, determinism_error(_Pred, _Declared, _Observed, property)).
265trap_alias(=>, existence_error(rule, _)).
266trap_alias(existence_error, existence_error(_,_)).
267trap_alias(type_error, type_error(_,_)).
268trap_alias(domain_error, domain_error(_,_)).
269trap_alias(permission_error, permission_error(_,_,_)).
270trap_alias(representation_error, representation_error(_)).
271trap_alias(resource_error, resource_error(_)).
272trap_alias(syntax_error, syntax_error(_)).
273
274trapping :-
275 findall(exception(Name, Term, NotCaught, Caught),
276 exception(Name, Term, NotCaught, Caught),
277 Trapping),
278 print_message(information, trapping(Trapping)).
279
280:- dynamic prolog:prolog_exception_hook/5. 281:- multifile prolog:prolog_exception_hook/5. 282
287
288:- public exception_hook/5. 289
290exception_hook(Ex, Ex, Frame, Catcher, _Debug) :-
291 thread_self(Me),
292 thread_property(Me, debug(true)),
293 broadcast(debug(exception(Ex))),
294 exception(_, Ex, NotCaught, Caught),
295 !,
296 ( Caught == true
297 -> true
298 ; Catcher == none,
299 NotCaught == true
300 ),
301 \+ direct_catch(Frame),
302 trace, fail.
303
309
310direct_catch(Frame) :-
311 prolog_frame_attribute(Frame, parent, Parent),
312 prolog_frame_attribute(Parent, predicate_indicator, system:catch/3),
313 prolog_frame_attribute(Frame, Level, MyLevel),
314 prolog_frame_attribute(Parent, Level, CatchLevel),
315 MyLevel =:= CatchLevel+1.
316
320
321install_exception_hook :-
322 installed(Ref),
323 ( nth_clause(_, I, Ref)
324 -> I == 1, ! 325 ; retractall(installed(Ref)),
326 erase(Ref), 327 fail
328 ).
329install_exception_hook :-
330 asserta((prolog:prolog_exception_hook(Ex, Out, Frame, Catcher, Debug) :-
331 exception_hook(Ex, Out, Frame, Catcher, Debug)), Ref),
332 assert(installed(Ref)).
333
334
335 338
339:- multifile
340 prolog:message//1. 341
342prolog:message(trapping([])) -->
343 [ 'No exception traps'-[] ].
344prolog:message(trapping(Trapping)) -->
345 [ 'Exception traps on'-[], nl ],
346 trapping(Trapping).
347prolog:message(trap(_Rule, Error, _Caught, _NotCaught)) -->
348 [ 'Installed trap for exception '-[] ],
349 exception(Error),
350 [ nl ].
351prolog:message(notrap([])) -->
352 [ 'No matching traps'-[] ].
353prolog:message(notrap(Trapping)) -->
354 [ 'Removed traps from exceptions'-[], nl ],
355 trapping(Trapping).
356
357trapping([]) --> [].
358trapping([exception(_Rule, Error, _Caught, _NotCaught)|T]) -->
359 [ ' '-[] ],
360 exception(Error),
361 [ nl ],
362 trapping(T).
363
364exception(Term) -->
365 { copy_term(Term, T2),
366 numbervars(T2, 0, _, [singletons(true)])
367 },
368 [ '~p'-[T2] ]