35
36:- module(pce_debug,
37 [ debugpce/0
38 , debugpce/1
39 , nodebugpce/0
40 , nodebugpce/1
41 , tracepce/1 42 , notracepce/1 43 , spypce/1 44 , nospypce/1 45 , checkpce/0 46 , show_slots/1 47 , pcerefer/1 48 , pcerefer/2 49 , pce_global_objects/1 50 ]). 51:- use_module(library(pce)). 52:- require([ forall/2
53 , pce_to_method/2
54 , append/3
55 , between/3
56 , genarg/3
57 ]). 58:- set_prolog_flag(generate_debug_info, false). 59:- meta_predicate test(0,-). 60
63
66
67debugpce :-
68 send(@pce, debugging, @on).
69nodebugpce :-
70 send(@pce, debugging, @off).
71
72
78
79debugpce(Subject) :-
80 send(@pce, debug_subject, Subject).
81
82nodebugpce(Subject) :-
83 send(@pce, nodebug_subject, Subject).
84
85
86
93
94tracepce(Spec) :-
95 method(Spec, Method),
96 send(Method, trace, full),
97 trace_feedback('Tracing', Method).
98
99notracepce(Spec) :-
100 !,
101 method(Spec, Method),
102 send(Method, trace, full, @off),
103 trace_feedback('Stopped tracing', Method).
104
108
109spypce(Spec) :-
110 method(Spec, Method),
111 send(Method, break, full),
112 ( prolog_method(Method)
113 -> debug
114 ; true
115 ),
116 trace_feedback('Spying', Method).
117
118nospypce(Spec) :-
119 method(Spec, Method),
120 send(Method, break, full, @off),
121 trace_feedback('Stopped spying', Method).
122
123method(Spec, Method) :-
124 pce_to_method(Spec, Method),
125 send(Method, instance_of, behaviour).
126
127
129
130prolog_method(Implementation) :-
131 send(Implementation, instance_of, method),
132 get(Implementation, message, Msg),
133 send(Msg, instance_of, c_pointer).
134
135trace_feedback(Action, Obj) :-
136 ( prolog_method(Obj)
137 -> Type = 'Prolog implementation of'
138 ; get(Obj?class_name, label_name, Type)
139 ),
140 get(Obj?context, name, ClassName),
141 get(Obj, name, Selector),
142 get(Obj, access_arrow, Arrow),
143 format('~w ~w: ~w ~w~w~n', [Action, Type, ClassName, Arrow, Selector]).
144
145
146 149
152
153pce_global_objects(Chain) :-
154 new(Chain, chain),
155 send(@pce, for_name_reference,
156 message(@prolog, '_append_reference', Chain, @arg1)).
157
158'_append_reference'(_, Name) :-
159 non_object_reference(Name),
160 !.
161'_append_reference'(Chain, Name) :-
162 send(Chain, '_append', @Name).
163
164non_object_reference('_object_to_itf_table').
165non_object_reference('_name_to_itf_table').
166non_object_reference('_handle_to_itf_table').
167
172
173checkpce :-
174 get(@pce, is_runtime_system, @on),
175 !,
176 send(checkpce, error, runtime_version).
177checkpce :-
178 test(check_pce_database, Status),
179 test(check_pce_types, Status),
180 test(check_classes, Status),
181 test(check_redefined_methods, Status),
182 Status = yes.
183
184check_classes :-
185 ( pce_expansion:compiling(_, _)
186 -> forall(pce_expansion:compiling(Class, Path),
187 ( file_base_name(Path, File),
188 send(@pce, format,
189 '[PCE: WARNING: definition of class \c
190 %s in ~s not closed]\n',
191 Class, File))),
192 fail
193 ; true
194 ).
195
196check_redefined_methods :-
197 findall(S, redefined_send_method(S), SL),
198 maplist(report_redefined_method, SL),
199 findall(G, redefined_get_method(G), GL),
200 maplist(report_redefined_method, GL),
201 SL == [],
202 GL == [].
203
204redefined_send_method(method(Class, Sel, B0, B1)) :-
205 pce_principal:pce_lazy_send_method(Sel, Class, B1),
206 ( pce_principal:pce_lazy_send_method(Sel, Class, B0)
207 -> B0 \== B1
208 ; fail
209 ).
210redefined_get_method(method(Class, Sel, B0, B1)) :-
211 pce_principal:pce_lazy_get_method(Sel, Class, B1),
212 ( pce_principal:pce_lazy_get_method(Sel, Class, B0)
213 -> B0 \== B1
214 ; fail
215 ).
216
217report_redefined_method(method(_, _, B0, B1)) :-
218 arg(1, B0, Id0), 219 arg(1, B1, Id1),
220 Id0 \== Id1,
221 !.
222report_redefined_method(method(Class, Sel, B0, B1)) :-
223 describe_location(B1, Loc1),
224 ( Loc1 = File:Line
225 -> Loc = file(File, Line)
226 ; true
227 ),
228 print_message(error,
229 error(pce(redefined_method(Class, Sel, B0, B1)),
230 Loc)).
231
232describe_location(Binder, File:Line) :-
233 genarg(_, Binder, source_location(File, Line)),
234 !.
235describe_location(_, '<no source>').
236
237
238check_pce_database :-
239 pce_global_objects(All),
240 send(All, '_check'),
241 send(All, done).
242
243check_pce_types :-
244 get(@pce, unresolved_types, Types),
245 get(Types, find_all,
246 message(@prolog, no_autoload_class, @arg1?context?print_name),
247 Unresolved),
248 ( send(Unresolved, empty)
249 -> true
250 ; send(@pce, format,
251 '[PCE: WARNING: The following type(s) have no associated class:\n'),
252 send(Unresolved, for_all,
253 message(@pce, format, '\t%N\n', @arg1)),
254 send(@pce, format, ']\n')
255 ).
256
257
258no_autoload_class(ClassName) :-
259 pce_prolog_class(ClassName), !, fail.
260no_autoload_class(ClassName) :-
261 pce_autoload:autoload_decl(ClassName, _), !, fail.
262no_autoload_class(_).
263
264
271
272show_slots(X) :-
273 get(X, '_class', Class),
274 get(Class, slots, Slots),
275 Max is Slots - 1,
276 X = @Ref,
277 get(X, '_class_name', ClassName),
278 format('@~w/~w~n', [Ref, ClassName]),
279 between(0, Max, Slot),
280 get(X, '_slot', Slot, Value),
281 get(Class, instance_variable, Slot, Var),
282 get(Var, name, Name),
283 format('~t~8|~w~t~30|~p~n', [Name, Value]),
284 fail ; true.
285
286
287 290
291pcerefer(Obj) :-
292 get(Obj, '_references', Refs),
293 format('~p has ~d references~n', [Obj, Refs]),
294 ( Refs > 0
295 -> pce_global_objects(All),
296 new(Found, number(0)),
297 send(All, for_slot_reference,
298 if(message(Obj, '_same_reference', @arg4),
299 message(@prolog, call,
300 pcerefer, Obj, @arg1, @arg2, @arg3, All, Found))),
301 send(All, done),
302 get(Found, value, FoundRefs),
303 ( Refs == FoundRefs
304 -> format('Found all references~n', [])
305 ; format('Found ~d of ~d references~n', [FoundRefs, Refs])
306 ),
307 free(Found)
308 ; true
309 ).
310
311
312pcerefer(From, Obj) :-
313 get(Obj, references, Refs),
314 format('~p has ~d references~n', [Obj, Refs]),
315 ( Refs > 0
316 -> new(Found, number(0)),
317 send(From, for_slot_reference,
318 if(Obj == @arg4,
319 message(@prolog, call,
320 pcerefer, Obj, @arg1, @arg2, @arg3, @nil, Found))),
321 free(Found)
322 ; true
323 ).
324
325:- public pcerefer/6. 326
327pcerefer(Obj, From, Type, Where, All, Found) :-
328 Obj \== All,
329 From \== All,
330 !,
331 get(From, '_class_name', ClassName),
332 format('~t~8|~w ~w of ~w/~w --> ~p~n',
333 [Type, Where, From, ClassName, Obj]),
334 send(Found, plus, 1).
335pcerefer(_, _, _, _, _, _).
336
337
338 341
342test(Goal, _) :-
343 Goal,
344 !.
345test(_, no).
346
347 350
351
352:- multifile
353 prolog:message/3. 354
355prolog:message(error(pce(redefined_method(Class, Sel, B0, B1)), _)) -->
356 { describe_location(B0, Loc0),
357 describe_location(B1, Loc1),
358 ( functor(B0, bind_send, _)
359 -> Arrow = (->)
360 ; Arrow = (<-)
361 )
362 },
363 [ '~w: ~w~w~w redefined'-[Loc1, Class, Arrow, Sel], nl,
364 '\tFirst definition at ~w'-[Loc0]
365 ]