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 set_spy_point(Head),
108 fail.
109spy_(_).
110
111set_spy_point(Head) :-
112 '$get_predicate_attribute'(Head, spy, 1),
113 !,
114 print_message(informational, already_spying(Head)).
115set_spy_point(Head) :-
116 '$spy'(Head).
117
118nospy(Spec) :-
119 notrace(nospy_(Spec)).
120
121nospy_(_:X) :-
122 var(X),
123 throw(error(instantiation_error, _)).
124nospy_(_:[]) :- !.
125nospy_(M:[H|T]) :-
126 !,
127 nospy(M:H),
128 nospy(M:T).
129nospy_(Spec) :-
130 prolog:debug_control_hook(nospy(Spec)),
131 !.
132nospy_(Spec) :-
133 '$find_predicate'(Spec, Preds),
134 '$member'(PI, Preds),
135 pi_to_head(PI, Head),
136 '$nospy'(Head),
137 fail.
138nospy_(_).
139
140nospyall :-
141 notrace(nospyall_).
142
143nospyall_ :-
144 prolog:debug_control_hook(nospyall),
145 fail.
146nospyall_ :-
147 spy_point(Head),
148 '$nospy'(Head),
149 fail.
150nospyall_.
151
152pi_to_head(M:PI, M:Head) :-
153 !,
154 pi_to_head(PI, Head).
155pi_to_head(Name/Arity, Head) :-
156 functor(Head, Name, Arity).
157
161
162:- '$hide'(debugging/0). 163debugging :-
164 current_prolog_flag(debug, DebugMode),
165 notrace(debugging_(DebugMode)).
166
167debugging_(DebugMode) :-
168 prolog:debug_control_hook(debugging(DebugMode)),
169 !.
170debugging_(DebugMode) :-
171 print_message(informational, debugging(DebugMode)),
172 ( DebugMode == true
173 -> findall(H, spy_point(H), SpyPoints),
174 print_message(informational, spying(SpyPoints))
175 ; true
176 ),
177 trapping,
178 forall(debugging_hook(DebugMode), true).
179
180spy_point(Module:Head) :-
181 current_predicate(_, Module:Head),
182 '$get_predicate_attribute'(Module:Head, spy, 1),
183 \+ predicate_property(Module:Head, imported_from(_)).
184
190
191:- multifile debugging_hook/1. 192
193
194 197
233
234:- dynamic
235 exception/4, 236 installed/1. 237
238trap(Error) :-
239 '$notrace'(trap_(Error)).
240
241trap_(Spec) :-
242 expand_trap(Spec, Formal),
243 gensym(ex, Rule),
244 asserta(exception(Rule, error(Formal, _), true, true)),
245 print_message(informational, trap(Rule, error(Formal, _), true, true)),
246 install_exception_hook,
247 debug.
248
249notrap(Error) :-
250 '$notrace'(notrap_(Error)).
251
252notrap_(Spec) :-
253 expand_trap(Spec, Formal),
254 Exception = error(Formal, _),
255 findall(exception(Name, Exception, NotCaught, Caught),
256 retract(exception(Name, error(Formal, _), Caught, NotCaught)),
257 Trapping),
258 print_message(informational, notrap(Trapping)).
259
260expand_trap(Var, _Formal), var(Var) =>
261 true.
262expand_trap(Alias, Formal), trap_alias(Alias, For) =>
263 Formal = For.
264expand_trap(Explicit, Formal) =>
265 Formal = Explicit.
266
270
271trap_alias(det, determinism_error(_Pred, _Declared, _Observed, property)).
272trap_alias(=>, existence_error(rule, _)).
273trap_alias(existence_error, existence_error(_,_)).
274trap_alias(type_error, type_error(_,_)).
275trap_alias(domain_error, domain_error(_,_)).
276trap_alias(permission_error, permission_error(_,_,_)).
277trap_alias(representation_error, representation_error(_)).
278trap_alias(resource_error, resource_error(_)).
279trap_alias(syntax_error, syntax_error(_)).
280
281trapping :-
282 findall(exception(Name, Term, NotCaught, Caught),
283 exception(Name, Term, NotCaught, Caught),
284 Trapping),
285 print_message(information, trapping(Trapping)).
286
287:- dynamic prolog:prolog_exception_hook/5. 288:- multifile prolog:prolog_exception_hook/5. 289
294
295:- public exception_hook/5. 296
297exception_hook(Ex, Ex, Frame, Catcher, _Debug) :-
298 thread_self(Me),
299 thread_property(Me, debug(true)),
300 broadcast(debug(exception(Ex))),
301 exception(_, Ex, NotCaught, Caught),
302 !,
303 ( Caught == true
304 -> true
305 ; Catcher == none,
306 NotCaught == true
307 ),
308 \+ direct_catch(Frame),
309 trace, fail.
310
316
317direct_catch(Frame) :-
318 prolog_frame_attribute(Frame, parent, Parent),
319 prolog_frame_attribute(Parent, predicate_indicator, system:catch/3),
320 prolog_frame_attribute(Frame, level, MyLevel),
321 prolog_frame_attribute(Parent, level, CatchLevel),
322 MyLevel =:= CatchLevel+1.
323
327
328install_exception_hook :-
329 installed(Ref),
330 ( nth_clause(_, I, Ref)
331 -> I == 1, ! 332 ; retractall(installed(Ref)),
333 erase(Ref), 334 fail
335 ).
336install_exception_hook :-
337 asserta((prolog:prolog_exception_hook(Ex, Out, Frame, Catcher, Debug) :-
338 exception_hook(Ex, Out, Frame, Catcher, Debug)), Ref),
339 assert(installed(Ref)).
340
341
342 345
346:- multifile
347 prolog:message//1. 348
349prolog:message(trapping([])) -->
350 [ 'No exception traps'-[] ].
351prolog:message(trapping(Trapping)) -->
352 [ 'Exception traps on'-[], nl ],
353 trapping(Trapping).
354prolog:message(trap(_Rule, Error, _Caught, _NotCaught)) -->
355 [ 'Installed trap for exception '-[] ],
356 exception(Error),
357 [ nl ].
358prolog:message(notrap([])) -->
359 [ 'No matching traps'-[] ].
360prolog:message(notrap(Trapping)) -->
361 [ 'Removed traps from exceptions'-[], nl ],
362 trapping(Trapping).
363
364trapping([]) --> [].
365trapping([exception(_Rule, Error, _Caught, _NotCaught)|T]) -->
366 [ ' '-[] ],
367 exception(Error),
368 [ nl ],
369 trapping(T).
370
371exception(Term) -->
372 { copy_term(Term, T2),
373 numbervars(T2, 0, _, [singletons(true)])
374 },
375 [ '~p'-[T2] ]