1 % (c) 2009-2019 Lehrstuhl fuer Softwaretechnik und Programmiersprachen,
2 % Heinrich Heine Universitaet Duesseldorf
3 % This software is licenced under EPL 1.0 (http://www.eclipse.org/org/documents/epl-v10.html)
4
5 :- module(tools_printing,[
6 print_term_summary/1, print_term_summary_hash/1,
7 print_term_summary_wo_nl/1,
8 print_functor/1,
9 print_var/1, print_vars/1,
10 watch/3,
11 trace_unify/2, trace_print/1, trace_print/2,
12 print_error/1,
13 print_message_on_output/2,
14 format_error/2,
15 print_red/2, print_red/1, print_green/1,
16 format_with_colour/4,
17 start_terminal_colour/2,
18 reset_terminal_colour/1,
19 print_time_stamp/1,
20 print_dynamic_pred/3, print_dynamic_fact/1,
21 print_goal/1,
22 nested_print_term/2
23 ]).
24
25
26 :- use_module(module_information).
27 :- module_info(group,infrastructure).
28 :- module_info(description,'This module contains printing/debug helper predicates.').
29
30 :- use_module(library(terms),[term_hash/2]).
31 print_term_summary_hash(T) :- print_term_summary(T),
32 term_hash(T,H), %% (H=179896960 -> trace ; true), %%
33 format('Hash = ~w~n',H).
34
35 %:- use_module(library(terms),[term_size/2]).
36 print_term_summary(T) :- print_term_summary_wo_nl(T),
37 %term_size(T,Sz), format(' term_size: ~w',[Sz]),
38 nl.
39
40 print_term_summary_wo_nl(N) :- var(N),!,print('VARIABLE: '),print(N).
41 print_term_summary_wo_nl((A,B)) :- print('('), print_term_summary_wo_nl(A),
42 print(','), print_term_summary_wo_nl(B),print(')').
43 print_term_summary_wo_nl(clpfd:Call) :- !, print(clpfd:Call).
44 print_term_summary_wo_nl(Module:Call) :- !,
45 print(Module), print(':'),print_term_summary_wo_nl(Call).
46 print_term_summary_wo_nl(bind(Var,Val)) :- !,print_arg(bind(Var,Val)).
47 print_term_summary_wo_nl(N) :- functor(N,F,Arity), print(F), print('/'),print(Arity),
48 N=..[F|Args], l_print_arg(Args).
49
50 l_print_arg(V) :- var(V),!, print('...').
51 l_print_arg([]).
52 l_print_arg([H|T]) :- print(': '), print_arg(H), l_print_arg(T).
53
54
55
56 :- use_module(library(avl)).
57 % USE MODULE NOT PERFORMED TO AVOID LOADING translate and all dependent modules
58 %:- use_module(translate,[print_bexpr_with_limit/2, print_bstate/1]).
59
60 print_arg(N) :- var(N),!,print_var(N).
61 print_arg(int(N)) :- !, (var(N) -> print_var_integer(N) ; print(int(N))).
62 print_arg(float(N)) :- !, print(float(N)).
63 print_arg(fd(N,GS)) :- !,
64 ((number(N),b_global_sets:is_b_global_constant(GS,N,Res)) -> print(Res)
65 ; print('fd('),print_integer(N),format(',~w)',GS)).
66 print_arg(rec(Fields)) :- !, print('rec('), print_arg(Fields),print(')').
67 print_arg(bind(Var,Val)) :- atomic(Var), !, print(Var),print('/'),print_arg(Val).
68 print_arg(field(Var,Val)) :- atomic(Var), !, print('field('),print(Var),print('/'),print_arg(Val),print(')').
69 print_arg(typedvalc(Val,Type,VarID,EnumWarning,Card)) :-
70 atomic(VarID), !, format('typedvalc for ~w :(',[VarID]),print_arg(Val),
71 format(',~w,~w,~w) ',[Type,EnumWarning,Card]).
72 print_arg(wfx(A,B,C,D)) :- !, print(wfx(A,B,C,D)).
73 print_arg(Module:Call) :- atomic(Module),!,
74 print(Module), print(':'),print_arg(Call).
75 print_arg(A) :- atomic(A),!, print(A).
76 print_arg(A) :- A=node(_,_,_,_,_),ground(A), !, print('AVLnode.size='),avl_size(A,Sz), print(Sz).
77 print_arg(avl_set(A)) :- ground(A), !,
78 (custom_explicit_sets:singleton_set(avl_set(A),El) -> print('AVL{'),print_arg(El),print('}')
79 ; avl_size(A,Sz),
80 (Sz>3 -> print('AVL.size='),print(Sz)
81 ; custom_explicit_sets:expand_custom_set_to_list(avl_set(A),ESet,_,print_arg),
82 print('AVL{'), l_print_arg(ESet), print('}')
83 )
84 ).
85 print_arg((A,B)) :- !, print('('),print_arg(A), print(','), print_arg(B), print(')').
86 print_arg(string(A)) :- !, print('string('),print_arg(A), print(')').
87 print_arg([]) :- !, print('[]').
88 print_arg([H|T]) :- T==[], !, print('['),print_arg(H),print(']').
89 print_arg([H|T]) :- nonvar(T),T=[H2|T2],T2==[], !,
90 print('['),print_arg(H),print(','),print_arg(H2),print(']').
91 print_arg([H|T]) :- nonvar(H), H=bind(_,_),!, get_list_up_to([H|T],10,S,ALL),
92 translate:print_bstate(S),
93 (ALL=all -> true ; print(', ... ')).
94 print_arg([H|T]) :- list_skeleton_size([H|T],Sz,Type), !,
95 print(Type),
96 ((Type=closed,ground([H|T])) -> print('&ground') ; true),
97 print(' LIST.size='), print(Sz),
98 (Sz<35 -> print(' ['), l_print_arg([H|T]), print(']') ; true).
99 print_arg(closure(P,T,B)) :- !, print('CLOSURE '),
100 (custom_explicit_sets:is_interval_closure(P,T,B,Low,Up) -> print([Low:Up])
101 ; print(P)). %, print(' | '), print(_B).
102 print_arg(mnf(Call)) :- !, print('mnf('),print_term_summary_wo_nl(Call), print(')').
103 print_arg(pp_mnf(Call)) :- !, print('mnf('),print_term_summary_wo_nl(Call), print(')').
104 print_arg(pp_cll(Call)) :- !, print('mnf('),print_term_summary_wo_nl(Call), print(')').
105 print_arg(b(Expr,T,I)) :- !,
106 (T==pred -> print('PRED(') ; print('BEXPR(')),
107 print_functor(Expr), print(','),
108 translate:print_bexpr_with_limit(b(Expr,T,I),200), print(')').
109 print_arg(span_predicate(A,B,C)) :-
110 error_manager:extract_line_col(span_predicate(A,B,C),Srow,Scol,Erow,Ecol), !,
111 format('span_predicate(~w:~w-~w:~w)',[Srow,Scol,Erow,Ecol]).
112 print_arg(N) :- print_functor(N).
113
114 :- use_module(library(clpfd),[fd_dom/2, fd_degree/2, fd_size/2]).
115 print_var(V) :- fd_dom(V,D), D \= inf..sup, fd_size(V,Sz), fd_degree(V,Dg),!,
116 format('INT VAR: ~w:~w [sz:~w,dg:~w] ',[V,D,Sz,Dg]).
117 %print(':('),frozen(V,Goal),write_term(Goal,[max_depth(3)]),print(')').
118 print_var(V) :- print('VARIABLE: '),print(V), print_frozen_var_info(V).
119 print_var_integer(X) :- print('int(?:'),fd_dom(X,Dom),print(Dom),
120 %print(':('),frozen(X,Goal),print(Goal),print(')')
121 print(')').
122
123 % try determine variable type from frozen info
124 print_frozen_var_info(V) :- frozen(V,G), (print_frozen_var_info2(G,V) -> true ; true).
125 print_frozen_var_info2((A,B),V) :- (print_frozen_var_info2(A,V) -> true ; print_frozen_var_info2(B,V)).
126 print_frozen_var_info2(b_interpreter_check:imply_true(_,_,_),_) :- print(' : BOOL').
127 print_frozen_var_info2(bool_pred:blocking_force_eq(V,_,_),Var) :- Var==V, print(' : BOOL').
128 print_frozen_var_info2(kernel_equality:eq_empty_set(V,_),Var) :- Var==V, print(' : SET').
129 % TO DO: add other co-routines for boolean values,...
130
131 :- use_module(library(lists),[maplist/2]).
132 print_vars(V) :- maplist(tools_printing:print_var,V),nl.
133
134 print_integer(I) :- (var(I) -> fd_dom(I,Dom), print('?:'),print(Dom) ; print(I)).
135
136 get_list_up_to([],_,[],all).
137 get_list_up_to([H|T],N,R,ALL) :-
138 (N<1 -> R=[],ALL=no ; N1 is N-1, R=[H|TR], get_list_up_to(T,N1,TR,ALL)).
139
140 list_skeleton_size(X,Sz,Type) :- var(X),!,Sz=0,Type=open.
141 list_skeleton_size([],0,closed).
142 list_skeleton_size([_|T],N,Type) :- list_skeleton_size(T,NT,Type), N is NT+1.
143
144
145 print_functor(N) :- var(N),!,print('VARIABLE: '),print(N).
146 print_functor(N) :- functor(N,F,Arity), print(F), print('/'),print(Arity).
147
148 % ---------------
149
150 :- block watch(-,?,?).
151 watch([],N,Pos) :- !,print_data([],N,Pos).
152 watch([H|T],N,Pos) :- !,print_data(H,N,Pos), P1 is Pos+1, watch(H,N,Pos), watch(T,N,P1).
153 watch((P1,P2),N,Pos) :- print_data((P1,P2),N,Pos), watch(P2,N,Pos).
154 watch(Other,N,Pos) :- print_data(Other,N,Pos).
155 print_data(Data,N,Pos) :- print(N), print(' @ '), print(Pos),print(' : '), print(Data),nl.
156
157 % ---------------
158
159 :- use_module(library(lists),[maplist/3]).
160 trace_unify(A,B) :- trace_unify_aux(A,B,0).
161 trace_unify_aux(A,B,Lvl) :- (var(A);var(B)),!,indent(Lvl),print(A),print(' <-> '), print(B),
162 if(A=B,true,(print(' FAILS'),nl,fail)),nl.
163 trace_unify_aux(A,B,Lvl) :- functor(A,FA,FAN), functor(B,FB,FBN),
164 indent(Lvl),print(FA/FAN),
165 A=..[_|As], B=..[_|Bs],
166 ((FA,FAN)=(FB,FBN)
167 -> (As=[] -> nl ; print('('),nl,l_trace_unify(As,Bs,Lvl))
168 ; format(' FUNCTOR MISMATCH : ~w/~w <-> ~w/~w~n',[FA,FAN,FB,FBN]),
169 maplist(abstract_top_level,As,AAs), AA =..[FA|AAs],
170 maplist(abstract_top_level,Bs,ABs), AB =..[FB|ABs],
171 indent(Lvl),
172 format(' TOP: ~w <-> ~w~n',[AA,AB]),
173 fail
174 ).
175 indent(0) :- !.
176 indent(X) :- X>0, print('+-'), X1 is X-1, indent(X1).
177
178 abstract_top_level(X,R) :- simple(X),!,R=X.
179 abstract_top_level(X,AX) :- functor(X,F,N), functor(AX,F,N).
180
181
182 l_trace_unify([],[],L) :- indent(L), print(')'),nl.
183 l_trace_unify([A|TA],[B|TB],Lvl) :- L1 is Lvl+1, trace_unify_aux(A,B,L1),
184 l_trace_unify(TA,TB,Lvl).
185
186 % ---------------
187
188 trace_print(A) :- trace_print(A,0,4).
189 trace_print(A,Max) :- trace_print(A,0,Max).
190
191 trace_print(A,Lvl,MaxLvl) :- Lvl >= MaxLvl,!, indent(Lvl), print(A),nl.
192 trace_print(A,Lvl,_MaxLvl) :- treat_as_atomic(A),!, indent(Lvl), print(A),nl.
193 trace_print([H|T],Lvl,MaxLvl) :- !, indent(Lvl), print('['),nl,
194 l_trace_print([H|T],Lvl,MaxLvl),
195 indent(Lvl), print(']'),nl.
196 %trace_print(A,Lvl,_MaxLvl) :- functor(A,_,1), arg(1,A,AN), atomic(AN),!, indent(Lvl), print(A),nl.
197 trace_print(A,Lvl,_MaxLvl) :- A=..[_|Args], maplist(atomic,Args),!,
198 indent(Lvl), print(A),nl.
199 trace_print(A,Lvl,MaxLvl) :- functor(A,FA,FAN),
200 indent(Lvl),print(FA/FAN),print('('),nl,
201 A=..[_|As], l_trace_print(As,Lvl,MaxLvl).
202
203 treat_as_atomic(A) :- var(A).
204 treat_as_atomic(A) :- atomic(A).
205 treat_as_atomic(nodeid(pos(_,_,_,_,_,_))).
206 treat_as_atomic(sharing(_,_,_,_)).
207 treat_as_atomic(ID/V) :- treat_as_atomic(ID),treat_as_atomic(V).
208 treat_as_atomic([H|T]) :- T==[], treat_as_atomic(H).
209
210 l_trace_print([],L,_MaxLvl) :- indent(L), print(')'),nl.
211 l_trace_print([A|TA],Lvl,MaxLvl) :- L1 is Lvl+1, trace_print(A,L1,MaxLvl),
212 l_trace_print(TA,Lvl,MaxLvl).
213
214 % -----------------------------------
215
216 % print on error stream
217 print_error(Error) :-
218 start_terminal_colour([red,bold],user_error),
219 call_cleanup(print_no_col(user_error,Error),reset_terminal_colour(user_error)).
220 %% flush_output(user_error), %%.
221 print_no_col(Stream,ErrorTerm) :-
222 write(Stream,'! '),
223 (var(ErrorTerm) -> write(Stream,'_')
224 ; write_term(Stream,ErrorTerm,[max_depth(20),numbervars(true)])),
225 nl(Stream).
226
227 print_message_on_output(Color,Message) :-
228 start_terminal_colour(Color,user_output),
229 call_cleanup(print_no_col(user_output,Message),reset_terminal_colour(user_output)).
230
231 format_error(Str,Args) :- format_with_colour(user_error,[red,bold],Str,Args).
232
233 format_with_colour(Stream,Colour,Str,Args) :-
234 start_terminal_colour(Colour,Stream),
235 call_cleanup(format(Stream,Str,Args),
236 reset_terminal_colour(Stream)).
237
238 :- load_files(library(system), [when(compile_time), imports([environ/2])]).
239 :- if(environ(no_terminal_colors,true)).
240 no_color.
241 print_red(X) :- write(X).
242 print_red(Stream,T) :- write(Stream,T).
243 print_green(X) :- write(X).
244 reset_terminal_colour(_).
245 start_terminal_colour(_,_).
246 :- else.
247 :- use_module(library(system),[environ/2]).
248 no_color :- environ('NO_COLOR',_). % see http://no-color.org
249 print_red(Stream,Term) :- no_color,!,
250 format(Stream,'~w',[Term]).
251 print_red(Stream,Term) :-
252 format(Stream,'\e[31m~w\e[0m',[Term]).
253
254 print_red(Term) :- no_color,!,
255 format('~w',[Term]).
256 print_red(Term) :-
257 format('\e[31m~w\e[0m',[Term]).
258
259 print_green(Term) :- no_color,!,
260 format('~w',[Term]).
261 print_green(Term) :-
262 format('\e[32m~w\e[0m',[Term]).
263
264 reset_terminal_colour(_) :- no_color,!.
265 reset_terminal_colour(Stream) :- write(Stream,'\e[0m').
266
267 % see https://misc.flogisoft.com/bash/tip_colors_and_formatting
268 start_terminal_colour(_,_) :- no_color,!.
269 start_terminal_colour(red,Stream) :- !, write(Stream,'\e[31m').
270 start_terminal_colour(green,Stream) :- !, write(Stream,'\e[32m').
271 start_terminal_colour(yellow,Stream) :- !, write(Stream,'\e[33m').
272 start_terminal_colour(blue,Stream) :- !, write(Stream,'\e[34m').
273 start_terminal_colour(magenta,Stream) :- !, write(Stream,'\e[35m').
274 start_terminal_colour(cyan,Stream) :- !, write(Stream,'\e[36m').
275 start_terminal_colour(light_gray,Stream) :- !, write(Stream,'\e[37m').
276 start_terminal_colour(dark_gray,Stream) :- !, write(Stream,'\e[90m').
277 start_terminal_colour(light_red,Stream) :- !, write(Stream,'\e[91m').
278 start_terminal_colour(light_green,Stream) :- !, write(Stream,'\e[92m').
279 start_terminal_colour(white,Stream) :- !, write(Stream,'\e[97m').
280 start_terminal_colour(bold,Stream) :- !, write(Stream,'\e[1m').
281 start_terminal_colour(underline,Stream) :- !, write(Stream,'\e[4m').
282 start_terminal_colour(dim,Stream) :- !, write(Stream,'\e[2m').
283 start_terminal_colour(black_background,Stream) :- !, write(Stream,'\e[49m').
284 start_terminal_colour(red_background,Stream) :- !, write(Stream,'\e[41m').
285 start_terminal_colour(green_background,Stream) :- !, write(Stream,'\e[42m').
286 start_terminal_colour(yellow_background,Stream) :- !, write(Stream,'\e[43m').
287 start_terminal_colour(white_background,Stream) :- !, write(Stream,'\e[107m').
288 start_terminal_colour(blink,Stream) :- !, write(Stream,'\e[5m').
289 start_terminal_colour(reverse,Stream) :- !, write(Stream,'\e[7m').
290 start_terminal_colour(hidden,Stream) :- !, write(Stream,'\e[8m').
291 start_terminal_colour(reset,Stream) :- !, write(Stream,'\e[0m').
292 start_terminal_colour([],_Stream) :- !.
293 start_terminal_colour([H|T],Stream) :- !, start_terminal_colour(H,Stream),start_terminal_colour(T,Stream).
294 start_terminal_colour(C,_Stream) :- format(user_error,'*** UNKNOWN COLOUR: ~w~n',[C]).
295 :- endif.
296
297 % -----------------------------------
298
299 :- use_module(library(system),[datime/1]).
300
301 print_time_stamp(Stream) :-
302 datime(datime(Year,Month,Day,Hour,Min,Sec)),
303 (Min<10
304 -> format(Stream,'~w/~w/~w - ~wh0~w ~ws',[Day,Month,Year,Hour,Min,Sec])
305 ; format(Stream,'~w/~w/~w - ~wh~w ~ws',[Day,Month,Year,Hour,Min,Sec])
306 ).
307
308 % -----------------------------------
309
310 print_dynamic_pred(InModule,Pred,N) :- nl,
311 write(':- dynamic '), print(Pred), write('/'),print(N), write('.'),nl,
312 functor(Call,Pred,N),
313 call(InModule:Call), write_term(Call,[quoted(true)]),write('.'),nl,fail.
314 print_dynamic_pred(InModule,Pred,N) :-
315 functor(Call,Pred,N),
316 (call(InModule:Call) -> true ; (write_with_numbervars(Call), write(' :- fail.'),nl)),
317 nl.
318
319 write_with_numbervars(Term) :- copy_term(Term,T), numbervars(T,0,_),
320 write_term(T,[quoted(true),numbervars(true)]).
321
322 print_dynamic_fact(Fact) :-
323 functor(Fact,Pred,N),
324 print(':- dynamic '), print(Pred), write('/'),print(N), write('.'),nl,
325 write_term(Fact,[quoted(true)]),write('.'),nl.
326
327 % -----------------------------------
328
329 print_goal(V) :- var(V),!, format(' ~w~n',[V]).
330 print_goal([A|B]) :- !,print_goal(A), print_goal(B).
331 print_goal((A,B)) :- !,print_goal(A), print_goal(B).
332 print_goal(A) :- format(' ~w~n',[A]).
333
334
335 % -----------------------------------
336
337 % possible applicaton: inspect size of terms transmitted to ProB2:
338 % prob2_interface:get_machine_formulas(Formulas), tell('formulasnest.pl'), nested_print_term(Formulas,6),told.
339
340 nested_print_term(Term,MaxNest) :- nested_print_term(0,MaxNest,Term).
341
342 indentws(0) :- !.
343 indentws(X) :- X>0, print(' '), X1 is X-1, indentws(X1).
344
345 :- use_module(library(terms),[term_size/2]).
346 nested_print_term(CurNesting,_Max,T) :- var(T),!, indent(CurNesting),write(T),nl.
347 nested_print_term(CurNesting,_,T) :- atom(T), atom_length(T,Len),
348 indent(CurNesting),
349 (Len > 100
350 -> atom_codes(T,Codes), length(Prefix,50), append(Prefix,_,Codes),
351 format('atom: len(~w): ~s...~n',[Len,Prefix])
352 ; format('~w~n',[T])).
353 nested_print_term(CurNesting,_,T) :- number(T), indent(CurNesting), format('~w~n',[T]).
354 nested_print_term(CurNesting,MaxNesting,T) :- CurNesting >= MaxNesting,!,
355 term_size(T,Sz), functor(T,F,N),
356 indentws(CurNesting),
357 (Sz>25000 -> Msg='****' ; Msg=''), format('~w/~w :: sz(~w)~w~n',[F,N,Sz,Msg]).
358 nested_print_term(CurNesting,MaxNesting,T) :-
359 list_skeleton_size(T,Len,closed), term_size(T,Sz),!,
360 indentws(CurNesting),format('[ list_len_sz(~w,~w)~n',[Len,Sz]),
361 C1 is CurNesting+1,
362 maplist(nested_print_term(C1,MaxNesting),T),
363 indentws(CurNesting),format('] list_len(~w)~n',[Len]).
364 nested_print_term(CurNesting,MaxNesting,T) :-
365 term_size(T,Sz), functor(T,F,N),
366 indentws(CurNesting),format('~w/~w( sz(~w)~n',[F,N,Sz]),
367 T =.. [_|Args], C1 is CurNesting+1,
368 maplist(nested_print_term(C1,MaxNesting),Args),
369 indentws(CurNesting),format('~w/~w)~n',[F,N]).
370
371