1 % (c) 2009-2026 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 %:- set_prolog_flag(source_info,on).
6 % comment in if you want source location, e.g., for exceptions,...
7 % you can also comment in a line in remove_debugging_calls in debugging_calls_te.pl to see location of nl/0
8 % (and ensure debugging_calls.pl is loaded below and in term_expansion hook is set in debugging_calls_te.pl)
9 % with ?- trace, leash(off). one can creep without entering return in the debugger; with leash([redo]) the debugger only stops at the Redo-Port. Use @<RETURN> to enter Prolog commands in the debugger.
10 % leash(exception) also useful
11 % Note: to run probcli from source for ProB2 change change probcli.sh: PROBCOMMAND=probproxy and start probsli -s 8888
12
13 :- module(prob_cli, [go_cli/0,
14 run_probcli/2, run_probcli_with_argv_string/1,
15 reset_cli/0, recognised_cli_option/4, recognised_option/2, go_proxy/0,
16 print_version/1, cli_print_statistics/1]).
17
18 :- set_prolog_flag(double_quotes, codes).
19
20 :- if(predicate_property(expects_dialect(_), _)).
21 :- expects_dialect(sicstus4).
22 :- endif.
23
24 :- multifile user:portray_message/2.
25 user:portray_message(informational, imported(_Nr,_M1,_M2)) :- !.
26 user:portray_message(informational, loading(_Nr,_,_File)) :- !.
27 %user:portray_message(informational, loaded(_Nr,compiled,_File,M,MS,_)) :- !, format('~w ms for ~w~n',[MS,M]).
28 user:portray_message(informational, loaded(_Nr,_CompiledLoaded,_File,_Module,_TimeMS,_Bytes)) :- !.
29 user:portray_message(informational, foreign_resource(_Nr,_Status,_File,_Mod)) :- !.
30 user:portray_message(informational, chr_banner) :- !.
31 %user:portray_message(informational, halt) :- !.
32 %user:portray_message(informational, prompt(off,0,user,off,off,off)) :- !.
33 %user:portray_message(informational, M) :- !, write(M),nl,nl.
34
35
36 :- meta_predicate if_option_set(-,0).
37 :- meta_predicate if_option_set(-,0,0).
38 :- meta_predicate if_options_set(-,0).
39 :- meta_predicate if_option_set_loaded(-,-,0).
40 :- meta_predicate ifm_option_set(-,0).
41 :- meta_predicate ifm_option_set(-,-,0).
42 :- meta_predicate ifm_option_set_loaded(-,-,0).
43
44
45 % patch for SICStus 4.3.3 performance issue
46 % sprm_14972_patch.pl BEGIN
47 :- if((current_prolog_flag(dialect, sicstus),
48 current_prolog_flag(version_data, sicstus(4,3,3,_,_)))).
49 prolog:wf_call_like_arg(A, B, C, D, E, F, G, H, I, _) :-
50 prolog:wellformed_body_iso(A, B, C, D, E, F, G, H, I, quiet),
51 !.
52 prolog:wf_call_like_arg(A, B, C, A, D, _, E, _, _, _) :-
53 F=E:A,
54 prolog:condense_layout(B, G),
55 prolog:comp_layout2(B, G, B, H),
56 C=call(F),
57 prolog:comp_layout1(B, H, D).
58 :- endif.
59 % sprm_14972_patch.pl END
60
61
62 %:- include('self_check_off.pl').
63
64 :- use_module(module_information).
65 :- module_info(group,cli).
66 :- module_info(description,'ProB start file in cli mode.').
67
68 %:- use_module(debugging_calls).
69 %:- register_debugging_calls([pp_mnf(*), pp_cll(*), mnf(*), mnf(-,*), det_call(*)]).
70 %:- disable_debugging_calls.
71
72 :- use_module(prob_startup, [startup_prob/0]).
73 %:- use_module(pathes,[set_search_pathes/0]). % called first to set_compile_time_search_pathes
74 :- use_module(tools,[string_concatenate/3,arg_is_number/2, print_memory_used_wo_gc/1, print_memory_used_wo_gc/0,
75 split_atom/3, get_options/5,
76 start_ms_timer/1, stop_ms_timer/1, stop_ms_timer/2, stop_ms_timer_with_msg/2]).
77 :- use_module(tools_printing,[print_error/1,format_with_colour/4, format_with_colour_nl/4]).
78 :- use_module(tools_strings,[atom_split/4,convert_atom_to_number/2]).
79 :- use_module(tools_meta,[safe_time_out/3]).
80 :- use_module(tools_lists,[count_occurences/2]).
81
82 :- use_module(preferences).
83 :- set_prob_application_type(probcli). %
84
85 :- use_module(library(lists)).
86 :- use_module(library(file_systems),[file_exists/1]).
87 :- use_module(library(system)).
88 :- use_module(library(codesio)).
89 :- use_module(library(between),[between/3]).
90 :- use_module(library(terms),[term_hash/2]).
91 :- use_module(library(random),[random/3, setrand/1]).
92
93 :- use_module(self_check,[disable_interaction_on_errors/0,
94 perform_self_check/2,turn_off_run_time_type_checks/0,turn_on_run_time_type_checks/0]).
95 :- use_module(debug).
96 :- use_module(error_manager).
97 :- use_module(translate,[pretty_type/2]).
98 :- use_module(tools,[safe_absolute_file_name/2, safe_absolute_file_name/3, convert_ms_time_to_string/2]).
99 :- use_module(extension('counter/counter'),
100 [counter_init/0, new_counter/1, get_counter/2, inc_counter/1, inc_counter/2, reset_counter/1]).
101 :- use_module(state_space,[current_expression/2]).
102
103
104 :- dynamic junit_mode/1.
105 :- use_module(junit_tests,[set_junit_dir/1, create_and_print_junit_result/4]).
106
107 :- use_module(b_trace_checking,[check_default_trace_for_specfile/1, tcltk_check_state_sequence_from_file/1,
108 tcltk_check_sequence_from_file/3, get_default_trace_file/3,
109 tcltk_save_history_as_trace_file/2,tcltk_save_history_as_trace_file/3]).
110 :- use_module(eventhandling,[store_virtual_event/1]).
111 :- use_module(bmachine,[b_set_initial_machine/0]).
112 :- use_module(specfile).
113 :- use_module(test_typechecker,[run_typecheck_testcase/2]).
114 :- use_module(basic_unit_tests). % basic unit tests
115 :- use_module(bsyntaxtree,[size_of_conjunction/2, get_texpr_id/2, get_texpr_description/2,
116 conjunction_to_list/2,
117 get_texpr_label/2, predicate_components/2, get_texpr_pos/2]).
118 :- use_module(bmachine,[b_write_machine_representation_to_file/3,
119 full_b_machine/1, b_write_eventb_machine_to_classicalb_to_file/1]).
120 :- use_module(state_space,[current_state_id/1, get_state_space_stats/4, compute_full_state_space_hash/1]).
121 :- use_module(xtl_interface,[set_cspm_main_process/1]).
122 :- use_module(extrasrc(meta_interface),[is_dot_command/1, call_dot_command_with_engine/4,
123 is_dot_command_for_expr/1,call_dot_command_with_engine_for_expr/5,
124 is_plantuml_command/1, is_plantuml_command_for_expr/1,
125 is_table_command/1, is_table_command_for_expr/1,
126 call_plantuml_command/2, call_plantuml_command_for_expr/4,
127 call_command/5, is_table_command/6, write_table_to_csv_file/3,
128 command_description/3]).
129 :- use_module(kodkodsrc(kodkod_test),[test_kodkod/1, compare_kodkod_performance/2]).
130 :- use_module(kodkodsrc(predicate_analysis),[test_predicate_analysis/0]).
131 :- use_module(b_show_history,[write_history_to_file/2,write_values_to_file/1,
132 write_all_values_to_dir/1,write_history_to_user_output/1]).
133 :- use_module(cbcsrc(sap), [write_all_deadlocking_paths_to_xml/1, test_generation_by_xml_description/1]).
134 :- use_module(smtlib_solver(smtlib2_cli),[smtlib2_file/2]).
135 :- use_module(disproversrc(disprover_test_runner), [run_disprover_on_all_pos/1,
136 load_po_file/1,print_disprover_stats/0, set_disprover_timeout/1,
137 set_disprover_options/1, reset_disprover_timeout/0]).
138 :- use_module(extrasrc(latex_processor), [process_latex_file/2]).
139 :- use_module(probltlsrc(ltl),[ltl_check_assertions/2,ltl_model_check/4]).
140 :- use_module(probltlsrc(ctl),[ctl_model_check/4]).
141
142 :- use_module(logger).
143 :- use_module(extension('zmq/master/master'),[start_master/8]).
144 :- use_module(extension('zmq/worker/worker'),[start_worker/5]).
145 :- use_module(extension('ltsmin/ltsmin'),
146 [start_ltsmin/4,ltsmin_init/3,ltsmin_loop/1,ltsmin_teardown/2,ltsmin_generate_ltlfile/2]).
147 :- use_module(extrasrc(coverage_statistics),[compute_the_coverage/5]).
148 :- use_module(value_persistance, [set_storage_directory/2, print_value_persistance_stats/0,
149 delete_cache_files_for_machine/1, delete_cache_files/0,
150 get_value_persistance_stats/1, show_cache_file_contents/1]).
151 :- use_module(prob_socketserver,[start_prob_socketserver/2]).
152 :- use_module(tcltk_interface).
153 %:- compile(gui_tcltk).
154 :- use_module(eclipse_interface).
155 :- use_module(prob2_interface,[start_animation/0, is_initialised_state/1, reset_animator/0,
156 set_eclipse_preference/2, update_preferences_from_spec/1,
157 load_cspm_spec_from_cspm_file/1, load_xtl_spec_from_prolog_file/1]).
158
159 start_probcli_timer(timer(T1,WT1)) :-
160 statistics(runtime,[T1,_]),
161 statistics(walltime,[WT1,_]).
162 stop_probcli_debug_timer(Timer,Msg) :-
163 (debug_mode(on) -> stop_probcli_timer(Timer,Msg),print_memory_used_wo_gc,nl ; true).
164 stop_probcli_timer(timer(T1,WT1),Msg) :- stop_probcli_timer(timer(T1,WT1),Msg,_).
165 stop_probcli_timer(timer(T1,WT1),Msg,WTotTime) :-
166 statistics(runtime,[T2,_]), TotTime is T2-T1,
167 statistics(walltime,[WT2,_]), WTotTime is WT2-WT1,
168 convert_ms_time_to_string(WT2,WTString),
169 format('~w ~w ms walltime (~w ms runtime), since start: ~w~n',[Msg,WTotTime,TotTime,WTString]),
170 !.
171 stop_probcli_timer(Timer,Msg,_) :- add_internal_error('Illegal timer call: ',stop_probcli_timer(Timer,Msg)).
172 print_total_probcli_timer :-
173 statistics(runtime,[T2,_]),
174 statistics(walltime,[WT2,_]),
175 format('Since start of probcli: ~w ms walltime (~w ms runtime)~n',[WT2,T2]).
176 get_probcli_elapsed_walltime(timer(_,WT1),WTotTime) :-
177 statistics(walltime,[WT2,_]), WTotTime is WT2-WT1.
178 get_probcli_elapsed_runtime(timer(RT1,_),RTotTime) :-
179 statistics(runtime,[RT2,_]), RTotTime is RT2-RT1.
180
181 :- meta_predicate timeout_call(0,-,-).
182 timeout_call(Call,NOW,PP) :- option(timeout(TO)),!,
183 statistics(runtime,[T1,_]),
184 safe_time_out(Call,TO,Res),
185 statistics(runtime,[T2,_]), Runtime is T2-T1,
186 formatsilent('Runtime for ~w: ~w ms~n',[PP,Runtime]),
187 (Res=time_out -> print('*** Timeout occurred: '), print(TO),nl,
188 print('*** Call: '), print(Call),nl,
189 nl,
190 writeln_log(timeout_occurred(NOW,Call))
191 ; true).
192 timeout_call(Call,_NOW,PP) :-
193 statistics(runtime,[T1,_]),
194 call(Call),
195 statistics(runtime,[T2,_]), Runtime is T2-T1,
196 formatsilent('Runtime for ~w: ~w ms~n',[PP,Runtime]).
197
198 set_junit_mode(X) :-
199 set_junit_dir(X),
200 retractall(junit_mode(_)),
201 statistics(runtime,[Start,_]),
202 assertz(junit_mode(Start)).
203
204 go_proxy :-
205 catch( run_probcli(['-s','8888'],[proxy]), halt(ExitCode),
206 ( nl,write('CLI halt prevented, exit code '),write(ExitCode),nl) ).
207
208 go_cli :-
209 % set_prob_application_type(probcli) is already done at compile_time
210 current_prolog_flag(argv,ArgV),
211 run_probcli_with_junit_check(ArgV).
212
213 initialise_cli :- counter_init,
214 new_counter(cli_execute_inits),
215 new_counter(cli_errors), new_counter(cli_warnings),
216 new_counter(cli_expected_errors),
217 new_counter(eval_string_nr).
218
219 % called from test_runner.pl:
220 reset_cli :-
221 announce_event(clear_specification),
222 announce_event(reset_prob),
223 reset_cli_options,
224 reset_expected_error_occurred,
225 reset_optional_errors_or_warnings,
226 reset_counter(cli_errors), reset_counter(cli_warnings),
227 reset_counter(cli_expected_errors),
228 reset_counter(eval_string_nr),
229 retractall(accumulated_infos(_,_,_)),
230 retractall(merged_individual_file_infos(_,_,_)),
231 retractall(individual_file_infos(_,_,_)),
232 (file_loaded(_)
233 -> clear_loaded_machines, % TODO: also treat by reset_prob eventhandling?
234 retractall(file_loaded(_,_)),
235 retractall(loaded_main_file(_,_))
236 ; true).
237
238 reset_cli_options :- option_verbose,verbose_off,fail.
239 reset_cli_options :- option(set_gc_trace(_X)),set_gc_trace(off),fail.
240 reset_cli_options :- option(profiling_on),profiling_off,fail.
241 % TODO: are there more options to reset?
242 reset_cli_options.
243
244 run_probcli_with_junit_check(ArgV) :-
245 catch( run_probcli(ArgV,[junit]),
246 halt(ExitCode),
247 ( ExitCode = 0 ->
248 true
249 ; ( junit_mode(S) ->
250 statistics(runtime,[E,_]), T is E - S,
251 create_and_print_junit_result(['Integration Tests'],ArgV,T,error([ExitCode]))
252 ; true),
253 throw(halt(ExitCode)))).
254
255
256 % a useful entry point for Jupyter to mimic probcli execution in notebooks
257 run_probcli_with_argv_string(ArgVAtom) :- split_argv_string(ArgVAtom,Atoms),
258 (Atoms = [probcli|Atoms2] -> true ; Atoms2=Atoms),
259 run_probcli(Atoms2,[run_probcli_with_argv_string]).
260
261 split_argv_string(ArgVAtom,Atoms) :- split_atom(ArgVAtom,[' '],Atoms). % TODO: treat quoting
262
263 run_probcli(ArgV,Context) :- % format(user_output,'~n* Starting probcli with argv: ~w~n~n',[ArgV]),
264 (catch(
265 run_probcli2(ArgV),
266 Exc,
267 process_exception(Exc,Context)
268 )
269 -> true
270 ; flush_output,
271 print_error('INTERNAL ERROR OCCURRED (run_probcli failed) !'),nl,
272 error_occurred(internal_error),
273 halt_exception(1)
274 ).
275
276 :- use_module(translate,[translate_error_term/2]).
277 %process_exception(Exception,_) :- write('Exception: '),write(Exception),nl,fail. % for debugging
278 process_exception(halt(A),_) :- !, throw(halt(A)).
279 process_exception('$aborted',_) :- !, throw('$aborted'). % thrown by SWI-Prolog on abort by user
280 process_exception(user_interrupt_signal,Context) :- !,
281 %add_error(probcli,'probcli interrupted by user (CTRL-C)').
282 statistics(walltime,[WStart,_]),
283 format_with_colour_nl(user_error,[red],'~nprobcli interrupted by user (CTRL-C), total walltime ~w ms',[WStart]),
284 (member(test_runner,Context)
285 -> throw(user_interrupt_signal) % will be caught by test_runner
286 ; error_occurred_with_msg(user_interrupt_signal,'probcli interrupted by user (CTRL-C)')
287 ).
288 process_exception(Exc,_) :-
289 (translate_error_term(Exc,S)
290 -> format_error_with_nl('Uncaught exception in probcli: ~w',[S])
291 ; true),
292 error_occurred(internal_error(exception(Exc))),fail.
293
294 no_command_issued :- \+ command_option(_).
295 command_option(X) :- option(X), \+ not_command_option(X).
296 not_command_option(verbose(_)).
297 not_command_option(profiling_on).
298 not_command_option(set_pref(_,_)).
299 not_command_option(set_preference_group(_,_)).
300 not_command_option(set_card(_,_)).
301 not_command_option(set_argv(_)).
302 not_command_option(silent).
303 not_command_option(strict_raise_error).
304 not_command_option(no_color).
305
306 probcli_startup :-
307 %print_total_probcli_timer,
308 startup_prob, % % startup_prob will already call init_preferences
309 %myheap_init,
310 initialise_cli.
311
312 :- load_files(library(system), [when(compile_time), imports([environ/2])]).
313 :- if(environ(prob_logging_mode,true)).
314 cli_set_options(ArgV,RemArgV) :-
315 cli_init_options(['-ll'|ArgV],RemArgV). %% adds -ll to have an automatically logging probcli to /tmp/prob_cli_debug.log
316 :- else.
317 cli_set_options(ArgV,RemArgV) :- cli_init_options(ArgV,RemArgV).
318 :- endif.
319
320 %:- use_module(extension('myheap/myheap')).
321 run_probcli2(ArgV) :- %print(probcli_startup),nl_time,
322 treat_important_options_beforehand(ArgV),
323 probcli_startup,
324 external_functions:reset_argv,
325 cli_set_options(ArgV,RemArgV), % recognise command-line options
326 %% cli_set_options(['-vv','-version'|ArgV],RemArgV), %% comment in to have an automatically verbose probcli
327 maplist(prob_cli:check_atom_looks_like_file,RemArgV),
328 (option(prolog_trace) -> error_manager:safe_trace ; true),
329 !,
330 run_probcli3(ArgV,RemArgV).
331
332 % treat important options beforehand, e.g., to enable debug prints straight-away, e.g., before probcli_startup
333 treat_important_options_beforehand(ArgV) :-
334 ? member(Opt,ArgV),recognised_option(Opt,RecognisedOpt),treat_important_option(RecognisedOpt),fail.
335 treat_important_options_beforehand(_).
336
337 treat_important_option(verbose(Nr)) :- verbose(Nr).
338 treat_important_option(set_gc_trace(X)) :- set_gc_trace(X).
339 treat_important_option(profiling_on) :- profiling_on.
340
341
342 run_probcli3(ArgV,RemArgV) :-
343 ( RemArgV=[File],no_command_issued,
344 get_filename_extension(File,Ext),
345 \+ do_not_execute_automatically(Ext)
346 % then assume we want to do -execute_all:
347 -> assert_option(execute(2147483647,false,current_state(1)))
348 ; true),
349 if_option_set(set_application_type(PAT),set_prob_application_type(PAT)),
350 if_option_set(test_mode,set_random_seed_to_deterministic_start_seed, set_new_random_seed),
351 ifm_option_set(verbose(VN),
352 verbose(VN), %tcltk_turn_debugging_on(5)),
353 tcltk_turn_debugging_off),
354 % TODO: reset the next three to default values if no flags present, in case we use them for tests:
355 if_option_set(set_gc_trace(GCT),set_gc_trace(GCT)),
356 if_option_set(set_gc_margin(GCM),set_gc_margin(GCM)),
357 if_option_set(set_gc_on_off(GCO),set_gc_on_off(GCO)),
358 if_option_set(profiling_on,profiling_on),
359 debug_print(9,'Command Line Arguments: '),debug_println(9,ArgV),
360 (debug_level_active_for(5) -> print_options ; true),
361 debug_print(6,'Command Line File Args: '),debug_println(6,RemArgV),
362 debug_flush_output,
363 if_option_set(cache_storage(StorageDir,SetStorMode), set_storage_directory(StorageDir,SetStorMode)),
364 if_option_set(parsercp(ParserLoc),
365 (add_message(parsercp,'Command -parcercp PATH deprecated, use -p JAVA_PARSER_PATH PATH',''),
366 set_preference(path_to_java_parser,ParserLoc))
367 ),
368 if_option_set(parserport(ParserPort),
369 connect_to_external_console_parser_on_port(ParserPort)),
370 generate_time_stamp(Datime,NOW),
371 if_option_set(log(LogF,Mode),
372 cli_start_logging(LogF,Mode,NOW,Datime,RemArgV)),
373 if_option_set(runtimechecking,
374 turn_on_run_time_type_checks,
375 turn_off_run_time_type_checks),
376 if_option_set(junit(JUX),
377 set_junit_mode(JUX)),
378 set_prefs,
379 (option_verbose, (option(set_prefs_from_file(_)) ; option(set_preference_group(_,_))),
380 get_non_default_preferences(list(NDPrefs))
381 -> format('Non-default preferences:~n',[]),print_list(NDPrefs),nl ; true),
382 set_optional_errors,
383 check_unavailable_options,
384 cli_show_help(ArgV,RemArgV),
385 if_option_set(set_argv(ArgVStr),
386 set_argv(ArgVStr)),
387 if_option_set(selfcheck(_,_),
388 cli_start_selfcheck),
389 if_option_set(typechecker_test(Filename),
390 (run_typecheck_testcase(Filename,typesok) -> halt_prob(NOW,0); halt_prob(NOW,1))),
391 if_option_set(install_prob_lib(LIBTOINSTALL,INSTALLOPTS), install_prob_lib(LIBTOINSTALL,INSTALLOPTS)),
392 if_options_set(print_version(VERSIONKIND), print_version(VERSIONKIND)),
393 if_option_set(check_java_version, check_java_version),
394 (debug_level_active_for(5) -> preferences:print_preferences ; true),
395 if_option_set(zmq_worker(Identifier), zmq_start_worker(Identifier, NOW)),
396 %if_option_set(zmq_worker2(MasterIP, Port, ProxyID, Logfile), zmq_start_worker(MasterIP,Port,ProxyID,Logfile,NOW)),
397 % process remaining arguments as files to load
398 % some utility commands which do not require main file:
399 ifm_option_set(indent_b_file_to_file(PPBFILE0,OUTFILE,OPTS),
400 indent_b_file_to_file(PPBFILE0,OUTFILE,OPTS)), % utility to format B file
401 ifm_option_set(pretty_print_prolog_file(PPFILE0,OUTFILE),
402 pretty_print_prolog_file(PPFILE0,OUTFILE)), % utility to print Prolog file
403 debug_println(6,processing(RemArgV)),
404 cli_load_files(RemArgV,NOW), % all CLI arguments which are not understood are supposed to be files to be treated
405 debug_println(19,finished_loading(RemArgV)),
406 if_option_set(socket(Port,Loopback),
407 cli_start_socketserver(Port,Loopback)),
408 % check_all_expected_errors_occurred(NOW), % is now checked for each file; socket_server should not generate errors ?
409 debug_println(20,'% probcli execution finished'),
410 cli_print_junit_results(ArgV),
411 debug_println(20,'% Stored Junit results'),
412 stop_xml_probcli_run(NOW),
413 debug_println(20,'% ProB Finished').
414
415 % finish logxml file by writing total number of errors and warnings
416 stop_xml_probcli_run(NOW) :-
417 get_counter(cli_errors,CErrs), get_counter(cli_warnings,CWarns), get_counter(cli_expected_errors,EErrs),
418 writeln_log_time(prob_finished(NOW,CErrs,CWarns)),
419 (EErrs>0
420 -> write_xml_element_to_log('probcli-errors',[errors/CErrs,warnings/CWarns,expected_errors/EErrs])
421 ; write_xml_element_to_log('probcli-errors',[errors/CErrs,warnings/CWarns])
422 ),
423 ((CErrs>0 ; CWarns>0) -> format(user_error,'! Total Errors: ~w, Warnings:~w~n',[CErrs,CWarns]) ; true),
424 stop_xml_group_in_log('probcli-run'). % Generating this tag means probcli ran to completion without segfault,...
425
426 % check if a cli argument looks like a proper filename
427 :- public check_file_arg/2. % is actually called when parsing options
428 check_file_arg(File,Command) :- normalise_option_atom(File,NF),
429 recognised_option(NF,_,_,_),!,
430 ajoin(['Command-line file argument for ', Command, ' looks like another probcli command: '],Msg),
431 add_warning(probcli,Msg,File).
432 check_file_arg(File,Command) :-
433 tools:check_filename_arg(File,Command).
434
435 % check if a remaining argument looks suspicious (e.g., like an unknown command)
436 check_atom_looks_like_file(Number) :- number(Number),!,
437 add_warning(probcli,'Command-line argument is a number (expected file name or probcli command): ',Number).
438 check_atom_looks_like_file(File) :- atom_codes(File,Codes),
439 check_codes_look_like_file(Codes,File).
440 check_codes_look_like_file(Codes,Arg) :-
441 check_codes_resembles_command(Codes,Arg),!.
442 check_codes_look_like_file([D|T],Arg) :- D >= 0'0, D =< 0'9,
443 nonmember(0'/,T), % detect things like 01_Jan/a.mch
444 !,
445 add_message(probcli,'Command-line argument looks like a number: ',Arg).
446 check_codes_look_like_file(_,_).
447
448 check_codes_resembles_command([45|_],Arg) :- !,
449 (get_possible_fuzzy_match_options(Arg,FuzzyMatches),
450 FuzzyMatches \= []
451 -> (FuzzyMatches=[FM]
452 -> ajoin(['Command-line argument ', Arg, ' looks like a probcli command! Did you mean: '],Msg),
453 add_warning(probcli,Msg,FM)
454 ; ajoin(['Command-line argument ', Arg, ' looks like a probcli command! Did you mean any of: '],Msg),
455 add_warning(probcli,Msg,FuzzyMatches)
456 )
457 ; get_possible_options_completion_msg(Arg,Completions)
458 -> ajoin(['Command-line argument ', Arg, ' looks like a probcli command! Did you mean: '],Msg),
459 add_warning(probcli,Msg,Completions)
460 ; add_message(probcli,'Command-line argument looks like an unknown probcli command: ',Arg)).
461
462 :- use_module(extrasrc(refinement_checker),[valid_failures_model/2]).
463 check_failures_mode(Shortcut,FailuresModel) :- valid_failures_model(FailuresModel,Shortcut),!.
464 check_failures_mode(Shortcut,trace) :-
465 add_warning(probcli,'Unrecognised refinement model flag (must be F, FD, T, R, RD, SF, V, VD; using default trace model T): ',Shortcut).
466
467 % ----------
468
469 cli_init_options(ArgV,RemArgV) :- %print(argv(ArgV)),nl,
470 append(ProBArgV,['--'|BArgV],ArgV),!, % pass arguments after -- to B via external_functions
471 cli_init_options2(ProBArgV,RemArgV),
472 debug_println(20,set_argv_from_list(BArgV)),
473 external_functions:set_argv_from_list(BArgV).
474 cli_init_options(ArgV,RemArgV) :- cli_init_options2(ArgV,RemArgV).
475 cli_init_options2(ArgV,RemArgV) :-
476 reset_options,
477 %%assertz(option(log('/tmp/ProBLog.log'))), print('LOGGING'),nl, %% coment in to build a version of probcli that automatically logs
478 ( get_options(ArgV,recognised_cli_option,Options,RemArgV,throw(halt(1))) ->
479 assert_all_options(Options)
480 ;
481 print_error(get_options_failed(ArgV)),definite_error_occurred).
482 cli_show_help(ArgV,RemArgV) :-
483 ( (option(help) ; ArgV=[]) ->
484 print_help, (RemArgV=[] -> halt_exception ; true)
485 ; true).
486 cli_start_logging(F,Mode,NOW,Datime,RemArgV) :-
487 debug_print(20,'%logging to: '), debug_println(20,F),
488 set_log_file(F), set_logging_mode(Mode),
489 start_xml_group_in_log('probcli-run'),
490 writeln_log(start_logging(NOW,F)),
491 version(V1,V2,V3,Suffix), revision(Rev), lastchangeddate(LCD),
492 writeln_log(version(NOW,V1,V2,V3,Suffix,Rev,LCD)), % still used by log_analyser
493 current_prolog_flag(version,PV),
494 write_xml_element_to_log(version,[major/V1,minor/V2,patch/V3,suffix/Suffix,revision/Rev,lastchanged/LCD,prolog/PV]),
495 findall(Opt, option(Opt), Options),
496 write_prolog_term_as_xml_to_log(options(NOW,Options)),
497 write_prolog_term_as_xml_to_log(files(NOW,RemArgV)), %
498 datime(Datime,DateRecord),
499 writeln_log(date(NOW,DateRecord)),
500 (DateRecord=datime(Yr,Mon,Day,Hr,Min,Sec)
501 -> write_xml_element_to_log(date,[year/Yr,month/Mon,day/Day,hour/Hr,minutes/Min,seconds/Sec]) ; true).
502
503 cli_start_selfcheck :-
504 %clear_loaded_machines_wo_errors,
505 b_set_initial_machine,
506 set_animation_mode(b),
507 store_virtual_event(clear_specification), % TO DO: try and get rid of the need for this
508 start_animation,
509 option(selfcheck(ModuleCombo,Opts)),
510 (atom(ModuleCombo),
511 atom_split(Module,':',TestNrA,ModuleCombo)
512 -> convert_atom_to_number(TestNrA,TestNr),
513 Opts2=[run_only_nr(TestNr)|Opts]
514 ; Module=ModuleCombo, Opts2=Opts
515 ),
516 (option(silent) -> Opts3=[silent|Opts2] ; option_verbose -> Opts3=[verbose|Opts2] ; Opts3=Opts2),
517 (perform_self_check(Module,Opts3) -> true ; error_occurred(selfcheck)),
518 fail.
519 cli_start_selfcheck.
520
521
522 :- dynamic file_loaded/2.
523 file_loaded(Status) :- file_loaded(Status,_File).
524
525
526 cli_load_files([],NOW) :- % no files are provided
527 !,
528 ( options_allow_start_without_file
529 -> debug_format(19,'Using empty machine to process probcli command~n',[]),
530 cli_set_empty_machine
531 ; we_did_something -> true
532 ; print('No file to process'),nl),
533 writeln_log_time(start_processing_empty_machine(NOW)),
534 start_xml_feature(process_file,filename,'$EMPTY_MACHINE',FINFO),
535 cli_process_loaded_file(NOW,'$EMPTY_MACHINE'),
536 check_all_expected_errors_occurred(NOW), % check that all expected errors occurred; below they will be checked for each file
537 stop_xml_feature(process_file,FINFO),
538 (option(benchmark_info_csv_output(_,_,_)) -> print_accumulated_infos(0) ; true).
539 cli_load_files(RemArgV,NOW) :-
540 cli_load_files2(RemArgV,NOW,0).
541
542
543 cli_set_empty_machine :- % TO DO: do this more properly here and for initialise_required
544 set_animation_mode(b),
545 bmachine:b_set_empty_machine,
546 assertz(file_loaded(true,'$$empty_machine')).
547
548 empty_machine_loaded :- file_loaded(true,'$$empty_machine').
549
550
551 options_allow_start_without_file :- option(run_benchmark(_,_,_)).
552 options_allow_start_without_file :- option(eval_repl(_)).
553 options_allow_start_without_file :- option(eval_string_or_file(_,_,_,_,_)).
554 options_allow_start_without_file :- option(check_log(_)).
555 options_allow_start_without_file :- option(process_latex_file(_,_)).
556 options_allow_start_without_file :- option(socket(_,_)).
557
558 we_did_something :- option(print_version(_)).
559 we_did_something :- option(check_java_version).
560 we_did_something :- option(check_parser_version).
561 we_did_something :- option(install_prob_lib(_,_)).
562 we_did_something :- option(indent_b_file_to_file(_,_,_)).
563 we_did_something :- option(pretty_print_prolog_file(_,_)).
564
565 option_only_works_for_single_file(zmq_assertion(_Identifier)).
566 option_only_works_for_single_file(zmq_master(_Identifier)).
567
568 clear_loaded_files :-
569 (file_loaded(_) -> clear_loaded_machines_wo_errors ; true).
570
571 % called if we have at least one file
572 cli_load_files2([],_,NrFilesProcessed) :- !,
573 debug_println(19,finished_procesing_all_files(NrFilesProcessed)),
574 print_accumulated_infos(NrFilesProcessed). % print summary of all runs for different files
575 cli_load_files2([F1,F2|T],NOW,_NrFilesProcessed) :-
576 option(Option),
577 option_only_works_for_single_file(Option),!,
578 add_error(probcli,'The following option can only be used for a single file: ',Option),
579 add_error(probcli,'Multiple files provided: ',[F1,F2|T]),
580 halt_prob(NOW,0).
581 cli_load_files2(RemArgV,NOW,NrFilesProcessed) :-
582 %print_total_probcli_timer,
583 clear_loaded_files,
584 retractall(file_loaded(_,_)),
585 RemArgV = [MainFile0|Rest],!,
586 N1 is NrFilesProcessed+1,
587 cli_load_files3(MainFile0,Rest,NOW,N1).
588 cli_load_files3(MainFile0,Rest,NOW,NrOfFile) :-
589 safe_absolute_file_name(MainFile0,MainFile,[access(none)]), % converts Windows slash into Unix slash,...
590 if_option_set(file_info,print_file_info(MainFile)),
591 ((Rest=[_|_] ; NrOfFile>1)
592 -> length(Rest,RLen), Tot is NrOfFile+RLen,
593 format('~n~n% Processing file ~w/~w: ~w~n',[NrOfFile,Tot,MainFile]) % was formatsilent
594 ; true),
595 start_xml_feature(process_file,filename,MainFile,FINFO),
596 ( file_exists(MainFile) ->
597 debug_println(6,file_exists(MainFile)),
598 ( load_main_file(MainFile,NOW,Already_FullyProcessed) ->
599 (Already_FullyProcessed==true
600 -> true
601 ; assertz(file_loaded(true,MainFile)),
602 trimcore_if_useful(Rest),
603 writeln_log_time(start_processing(NOW)),
604 start_probcli_timer(Timer),
605 catch((cli_process_loaded_file(NOW,MainFile)
606 -> stop_probcli_debug_timer(Timer,'% Finished processing file after')
607 ; print_error('Processing or loading file failed: '), print_error(MainFile),
608 start_repl_even_after_failure
609 ),
610 user_interrupt_signal, % catch CTRL-C by user but give chance to enter REPL
611 start_repl_even_after_failure
612 ),
613 writeln_log_time(finished_processing(NOW))
614 )
615 ;
616 assertz(file_loaded(error,MainFile)),
617 print_error('Loading Specification Failed'),
618 writeln_log_time(loading_failed(NOW,MainFile)),
619 error_occurred(load_main_file)
620 %start_repl_even_after_failure : TODO: fix issues with bmachine not precompiled and counter extension
621 ),
622 nls,
623 ifm_option_set(indent_main_b_file(PPFILE0),
624 indent_main_b_file(PPFILE0)),
625 ifm_option_set(pretty_print_prolog_file(PPFILE0),
626 pretty_print_prolog_file(PPFILE0))
627 ; % not file_exists
628 nl, assertz(file_loaded(error,MainFile)),
629 (number(MainFile0)
630 -> add_error(load_main_file,'Command-line argument is a number which is not associated with a command and does not exist as file: ',MainFile0)
631 ; atom_codes(MainFile0,[45|_]) % starts with a dash - : probably an illegal command-line option
632 -> add_error(load_main_file,'Specified option or file does not exist: ',MainFile0)
633 ; get_filename_extension(MainFile,Ext), \+ known_spec_file_extension(Ext,_)
634 -> (Ext = '' -> EMsg = 'Specified file does not exist and has no file extension:'
635 ; ajoin(['Specified file does not exist and has an unrecognised file extension ".',Ext,'" :'], EMsg)
636 ),
637 add_error(load_main_file,EMsg,MainFile)
638 ; add_error(load_main_file,'Specified file does not exist:',MainFile)
639 )
640 ),
641 check_all_expected_errors_occurred(NOW),
642 stop_xml_feature(process_file,FINFO),
643
644 debug_println(19,reset_expected_error_occurred),
645 reset_expected_error_occurred, % reset for next file
646 debug_println(19,resetting_errors),
647 reset_errors,
648 debug_println(19,update_time_stamp),
649 NOW1 is NOW+1,
650 update_time_stamp(NOW1),
651 debug_println(19,remaining_files_to_process(Rest)),
652 cli_load_files2(Rest,NOW1,NrOfFile).
653
654 start_repl_even_after_failure :-
655 (option(eval_repl([]))
656 -> format_with_colour_nl(user_output,[blue],'Starting REPL, but ignoring any other commands',[]),
657 % TODO: check if setup_constants_fails and then suggest e.g. :core @PROPERTIES command
658 start_repl_if_required % can be useful to debug properties, e.g, one can fix an error and reload
659 ; true
660 ).
661
662 print_file_info(F) :-
663 print('Specification_File('), print(F), print(')'),nl.
664
665 :- use_module(probsrc(tools),[statistics_memory_used/1]).
666 trimcore_if_useful(_) :- option(release_java_parser),!, prob_trimcore.
667 % if user wants to release java parser, this is an indication that the .prob files are big and it can be good to free memory
668 trimcore_if_useful([]) :- % try and reduce Prologs memory consumption, see also PROLOGKEEPSIZE parameter
669 % a lot of memory can be consumed loading .prob file and doing machine construction
670 !,
671 (option(X), memory_intensive_option(X)
672 -> debug_format(9,'Not trimming memory usage because of memory intensive option: ~w~n',[X])
673 ; statistics_memory_used(M), M< 300000000 % less than 300 MB used
674 -> debug_format(9,'Not trimming memory usage because of memory used is already low: ~w~n',[M])
675 ; prob_trimcore
676 ).
677 trimcore_if_useful(_) :- debug_println(9,'Not trimming memory usage as there are still files to process').
678
679 prob_trimcore :- (option_verbose ; option(release_java_parser)),!,prob_trimcore_verbose.
680 prob_trimcore :- prob_trimcore_silent.
681
682 prob_trimcore_verbose :-
683 print('Memory used before trimming: '),print_memory_used_wo_gc,flush_output, nl_time,
684 prob_trimcore_silent,
685 print('Memory used after trimming : '),print_memory_used_wo_gc,flush_output, nl_time.
686 prob_trimcore_silent :-
687 garbage_collect, % is important, otherwise trimming may achieve very little
688 trimcore.
689
690 memory_intensive_option(cli_mc(_)).
691 memory_intensive_option(ltl_formula_model_check(_,_)).
692 memory_intensive_option(ctl_formula_model_check(_,_)).
693 memory_intensive_option(pctl_formula_model_check(_,_)).
694 memory_intensive_option(refinement_check(_,_,_)).
695 memory_intensive_option(generate_all_traces_until(_,_,_)).
696
697 % ---------------------
698
699 % process all the commands for a loaded file:
700 cli_process_loaded_file(NOW,MainFile) :-
701 (real_error_occurred -> print_error('% *** Errors occurred while loading ! ***'),nl,nl ; true),
702 get_errors, reset_errors,
703 if_option_set(kodkod_performance(KPFile,Iterations),
704 compare_kodkod_performance1(KPFile,Iterations,NOW)),
705 if_option_set(kodkod_comparision(MaxResiduePreds),
706 test_kodkod_and_exit(MaxResiduePreds,NOW)),
707 % if_option_set(add_csp_guide(CspGuide), tcltk_add_csp_file(CspGuide)), %% moved to later to ensure B machine is precompiled; allows e.g. type_check_csp_and_b to run
708
709 if_option_set(csp_main(MAINPROC),
710 set_cspm_main_process(MAINPROC)),
711
712 if_option_set(zmq_master(Identifier), zmq_start_master(invariant,Identifier)),
713 %if_option_set(zmq_master(IP, Logfile), zmq_start_master(invariant,200,-1,5000,0,IP,Logfile)),
714
715 ifm_option_set(check_machine_file_sha(FileToCheck,ExpectedSha1Hash),
716 check_machine_file_sha(FileToCheck,ExpectedSha1Hash)),
717 ifm_option_set(clear_value_persistance_cache(MachineToClear),
718 delete_cache_files_for_machine(MachineToClear)),
719 ifm_option_set(clear_value_persistance_cache,
720 delete_cache_files),
721
722 % STARTING ANIMATION/MODEL CHECKING
723 cli_start_animation(NOW),
724
725 if_option_set_loaded(cli_core_properties(MaxCoreSize),cli_core_properties,
726 cli_core_properties(MaxCoreSize)),
727
728 if_option_set_loaded(default_trace_check,default_trace_check,
729 cli_start_default_trace_check(MainFile)),
730 if_option_set_loaded(trace_check(TrStyle,TraceFile,ChkMode),trace_check,
731 cli_start_trace_check(TrStyle,TraceFile,ChkMode)),
732
733 cli_process_loaded_file_afer_start_animation(NOW).
734
735 cli_process_loaded_file_afer_start_animation(NOW) :-
736 ifm_option_set(cli_print_machine_info(IKind),
737 cli_print_machine_info(IKind)),
738 ifm_option_set(pretty_print_internal_rep(PPFILE1,MachName1,TYPES1,ASCII1),
739 pretty_print_internal_rep(PPFILE1,MachName1,TYPES1,ASCII1)),
740 ifm_option_set(pretty_print_internal_rep_to_B(PPFILE3),
741 b_write_eventb_machine_to_classicalb_to_file(PPFILE3)),
742
743 if_option_set_loaded(state_trace(TraceFile),state_trace,
744 cli_start_trace_state_check(TraceFile)),
745
746 if_option_set(evaldot(EvalDotF),
747 set_eval_dot_file(EvalDotF)),
748
749 (initialise_required
750 -> check_loaded(initialise),
751 cli_start_initialisation(NOW),
752 writeln_log_time(initialised(NOW))
753 ; true),
754 if_option_set(check_abstract_constants,
755 check_abstract_constants),
756
757 if_option_set(zmq_assertion(Identifier),
758 zmq_start_master(assertion,Identifier)),
759
760 if_option_set(cli_lint,cli_lint(_)),
761 ifm_option_set_loaded(cli_lint(LintCheck),cli_lint,cli_lint(LintCheck)),
762 if_option_set(cli_wd_check(Disch,TotPos),cli_wd_check(Disch,TotPos)),
763 if_option_set(cli_wd_inv_proof(UnchangedNr,ProvenNr,TotPOsNr),cli_wd_inv_proof(UnchangedNr,ProvenNr,TotPOsNr)),
764 if_option_set(cli_start_mc_with_tlc,cli_start_mc_with_tlc),
765 if_option_set(cli_start_sym_mc_with_lts(LType),cli_start_sym_mc_with_lts(LType)),
766
767 if_option_set(cli_symbolic_model_check(Algorithm),cli_symbolic_model_check(Algorithm)),
768
769 if_option_set_loaded(cli_check_properties,check_properties,
770 cli_check_properties(NOW)),
771 ifm_option_set_loaded(cli_check_assertions(ALL,ReqInfos),check_assertions,
772 cli_check_assertions(ALL,ReqInfos,NOW)),
773 if_option_set(set_goal(GOAL),
774 cli_set_goal(GOAL)),
775 if_option_set(set_searchscope(SCOPE),
776 cli_set_searchscope(SCOPE)),
777 ifm_option_set_loaded(cli_mc(Nr,MCOpts),model_check,
778 cli_start_model_check(Nr,NOW,MCOpts)),
779 ifm_option_set_loaded(cli_simulate(File,Reps,Steps,SimOpts),simulate,
780 cli_simulate(File,Reps,Steps,SimOpts)),
781 ifm_option_set_loaded(cli_random_animate(Steps,ErrOnDeadlock),animate,
782 cli_random_animate(NOW,Steps,ErrOnDeadlock)),
783 ifm_option_set_loaded(execute(ESteps,ErrOnDeadlock,From),execute,
784 cli_execute(ESteps,ErrOnDeadlock,From)),
785 ifm_option_set_loaded(animate_until_ltl(LTLFormula,ExOption,ExpResult,ExpSteps),execute,
786 animate_until_ltl(LTLFormula,ExOption,ExpResult,ExpSteps)),
787 if_option_set_loaded(pa_check,predicate_analysis,
788 test_predicate_analysis),
789
790 cbc_check(NOW),
791
792 ifm_option_set_loaded(logxml_write_ids(Prefix,IDScope),logxml_write_ids,
793 logxml_write_ids(Prefix,IDScope)),
794
795 if_options_set(generate_read_write_matrix_csv(RWCsvFile),
796 generate_read_write_matrix(RWCsvFile)),
797 if_options_set(feasibility_analysis_csv(TimeOut,EnablingCsvFile),
798 do_feasibility_analysis(TimeOut,EnablingCsvFile)),
799 ifm_option_set_loaded(mcm_tests(ADepth1,AMaxS,ATarget1,Output1),mcm_test_cases,
800 mcm_test_case_generation(ADepth1,AMaxS,ATarget1,Output1)),
801 ifm_option_set_loaded(all_deadlocking_paths(File),all_deadlocking_paths,
802 write_all_deadlocking_paths_to_xml(File)),
803 ifm_option_set_loaded(cbc_tests(ADepth2,ATarget2,Output2),cb_test_cases,
804 cbc_test_case_generation(ADepth2,ATarget2,Output2)),
805 ifm_option_set_loaded(test_description(TestDescFile),cb_test_cases,
806 test_generation_by_xml_description(TestDescFile)),
807 if_options_set(csp_in_situ_refinement_check(RP,RType,RQ),
808 cli_csp_in_situ_refinement_check(RP,RType,RQ,NOW)),
809 if_options_set(csp_checkAssertion(Proc,Model,AssertionType),
810 cli_checkAssertion(Proc,Model,AssertionType,NOW)),
811 if_options_set(check_csp_assertion(Assertion),
812 cli_check_csp_assertion(Assertion,NOW)),
813 if_options_set(refinement_check(RefFile,FailuresModel,RefNrNodes),
814 cli_start_refinement_check(RefFile,FailuresModel,RefNrNodes,NOW)),
815 if_options_set(ctl_formula_model_check(CFormula,CExpected),
816 (timeout_call(cli_ctl_model_check(CFormula,init,CExpected,_),NOW,ctl_model_check) -> true; true)),
817 if_options_set(pctl_formula_model_check(PFormula,PExpected),
818 (timeout_call(cli_pctl_model_check(PFormula,init,PExpected,_),NOW,ctl_model_check) -> true; true)),
819 % TO DO print ctl/ltl statistics
820 if_options_set(csp_get_assertions,cli_csp_get_assertions),
821 if_options_set(eval_csp_expression(CspExpr),cli_eval_csp_expression(CspExpr)),
822 if_options_set(csp_translate_to_file(PlFile),cli_csp_translate_to_file(PlFile)),
823 if_options_set(get_coverage_information(CovFileName),cli_get_coverage_information(CovFileName)), %% TODO: replace
824 if_options_set(vacuity_check,cli_vacuity_check),
825 if_option_set_loaded(check_goal,check_goal,cli_check_goal),
826 if_option_set_loaded(animate,animate,
827 (interactive_animate_machine -> true ; true)),
828 if_option_set(ltsmin, start_ltsmin_srv('/tmp/ltsmin.probz', NOW)),
829 if_option_set(ltsmin2(EndpointPath), start_ltsmin_srv(EndpointPath, NOW)),
830 if_option_set(ltsmin_ltl_output(Path), ltsmin_ltl_output(Path, NOW)),
831 if_options_set(run_benchmark(Kind,Option,Path), run_benchmark(Kind,Option,Path)),
832 evaluate_from_commandline,
833 if_option_set_loaded(ltl_assertions,check_ltl_assertions,
834 (timeout_call(ltl_check_assertions,NOW,check_ltl_assertions) -> true; true)),
835 ifm_option_set_loaded(ltl_formula_model_check(LFormula,LExpected),check_ltl_assertions,
836 (option(cli_start_sym_mc_with_lts(_))-> true % we request LTSMin, do not start prob model check
837 ; timeout_call(cli_ltl_model_check(LFormula,init,LExpected,_),NOW,ltl_formula_model_check)
838 -> true; true)),
839 ifm_option_set_loaded(ltl_file(LtlFilename),check_ltl_file,
840 (ltl_check_file(LtlFilename) -> true; true)),
841 ifm_option_set_loaded(visb_history(VJSONFile,VHTMLFile,Options),visb,
842 cli_visb_history(VJSONFile,VHTMLFile,Options)),
843 ifm_option_set_loaded(history(HistoryFilename),history,
844 cli_print_history(HistoryFilename)),
845 ifm_option_set_loaded(print_values(ValuesFilename),sptxt,
846 cli_print_values(ValuesFilename)),
847 ifm_option_set_loaded(print_all_values(ValuesDirname),print_all_values,
848 cli_print_all_values(ValuesDirname)),
849 ifm_option_set_loaded(generate_all_traces_until(LTL_Stop_AsAtom,FilePrefix),generate_all_traces_until,
850 cli_generate_all_traces_until(LTL_Stop_AsAtom,FilePrefix)),
851 if_options_set(save_state_for_refinement(SaveRefF),
852 tcltk_save_specification_state_for_refinement(SaveRefF)),
853 if_options_set(rule_report(File),
854 rule_validation:generate_report(File)),
855 if_options_set(proof_export(Style,File),
856 sequent_prover_exports:export_proof_for_current_state(Style,File)),
857 if_options_set(dot_command(DCommand1,DotFile1,DotEngine1),
858 dot_command(DCommand1,DotFile1,DotEngine1)),
859 if_options_set(dot_command_for_expr(DECommand,Expr,DotFile,Opts,DotEngine),
860 dot_command_for_expr(DECommand,Expr,DotFile,Opts,DotEngine)),
861 if_options_set(plantuml_command(PCommand1,UmlFile1),
862 plantuml_command(PCommand1,UmlFile1)),
863 if_options_set(plantuml_command_for_expr(PECommand,Expr,UmlFile,Opts),
864 plantuml_command_for_expr(PECommand,Expr,UmlFile,Opts)),
865 if_options_set(csv_table_command(TECommand,TableFormulas,TableOptions,TableCSVFile),
866 csv_table_command(TECommand,TableFormulas,TableOptions,TableCSVFile)),
867 if_options_set(evaluate_expression_over_history_to_csv_file(HistExpr,HistDotFile),
868 tcltk_interface:evaluate_expression_over_history_to_csv_file(HistExpr,HistDotFile)),
869 if_options_set(enabling_analysis_csv(EnablingCsvFile),
870 do_enabling_analysis_csv(EnablingCsvFile,NOW)),
871 if_options_set(process_latex_file(LatexF1,LatexF2),
872 process_latex_file(LatexF1,LatexF2)),
873 ifm_option_set(coverage(Nodes,Operations,ShowEnabledInfo),
874 cli_show_coverage(Nodes,Operations,ShowEnabledInfo,NOW)),
875 ifm_option_set(check_statespace_hash(ExpectedHash,Kind),
876 cli_check_statespace_hash(ExpectedHash,Kind)),
877 ifm_option_set(check_op_cache(ExpectedC),
878 cli_check_op_cache(ExpectedC)),
879 ifm_option_set(coverage(ShowEnabledInfo),
880 cli_show_coverage(ShowEnabledInfo,NOW)),
881 if_option_set(save_state_space(StateFile),
882 save_state_space(StateFile)),
883 ifm_option_set(cli_print_statistics(SPARA),
884 cli_print_statistics(SPARA)),
885 if_option_set(show_cache(SCVM),
886 show_cache(SCVM)),
887 if_option_set(cli_cache_stats_check(CStats),cli_cache_stats_check(CStats)),
888 if_option_set(check_complete, check_complete),
889 if_option_set(check_complete_operation_coverage, check_complete_operation_coverage),
890 if_option_set(check_scc_for_ltl_formula(LtlFormula,SCC),cli_check_scc_for_ltl_formula(LtlFormula,SCC)).
891
892 % what needs to be done for files like .po files, where all processing is already done:
893 cli_process_options_for_alrady_fully_processed_file(_MainFile) :-
894 ifm_option_set(cli_print_statistics(SPARA),
895 cli_print_statistics(SPARA)).
896
897 show_cache(default) :- !,
898 (option_verbose -> show_cache(normal) ; show_cache(verbose)).
899 show_cache(Verbose) :-
900 show_cache_file_contents(Verbose).
901
902 cli_cache_stats_check(Expected) :-
903 get_value_persistance_stats(Stats),
904 check_required_infos(Expected,Stats,check_cache_stats).
905
906 % new profiler
907 %:- use_module('../extensions/profiler/profiler.pl').
908 %cli_print_statistics :- pen,nl,garbage_collect,statistics,nl,state_space:state_space_initialise_with_stats.
909
910 :- use_module(runtime_profiler,[print_runtime_profile/0]).
911 :- use_module(source_profiler,[print_source_profile/0]).
912 :- use_module(memoization,[print_memo_profile/0]).
913 :- use_module(state_packing,[print_state_packing_profile/0]).
914 :- use_module(external_functions,[print_external_function_instantiation_profile/0]).
915
916 % old profiler
917 :- use_module(covsrc(hit_profiler),[print_hit_profile_statistics/0]).
918 :- use_module(extrasrc(b_operation_cache),[print_op_cache_profile/0, reset_b_operation_cache_with_statistics/0]).
919 :- use_module(memoization,[reset_memo_with_statistics/0]).
920 :- use_module(disproversrc(disprover),[print_prover_result_stats/0]).
921 :- use_module(probsrc(tools),[print_mb/1]).
922 cli_print_statistics(hshow) :- !,
923 print_machine_topological_order.
924 cli_print_statistics(memory) :- !,
925 print_memory_statistics(user_output).
926 cli_print_statistics(value_persistance_stats) :- !,
927 print_value_persistance_stats.
928 cli_print_statistics(sicstus_profile) :- !,
929 format('SICStus Prolog PROFILE STATISTICS~n',[]),
930 sicstus_profile_statistics.
931 cli_print_statistics(disprover_profile) :- !,
932 print_prover_result_stats.
933 cli_print_statistics(prob_profile) :- !,
934 statistics(walltime,[WT,_]),
935 statistics(runtime,[RT,_]),
936 format('--------------------------~nPROB PROFILING INFORMATION after ~w ms walltime (~w ms runtime) ',[WT,RT]),
937 statistics_memory_used(M), print_mb(M),nl,
938 print_source_profile,
939 print_runtime_profile,
940 print_memo_profile,
941 print_state_packing_profile,
942 print_external_function_instantiation_profile,
943 (get_preference(operation_reuse_setting,false) -> true ; print_op_cache_profile). % relevant for test 2152 under SWI
944 cli_print_statistics(hit_profile) :- !,
945 (print_hit_profile_statistics -> true ; true). % mainly used by external functions
946 cli_print_statistics(op_cache_profile) :- !,
947 get_preference(try_operation_reuse,OR),
948 format('PROB OPERATION_REUSE (value:~w) STATISTICS~n',[OR]),
949 print_op_cache_profile.
950 cli_print_statistics(simb_profile) :- !,
951 print_simb_profile.
952 cli_print_statistics(full) :- format('PROB FULL STATISTICS~n',[]),
953 sicstus_profile_statistics,
954 garbage_collect,
955 statistics,
956 nl,
957 print_op_cache_profile,
958 print_prover_result_stats,
959 state_space:state_space_initialise_with_stats,
960 reset_memo_with_statistics,
961 reset_b_operation_cache_with_statistics.
962
963 print_memory_statistics(Stream) :-
964 garbage_collect,
965 write(Stream,'ProB memory used: '),
966 print_memory_used_wo_gc(Stream), nl(Stream), flush_output(Stream).
967
968 sicstus_profile_statistics :-
969 %(hit_profiler:print_hit_profile_statistics -> true ; true), % only used by external functions
970 (option(profiling_on)
971 -> catch(print_profile,
972 error(existence_error(_,_),_),
973 print_red('SICStus Prolog Profiler can only be used when running from source'))
974 ; true).
975
976
977 :- use_module(state_space,[not_all_transitions_added/1, not_invariant_checked/1,
978 not_interesting/1, get_operation_name_coverage_infos/4]).
979 check_complete :-
980 (tcltk_find_max_reached_node(Node1) ->
981 add_error(check_complete,'Maximum number of transitions reached for at least one state: ',Node1) ; true),
982 (not_all_transitions_added(Node2) ->
983 add_error(check_complete,'At least one state was not examined: ',Node2) ; true),
984 (not_invariant_checked(Node3) ->
985 add_error(check_complete,'The invariant was not checked for at least one state: ',Node3) ; true),
986 (not_interesting(Node4) ->
987 add_message(check_complete,'At least one state was ignored (not satisfying the SCOPE predicate): ',Node4) ; true).
988
989 check_complete_operation_coverage :-
990 (state_space: operation_name_not_yet_covered(OpName) ->
991 add_error(check_complete_operation_coverage,'At least one operation is not covered: ', OpName)
992 ; true).
993
994 show_operation_coverage_summary(NOW) :-
995 get_operation_name_coverage_infos(PossibleNr,FeasibleNr,UncovNr,UncoveredList),
996 writeln_log(uncovered_info(NOW,PossibleNr,UncoveredList)),
997 (UncovNr=0 -> format(' All ~w possible operations have been covered',[PossibleNr]),nl
998 ; (FeasibleNr=PossibleNr
999 -> format(' The following ~w operations (out of ~w) were not covered:~n ~w~n',
1000 [UncovNr, PossibleNr,UncoveredList])
1001 ; INr is PossibleNr-FeasibleNr,
1002 format(' The following ~w operations (out of ~w with ~w infeasible) were not covered:~n ~w~n',
1003 [UncovNr, PossibleNr, INr,UncoveredList])
1004 )).
1005 show_initialisation_summary(NOW) :-
1006 findall(ID,state_space:is_concrete_constants_state_id(ID),L),
1007 length(L,Nr), N1 is Nr+1, % for root
1008 writeln_log(uninitialised_states(NOW,N1)),
1009 format(' Uninitialised states: ~w (root and constants only)~n',[N1]).
1010
1011 % ---------------------
1012
1013 animation_mode_does_not_support_animation(File) :-
1014 loaded_main_file(smt2,File).
1015 cli_start_animation(NOW) :-
1016 file_loaded(true,LoadedFile),
1017 \+ animation_mode_does_not_support_animation(LoadedFile),
1018 !,
1019 debug_println(20,'% Starting Animation'),
1020 writeln_log_time(start_animation(NOW)),
1021 start_probcli_timer(Timer1),
1022 start_animation_without_computing,
1023 stop_probcli_debug_timer(Timer1,'% Finished Starting Animation'),
1024 if_option_set(add_csp_guide(CspGuide), tcltk_add_csp_file(CspGuide)),
1025
1026 xml_log_machine_statistics,
1027 getAllOperations(Ops),
1028 debug_print(20,'Operations: '), debug_println(20,Ops),
1029
1030 (we_need_only_static_assertions(ALL)
1031 -> debug_println(20,'% Projecting on static ASSERTIONS'),
1032 b_interpreter:set_projection_on_static_assertions(ALL) ; true),
1033
1034 (option(load_state(File))
1035 -> debug_println(20,'% Loading stored state from file'),
1036 state_space:tcltk_load_state(File)
1037 ; computeOperations_for_root_required ->
1038 debug_println(20,'% Searching for valid initial states'),
1039 start_probcli_timer(Timer2),
1040 cli_computeOperations(EO),
1041 stop_probcli_debug_timer(Timer2,'% Finished searching for valid initial states'),
1042 debug_println(10,EO)
1043 ; debug_println(20,'% No initialisation required')
1044 ).
1045 cli_start_animation(_NOW).
1046
1047 start_animation_without_computing :-
1048 update_preferences_from_spec(ListOfPrefs),
1049 (ListOfPrefs=[] -> true ; write_prolog_term_as_xml_to_log(b_machine_preferences(ListOfPrefs))),
1050 set_prefs, % override SET_PREF in DEFINITIONS with values from command-line;
1051 start_animation,
1052 ifm_option_set(add_additional_property(PROP),
1053 cli_add_additional_property(PROP)),
1054 get_errors.
1055
1056 animate_until_ltl(LTLFormula,ExOption,ExpectedResult,ExpectedNrSteps) :-
1057 tcltk_animate_until(LTLFormula,ExOption,StepsExecuted,Result),
1058 formatsilent('Found trace of length ~w for LTL formula. Result: ~w ~n',[StepsExecuted,Result]),
1059 print_history_as_counter_example(false), % TODO: only print from current id before command
1060 (ExpectedResult=Result -> true % Result can be ltl_found, maximum_nr_of_steps_reached, deadlock
1061 ; add_error(animate_until_ltl,'Unexpected animation result: ',Result),
1062 error_occurred(animate_until_ltl)
1063 ),
1064 (ExpectedNrSteps=StepsExecuted -> true
1065 ; add_error(animate_until_ltl,'Unexpected number of animation steps: ',StepsExecuted),
1066 error_occurred(animate_until_ltl)
1067 ).
1068
1069 % ---------------------
1070
1071 % an execution engine with minimal overhead: states are not stored in visited_expression database, only first enabled operation is taken
1072
1073 cli_execute(Steps,ErrorOnDeadlock,FromWhere) :-
1074 temporary_set_preference(operation_reuse_setting,false,ChangeOccured),
1075 (ChangeOccured=true % operation reuse not compatible with cut used below after solution found
1076 -> add_debug_message(execute_model,'Disabling OPERATION_REUSE preference for -execute ',Steps) ; true),
1077 call_cleanup(cli_execute2(Steps,ErrorOnDeadlock,FromWhere),
1078 reset_temporary_preference(operation_reuse_setting,ChangeOccured)).
1079 cli_execute2(Steps,ErrorOnDeadlock,FromWhere) :-
1080 FromWhere=from_all_initial_states,!,
1081 % try out all initial states and from each of those perform deterministic execution
1082 start_ms_timer(Start),
1083 format('Running execute from all initial states~n',[]),
1084 reset_counter(cli_execute_inits),
1085 findall(Result,
1086 (cli_trans(root,Action,CurState,0,'$NO_OPERATION'), %print(Action),nl,
1087 (\+ functor(Action,'$setup_constants',_)
1088 -> inc_counter(cli_execute_inits,Nr),
1089 format('~nExecuting model from initial state ~w~n',[Nr]),
1090 (option(animate_stats) -> print_state_silent(CurState) ; true),
1091 (cli_execute_from(CurState,Steps,ErrorOnDeadlock,1,Result) -> true)
1092 ; format('~nInitialising state~n',[]), % we need to execute initialise_machine
1093 cli_trans(CurState,_ActionName,NewState,0,'$NO_OPERATION'),
1094 inc_counter(cli_execute_inits,Nr),
1095 format('~nExecuting model from initial state ~w with constants~n',[Nr]),
1096 (option(animate_stats) -> print_state_silent(NewState) ; true),
1097 (cli_execute_from(NewState,Steps,ErrorOnDeadlock,2,Result) -> true)
1098 )), Results),
1099 get_counter(cli_execute_inits,Nr),
1100 format('---------~nTotal runtime for all ~w executions:',[Nr]),nl,
1101 stop_ms_timer(Start),
1102 count_occurences(Results,Occs), format('Results: ~w~n',[Occs]).
1103 cli_execute2(Steps,ErrorOnDeadlock,current_state(Repetitions)) :-
1104 current_expression(ID,CurState),
1105 start_xml_feature(execute,max_steps,Steps,FINFO),
1106 start_ms_timer(Start),
1107 (between(1,Repetitions,RepNr),
1108 % with -strict option we will stop after first error found
1109 % for repetitions you should probably set RANDOMISE_OPERATION_ORDER and RANDOMISE_ENUMERATION_ORDER to TRUE
1110 debug_format(19,'Starting execute (~w/~w) from state ~w with maximum number of steps ~w~n',[RepNr,Repetitions,ID,Steps]),
1111 (cli_execute_from(CurState,Steps,ErrorOnDeadlock,1,_Result) -> fail ; fail)
1112 ; Repetitions>1 -> stop_ms_timer_with_msg(Start,'-execute-repeat')
1113 ; true),
1114 stop_xml_feature(execute,FINFO).
1115
1116 :- use_module(bmachine,[b_top_level_operation/1]).
1117 allow_filter_unused_constants :-
1118 b_or_z_mode,
1119 b_top_level_operation(_), % we can filter out unused constants, unless there are no operations in which case the user probably wants to see the constant values
1120 \+ options_can_eval_any_cst,
1121 \+ option(cache_storage(_,_)). % we do not know what constants other machines using the cache may use
1122
1123 options_can_eval_any_cst :- option(eval_repl(_)).
1124 options_can_eval_any_cst :- option(eval_string_or_file(_,_,_,_,_)).
1125 options_can_eval_any_cst :- option(dot_command(_,_,_)).
1126 options_can_eval_any_cst :- option(dot_command_for_expr(_,_,_,_,_)).
1127 options_can_eval_any_cst :- option(process_latex_file(_,_)).
1128 options_can_eval_any_cst :- option(logxml_write_ids(all,_)). % the user writes out constants (not just variables) to file: also do not filter
1129
1130 :- dynamic execute_timeout_occurred/0.
1131
1132 cli_execute_from(CurState,Steps,ErrorOnDeadlock,FirstStepNr,Result) :-
1133 retractall(max_walltime(_,_,_)),
1134 retractall(execute_timeout_occurred),
1135 start_ms_timer(Start),
1136 (allow_filter_unused_constants -> temporary_set_preference(filter_unused_constants,true,CHNG) ; true),
1137 cli_execute_aux(FirstStepNr,Steps,CurState,_MEMO,ErrorOnDeadlock,'$NO_OPERATION',Result),
1138 (allow_filter_unused_constants -> reset_temporary_preference(filter_unused_constants,CHNG) ; true),
1139 (option(silent) -> true ; stop_ms_timer_with_msg(Start,'-execute')),
1140 print_max_walltime.
1141
1142 :- use_module(tools_strings,[ajoin/2, ajoin_with_sep/3]).
1143 :- use_module(external_functions,[reset_side_effect_occurred/0, side_effect_occurred/1]).
1144 cli_execute_aux(Nr,Steps,CurState,_,_ErrorOnDeadlock,_LastActionName,Result) :- Nr>Steps,!,
1145 formatsilent('Stopping execution after ~w steps~n',[Steps]), Result = stopped,
1146 print_state_silent(CurState),
1147 cli_execute_add_virtual_transition(Steps,CurState,Result).
1148 cli_execute_aux(Nr,Steps,CurState0,MEMO,ErrorOnDeadlock,LastActionName,Result) :-
1149 (Nr mod 5000 =:= 0, \+option(animate_stats), \+option(silent)
1150 -> (var(LastActionName) -> format('Step ~w~n',[Nr])
1151 ; format('Step ~w (after ~w)~n',[Nr,LastActionName])),
1152 (option_verbose -> print_state_silent(CurState0) ; true),
1153 %copy_term(CurState0,CurState), tools_printing:print_term_summary((CurState0)),nl,
1154 !,
1155 garbage_collect,
1156 !,
1157 print('Memory used: '),print_memory_used_wo_gc,flush_output,nl %nl_time
1158 ; true),
1159 prepare_state_for_specfile_trans(CurState0,unknown,MEMO,CurState), % ensure we memoize expanded constants in MEMO
1160 % avoid re-expanding constants in every state !
1161 % relevant e.g. for probcli -execute 20001 DataValidationTestSmallStep.mch -init
1162 (cli_invariant_ko(CurState,LastActionName,InvStatus,CliErr) -> % also recognises no_inv command
1163 N1 is Nr-1,
1164 ajoin(['INVARIANT ',InvStatus,' after ',N1,' steps (after ',LastActionName,').'],ErrMsg),
1165 format('~w~n',[ErrMsg]),!,
1166 print_state_silent(CurState),
1167 error_occurred_with_msg(CliErr,ErrMsg),
1168 Result=CliErr,
1169 cli_execute_add_virtual_transition(N1,CurState,Result,NewID),
1170 %(option_verbose -> b_interpreter:analyse_invariant_for_state(NewID) ; true)
1171 b_interpreter:analyse_invariant_for_state(NewID)
1172 ; cli_assertions_ko(CurState,LastActionName,AssRes) -> % also recognises no_inv command
1173 N1 is Nr-1,
1174 format('ASSERTIONS ~w after ~w steps (after ~w).~n',[AssRes,N1,LastActionName]),!,
1175 print_state_silent(CurState),
1176 error_occurred(assertion_violation), Result=assertion_violation,
1177 cli_execute_add_virtual_transition(N1,CurState,Result)
1178 ; cli_goal_found(CurState) -> % also recognizes no_goal command
1179 N1 is Nr-1,
1180 format('GOAL FOUND after ~w steps (after ~w).~n',[N1,LastActionName]),!,
1181 print_state_silent(CurState), Result=goal_found,
1182 cli_execute_add_virtual_transition(N1,CurState,Result)
1183 ; reset_side_effect_occurred,
1184 cli_trans(CurState,ActionName,NewState,Nr,LastActionName), % Compute new transition
1185 !,
1186 N1 is Nr+1,
1187 (NewState=CurState0, % could be expensive for large states; states are expanded ! % TO DO: look only at written variables ?!
1188 \+ side_effect_occurred(file)
1189 -> formatsilent('Infinite loop reached after ~w steps (looping on ~w).~n',[N1,ActionName]),
1190 Result=loop,
1191 print_state_silent(CurState),
1192 cli_execute_add_virtual_transition(N1,CurState,Result)
1193 ; cli_execute_aux(N1,Steps,NewState,MEMO,ErrorOnDeadlock,ActionName,Result))
1194 ).
1195 cli_execute_aux(Nr,_Steps,CurState,_,_ErrorOnDeadlock,LastActionName,Result) :- execute_timeout_occurred,!,
1196 N1 is Nr-1,
1197 formatsilent('Timeout occurred after ~w steps (after ~w).~n',[N1,LastActionName]),
1198 Result=time_out,
1199 print_state_silent(CurState),
1200 cli_execute_add_virtual_transition(N1,CurState,Result).
1201 cli_execute_aux(Nr,_Steps,CurState,_,ErrorOnDeadlock,LastActionName,Result) :- N1 is Nr-1,
1202 formatsilent('Deadlock reached after ~w steps (after ~w).~n',[N1,LastActionName]),
1203 Result=deadlock,
1204 (ErrorOnDeadlock=true,\+ option(no_deadlocks) -> error_occurred(deadlock) ; true),
1205 print_state_silent(CurState),
1206 cli_execute_add_virtual_transition(N1,CurState,Result).
1207
1208 check_nr_of_steps(Steps) :- option(execute_expect_steps(ExpSteps)),
1209 (Steps = ExpSteps -> formatsilent('The expected number of steps were executed: ~w~n',[Steps]),fail
1210 ; true),
1211 !,
1212 ajoin(['Unexpected number of steps ',Steps,', expected:'],Msg),
1213 add_error(cli_execute,Msg,ExpSteps).
1214 check_nr_of_steps(_).
1215
1216 cli_execute_add_virtual_transition(Steps,CurState,Result) :-
1217 cli_execute_add_virtual_transition(Steps,CurState,Result,_).
1218 cli_execute_add_virtual_transition(Steps,CurState,Result,ToID) :-
1219 current_state_id(CurID),
1220 write_xml_element_to_log(executed,[steps/Steps,result/Result]),
1221 (Steps=0 -> true
1222 ; some_command_requires_state_space % check whether storing is actually useful for any outstanding command
1223 -> (CurID=root
1224 -> tcltk_interface:tcltk_add_cbc_state(CurState,'$execute'(Steps)) % generate separate constants state
1225 ; tcltk_interface:tcltk_add_new_transition(CurID,'$execute'(Steps),ToID,CurState,[]),
1226 tcltk_goto_state('$execute'(Steps),ToID)
1227 ),
1228 debug_format(19,'Added transition ~w -> ~w to state space for ~w execution steps~n',[CurID,ToID,Steps])
1229 ; debug_format(19,'Not adding transition for -execute ~w steps; not required by other commands~n',[Steps])
1230 ),
1231 check_nr_of_steps(Steps).
1232
1233 some_command_requires_state_space :-
1234 option(X),
1235 \+ does_not_require_state_space(X),
1236 !.
1237 does_not_require_state_space(execute_expect_steps(_)).
1238 does_not_require_state_space(execute(_,_,_)).
1239 does_not_require_state_space(animate_stats).
1240 does_not_require_state_space(execute_monitoring).
1241 does_not_require_state_space(set_pref(_,_)).
1242 does_not_require_state_space(set_preference_group(_,_)).
1243 does_not_require_state_space(timeout(_)).
1244 does_not_require_state_space(verbose(_)).
1245 does_not_require_state_space(verbose_off).
1246 does_not_require_state_space(silent).
1247 does_not_require_state_space(force_no_silent).
1248 does_not_require_state_space(strict_raise_error).
1249 does_not_require_state_space(release_java_parser).
1250 does_not_require_state_space(fast_read_prob).
1251 does_not_require_state_space(file_info).
1252 does_not_require_state_space(print_version(_)).
1253 does_not_require_state_space(check_java_version).
1254 does_not_require_state_space(pretty_print_internal_rep(_,_,_,_)).
1255 does_not_require_state_space(expect_error(_)).
1256 does_not_require_state_space(optional_error(_)).
1257 does_not_require_state_space(no_deadlocks).
1258 does_not_require_state_space(no_invariant_violations).
1259 does_not_require_state_space(no_goal).
1260 does_not_require_state_space(no_assertion_violations).
1261 does_not_require_state_space(no_state_errors).
1262 does_not_require_state_space(no_counter_examples).
1263 does_not_require_state_space(no_color).
1264 % TODO: register more commands that do not require the state space
1265
1266 :- dynamic max_walltime/3.
1267 print_max_walltime :- (max_walltime(Action,Nr,WT),option_verbose
1268 -> format('% Maximum walltime ~w ms at step ~w for ~w.~n',[WT,Nr,Action]) ; true).
1269
1270 % will be used to compute a single successor
1271 % b_operation_cannot_modify_state
1272 cli_trans(CurState,ActionName,NewState,Nr,LastActionName) :-
1273 option(animate_stats),!, % provide statistics about the animation
1274 start_probcli_timer(Timer),
1275 cli_trans_aux(CurState,ActionName,Act,NewState,Nr,LastActionName),
1276 (option_verbose -> translate:translate_event(Act,TStr)
1277 ; translate:translate_event_with_limit(Act,100,TStr)),
1278 format('~w~5|: ~w~n',[Nr,TStr]),
1279 format(' ~5|',[]),stop_probcli_timer(Timer,' '),
1280 (option_verbose -> format(' ~5|',[]),print_memory_used_wo_gc,nl ; true),
1281 flush_output,
1282 get_probcli_elapsed_walltime(Timer,WallTime),
1283 get_probcli_elapsed_runtime(Timer,RunTime),
1284 accumulate_infos(animate_stats,[step-1,step_nr-Nr,runtime-RunTime,walltime-WallTime]),
1285 (max_walltime(_,_,MWT), MWT >= WallTime -> true
1286 ; retractall(max_walltime(_,_,_)),
1287 assertz(max_walltime(ActionName,Nr,WallTime))).
1288 cli_trans(CurState,ActionName,NewState,Nr,LastActionName) :-
1289 cli_trans_aux(CurState,ActionName,_,NewState,Nr,LastActionName).
1290
1291 cli_trans_aux(CurState,ActionName,Act,NewState,Nr,LastActionName) :-
1292 option(timeout(TO)),!,
1293 safe_time_out(cli_trans_aux2(CurState,ActionName,Act,NewState,LastActionName),TO,Res),
1294 (Res=time_out -> format_error_with_nl('! Timeout occurred while performing step ~w of execute: ~w ms',[Nr,TO]),
1295 % TO DO: try and obtain operation name in which time-out occured
1296 error_occurred(time_out,execute),
1297 assertz(execute_timeout_occurred),
1298 fail
1299 ; true).
1300 cli_trans_aux(CurState,ActionName,Act,NewState,_Nr,LastActionName) :-
1301 cli_trans_aux2(CurState,ActionName,Act,NewState,LastActionName).
1302
1303 cli_trans_aux2(CurState,ActionName,Act,NewState,LastActionName) :-
1304 catch_enumeration_warning_exceptions(
1305 (throw_enumeration_warnings_in_current_scope,
1306 cli_execute_trans(CurState,ActionName,Act,NewState,LastActionName), % no time-out !
1307 (error_occurred_in_error_scope -> ErrorEvent=true ; ErrorEvent=false)
1308 ),
1309 (error_occurred(virtual_time_out_execute),
1310 ActionName = '*** VIRTUAL_TIME_OUT ***', Act=ActionName,
1311 CurState=NewState) % this forces loop detection above; not very elegant way of signalling
1312 ),
1313 (ErrorEvent==true,option(strict_raise_error)
1314 -> print('*** ERROR OCCURED DURING EXECUTE ***'),nl, error_occurred(execute),fail
1315 ; true).
1316
1317 :- use_module(runtime_profiler,[profile_single_call/3]).
1318 :- use_module(specfile,[get_specification_description/2]).
1319 cli_execute_trans(CurState,ActionName,Act,NewState,LastActionName) :-
1320 statistics(runtime,[StartExecuteForState,_]),
1321 get_possible_next_operation_for_execute(CurState,LastActionName,ActionName),
1322 start_check_disabled(ActionName,StartActionTime),
1323 catch(
1324 profile_single_call(ActionName,
1325 unknown, % state Unknown
1326 specfile_trans_with_check(CurState,ActionName,Act,NewState,Residue) % no time-out !
1327 ),
1328 EXC,
1329 (translate_exception(EXC,EMSG),
1330 (nonvar(ActionName)
1331 -> get_specification_description(operation,OP),
1332 format_with_colour_nl(user_error,[red,bold],'~n*** ~w while executing ~w "~w"~n',[EMSG,OP,ActionName])
1333 ; get_specification_description(operations,OP),
1334 format_with_colour_nl(user_error,[red,bold],'~n*** ~w while computing ~w~n',[EMSG,OP])
1335 ),
1336 perform_feedback_options_after_exception,
1337 throw(EXC))),
1338 (Residue=[]
1339 -> check_trans_time(StartExecuteForState,StartActionTime,ActionName)
1340 ; error_occurred(cli_execute_residue(ActionName,Residue,Act))).
1341
1342 :- use_module(probsrc(static_enabling_analysis),[static_cannot_enable/2,
1343 static_disables_itself/1, static_disabled_after/2]).
1344 % compute all possible next operations to try out in -execute, based on LastActionName
1345 % the predicate makes use of the fact that operations are tried in order
1346 get_possible_next_operation_for_execute(CurState,LastActionName,ActionName) :-
1347 get_preference(randomise_operation_order,false),
1348 get_preference(use_po,true), % PROOF_INFO: should we use a proper preference for use_po_for_execute ?
1349 b_or_z_mode,
1350 b_top_level_operation(LastActionName),
1351 % prevent trying ActionName which we know is infeasible according to previous LastActionName
1352 % we rely on the fact that execute tries the operations in order
1353 findall(AN,specfile_possible_trans_name_for_successors(CurState,AN),ANS),
1354 !,
1355 member_with_last(ActionName,ANS,LastActionName,FoundLast),
1356 (var(FoundLast)
1357 -> % ActionName occurs before LastActionName, this means
1358 % we did try this ActionName at the last execution step and it was not possible
1359 % format('** Checking operation ~w against ~w~n',[ActionName,LastActionName]),debug:nl_time,
1360 %Note: we could use result of cbc enabling analysis if it was performed
1361 (static_cannot_enable(LastActionName,ActionName)
1362 -> %format('Operation ~w : ~w cannot be enabled by ~w : ~w~n',[Nr2,ActionName,Nr1,LastActionName]),
1363 %print('- '),
1364 fail
1365 ; true
1366 )
1367 ; ActionName=LastActionName, static_disables_itself(ActionName)
1368 -> %format('** Operation ~w cannot be enabled after itself~n',[ActionName]),
1369 fail
1370 %; static_disabled_after(LastActionName,ActionName) % TODO: check if this more general case is worth it
1371 % -> format('** Operation ~w cannot be enabled after ~w~n',[ActionName,LastActionName]),
1372 % fail
1373 ; true % we did not try this ActionName at the last execution step
1374 ).
1375 get_possible_next_operation_for_execute(CurState,_LastActionName,ActionName) :-
1376 specfile_possible_trans_name_for_successors(CurState,ActionName).
1377
1378 % like member but instantiate FoundLast when we pass the element Last
1379 member_with_last(X,[H|T],Last,FoundLast) :-
1380 (H=Last -> !,FoundLast=true, member(X,[H|T]) ; X=H).
1381 member_with_last(X,[_|T],Last,FoundLast) :- member_with_last(X,T,Last,FoundLast).
1382
1383 :- use_module(probsrc(value_persistance),[start_cache_execute_modus/1,stop_cache_execute_modus/0,
1384 add_new_transition_to_cache_from_expanded_state/4]).
1385 % also checks whether a setup_constants_inconsistent error should be raised:
1386 specfile_trans_with_check(CurState,ActionName,Act,NewState,Residue) :-
1387 start_cache_execute_modus(CacheInfo),
1388 if(specfile_trans_or_partial_trans(CurState,ActionName,Act,NewState,_TransInfo,Residue,Partial), % no time-out !
1389 (check_partial_trans(Partial,ActionName),
1390 (Partial=true -> true ; add_new_transition_to_cache_from_expanded_state(CurState,Act,NewState,CacheInfo)),
1391 stop_cache_execute_modus
1392 ),
1393 (stop_cache_execute_modus,
1394 check_deadlock_fail(ActionName) % add_deadlock_to_cache_from_expanded_state(CurState,ActionName)
1395 )
1396 ).
1397
1398 % check whether we should raise errors on deadlock in -execute:
1399 check_deadlock_fail('$setup_constants') :- !, error_occurred(setup_constants_inconsistent),fail.
1400
1401 % check whether we should raise errors due to partial transitions in -execute:
1402 check_partial_trans(true,'$setup_constants') :- !, error_occurred(setup_constants_inconsistent).
1403 check_partial_trans(true,ActionName) :- !, format('Unknown partial transition: ~w~n',[ActionName]),
1404 error_occurred(setup_constants_inconsistent).
1405 check_partial_trans(_,_).
1406
1407 % check if we did not spend too much time on disabled operations and print warning if we do
1408 check_trans_time(StartExecuteForState,StartActionTime,ActionName) :-
1409 option(execute_monitoring),
1410 statistics(runtime,[CurrentTime,_]),
1411 Delta1 is StartActionTime-StartExecuteForState,
1412 Delta2 is CurrentTime-StartActionTime,
1413 Delta1 > 100, Delta1 > Delta2,
1414 !,
1415 format_with_colour(user_output,[blue],'~n ~5|: WARNING from -execute_monitor: ~w ms for disabled operations and ~w ms for operation ~w itself~n',[Delta1,Delta2,ActionName]).
1416 check_trans_time(_,_,_).
1417
1418 % check if we did not spend too much time on a single disabled operations and print warning if we do
1419 start_check_disabled(ActionName,StartActionTime) :- option(execute_monitoring),!,
1420 statistics(runtime,[StartActionTime,_]),
1421 (true
1422 ; statistics(runtime,[EndActionTime,_]),
1423 Delta is EndActionTime - StartActionTime,
1424 Delta > 50,
1425 format_with_colour(user_output,[blue],'~n ~5|: WARNING from -execute_monitor: ~w ms for disabled operation ~w~n',[Delta,ActionName]),
1426 fail
1427 ).
1428 start_check_disabled(_,0).
1429
1430 translate_exception(user_interrupt_signal,'User-Interrupt (CTRL-C)').
1431 translate_exception(enumeration_warning(_,_,_,_,_),'Enumeration Warning').
1432 translate_exception(E,E).
1433
1434 :- use_module(bmachine,[b_machine_has_constants/0]).
1435 print_state_silent(_) :- option(silent),!.
1436 print_state_silent(CurState) :- \+ b_or_z_mode, !, translate:print_state(CurState), nl.
1437 print_state_silent(CurState) :- (option_verbose;\+ b_machine_has_constants),!,
1438 translate:print_bstate_limited(CurState,1000,-1),nl.
1439 print_state_silent(CurState) :- remove_constants(CurState,VarState),
1440 % only print variables
1441 format('VARIABLES (use -v to see constants or -silent to suppress output):~n',[]),
1442 translate:print_bstate_limited(VarState,1000,-1),nl.
1443
1444 :- use_module(bmachine,[b_is_constant/1]).
1445 is_constant_binding(bind(C,_)) :- b_is_constant(C).
1446 remove_constants(const_and_vars(_,Vars),Res) :- !,Res=Vars.
1447 remove_constants([H|T],Res) :- !,exclude(prob_cli:is_constant_binding,[H|T],Res).
1448 remove_constants(root,Res) :- !,Res=[].
1449 remove_constants(concrete_constants(_),Res) :- !, Res=[].
1450 remove_constants(X,X).
1451
1452 % write vars to xml log file if they start with a given prefix
1453 logxml_write_ids(variables,Prefix) :- !,
1454 current_expression(_,CurState),
1455 remove_constants(CurState,VarState),
1456 % TO DO: store also final state in xml_log
1457 write_bstate_to_log(VarState,Prefix).
1458 logxml_write_ids(_,Prefix) :- !,
1459 current_expression(_,CurState),
1460 expand_const_and_vars_to_full_store(CurState,EState),
1461 write_bstate_to_log(EState,Prefix).
1462
1463 :- use_module(bmachine,[b_get_invariant_from_machine/1, b_specialized_invariant_for_op/2, b_machine_has_constants/0]).
1464 cli_invariant_ko(_,_,_,_) :- option(no_invariant_violations),!,fail. % user asks not to check it
1465 cli_invariant_ko(_,_,_,_) :- get_preference(do_invariant_checking,false),!,fail. % user asks not to check it via preference
1466 cli_invariant_ko(CurState,LastActionName,ResInvStatus,CliError) :-
1467 profile_single_call('INVARIANT',unknown,cli_invariant_ko2(CurState,LastActionName,ResInvStatus,CliError)).
1468 cli_invariant_ko2(CurState,LastActionName,ResInvStatus,CliError) :-
1469 state_corresponds_to_initialised_b_machine(CurState,BState),!,
1470 start_probcli_timer(InvTimer),
1471 (b_specialized_invariant_for_op(LastActionName,Invariant) -> true
1472 %, print('Specialized invariant: '),translate:print_bexpr(Invariant),nl
1473 ; b_get_invariant_from_machine(Invariant)),
1474 cli_test_pred(BState,'INVARIANT',Invariant,ResInvStatus),
1475 stop_probcli_debug_timer(InvTimer,'Finished Invariant Checking'),
1476 ResInvStatus \= 'TRUE',
1477 (ResInvStatus == 'FALSE' -> CliError = invariant_violation
1478 ; ResInvStatus == 'UNKNOWN' -> CliError = invariant_unknown
1479 ; ResInvStatus == 'TIME-OUT' -> CliError = invariant_time_out
1480 ; format_error_with_nl('Unexpected invariant status: ~w',[ResInvStatus]),
1481 CliError= invariant_unknown).
1482 %cli_invariant_ko(_,_,_,_) :- fail. % not yet initialised
1483
1484 :- use_module(b_interpreter,[b_test_boolean_expression_for_ground_state/4]).
1485 cli_test_pred(BState,PredKind,Pred) :- cli_test_pred(BState,PredKind,Pred,'TRUE').
1486 % comment in following clause to get more precise location for exceptions/virtual timeouts:
1487 %cli_test_pred(BState,PredKind,Pred,Res) :- option_verbose, bsyntaxtree:decompose_conjunct(Pred,A,B),!,
1488 % cli_test_pred(BState,PredKind,A,ResA), (ResA = 'TRUE' -> cli_test_pred(BState,PredKind,B,Res) ; Res = ResA).
1489 cli_test_pred(BState,PredKind,Pred,Res) :- option(timeout(TO)),!,
1490 debug_format(9,'Testing ~w with time-out ~w~n',[PredKind,TO]),
1491 safe_time_out(cli_test_pred2(BState,PredKind,Pred,Res), TO, TRes),
1492 (Res=time_out -> TRes='TIME-OUT' ; true).
1493 cli_test_pred(BState,PredKind,Pred,Res) :-
1494 debug_format(9,'Checking ~w without a time-out~n',[PredKind]),
1495 cli_test_pred2(BState,PredKind,Pred,Res).
1496 cli_test_pred2(BState,PredKind,Pred,Res) :-
1497 % currently does not do a time-out: % b_interpreter calls: time_out_with_enum_warning_one_solution_no_new_error_scope
1498 catch(
1499 on_enumeration_warning(b_test_boolean_expression_for_ground_state(Pred,[],BState,PredKind ), (
1500 add_error(cli_test_pred,'Enumeration warning while testing',PredKind,Pred),
1501 cli_print_pred_info(Pred),
1502 Res='UNKNOWN')
1503 ),
1504 E,
1505 (
1506 ajoin(['VIRTUAL TIME-OUT or exception while testing ',PredKind,': '],Msg),
1507 add_error(cli_test_pred,Msg,E,Pred), % E can also be user_interrupt_signal
1508 cli_print_pred_info(Pred),
1509 Res='UNKNOWN'
1510 )
1511 ),
1512 !,
1513 (var(Res) -> Res = 'TRUE' ; true).
1514 cli_test_pred2(_BState,_PredKind,_Pred,'FALSE').
1515
1516 cli_print_pred_info(Pred) :- get_texpr_label(Pred,Label),
1517 format('Label = ~w~n',[Label]),fail.
1518 cli_print_pred_info(Pred) :- get_texpr_description(Pred,Desc),
1519 format('Description = ~w~n',[Desc]),fail.
1520 %cli_print_pred_info(Pred) :- bsyntaxtree:get_texpr_pos(Pred,Pos), Pos \= none, translate_span(Pos,Str),
1521 % format('Location = ~w~n',[Str]),fail.
1522 cli_print_pred_info(Pred) :-
1523 option_verbose,
1524 write('Predicate: '), translate:nested_print_bexpr(Pred),nl.
1525
1526 :- use_module(bmachine,[get_assertions_from_machine/2]).
1527 % TO DO: also check static assertions
1528 cli_assertions_ko(_,_,_) :- option(no_assertion_violations),!,fail. % user asks not to check it
1529 cli_assertions_ko(CurState,_LastActionName,Res) :-
1530 state_corresponds_to_initialised_b_machine(CurState,BState),
1531 get_assertions_from_machine(dynamic,Assertions), % TO DO: do something similar to b_specialized_invariant_for_op
1532 !,
1533 profile_single_call('ASSERTIONS',unknown,cli_assertions_ko2(BState,Assertions,Res)).
1534
1535
1536 cli_assertions_ko2(BState,Assertions,Res) :-
1537 start_probcli_timer(AssTimer),
1538 %nl,nl,print(check),nl,maplist(translate:print_bexpr,Assertions),nl,
1539 (member(Ass,Assertions),
1540 cli_test_pred(BState,'ASSERTION',Ass,Res),
1541 Res \= 'TRUE' -> true
1542 ; Res = 'TRUE'
1543 ),
1544 stop_probcli_debug_timer(AssTimer,'Finished Checking Assertions'),
1545 Res \= 'TRUE'.
1546
1547
1548 :- use_module(bmachine,[b_get_machine_goal/1]).
1549 cli_goal_found(_):- option(no_goal),!,fail.
1550 cli_goal_found(CurState) :-
1551 b_get_machine_goal(Goal),
1552 state_corresponds_to_initialised_b_machine(CurState,BState),
1553 profile_single_call('GOAL',unknown,cli_goal_found2(Goal,BState)).
1554 cli_goal_found2(Goal,BState) :-
1555 b_test_boolean_expression_for_ground_state(Goal,[],BState,'GOAL').
1556
1557
1558 :- use_module(extrasrc(simb_parser),[load_simb_file/1]).
1559 :- use_module(extrasrc(simb_simulator),[run_simb_simulation/2, print_simb_profile/0]).
1560 % SimB simulation
1561 cli_simulate(File,Repetitions,Steps,SimOpts) :-
1562 load_simb_file(File),!,
1563 findall(O,get_simb_option(O),SimOpts2,SimOpts),
1564 debug_format(19,'Simulate max. ~w steps with options ~w~n',[Steps,SimOpts2]),
1565 run_simb_simulations(Repetitions,Steps,SimOpts2).
1566 run_simb_simulations(Reps,_,_) :- Reps<1, !.
1567 run_simb_simulations(Reps,Steps,SimOpts) :-
1568 run_simb_simulation(Steps,SimOpts),!,
1569 R1 is Reps-1,
1570 run_simb_simulations(R1,Steps,SimOpts).
1571
1572 :- use_module(probltlsrc(ltl_tools),[temporal_parser/3]).
1573 get_simb_option(O) :- option(simb_option(O)).
1574 get_simb_option(ltl_stop_condition(LtlStopFormula)) :-
1575 option(simb_ltl_stop_condition(LTL_Stop_AsAtom)),
1576 temporal_parser(LTL_Stop_AsAtom,ltl,LtlStopFormula).
1577
1578 % random animation
1579 :- public cli_random_animate/2. % for repl to use -animate command
1580 cli_random_animate(Steps,Err) :- probcli_time_stamp(NOW),
1581 cli_random_animate(NOW,Steps,Err).
1582 cli_random_animate(_NOW,Steps,ErrorOnDeadlock) :-
1583 start_xml_feature(random_animate,max_steps,Steps,FINFO),
1584 start_ms_timer(Start),
1585 perform_random_steps(Steps,ErrorOnDeadlock),
1586 (option(silent) -> true ; stop_ms_timer_with_msg(Start,'-animate')),
1587 %tcltk_save_history_as_trace_file(prolog,user),
1588 stop_xml_feature(random_animate,FINFO).
1589
1590 :- use_module(bmachine,[b_get_assertions/3]).
1591 we_need_only_static_assertions(ALL) :- specfile:b_or_z_mode,
1592 (option(cli_check_assertions(main,_)) -> ALL=main
1593 ; option(cli_check_assertions(ALL,_))),
1594 % we do an assertion check
1595 \+ ((option(A), option_requires_all_properties(A))),
1596 b_get_assertions(ALL,dynamic,[]). % the assertions do not reference variables
1597
1598 % do we need all properties/constants of the machine, or only certain ones (e.g., static)
1599 option_requires_all_properties(cli_mc(_,_)).
1600 option_requires_all_properties(cli_check_properties). % we may want to check all properties
1601 option_requires_all_properties(cli_core_properties(_)).
1602 option_requires_all_properties(cli_random_animate(_)).
1603 option_requires_all_properties(default_trace_check).
1604 option_requires_all_properties(trace_check(_,_,_)).
1605 option_requires_all_properties(state_trace(_)).
1606 option_requires_all_properties(mcm_tests(_,_,_,_)).
1607 option_requires_all_properties(cbc_tests(_,_,_)).
1608 option_requires_all_properties(animate).
1609 option_requires_all_properties(initialise). % INITIALISATION may access constants
1610 option_requires_all_properties(eval_repl(_)).
1611 option_requires_all_properties(eval_string_or_file(_,_,_,_,_)).
1612 option_requires_all_properties(ltl_assertions).
1613 option_requires_all_properties(ltl_file(_)).
1614 option_requires_all_properties(refinement_check(_,_,_)).
1615 option_requires_all_properties(cli_start_mc_with_tlc).
1616 option_requires_all_properties(cli_symbolic_model_check(_)).
1617 option_requires_all_properties(process_latex_file(_,_)).
1618 option_requires_all_properties(cli_wd_check(_,_)).
1619 option_requires_all_properties(cli_lint(_)).
1620 option_requires_all_properties(visb_history(_,_,_)).
1621
1622 :- use_module(b_intelligent_trace_replay,[replay_json_trace_file/2]).
1623 :- public default_trace_check/0.
1624 default_trace_check :- loaded_main_file(_,MainFile),
1625 cli_start_default_trace_check(MainFile).
1626 cli_start_default_trace_check(MainFile) :-
1627 debug_println(20,'% Starting Default Trace Check: '),
1628 (check_default_trace_for_specfile(MainFile) -> true ; error_occurred(trace_check)).
1629
1630 default_json_trace_save :-
1631 loaded_main_file(_,MainFile),
1632 get_default_trace_file(MainFile,'.prob2trace',HistFile),
1633 format('Saving history to JSON ProB2-UI default trace file: ~w~n',[HistFile]),
1634 tcltk_save_history_as_trace_file(json,HistFile).
1635 cli_start_trace_check(json,File,default_trace_replay) :- !,
1636 replay_json_trace_file(File,Status),
1637 (Status=perfect -> true
1638 ; Status = imperfect -> add_warning(trace_replay,'Imperfect JSON trace replay:',Status)
1639 ; add_error(trace_replay,'Failed JSON trace replay:',Status)
1640 ).
1641 cli_start_trace_check(Style,File,Mode) :-
1642 debug_format(20,'% Starting Trace Check (~w:~w): ~w~n',[Style,Mode,File]),
1643 (tcltk_check_sequence_from_file(Style,File,Mode) -> true ; error_occurred(trace_check)).
1644 cli_start_trace_state_check(File) :-
1645 debug_println(20,'% Starting Trace Check: '),
1646 (tcltk_check_state_sequence_from_file(File) -> true ; error_occurred(state_trace)).
1647
1648 % is it necessary to compute enabled operations for root state
1649 computeOperations_for_root_required :- initialise_required.
1650 computeOperations_for_root_required :- option(default_trace_check).
1651 computeOperations_for_root_required :- option(trace_check(_,_,_)).
1652 computeOperations_for_root_required :- option(state_trace(_)).
1653 computeOperations_for_root_required :- option(ltl_assertions).
1654 computeOperations_for_root_required :- option(cli_random_animate(_,_)).
1655 computeOperations_for_root_required :- option(socket(_,_)).
1656 computeOperations_for_root_required :- option(cli_mc(_,_)).
1657 computeOperations_for_root_required :- option(ltl_file(_)).
1658 computeOperations_for_root_required :- option(ltl_formula_model_check(_,_)).
1659 computeOperations_for_root_required :- option(ctl_formula_model_check(_,_)).
1660 computeOperations_for_root_required :- option(pctl_formula_model_check(_,_)).
1661 computeOperations_for_root_required :- option(refinement_check(_,_,_)).
1662 computeOperations_for_root_required :- option(csp_in_situ_refinement_check(_,_)).
1663 computeOperations_for_root_required :- option(csp_checkAssertion(_,_)).
1664 computeOperations_for_root_required :- option(mcm_tests(_,_,_,_)).
1665 computeOperations_for_root_required :- option(mcm_cover(_)).
1666
1667 % is an initialisation mandatory:
1668 initialise_required :- option(initialise), \+ empty_machine_loaded.
1669 initialise_required :- \+ option(default_trace_check), \+ option(trace_check(_,_,_)), \+ option(state_trace(_)),
1670 \+ option(load_state(_)),
1671 \+ empty_machine_loaded,
1672 \+ (option(execute(Nr,_,_)), Nr>=2), % execute will also initialise machine
1673 init_req2.
1674 init_req2 :- option(cli_check_properties).
1675 init_req2 :- option(zmq_assertion(_,_,_)).
1676 init_req2 :- option(cli_check_assertions(_,_)).
1677 init_req2 :- option(process_latex_file(_,_)).
1678 init_req2 :- option(eval_string_or_file(_,_,_,_,_)). % ensure that we initialise/precompile empty machine in case no main file specified; currently no longer required
1679 init_req2 :- option(check_abstract_constants).
1680 init_req2 :- option(visb_click(_)).
1681 init_req2 :- option(dot_command_for_expr(Cat,_,_,_,_)),
1682 nonmember(Cat,[transition_diagram,expression_coverage]). % see test 1033, option also works with empty state space
1683 %init_req2 :- option(csv_table_command(Cat,_,_,_)), ...
1684
1685 :- public initialise/0. % for REPL
1686 initialise :- probcli_time_stamp(NOW),cli_start_initialisation(NOW).
1687
1688 cli_start_initialisation(NOW) :-
1689 debug_println(20,'% Performing INITIALISATION: '),
1690 (perform_random_initialisation -> true ;
1691 writeln_log_time(cli_start_initialisation_failed(NOW)),
1692 fail).
1693
1694 :- use_module(wdsrc(well_def_analyser),[analyse_wd_for_machine/4]).
1695 :- public cli_wd_check/2. % for REPL
1696 cli_wd_check(ExpectedDis,ExpectedTot) :-
1697 (option(timeout(TO)) -> true ; TO=5000), % this is global_time_out option
1698 (option(silent) -> Opts=[discharge_po,ignore_wd_infos,reorder_conjuncts]
1699 ; Opts=[create_not_discharged_msg(warning),discharge_po,ignore_wd_infos,reorder_conjuncts]),
1700 statistics(walltime,[W1,_]),
1701 safe_time_out(analyse_wd_for_machine(NrDischarged,NrTot,_Res,Opts),TO,Res),
1702 statistics(walltime,[W2,_]), WT is W2-W1,
1703 (Res=time_out -> accumulate_infos(wd_check,[timeout-1,walltime-WT]), % discharged and total are unknown
1704 add_error(cli_wd_check,'TIME-OUT in WD Analysis (use -global_time_out X to increase it)')
1705 ; format(user_output,'WD Analysis Result: discharged ~w / ~w',[NrDischarged,NrTot]),
1706 (NrTot >0
1707 -> Perc is 100*NrDischarged/NrTot,
1708 (NrDischarged=NrTot -> Col=[green,bold] ; Col=[red])
1709 ; Perc = 100, Col=[]),
1710 format_with_colour(user_output,Col,' (~2f %)~n',[Perc]),
1711 WDInfos = [discharged-NrDischarged,timeout-0,total-NrTot,walltime-WT],
1712 accumulate_infos(wd_check,WDInfos),
1713 (ExpectedDis==ExpectedTot, ExpectedTot = NrTot -> true ; true), % for -wd-check-all: bind ExpectedDis
1714 check_required_infos([discharged-ExpectedDis,total-ExpectedTot],WDInfos,cli_wd_check)
1715 ).
1716 :- use_module(wdsrc(well_def_analyser),[analyse_invariants_for_machine/5]).
1717 cli_wd_inv_proof(UnchangedNr,ProvenNr,TotPOsNr) :-
1718 (option(timeout(TO)) -> true ; TO=5000),
1719 Options=[],
1720 statistics(walltime,[W1,_]),
1721 safe_time_out(analyse_invariants_for_machine(UnchangedNr,ProvenNr,UnProvenNr,TotPOsNr,Options),TO,Res),
1722 statistics(walltime,[W2,_]), WT is W2-W1,
1723 (Res=time_out -> accumulate_infos(wd_inv_proof,[timeout-1,walltime-WT]), % discharged and total are unknown
1724 add_error(cli_wd_check,'TIME-OUT in WD Invariant Proving (use -global_time_out X to increase it)')
1725 ;
1726 (TotPOsNr>0 -> Perc is (UnchangedNr+ProvenNr)*100/ TotPOsNr ; Perc = 100.0),
1727 format('Proof summary for ~w Invariant POs (~2f % discharged): ~w unchanged, ~w proven, ~w unproven~n',
1728 [TotPOsNr,Perc,UnchangedNr,ProvenNr,UnProvenNr]),
1729 WDInfos = [proven-ProvenNr,timeout-0,total-TotPOsNr,unchanged-UnchangedNr,unproven-UnProvenNr,walltime-WT],
1730 accumulate_infos(wd_inv_proof,WDInfos)
1731 ).
1732
1733
1734 :- use_module(bmachine_static_checks,[extended_static_check_machine/1]).
1735 :- use_module(visbsrc(visb_visualiser),[extended_static_check_default_visb_file/0]).
1736 :- use_module(extrasrc(simb_parser),[extended_static_check_default_simb_file/0]).
1737 % perform some additional static checks
1738 :- public cli_lint/0. % for REPL
1739 cli_lint(Check) :-
1740 extended_static_check_machine(Check),
1741 (unavailable_extension(visb_extension,_) -> true
1742 ; (var(Check) ; Check=visb) -> extended_static_check_default_visb_file
1743 ; true),
1744 (Check=simb -> extended_static_check_default_simb_file ; true).
1745 cli_lint :- cli_lint(_).
1746
1747
1748 :- use_module(extrasrc(predicate_debugger),[tcltk_debug_properties/3]).
1749 :- use_module(state_space,[current_state_corresponds_to_setup_constants_b_machine/0]).
1750 :- public cli_check_properties/0. % for REPL
1751 cli_check_properties :- probcli_time_stamp(NOW),
1752 cli_check_properties(NOW).
1753 cli_check_properties(NOW) :-
1754 printsilent('% Checking PROPERTIES: '),nls,
1755 writeln_log_time(starting_check_properties(NOW)),
1756 ( current_state_corresponds_to_setup_constants_b_machine ->
1757 set_analyse_hook('_P'),
1758 predicate_evaluator:tcltk_analyse_properties(_PROPRES,PROPInfos),
1759 unset_analyse_hook,
1760 printsilent(PROPInfos),nls, % ex: [total/33,true/29,false/0,unknown/4,timeout/4,runtime/49950]
1761 accumulate_infos(properties,PROPInfos),
1762 write_important_xml_element_to_log(check_properties,PROPInfos),
1763 (predicate_evaluator:check_summary_all_true(PROPInfos) -> true
1764 ; print_error('Not all PROPERTIES true'), error_occurred(check_properties))
1765 ;
1766 (tcltk_debug_properties(list(PROPRES),false,Satisfiable)
1767 -> printsilent(PROPRES),nls,
1768 printsilent(Satisfiable),nls
1769 ; error_occurred(debug_properties_failed))
1770 ),
1771 writeln_log_time(finished_check_properties(NOW,PROPInfos)),
1772 loaded_root_filename(RootName),
1773 formatsilent('% Finished checking PROPERTIES of ~w~n',[RootName]).
1774
1775 % TODO: provide argument so that we run it only if necessary; e.g., when ProB has not already found a solution
1776
1777 cli_core_properties(Algorithm) :-
1778 format('% Checking CONSISTENCY of PROPERTIES by finding UNSAT CORE (using ~w)~n',[Algorithm]),
1779 b_get_properties_from_machine(Properties),!,
1780 size_of_conjunction(Properties,NrOfConjuncts),
1781 statistics(walltime,[W1,_]),
1782 (find_core(Algorithm,Properties,Core,Result)
1783 -> statistics(walltime,[W2,_]), WTime is W2-W1,
1784 length(Core,Len),
1785 accumulate_infos(properties_core,[contradiction_found-1,core_length-Len,
1786 properties-NrOfConjuncts,walltime-WTime]),
1787 format('UNSAT CORE of length ~w found, PROPERTIES are inconsistent! (~w, ~w ms walltime using ~w)~n',[Len,Result,WTime,Algorithm]),
1788 translate:nested_print_bexpr_as_classicalb(Core),
1789 format('% END OF UNSAT CORE (~w conjuncts)~n',[Len])
1790 % TODO: raise setup_constants_fails and avoid trying to solve properties later
1791 ; statistics(walltime,[W2,_]), WTime is W2-W1,
1792 accumulate_infos(properties_core,[contradiction_found-0,core_length-0,
1793 properties-NrOfConjuncts,walltime-WTime]),
1794 format('No small UNSAT CORE found, PROPERTIES may be consistent (~w ms walltime).~n',[WTime])
1795 ).
1796
1797 :- use_module(extrasrc(unsat_cores),[quick_bup_core_up_to/4]).
1798 :- use_module(wdsrc(well_def_analyser),[find_inconsistent_axiom/3]).
1799 find_core(wd_prover,_,Core,Result) :-
1800 find_inconsistent_axiom([],Axiom,NecHyps),
1801 Core = [Axiom|NecHyps], Result = contradiction_found.
1802 find_core(z3_bup(MaxSize),Properties,Core,Result) :-
1803 (var(MaxSize) -> MaxSize=2 ; true),
1804 quick_bup_core_up_to(Properties,MaxSize,Core,Result).
1805
1806
1807 % -----------------------
1808
1809 :- public cli_check_assertions/2. % for REPL
1810 cli_check_assertions(ALL,RI) :-
1811 probcli_time_stamp(NOW),
1812 cli_check_assertions(ALL,RI,NOW).
1813 cli_check_assertions(ALL,ReqInfos,NOW) :-
1814 printsilent('% Checking ASSERTIONS: '),nls,
1815 writeln_log_time(starting_check_assertions(NOW)),
1816 set_analyse_hook('_A'), % for dot output, in case users wants to generate dot files for assertions
1817 predicate_evaluator:tcltk_analyse_assertions(ALL,_ASSRES,Infos), % also checks CSP assertions
1818 unset_analyse_hook,
1819 printsilent(Infos),nls,
1820 accumulate_infos(assertions,Infos),
1821 write_important_xml_element_to_log(check_assertions,Infos),
1822 check_required_infos(ReqInfos,Infos,check_assertions),
1823 writeln_log_time(finished_check_assertions(NOW,Infos)),
1824 loaded_root_filename(RootName),
1825 formatsilent('% Finished checking ASSERTIONS of ~w~n',[RootName]),!.
1826 cli_check_assertions(ALL,ReqInfos,NOW) :-
1827 add_internal_error('Analyse ASSERTIONS unexpectedly failed',cli_check_assertions(ALL,ReqInfos,NOW)),
1828 error_occurred(internal_error).
1829 cli_set_goal(GOAL) :-
1830 debug_println(20,set_goal(GOAL)), %print(set_goal(GOAL)), nl,
1831 (bmachine:b_set_machine_goal(GOAL) -> true
1832 ; add_error(scope,'Setting GOAL predicate failed:',GOAL)).
1833 cli_add_additional_property(PROP) :-
1834 debug_println(20,add_additional_property(PROP)),
1835 (bmachine:add_additional_property(PROP,'command line -property') -> true
1836 ; add_error(scope,'Adding additional predicate to PROPERTIES failed:',PROP)).
1837 cli_set_searchscope(GOAL) :-
1838 debug_println(20,set_searchscope(GOAL)),
1839 format('Setting SCOPE for verification: ~w~n (Only states satisfying this predicate will be examined)~n',[GOAL]),
1840 (b_or_z_mode, bmachine:b_set_machine_searchscope(GOAL) -> true
1841 ; (xtl_mode, xtl_interface:xtl_set_search_scope(GOAL) -> true
1842 ; add_error(scope,'Setting model checking search SCOPE failed:',GOAL))
1843 ).
1844 cli_check_goal :- \+ b_get_machine_goal(_),!,
1845 add_error(cli_check_goal,'No GOAL DEFINITION found'),
1846 error_occurred(cli_check_goal).
1847 cli_check_goal :-
1848 printsilent('% Checking GOAL predicate: '),nls,
1849 tcltk_analyse_goal(_List,Summary),
1850 debug_println(20,Summary),
1851 accumulate_infos(check_goal,Summary),
1852 write_important_xml_element_to_log(check_goal,Summary),
1853 check_required_infos([false/0,unknown/0],Summary,check_goal).
1854 :- public cli_mc/2. % for REPL
1855 cli_mc(Nr,Opts) :- probcli_time_stamp(NOW), cli_start_model_check(Nr,NOW,Opts).
1856 cli_start_model_check(Nr,NOW,Options) :-
1857 (member(reset_state_space,Options)
1858 -> formatsilent('Resetting state space for benchmarking model checking (limit:~w, options:~w)~n',[Nr, Options]),
1859 announce_event(reset_specification) % for benchmarking purposes
1860 %,state_space:portray_state_space,nl
1861 ; true),
1862 start_xml_feature(model_check,max_states,Nr,FINFO),
1863 regular_safety_model_check_now(Nr,Time,WallTime,MCRes,NOW),
1864 %nl,
1865 stop_xml_feature(model_check,FINFO),
1866 get_state_space_stats(TS,TT,PT,IgnT),
1867 statistics_memory_used(Mem),
1868 (MCRes=time_out -> TInfos=[timeout/1] ; TInfos=[]),
1869 accumulate_infos(model_check,[runtime-Time,walltime-WallTime, % mc only runtime, and total wall time
1870 processed_states/PT,total_states/TS,total_transitions/TT,
1871 ignored_states/IgnT, memory_used/Mem|TInfos]), %for bench_csv output
1872 writeln_log_time(model_check(NOW,Nr,Time,WallTime,MCRes)),
1873 (select(repeat(RepNr),Options,RestOptions)
1874 -> (RepNr>1
1875 -> N1 is RepNr-1,
1876 cli_start_model_check(Nr,NOW,[repeat(N1)|RestOptions])
1877 ; merge_accumulated_infos(model_check)
1878 )
1879 ; true
1880 ).
1881
1882 cli_start_mc_with_tlc :-
1883 (animation_mode(b), \+ animation_minor_mode(eventb) -> true
1884 ; error_manager: add_error_and_fail(mc_with_tlc,'TLC4B tool can be used only for classical B models.')),
1885 % TO DO: use b_write_eventb_machine_to_classicalb_to_file to do conversion
1886 catch(
1887 safe_absolute_file_name(prob_lib('TLC4B.jar'),TLC4BTool),
1888 error(E,_),
1889 error_manager:add_error_fail(get_tlc_command,'Could not find TLC4B.jar file.',E)),
1890 start_xml_feature(model_check_with_tlc,tlc4bjar,TLC4BTool,FINFO),
1891 construct_and_execute_tlc_command(TLC4BTool),
1892 stop_xml_feature(model_check_with_tlc,FINFO).
1893
1894 :- use_module(system_call,[system_call/4]).
1895 construct_and_execute_tlc_command(TLC4BTool) :-
1896 parsercall: get_java_command_path(JavaCmd),
1897 loaded_main_file(File),
1898 % determine extra arguments:
1899 (get_preference(tlc_number_of_workers,TLCWorkers), TLCWorkers>1
1900 -> number_codes(TLCWorkers,CC), atom_codes(TLAWA,CC), WW = ['-workers',TLAWA]
1901 ; WW=[]),
1902 (option(no_assertion_violations) -> WA = ['-noass'] ; WA=[]),
1903 (option(no_deadlocks) -> WD = ['-nodead'] ; WD=[]),
1904 (option(no_invariant_violations) -> WI = ['-noinv'] ; WI=[]),
1905 (option(no_goal) -> WG = ['-nogoal'] ; WG=[]),
1906 (option(no_ltl) -> WL = ['-noltl'] ; WL=[]),
1907 (option_verbose -> WV = ['-verbose'] ; WV=[]),
1908 (option(silent) -> WS = ['-silent'] ; WS=[]),
1909 (option(logtlc(Log)) -> WLG = ['-log',Log] ; WLG=[]),
1910 (get_preference(tlc_use_prob_constant_setup,true),
1911 tcltk_get_constants_predicate(DNF_Pred)
1912 -> WCS = ['-constantssetup', DNF_Pred]
1913 ; WCS=[]),
1914 append([WW,WA,WD,WI,WG,WL,WCS,WV,WS,WLG,[File]],TLCArgs),
1915 debug_println(19,tlc_args(TLCArgs)),
1916 statistics(walltime,[W1,_]),
1917 % we could call get_jvm_options: '-Xss5m' is useful e.g. for Generated1000.mch
1918 system_call(JavaCmd, ['-Xss5m', '-jar', TLC4BTool | TLCArgs], Text,JExit),
1919 statistics(walltime,[W2,_]),
1920 WTime is W2-W1,
1921 formatsilent('exit : ~w walltime: ~w ms~n',[JExit,WTime]),
1922 (JExit=exit(0)
1923 -> accumulate_infos(mc_with_tlc,[walltime-WTime,model_check_ok-1])
1924 ; accumulate_infos(mc_with_tlc,[walltime-WTime,model_check_error-1]),
1925 add_error(construct_and_execute_tlc_command,'Error while model checking with TLC: ',TLC4BTool/File),
1926 atom_codes(T,Text),
1927 add_error_fail(construct_and_execute_tlc_command,'Std error: ',T)
1928 ).
1929
1930 % SymbolicOrSequential = symbolic or sequential
1931 cli_start_sym_mc_with_lts(SymbolicOrSequential) :-
1932 (option(no_deadlocks) -> NoDead = true ; NoDead = false),
1933 (option(no_invariant_violations) -> NoInv = true ; NoInv = false), % does LTSMin support goal checking
1934 findall(Option,option(ltsmin_option(Option)),MoreFlags1),
1935 findall(ltl_formula(LTLF),option(ltl_formula_model_check(LTLF,_)),MoreFlags2),
1936 append(MoreFlags1,MoreFlags2,MoreFlags),
1937 (NoDead = false, NoInv = false ->
1938 print_error('ERROR: cannot start LTSmin with both deadlock and invariant checking'),
1939 print_error(' use either the -noinv or -nodead flag'),
1940 flush_output(user_error)
1941 ; true),
1942 formatsilent('starting prob2lts-sym/seq (flags nodead=~w, noinv=~w, moreflags=~w)~n',[NoDead,NoInv,MoreFlags]),
1943 statistics(walltime,[W1,_]),
1944 start_ltsmin(SymbolicOrSequential, [NoDead, NoInv], MoreFlags,Result),
1945 process_ltsmin_result(Result,AccInfos),
1946 statistics(walltime,[W2,_]), WT is W2-W1,
1947 accumulate_infos(mc_with_lts_min(SymbolicOrSequential),[walltime-WT|AccInfos]).
1948 % TO DO: start lts-sym + start start_ltsmin_srv('/tmp/ltsmin.probz', NOW) + print output
1949
1950 :- use_module(extension('ltsmin/ltsmin_trace'),[csv_to_trace/3]).
1951 process_ltsmin_result(ltsmin_model_checking_ok,[model_check_ok-1]) :-
1952 print_green('LTSMin found no counter example\n').
1953 process_ltsmin_result(ltsmin_model_checking_aborted,[model_check_aborted-1]) :-
1954 add_warning(ltsmin_model_checking_aborted,'LTSMin was aborted (e.g., by CTRL-C)').
1955 process_ltsmin_result(ltsmin_counter_example_found(CsvFile),[model_check_counter_example-1]) :-
1956 add_error(ltsmin_counter_example_found,'LTSMin found a counter example, written to:',CsvFile),
1957 (option(silent) -> true
1958 ; csv_to_trace(CsvFile,_States,Transitions) ->
1959 print('*** TRACE: '),nl,print_list(Transitions) % ,print(_States),nl
1960 ; add_error(ltsmin,'Could not extract trace information from LTSmin file: ',CsvFile)
1961 ).
1962
1963 :- use_module(symbolic_model_checker(ic3), [ic3_symbolic_model_check/1]).
1964 :- use_module(symbolic_model_checker(ctigar), [ctigar_symbolic_model_check/1]).
1965 :- use_module(symbolic_model_checker(kinduction), [kinduction_symbolic_model_check/1,
1966 tinduction_symbolic_model_check/1]).
1967 :- use_module(symbolic_model_checker(bmc), [bmc_symbolic_model_check/1]).
1968 cli_symbolic_model_check(Algorithm) :-
1969 debug_format(20,'% Starting Symbolic Model Check. Using ~w Algorithm', [Algorithm]),
1970 start_xml_feature(model_check,algorithm,Algorithm,FINFO),
1971 (animation_mode(b)
1972 -> true
1973 ; error_manager:add_error_and_fail(cli_symbolic_model_check,'Symbolic Model Checking is currently only available for B and Event-B.')),
1974 perform_symbolic_model_checking(Algorithm,Result),
1975 handle_symbolic_model_check_result(Result),
1976 stop_xml_feature(model_check,FINFO).
1977
1978 perform_symbolic_model_checking(ic3,Result) :- !, ic3_symbolic_model_check(Result).
1979 perform_symbolic_model_checking(ctigar,Result) :- !, ctigar_symbolic_model_check(Result).
1980 perform_symbolic_model_checking(kinduction,Result) :- !, kinduction_symbolic_model_check(Result).
1981 perform_symbolic_model_checking(tinduction,Result) :- !, tinduction_symbolic_model_check(Result).
1982 perform_symbolic_model_checking(bmc,Result) :- !, bmc_symbolic_model_check(Result).
1983 perform_symbolic_model_checking(Alg,_) :- add_error_fail(cli_symbolic_model_check,'Invalid symbolic model checking algorithm: ',Alg).
1984
1985 handle_symbolic_model_check_result(counterexample_found) :- !, error_occurred(invariant_violation).
1986 handle_symbolic_model_check_result(property_holds) :- !,
1987 format('Model checking complete, invariant holds~n',[]).
1988 handle_symbolic_model_check_result(solver_and_provers_too_weak) :- !,
1989 format('Model checking incomplete because a constraint could not be solved in time~n',[]),
1990 error_occurred(model_check_incomplete).
1991 handle_symbolic_model_check_result(limit_reached) :- !,
1992 format('Model checking incomplete because an iteration limit was reached~n',[]),
1993 error_occurred(model_check_incomplete).
1994
1995 zmq_start_master(invariant,Identifier) :-
1996 start_animation_without_computing,
1997 zmq_get_initialisation_term(InitTerm),
1998 (option(strict_raise_error) -> Strict = 1 ; Strict = 0),
1999 get_preference(port, PortStart),
2000 get_preference(max_states, Max),
2001 get_preference(ip, IP),
2002 get_preference(logdir, LogDir),
2003 get_preference(tmpdir, TmpDir),
2004 get_preference(hash_cycle, HashCycle),
2005 atom_concat(LogDir, '/distb-', ATmp),
2006 atom_concat(ATmp, Identifier, Logfile),
2007 atom_concat(TmpDir, '/db-distb-', TTmp),
2008 atom_concat(TTmp, Identifier, TmpDir2),
2009 start_master(InitTerm,Max,PortStart,Strict,IP,Logfile,TmpDir2,HashCycle),
2010 halt.
2011 zmq_start_master(assertion,Identifier) :-
2012 get_preference(port, PortStart),
2013 get_preference(logdir, LogDir),
2014 get_preference(ip, IP),
2015 get_preference(tmpdir, TmpDir),
2016 get_preference(hash_cycle, HashCycle),
2017 atom_concat(LogDir, '/distb-', ATmp),
2018 atom_concat(ATmp, Identifier, Logfile),
2019 atom_concat(TmpDir, '/db-distb-', TTmp),
2020 atom_concat(TTmp, Identifier, TmpDir2),
2021 current_state_corresponds_to_setup_constants_b_machine,
2022 animation_mode(b),
2023 full_b_machine(Machine),
2024 b_get_assertions(_,static,SAss),
2025 b_get_assertions(_,dynamic,DAss),
2026 append(SAss,DAss,Ass),
2027 count_assertions(Ass,0,N),
2028 assertz(master:assertion_count(N)),
2029 current_expression(_,State1),
2030 specfile:state_corresponds_to_set_up_constants(State1,State),
2031 zmq_get_important_options(Options),
2032 (option(strict_raise_error) -> Strict = 1 ; Strict = 0),
2033 %start_master(assertions(classical_b(Machine,Options),State,Ass),2,-1,PortStart,0,Strict,IP,Logfile,TmpDir2),
2034 start_master(assertions(classical_b(Machine,Options),State,Ass),2,PortStart,Strict,IP,Logfile,TmpDir2,HashCycle),
2035 halt.
2036
2037 zmq_get_initialisation_term(Term) :-
2038 (animation_mode(b) ; animation_mode(csp_and_b)), % CSP file not yet added when ZMQ master starts working
2039 \+ animation_minor_mode(eventb),
2040 option(add_csp_guide(CspGuide)),
2041 !, % Classical B + CSP
2042 debug_println(20,'ZMQ: Transferring CSP || B model'),
2043 full_b_machine(Machine),
2044 % TO DO: extract CSP Term rather than file name: will not work for distribution on other file-systems
2045 zmq_get_important_options(Options),
2046 Term = classical_b_with_csp(Machine,CspGuide,Options).
2047 zmq_get_initialisation_term(Term) :-
2048 debug_println(20,'Generating ZMQ Worker Initialisation'),
2049 animation_mode(b), \+ animation_minor_mode(eventb), !, % Classical B
2050 debug_println(20,'ZMQ: Transferring Classical-B model'),
2051 full_b_machine(Machine),
2052 zmq_get_important_options(Options),
2053 Term = classical_b(Machine,Options).
2054 zmq_get_initialisation_term(Term) :-
2055 animation_mode(b), animation_minor_mode(eventb), !, % Event-B
2056 debug_println(20,'ZMQ: Transferring Event-B model'),
2057 full_b_machine(Machine),
2058 zmq_get_important_options(Options),
2059 Term = eventb(Machine,Options).
2060 zmq_get_initialisation_term(Term) :-
2061 animation_mode(cspm),
2062 loaded_main_file(MainCSPFile),!, % TO DO: pass CSP Prolog term rather than file name (for distribution)
2063 zmq_get_important_options(Options),
2064 debug_println(20,'ZMQ: Transferring CSP specification'),
2065 Term = csp_specification(MainCSPFile,Options).
2066 zmq_get_initialisation_term(_Term) :-
2067 \+ real_error_occurred, % otherwise error occured while loading
2068 animation_mode(Mode),
2069 add_internal_error('Unsupported formalism for ZMQ', Mode),
2070 fail.
2071
2072 zmq_get_initialisation_term(filename(FN)) :-
2073 loaded_main_file(FN).
2074
2075 % get important command-line options to be transmitted to probcli worker
2076 zmq_get_important_options(Options) :- findall(O, (option(O), zmq_important_option(O)), Options),
2077 debug_println(20,transferring_zmq_options_to_workers(Options)).
2078 zmq_important_option(coverage(_)).
2079 zmq_important_option(expect_error(_)).
2080 zmq_important_option(optional_error(_)).
2081 zmq_important_option(file_info).
2082 zmq_important_option(log(_)).
2083 zmq_important_option(print_version(_)).
2084 zmq_important_option(profiling_on).
2085 zmq_important_option(set_card(_,_)).
2086 zmq_important_option(set_pref(_,_)).
2087 zmq_important_option(set_preference_group(_,_)).
2088 zmq_important_option(statistics).
2089 zmq_important_option(csv_table_command(_,_,_,_)).
2090 zmq_important_option(verbose(_)).
2091 zmq_important_option(set_searchscope(_)).
2092 zmq_important_option(no_invariant_violations).
2093 %zmq_important_option(no_deadlocks).
2094 %zmq_important_option(no_goal).
2095 % we could consider also supporting: -argv, -cache, -prefs FILE csp_main(ProcessName) profiling_on prob_profile runtimechecking
2096
2097 % set options received by a zmq worker
2098 :- use_module(b_global_sets, [set_user_defined_scope/2]).
2099 :- use_module(tools_strings, [convert_cli_arg/2]).
2100 zmq_set_important_options(Options) :- debug_println(20,setting_zmq_options(Options)),
2101 maplist(prob_cli:zmq_set_option,Options).
2102 zmq_set_option(file_info) :- !, file_info.
2103 zmq_set_option(log(F)) :- !,
2104 generate_time_stamp(Datime,NOW),
2105 cli_start_logging(F,ascii,NOW,Datime,[zmq_worker]).
2106 zmq_set_option(print_version(V)) :- !, print_version(V).
2107 zmq_set_option(profiling_on) :- !, profiling_on.
2108 zmq_set_option(set_card(Set,V)) :- !,
2109 convert_cli_arg(V,Value),
2110 set_user_defined_scope(Set,Value).
2111 zmq_set_option(set_pref(P,V)) :- !, set_pref(P,V).
2112 zmq_set_option(set_preference_group(P,V)) :- !, set_preference_group(P,V).
2113 zmq_set_option(verbose(Nr)) :- !, verbose(Nr).
2114 zmq_set_option(O) :- zmq_delayed_option(O),!, assert_option(O). % DO IT LATER
2115 zmq_set_option(O) :- add_internal_error('Unsupported option for ZMQ worker: ',zmq_set_option(O)).
2116
2117 zmq_delayed_option(coverage(_)).
2118 zmq_delayed_option(expect_error(_)).
2119 zmq_delayed_option(expect_error_pos(_,_,_)).
2120 zmq_delayed_option(optional_error(_)).
2121 zmq_delayed_option(statistics).
2122 zmq_delayed_option(set_searchscope(_)).
2123 zmq_delayed_option(no_invariant_violations). % not supported yet
2124
2125 ltsmin_ltl_output(Filename, NOW) :-
2126 if_option_set(ltl_formula_model_check(Formula, _),true),
2127 ltsmin_generate_ltlfile(Formula, Filename),
2128 halt_prob(NOW,0). % if we additionally specify -ltsformula, we do not want to model check it
2129
2130
2131 start_ltsmin_srv(X, NOW) :-
2132 nls,println_silent('Starting LTSMin Server...'),
2133 if_option_set(ltl_formula_model_check(Formula, _),true),
2134 ltsmin_init(X, Zocket, Formula),
2135 ltsmin_loop(Zocket),
2136 ltsmin_teardown(Zocket, X),
2137 nls,println_silent('Stopped LTSMin Server.'),
2138 halt_prob(NOW,0). % if we additionally specify -ltsformula, we do not want to model check it
2139
2140 zmq_start_worker(Identifier, NOW) :-
2141 get_preference(port, Port),
2142 get_preference(logdir, LogDir),
2143 get_preference(tmpdir, TmpDir),
2144 get_preference(proxynumber, ProxyNumber),
2145 /* TODO: ensure directory exists (pk, 09.01.2018) */
2146 atom_concat(LogDir, '/worker-', ATmp),
2147 atom_concat(ATmp, Identifier, Logfile),
2148 % TODO: tmp dir currently not used
2149 atom_concat(TmpDir, '/db-worker-', TTmp),
2150 atom_concat(TTmp, Identifier, TmpDir2),
2151 start_worker(Port,ProxyNumber,Logfile,TmpDir2,zmq_worker_load_model),
2152 formatsilent('ZMQ worker finished (Port:~w)~n',[Port]),
2153 cli_process_loaded_file_afer_start_animation(NOW),
2154 println_silent('Exiting probcli worker'),
2155 halt_prob(NOW,0).
2156
2157 zmq_start_animation :-
2158 prob2_interface:start_animation,
2159 if_option_set(set_goal(GOAL),
2160 cli_set_goal(GOAL)), % not used yet
2161 if_option_set(set_searchscope(SCOPE),
2162 cli_set_searchscope(SCOPE)),
2163 cli_computeOperations(_).
2164 zmq_worker_load_model(classical_b(Machine,Options)) :- !,
2165 debug_println(20,'ZMQ WORKER: Loading classical B model'),
2166 zmq_set_important_options(Options),
2167 bmachine:b_machine_reset, bmachine:assert_main_machine(Machine),
2168 set_animation_mode(b),
2169 zmq_start_animation.
2170 zmq_worker_load_model(classical_b_with_csp(Machine,CspGuide,Options)) :- !,
2171 debug_println(20,'ZMQ WORKER: Loading CSP || B model'),
2172 zmq_set_important_options(Options),
2173 bmachine:b_machine_reset, bmachine:assert_main_machine(Machine),
2174 set_animation_mode(b),
2175 prob2_interface:start_animation,
2176 tcltk_add_csp_file(CspGuide), % TO DO: use CSP Prolog term rather than filename <----------------
2177 zmq_start_animation.
2178 zmq_worker_load_model(eventb(Machine,Options)) :- !,
2179 print(loading_eventb(Options)),nl,
2180 zmq_set_important_options(Options),
2181 bmachine:b_machine_reset, bmachine:assert_main_machine(Machine),
2182 set_animation_mode(b), set_animation_minor_mode(eventb),
2183 zmq_start_animation.
2184 zmq_worker_load_model(csp_specification(CSPFile,Options)) :-
2185 zmq_set_important_options(Options),
2186 load_cspm_spec_from_cspm_file(CSPFile), % TO DO: pass CSP Prolog term rather than filename
2187 zmq_start_animation.
2188 zmq_worker_load_model(filename(FN)) :- !,
2189 printsilent('loading file by filename\n'),flush_output,
2190 ( is_eventb_b(FN) ->
2191 eclipse_interface:load_eventb_file(FN)
2192 ;
2193 bmachine:b_load_machine_probfile(FN)),
2194 zmq_start_animation.
2195 zmq_worker_load_model(assertions(Machine,State,Assertions)) :- !,
2196 assertz(assertion_counter(-1)),
2197 println_silent(loaded_model_for_assertion_checking),
2198 zmq_worker_load_model(Machine),
2199 assertz(worker:assertion_state(State)),
2200 make_assertionwps(Assertions).
2201 % assert current state
2202 zmq_worker_load_model(Other) :-
2203 add_internal_error('ZMQ worker: Unexpected machine description', zmq_worker_load_model(Other)),
2204 fail.
2205
2206
2207 :-dynamic assertion_counter/1.
2208
2209 count_assertions([],A,A).
2210 count_assertions([H|T],A,R) :- size_of_conjunction(H,N1),
2211 NN is A + N1,
2212 count_assertions(T,NN,R).
2213
2214 make_assertionwps([]).
2215 make_assertionwps([H|T]) :- conjunction_to_list(H,HL),
2216 sort_assertions(HL,SL),
2217 append_assertion(SL),
2218 make_assertionwps(T).
2219
2220 append_assertion([]).
2221 append_assertion([H|T]) :- assertion_counter(N),
2222 retractall(assertion_counter(_)),
2223 N1 is N + 1,
2224 assertz(assertion_counter(N1)),
2225 assertz(worker:assertion_task(N1,H)),
2226 append_assertion(T).
2227
2228 %assertions_order(A,B) :- term_size(A,NA),term_size(B,NB), NA > NB.
2229 sort_assertions(X,X).
2230 % :- samsort(assertions_order,X,Y).
2231
2232
2233
2234 is_eventb_b(FN) :- append(_,FN,".eventb").
2235 % load_model(Initialisation)
2236
2237
2238 :- use_module(predicate_evaluator).
2239 :- use_module(bmachine,[b_machine_name/1]).
2240 set_analyse_hook(AddPrefix) :- % set a hook to write false/unknown expressions into a dot file
2241 reset_dot_file_number,
2242 if_options_set(dot_analyse_output_prefix(_Path),
2243 (set_dot_file_prefix_if_option_set(AddPrefix),
2244 register_conjunct_error_hook(prob_cli:pred_eval_hook))).
2245 unset_analyse_hook :- predicate_evaluator:reset_conjunct_error_hook.
2246
2247 :- use_module(tools,[get_modulename_filename/2]).
2248 loaded_root_filename(RootName) :- loaded_main_file(MainFile),
2249 get_modulename_filename(MainFile,RootName).
2250
2251 set_dot_file_prefix_if_option_set(AddPrefix) :-
2252 if_options_set(dot_analyse_output_prefix(Path),
2253 (loaded_root_filename(RootName),
2254 % we could also use b_machine_hierarchy:main_machine_name(RootName)
2255 string_concatenate(Path,RootName,P1),
2256 string_concatenate(P1,AddPrefix,FullPath),
2257 set_dot_file_prefix(FullPath),
2258 debug_println(9,dot_file_prefix(FullPath)))).
2259
2260 % Status: true, false, unknown
2261 :- public pred_eval_hook/5.
2262 pred_eval_hook(_Conjunct,true,_EnumWarning,_IsExpanded, _CS) :-
2263 \+ option(dot_generate_for_all_formulas),!. % don't generate .dot for true formulas, unless explicitly requested
2264 pred_eval_hook(Conjunct,Status,_EnumWarning,_IsExpanded, CS) :-
2265 printsilent('Generating dotfile for: '),printsilent(CS),nls,
2266 (write_dot_graph_to_new_file(Status,Conjunct) -> true
2267 ; add_error(dot_output,'Writing dot to file failed: ',CS)).
2268
2269
2270 :- dynamic dot_file_prefix/1.
2271 :- dynamic dot_file_number/1.
2272
2273 dot_file_prefix('~/Desktop/dot').
2274 set_dot_file_prefix(F) :- retractall(dot_file_prefix(_)), assertz(dot_file_prefix(F)).
2275 dot_file_number(0).
2276 reset_dot_file_number :- retractall(dot_file_number(_)), assertz(dot_file_number(0)).
2277 get_next_nr(GNr) :- retract(dot_file_number(Nr)), N1 is Nr+1,
2278 assertz(dot_file_number(N1)), GNr = Nr.
2279 write_dot_graph_to_new_file(Status,BExpr) :-
2280 dot_file_prefix(Dir),get_next_nr(Nr),
2281 string_concatenate('_',Status,Str1),
2282 string_concatenate(Nr,Str1,NS),
2283 string_concatenate(Dir,NS,F1),
2284 atom_concat(F1,'.dot',FileName),
2285 tcltk_interface:write_dot_file_for_pred_expr(BExpr,FileName).
2286
2287 % get dot file name if dot_output has been set
2288 get_dot_file(Type,FileName) :- option(dot_analyse_output_prefix(_)),
2289 set_dot_file_prefix_if_option_set(Type),
2290 dot_file_prefix(Dir),
2291 string_concatenate('_',Type,Str1),
2292 string_concatenate(Dir,Str1,F1),
2293 atom_concat(F1,'.dot',FileName).
2294
2295 :- use_module(extrasrc(refinement_checker),
2296 [tcltk_refinement_search/3, tcltk_load_refine_spec_file/1, tcltk_save_specification_state_for_refinement/1]).
2297 cli_csp_in_situ_refinement_check(P,Type,Q,NOW) :-
2298 debug_println(20,'% Starting CSP Refinement Check'),
2299 loaded_main_file(CSPFile),
2300 ajoin_with_sep(['assert',P,Type,Q], ' ',Assertion),
2301 start_xml_feature(csp_refinement_check,assertion,Assertion,FINFO),
2302 ( timeout_call(tcltk_interface:tcltk_check_csp_assertion(Assertion,CSPFile,'False',_PlTerm,RefTrace),NOW,'cspref')
2303 -> check_ref_result(RefTrace)
2304 ; true),
2305 stop_xml_feature(csp_refinement_check,FINFO).
2306 cli_start_refinement_check(RefFile,FailuresModel,RefNrNodes,NOW) :-
2307 start_xml_feature(refinement_check,file,RefFile,FINFO),
2308 tcltk_load_refine_spec_file(RefFile),
2309 ( timeout_call(tcltk_refinement_search(RefTrace,FailuresModel,RefNrNodes),NOW,refinement_check)
2310 -> check_ref_result(RefTrace)
2311 ; true),
2312 stop_xml_feature(refinement_check,FINFO).
2313 check_ref_result(RefTrace) :-
2314 ( RefTrace==no_counter_example ->
2315 print('==> Refinement Check Successful'),nl
2316 ; RefTrace==no_counter_example_found ->
2317 print('==> Refinement Check did not find Counter-Example but is incomplete'),nl,
2318 error_occurred(refinement_check_incomplete)
2319 ;
2320 print('*** Refinement Check Counter-Example: ***'),nl, print(RefTrace),nl,
2321 print('*** Refinement Check Failed ***'),nl,
2322 error_occurred(refinement_check_fails)).
2323 cli_checkAssertion(Proc,Model,AssertionType,_NOW) :-
2324 loaded_main_file(CSPFile),
2325 ajoin(['assert ',Proc,' :[ ',AssertionType,'[',Model,']',' ]'],Assertion),
2326 start_xml_feature(csp_deadlock_check,assertion,Assertion,FINFO),
2327 ( /*timeout_call(*/tcltk_interface:tcltk_check_csp_assertion(Assertion,CSPFile,'False',_PlTerm,ResTrace)/*,NOW,a)*/
2328 -> check_model_result(Assertion,ResTrace)
2329 ; true),
2330 stop_xml_feature(csp_deadlock_check,FINFO).
2331 cli_check_csp_assertion(Assertion,NOW) :-
2332 start_xml_feature(csp_assertion_check,assertion,Assertion,FINFO),
2333 loaded_main_file(CSPFile),
2334 ajoin(['assert ',Assertion],AssertionFull),
2335 ( timeout_call(tcltk_interface:tcltk_check_csp_assertion(AssertionFull,CSPFile,_Negated,PlTerm,ResTrace),NOW,csp_assertion_check)
2336 -> check_model_result(PlTerm,ResTrace)
2337 ; true),
2338 stop_xml_feature(csp_assertion_check,FINFO).
2339
2340
2341
2342 check_model_result(AssertionPlTerm,ResTrace) :-
2343 ( ResTrace==no_counter_example ->
2344 printsilent('==> Model Check Successful'),nls
2345 ;
2346 (functor(AssertionPlTerm,assertRef,_Arity) ->
2347 print('*** Refinement Check Counter-Example: ***'),nl, print(ResTrace),nl,
2348 print('*** Refinement Check Failed ***'),nl,
2349 error_occurred(refinement_check_fails)
2350 ;
2351 print('*** Model Check Counterexample: ***'),nl,print(ResTrace),nl,
2352 print('*** Model Check Failed ***'),nl,
2353 error_occurred(model_check_fails))
2354 ).
2355 :- use_module(probcspsrc(haskell_csp),[get_csp_assertions_as_string/2,
2356 parse_and_load_cspm_file_into_specific_pl_file/2,
2357 evaluate_csp_expression/2, evaluate_csp_expression/3]).
2358 cli_csp_get_assertions :-
2359 loaded_main_file(CSPFile),
2360 get_csp_assertions_as_string(CSPFile,String),
2361 print('*** Assertions in File (separated by $) ***'),nl,print(String),nl.
2362 cli_eval_csp_expression(E) :-
2363 (loaded_main_file(CSPFile) ->
2364 evaluate_csp_expression(E, CSPFile, Res)
2365 ; evaluate_csp_expression(E,Res)
2366 ), print('Evaluated Expression: '),nl,print(Res),nl.
2367 cli_csp_translate_to_file(PlFile) :-
2368 loaded_main_file(CSPFile),
2369 parse_and_load_cspm_file_into_specific_pl_file(CSPFile,PlFile).
2370 :- use_module(probltlsrc(ltl_fairness),[check_scc_ce/2]).
2371 cli_check_scc_for_ltl_formula(LtlFormula,SCC) :-
2372 check_scc_ce(LtlFormula,SCC).
2373
2374 :- use_module(extrasrc(coverage_statistics),[pretty_print_coverage_information_to_file/1]).
2375 cli_get_coverage_information(FileName) :-
2376 pretty_print_coverage_information_to_file(FileName).
2377 cli_vacuity_check :-
2378 eclipse_interface:get_vacuous_invariants(L),
2379 (L=[] -> print('No vacuous invariants'),nl
2380 ; maplist(prob_cli:add_vacuous_invariant,L)).
2381 add_vacuous_invariant(Inv) :-
2382 translate:translate_bexpression(Inv,TI),
2383 add_error(vacuity_check,'Vacuous invariant: ',TI).
2384 cli_start_socketserver(Port,Loopback) :-
2385 printsilent('Starting Socket Server'),nls,
2386 safe_absolute_file_name(prob_home('.'),AppDir),
2387 printsilent('Application Path: '),printsilent(AppDir),nls,
2388 disable_interaction_on_errors,
2389 ( start_prob_socketserver(Port,Loopback) -> true
2390 ;
2391 print('Starting socket server failed, Port: '), print(Port),nl),
2392 printsilent('Finished Socket Server'),nls.
2393 :- use_module(tools_platform, [platform_is_64_bit/0]).
2394 cli_check_statespace_hash(Expected,Kind) :-
2395 printsilent('Computing hash of entire statespace: '),
2396 compute_full_state_space_hash(Hash),
2397 printsilent(Hash),nls, % TO DO: maybe also compute hash for transitions and check that
2398 (Hash=Expected -> true
2399 ; Kind=='64bit', \+ platform_is_64_bit -> format('Hash does not match ~w (but was computed on 64-bit system)~n',[Expected])
2400 ; Kind=='32bit', platform_is_64_bit -> format('Hash does not match ~w (but was computed on 32-bit system)~n',[Expected])
2401 ; add_error(hash,'Expected Statespace Hash to be: ',Expected)).
2402 :- use_module(extrasrc(b_operation_cache),[get_op_cache_stats/1]).
2403 cli_check_op_cache(ReqInfos) :-
2404 get_op_cache_stats(Stats),
2405 (ReqInfos=[] -> format('Operation caching statistics: ~w~n',[Stats])
2406 ; formatsilent('Operation caching statistics: ~w~n',[Stats])),
2407 accumulate_infos(op_cache,Stats),
2408 check_required_infos(ReqInfos,Stats,op_cache_stats).
2409 cli_show_coverage(ShowEnabledInfo,NOW) :-
2410 cli_show_coverage(_Nodes,_Operations,ShowEnabledInfo,NOW).
2411 cli_show_coverage(Nodes,Operations,ShowEnabledInfo,NOW) :-
2412 ShowEnabledInfo == just_check_stats,!, % no printing of individual transition coverage
2413 get_state_space_stats(TotalNodeSum,TotalTransSum,_ProcessedTotal,_), % no computation overhead
2414 writeln_log(computed_coverage(NOW,TotalNodeSum,TotalTransSum)),
2415 check_totals(Nodes,Operations,TotalNodeSum,TotalTransSum).
2416 cli_show_coverage(Nodes,Operations,ShowEnabledInfo,NOW) :-
2417 ShowEnabledInfo == just_summary,
2418 !, % no printing of detailed transition coverage (avoid traversing state space)
2419 get_state_space_stats(TotalNodeSum,TotalTransSum,ProcessedTotal,Ignored), % no computation overhead
2420 writeln_log(computed_coverage(NOW,TotalNodeSum,TotalTransSum)),
2421 format('Coverage:~n States: ~w (~w processed, ~w ignored)~n Transitions: ~w~n',
2422 [TotalNodeSum,ProcessedTotal,Ignored,TotalTransSum]),
2423 show_initialisation_summary(NOW),
2424 show_operation_coverage_summary(NOW),
2425 (invariant_violated(ID) -> format('At least one state violates the invariant (~w) ~n',[ID]) ; true),
2426 check_totals(Nodes,Operations,TotalNodeSum,TotalTransSum).
2427 cli_show_coverage(Nodes,Operations,ShowEnabledInfo,NOW) :-
2428 print('Coverage:'),nl,
2429 compute_the_coverage(Res,TotalNodeSum,TotalTransSum,ShowEnabledInfo,false),
2430 writeln_log(computed_coverage(NOW,TotalNodeSum,TotalTransSum)),
2431 print(Res),nl,
2432 check_totals(Nodes,Operations,TotalNodeSum,TotalTransSum).
2433 check_totals(Nodes,Operations,TotalNodeSum,TotalTransSum) :-
2434 ( Nodes=TotalNodeSum -> true
2435 ;
2436 add_error(probcli,'Unexpected number of nodes: ',TotalNodeSum),
2437 add_error(probcli,'Expected: ',Nodes),error_occurred(coverage)),
2438 ( Operations=TotalTransSum -> true
2439 ;
2440 add_error(probcli,'Unexpected number of transitions: ',TotalTransSum),
2441 add_error(probcli,'Expected: ',Operations),error_occurred(coverage)).
2442
2443
2444 :- use_module(bmachine,[b_machine_statistics/2, b_get_main_filename/1, b_get_all_used_filenames/1,get_full_b_machine_sha_hash/1]).
2445 :- use_module(tools_strings,[get_hex_bytes/2]).
2446 cli_print_machine_info(statistics) :-
2447 b_machine_name(Name),
2448 %(b_get_main_filename(File) -> true ; File=unknown),
2449 format('Machine statistics for ~w:~n',[Name]),
2450 findall(Key/Nr,b_machine_statistics(Key,Nr),L),
2451 maplist(prob_cli:print_keynr,L),!.
2452 cli_print_machine_info(files(WithSha)) :-
2453 b_machine_name(Name),
2454 (WithSha = with_sha -> Msg2='and SHA1 ' ; Msg2=''),
2455 format('Files ~wused for machine ~w:~n',[Msg2,Name]),
2456 b_get_all_used_filenames(Files),
2457 maplist(prob_cli:print_individual_file(WithSha),Files),!.
2458 cli_print_machine_info(hash(Expected)) :-
2459 b_machine_name(MainName), % to do: findall machines and hashes
2460 get_full_b_machine_sha_hash(HashBytes),
2461 get_hex_bytes(HashBytes,Hash),
2462 format('SHA hash for machine ~w = ~s~n',[MainName,Hash]),!,
2463 write_xml_element_to_log(machine_hash,[hash/Hash]),
2464 (var(Expected) -> true
2465 ; atom_codes(Expected,Hash)
2466 -> format_with_colour_nl(user_output,[green],'Machine hash for ~w matches provided hash.',[MainName])
2467 ; add_error(machine_hash_check,'Unexpected machine hash, expected: ',Expected)).
2468 cli_print_machine_info(Kind) :- add_error(machine_stats,'Could not obtain machine information:',Kind).
2469 print_keynr(Key/Nr) :- format(' ~w : ~w~n',[Key,Nr]).
2470 :- use_module(extension('probhash/probhash'),[raw_sha_hash_file/3]).
2471 :- use_module(tools_strings,[get_hex_bytes/2]).
2472 print_individual_file(with_sha,File) :- Span = machine_info,
2473 raw_sha_hash_file(File,Term,Span),
2474 get_hex_bytes(Term,SHAHexCodes),
2475 format(' ~w, ~s~n',[File,SHAHexCodes]).
2476 print_individual_file(_,File) :- format(' ~w~n',[File]).
2477
2478 check_machine_file_sha(File,ExpectedHash) :- Span = check_machine_file_sha,
2479 get_full_machine_file_path(File,AbsFile),
2480 raw_sha_hash_file(AbsFile,Term,Span),
2481 get_hex_bytes(Term,SHAHexCodes), atom_codes(ExpectedHash,ExpectedShaCodes),
2482 (SHAHexCodes=ExpectedShaCodes
2483 -> format_with_colour_nl(user_output,[green],'Checked SHA1 hash for file ~w is ~s',[AbsFile,SHAHexCodes])
2484 ; add_error(check_machine_file_sha,'Unexpected SHA1 hash of file:',AbsFile),
2485 format_with_colour_nl(user_error,[orange],'! Expected: ~w~n! Actual : ~s',[ExpectedHash,SHAHexCodes])
2486 ).
2487
2488 :- use_module(bmachine,[get_machine_file_number/4, b_absolute_file_name_relative_to_main_machine/2]).
2489 :- use_module(probsrc(tools), [get_parent_directory/2]).
2490 get_full_machine_file_path(File,AbsFile) :-
2491 get_modulename_filename(File,Name),
2492 (get_filename_extension(File,ExtF), ExtF \= ''
2493 -> true ; debug_format(19,'No extension provided for file ~w~n',[File])),
2494 (get_machine_file_number(Name,ExtF,_Nr,AbsFile)
2495 -> get_parent_directory(File,Parent),
2496 (Parent='' -> true % no path provided
2497 ; File=AbsFile -> true % full path provided
2498 ; b_absolute_file_name_relative_to_main_machine(File,AbsFile) -> true % consistent partial path provided
2499 ; add_error(check_machine_file_sha,'File path (relative to main model) is inconsistent with used file:',File),
2500 b_absolute_file_name_relative_to_main_machine(File,AbsFile1),
2501 format_with_colour_nl(user_error,[orange],'! Full path in -check_machine_file_sha:~n ~w',[AbsFile1]),
2502 format_with_colour_nl(user_error,[orange],'! File actually used in B main model :~n ~w',[AbsFile])
2503 )
2504 ; get_machine_file_number(_,_,_,_) ->
2505 add_error(check_machine_file_sha,'Could not locate the file for:',File),
2506 b_absolute_file_name_relative_to_main_machine(File,AbsFile)
2507 ; add_message(check_machine_file_sha,'No main B machine loaded for, converting to absolute path: ',File),
2508 absolute_file_name(File,AbsFile)
2509 ).
2510
2511 :- use_module(tools,[get_tail_filename/2]).
2512 xml_log_machine_statistics :-
2513 animation_mode(Major),
2514 (animation_minor_mode(Minor) -> true ; Minor=none),
2515 write_xml_element_to_log(animation_mode,[major/Major,minor/Minor]),
2516 (b_or_z_mode, b_machine_name(Main)
2517 -> findall(Key/Nr,b_machine_statistics(Key,Nr),BMachStats),
2518 (b_get_main_filename(MainFile) -> get_tail_filename(MainFile,TailFile) ; TailFile = unknown),
2519 write_xml_element_to_log(b_machine_statistics,[machine_name/Main, tail_filename/TailFile|BMachStats])
2520 ; true).
2521
2522 cli_print_junit_results(ArgV) :-
2523 junit_mode(S),!,
2524 statistics(runtime,[E,_]),
2525 T is E - S,
2526 create_and_print_junit_result(['Integration Tests'],ArgV,T,pass).
2527 cli_print_junit_results(_).
2528
2529 :- use_module(visbsrc(visb_visualiser),[load_visb_file/1,
2530 tcltk_perform_visb_click_event/1, generate_visb_html_for_history/2]).
2531 cli_visb_history(JSONFile,HTMLFile,Options) :-
2532 (load_visb_file(JSONFile)
2533 -> ifm_option_set(visb_click(SVGID),tcltk_perform_visb_click_event(SVGID)), % simulate clicks if requested
2534 generate_visb_html_for_history(HTMLFile,Options)
2535 ; true). % errors already reported
2536
2537 cli_print_history(HistFile) :-
2538 findall( O, option(history_option(O)), Options),
2539 debug_println(9,writing_history_to_file(HistFile)),
2540 (select(trace_file,Options,ROpt) -> tcltk_save_history_as_trace_file(prolog,ROpt,HistFile) % save as Prolog trace file for replay with -t
2541 ; select(json,Options,ROpt) -> tcltk_save_history_as_trace_file(json,ROpt,HistFile) % save for replay with ProB2 UI
2542 ; write_history_to_file(HistFile,Options) -> true
2543 ; add_error(history,'Writing history to file failed: ',HistFile)).
2544
2545 cli_print_values(ValuesFilename) :-
2546 (write_values_to_file(ValuesFilename) -> true ; add_error(sptxt,'Writing values to file failed: ',ValuesFilename)).
2547 cli_print_all_values(ValuesDirname) :-
2548 (write_all_values_to_dir(ValuesDirname) -> true ; add_error(sstxt,'Writing all values to directory failed: ',ValuesDirname)).
2549
2550 :- use_module(probltlsrc(trace_generator),[generate_all_traces_until/4]).
2551
2552 cli_generate_all_traces_until(LTL_Stop_AsAtom,FilePrefix) :-
2553 generate_all_traces_until(LTL_Stop_AsAtom,FilePrefix,Result,NrTracesGenerated),
2554 format_with_colour_nl(user_error,[blue],'Generated ~w traces, result=~w~n',[NrTracesGenerated,Result]).
2555
2556 :- dynamic probcli_time_stamp/1.
2557 generate_time_stamp(NOW,TS) :- retractall(probcli_time_stamp(_)),
2558 now(NOW),
2559 current_prolog_flag(argv,ArgV),term_hash(ArgV,Hash),
2560 Rnd is Hash mod 1000,
2561 % random(0,1000,Rnd), always returns 216 % TO DO: try to get milliseconds from some library function
2562 TS is (NOW*1000)+Rnd,
2563 assertz(probcli_time_stamp(TS)).
2564 update_time_stamp(NOW1) :- retractall(probcli_time_stamp(_)),
2565 assertz(probcli_time_stamp(NOW1)).
2566
2567 %get_errors :- \+ real_error_occurred,!, (get_error(_Source,_Msg) -> print('*** Warnings occurred'),nl ; true), reset_errors.
2568 get_errors :-
2569 (get_preference(view_probcli_errors_using_bbresults,true)
2570 -> tools_commands:show_errors_with_bb_results([current]) ; true),
2571 get_error_sources.
2572
2573 get_error_sources :- get_error_with_span(ErrSource,Msg,Span), !,
2574 error_occurred_with_msg(ErrSource,Msg,Span),
2575 findall(1,get_error(ErrSource,_),L), length(L,Nr),
2576 (Nr>0 -> N1 is Nr+1, get_error_category_and_type(ErrSource,Cat,Type),
2577 (Type=error -> print_error('*** Occurences of this error: ')
2578 ; print_error('*** Occurences of this warning: ')),
2579 print_error(N1),
2580 write_xml_element_to_log(multiple_errors_occurred,[category/Cat,(type)/Type,number/N1])
2581 ; true),
2582 get_error_sources.
2583 get_error_sources.
2584
2585 :- use_module(state_space,[state_error/3, invariant_violated/1, time_out_for_invariant/1, time_out_for_assertions/1, time_out_for_node/3]).
2586 ?get_state_space_errors :- option(strict_raise_error),
2587 !,
2588 (\+ option(no_invariant_violations),invariant_violated(ID)
2589 -> (option_verbose ->
2590 format('Invariant violation in state with id = ~w~n',[ID]),
2591 b_interpreter:analyse_invariant_for_state(ID) % caused issue for test 1076
2592 ; format('Invariant violation in state with id = ~w (use -v to print more details)~n',[ID])
2593 ),
2594 error_occurred(invariant_violation)
2595 ; true),
2596 (state_error(_,_,abort_error(TYPE,Msg,_,Span)) -> error_occurred(TYPE,error,Span,Msg) ; true),
2597 get_state_errors(_).
2598 get_state_space_errors.
2599
2600 get_state_errors(ID) :- state_error(ID,_,X), X\=invariant_violated, X\=abort_error(_,_,_,_),
2601 create_state_error_description(X,Msg),error_occurred(Msg),fail.
2602 get_state_errors(ID) :- time_out_for_invariant(ID),error_occurred(time_out_for_invariant),fail.
2603 get_state_errors(ID) :- time_out_for_assertions(ID),error_occurred(time_out_for_assertions),fail.
2604 get_state_errors(ID) :- time_out_for_node(ID,_,time_out),error_occurred(time_out),fail.
2605 get_state_errors(ID) :-
2606 time_out_for_node(ID,_,virtual_time_out(_)), %print(virtual_time_out_for_node(ID)),nl,
2607 error_occurred(virtual_time_out),fail.
2608 get_state_errors(_).
2609
2610
2611 create_state_error_description(eventerror(Event,Error,_),Description) :- !,
2612 functor(Error,Functor,_),
2613 ajoin(['event_error:',Event,':',Functor],Description).
2614 create_state_error_description(StateError,Description) :-
2615 functor(StateError,Functor,_),
2616 atom_concat('state_error:',Functor,Description).
2617
2618 % require a real machine to be loaded
2619 check_loaded_not_empty(Action) :-
2620 file_loaded(true,'$$empty_machine'),!,
2621 add_error(probcli,'No file specified; cannot perform command: ',Action),
2622 error_occurred(loading),fail.
2623 check_loaded_not_empty(Action) :- check_loaded(Action).
2624
2625 check_loaded(Action) :-
2626 ( file_loaded(true) -> true
2627 ; file_loaded(error) -> fail /* we have already generated error message */
2628 ;
2629 add_error(probcli,'No file specified; cannot perform action: ',Action),
2630 error_occurred(loading),fail).
2631
2632 :- dynamic loaded_main_file/2.
2633 loaded_main_file(File) :- loaded_main_file(_Ext,File).
2634
2635 :- use_module(tools,[get_filename_extension/2]).
2636 load_main_file(MainFile,NOW,Already_FullyProcessed) :- retractall(loaded_main_file(_,_)),
2637 debug_print(20,'% Loading: '), debug_println(20,MainFile),
2638 writeln_log_time(loading(NOW,MainFile)),
2639 get_filename_extension(MainFile,Ext),
2640 debug_println(6,file_extension(Ext)),
2641 file_extension_can_be_loaded(Ext,MainFile),
2642 start_probcli_timer(Timer),
2643 load_spec_file(Ext,MainFile,Already_FullyProcessed),
2644 stop_probcli_debug_timer(Timer,'% Finished loading'),
2645 (Already_FullyProcessed==true -> true
2646 ; assertz(loaded_main_file(Ext,MainFile))).
2647
2648 known_spec_file_extension('P',xtl).
2649 known_spec_file_extension(als,alloy).
2650 known_spec_file_extension(csp,csp).
2651 known_spec_file_extension(cspm,csp).
2652 known_spec_file_extension(def,b).
2653 known_spec_file_extension(eval,b_eval).
2654 known_spec_file_extension(eventb,eventb).
2655 known_spec_file_extension(fuzz,z).
2656 known_spec_file_extension(imp,b).
2657 known_spec_file_extension(mch,b).
2658 known_spec_file_extension(pb,b).
2659 known_spec_file_extension(pl,xtl).
2660 known_spec_file_extension(pla,alloy). % Prolog AST of Alloy translation
2661 known_spec_file_extension(probpo,sequent_prover). % disprover PO files
2662 known_spec_file_extension(prob,b).
2663 known_spec_file_extension(ref,b).
2664 known_spec_file_extension(rmch,b_rules).
2665 known_spec_file_extension(smt,smt).
2666 known_spec_file_extension(smt2,smt).
2667 known_spec_file_extension(sys,b).
2668 known_spec_file_extension(tex,z).
2669 known_spec_file_extension(tla,tla).
2670 known_spec_file_extension(zed,z).
2671
2672 :- use_module(pathes_extensions_db, [load_spec_file_requires_extension/2]).
2673 :- use_module(pathes_lib, [available_extension/1, unavailable_extension/2]).
2674 % check if we can load the file extension given available ProB extensions
2675 file_extension_can_be_loaded(FileExt,_) :- known_spec_file_extension(FileExt,Mode),
2676 load_spec_file_requires_extension(Mode,ProBExtension),
2677 unavailable_extension(ProBExtension,Reason),!,
2678 ajoin(['File with ending .', FileExt,' cannot be loaded because extension not available (',Reason,'):'],Msg),
2679 add_error(probcli,Msg,ProBExtension),
2680 fail.
2681 file_extension_can_be_loaded(_,_). % assume ok; if unrecognized we will load as B machine
2682
2683 %load_spec_file('pl',MainFile) :- !, load_cspm_spec_from_pl_file(MainFile). % no longer needed ?
2684 load_spec_file('pl',MainFile) :- !, load_xtl_spec_from_prolog_file(MainFile).
2685 load_spec_file('csp',MainFile) :- !, load_cspm_spec_from_cspm_file(MainFile).
2686 load_spec_file('cspm',MainFile) :- !, load_cspm_spec_from_cspm_file(MainFile).
2687 load_spec_file('P',MainFile) :- !, load_xtl_spec_from_prolog_file(MainFile).
2688 load_spec_file('p',MainFile) :- !, load_xtl_spec_from_prolog_file(MainFile). % sometimes windows is confused about the upper case letter....
2689 load_spec_file('probpo',MainFile) :- !, load_xtl_spec_from_prolog_file(MainFile). % load (Disprover) PO files in sequent_prover mode
2690 load_spec_file('eventb',MainFile) :- !, load_eventb_file(MainFile).
2691 load_spec_file('v',MainFile) :- !,
2692 print('Warning: .v proof rule file format no longer supported, use -eval_rule_file FILE'),nl,
2693 % but even that may not work; some older rule files required predicate variables
2694 load_b_file_with_options(MainFile). % Siemens Rule File; now use -eval_rule_file
2695 load_spec_file('prob',MainFile) :- !,load_prob_file_with_options(MainFile). % .prob files
2696 load_spec_file('mch',MainFile) :- !,load_b_file_with_options(MainFile).
2697 load_spec_file('sys',MainFile) :- !,load_b_file_with_options(MainFile).
2698 load_spec_file('ref',MainFile) :- !,load_b_file_with_options(MainFile).
2699 load_spec_file('imp',MainFile) :- !,load_b_file_with_options(MainFile).
2700 load_spec_file('rmch',MainFile) :- !,load_b_file_with_options(MainFile).
2701 load_spec_file('def',MainFile) :- !,load_b_file_with_options(MainFile). % .def DEFINITIONS file
2702 load_spec_file('fuzz',MainFile) :- !,tcltk_open_z_file(MainFile).
2703 load_spec_file('tex',MainFile) :- !,tcltk_open_z_tex_file(MainFile).
2704 load_spec_file('zed',MainFile) :- !,tcltk_open_z_tex_file(MainFile). % proz .zed file
2705 load_spec_file('als',MainFile) :- !,tcltk_open_alloy_file(MainFile).
2706 load_spec_file('pla',MainFile) :- !,tcltk_open_alloy_prolog_ast_file(MainFile). % maybe we should detect .als.pl
2707 load_spec_file('tla',MainFile) :- !, load_tla_file(MainFile).
2708 load_spec_file('eval',File) :- !, % .eval file
2709 cli_set_empty_machine,
2710 assertz(option(eval_string_or_file(file(default),File,exists,_,norecheck))).
2711 load_spec_file('pb',File) :- !, cli_set_empty_machine, % .pb file
2712 cli_set_empty_machine,
2713 assertz(option(eval_string_or_file(file(default),File,exists,_,norecheck))).
2714 %load_spec_file('pml',MainFile) :- !,parsercall:call_promela_parser(MainFile),
2715 % parsercall:promela_prolog_filename(MainFile,PrologFile),
2716 % println_silent(consulting(PrologFile)),
2717 % tcltk_open_promela_file(PrologFile).
2718 load_spec_file(EXT,MainFile) :- print_error('Unknown file extension, assuming B machine:'),
2719 print_error(EXT),
2720 load_b_file_with_options(MainFile).
2721
2722 load_spec_file(EXT,MainFile, Already_FullyProcessed) :-
2723 (EXT='probpo' ; EXT= 'pl'),
2724 % we could check: xtl_interface:check_is_po_file(MainFile,EXT); adds warning for .pl files
2725 load_pl_file_with_disprover(MainFile), !,
2726 Already_FullyProcessed=true,
2727 printsilent('Processing PO file: '),printsilent(MainFile),nls,
2728 load_po_file(MainFile),
2729 (option(timeout(TO)) -> set_disprover_timeout(TO) ; reset_disprover_timeout),
2730 (option(disprover_options(L)) -> set_disprover_options(L) ; set_disprover_options([])),
2731 println_silent('Running ProB Disprover'),
2732 run_disprover_on_all_pos(Summary),
2733 print_disprover_stats,
2734 accumulate_infos(disprover,[po_files-1|Summary]),
2735 get_errors,
2736 (option(cli_check_disprover_result(Infos)) -> check_required_infos(Infos,Summary,load_po_file)
2737 ; option(strict_raise_error) -> check_required_infos([false-0,unknown-0,failure-0],Summary,load_po_file)
2738 % TO DO: provide way for user to specify expected info
2739 ; true),
2740 cli_process_options_for_alrady_fully_processed_file(MainFile),
2741 clear_loaded_machines.
2742 load_spec_file(EXT,MainFile,Already_FullyProcessed) :- (EXT='smt2' ; EXT= 'smt'), !,
2743 Already_FullyProcessed=true,
2744 printsilent('Processing SMT file: '),printsilent(MainFile),nls,
2745 (option(eval_repl([])) -> Opts = [repl] ; Opts=[]),
2746 smtlib2_file(MainFile,Opts).
2747 load_spec_file(EXT,F,false) :- load_spec_file(EXT,F).
2748
2749 % check if we should load a pl file using the disprover runner; if not we will load it in XTL mode
2750 load_pl_file_with_disprover(_MainFile) :- option(disprover_options(_)).
2751 load_pl_file_with_disprover(_MainFile) :- option(cli_check_disprover_result(_)).
2752 load_pl_file_with_disprover(_) :-
2753 \+ computeOperations_for_root_required,
2754 \+ (option(A), option_requires_all_properties(A)).
2755
2756
2757 load_prob_file_with_options(File) :-
2758 (option(release_java_parser) -> Options = [use_fastread] ; Options = []),
2759 load_prob_file(File,Options).
2760 load_b_file_with_options(File) :-
2761 (option(release_java_parser) -> Options = [release_java_parser,use_fastread]
2762 ; option(fast_read_prob) -> Options = [use_fastread] % use fastread for large .prob files
2763 ; Options = []),
2764 % TO DO: automatically release if no option requires parsing and no more file uses it; or print warning if release will affect other options like -repl (DEFINITIONS not available,...)
2765 load_b_file(File,Options).
2766
2767 % do not perform -execute_all if no parameters provided
2768 do_not_execute_automatically('pl').
2769 do_not_execute_automatically('smt2').
2770
2771 test_kodkod_and_exit(MaxResiduePreds,NOW) :-
2772 start_animation_without_computing,
2773 test_kodkod(MaxResiduePreds),
2774 halt_prob(NOW,0).
2775
2776 compare_kodkod_performance1(KPFile,Iterations,NOW) :-
2777 start_animation_without_computing,
2778 compare_kodkod_performance(KPFile,Iterations),
2779 halt_prob(NOW,0).
2780
2781 :- use_module(parsercall,[check_java_version/2,get_parser_version/1, ensure_console_parser_launched/0,
2782 connect_to_external_console_parser_on_port/1]).
2783 check_java_version :- check_java_version(V,Result),
2784 format('Result of checking Java version:~n ~w~n',[V]),
2785 (Result=compatible -> check_parser_version
2786 ; add_error(check_java_version,V)).
2787
2788 check_parser_version :- get_parser_version(PV),!,
2789 format(' ProB B Java Parser available in version: ~w.~n',[PV]). % will also launch parser
2790 check_parser_version :- add_error(check_parser_version,'Cannot start Java B Parser to obtain version number').
2791
2792 :- use_module(pathes_lib,[install_lib_component/2]).
2793 install_prob_lib(Lib,Opts) :- install_lib_component(Lib,Opts).
2794
2795 print_version(Kind) :- print_version(Kind,user_output).
2796
2797 print_version(short,Stream) :- print_short_version(Stream).
2798 print_version(cpp,Stream) :- print_cpp_version(Stream).
2799 print_version(java,Stream) :- print_java_version(Stream).
2800 print_version(full,Stream) :- print_full_version(Stream).
2801 print_version(full_verbose,Stream) :- print_full_version(Stream,verbose).
2802 print_version(host,Stream) :- print_host_version(Stream).
2803 print_version(lib,Stream) :- check_lib_contents(Stream,verbose).
2804
2805 :- use_module(version).
2806 print_short_version(Stream) :-
2807 version(V1,V2,V3,Suffix),revision(Rev),
2808 format(Stream,'VERSION ~p.~p.~p-~p (~p)~N',[V1,V2,V3,Suffix,Rev]).
2809
2810 :- use_module(parsercall,[get_parser_version/1, get_java_command_path/1, get_java_fullversion/1]).
2811 :- use_module(pathes_lib,[check_lib_contents/2]).
2812 print_full_version(Stream) :-
2813 (option_verbose ->
2814 (option_very_verbose
2815 -> print_full_version(Stream,very_verbose)
2816 ; print_full_version(Stream,verbose)
2817 )
2818 ; print_full_version(Stream,normal)
2819 ).
2820 print_full_version(Stream,Verbose) :-
2821 format(Stream,'ProB Command Line Interface~n',[]),
2822 print_probcli_version(Stream),
2823 ( Verbose=normal -> true
2824 ;
2825 current_prolog_flag(system_type,SysType),
2826 format(Stream,' Prolog System Type: ~p~N', [SysType]), % development or runtime
2827 safe_absolute_file_name(prob_home('.'),AppDir),
2828 format(Stream,' Application Path: ~p~N', [AppDir]),
2829 print_host_version(Stream),
2830 print_java_version(Stream),
2831 print_cpp_version(Stream),
2832 (Verbose = very_verbose
2833 -> print_prolog_flags(Stream), print_extensions(Stream), print_modules(Stream),
2834 check_lib_contents(Stream,verbose)
2835 ; check_lib_contents(Stream,silent)
2836 )
2837 ), print_compile_time_flags.
2838
2839 print_java_version(Stream) :-
2840 (get_java_command_path(JavaPath)
2841 -> format(Stream,' Java Runtime: ~p~N', [JavaPath]),
2842 (get_java_fullversion(JavaVersion)
2843 -> format(Stream,' Java Version: ~s~N', [JavaVersion])
2844 ; format(Stream,' Java Version: *** not available ***~N',[])
2845 ),
2846 (get_parser_version(ParserVersion)
2847 -> format(Stream,' Java Parser: ~p~N', [ParserVersion])
2848 ; format(Stream,' Java Parser: *** not available ***~N',[])
2849 )
2850 ; format(Stream,' Java Runtime: *** not available ***~N',[])
2851 ).
2852
2853 :- use_module(tools_platform, [host_platform/1, host_processor/1]).
2854 print_host_version(Stream) :-
2855 host_platform(HP),
2856 host_processor(Proc),
2857 (platform_is_64_bit -> Bits=64 ; Bits=32),
2858 format(Stream,' Host Processor: ~w (~w bits)~n Host Operating System: ~w~n',[Proc,Bits,HP]).
2859
2860
2861 print_probcli_version(Stream) :-
2862 full_version_str(VersStr),
2863 revision(Rev), lastchangeddate(LCD),
2864 current_prolog_flag(dialect, Dialect),
2865 (Dialect= swi, current_prolog_flag(version_git,PV) -> true
2866 ; current_prolog_flag(version,PV)
2867 ),
2868 format(Stream,' VERSION ~w (~p)~N ~p~N Prolog (~w): ~p~N',
2869 [VersStr,Rev,LCD,Dialect, PV]).
2870
2871
2872 :- use_module(compile_time_flags,[compile_time_flags/1, relevant_prolog_flags/1]).
2873 :- use_module(extension('regexp/regexp'),[get_cpp_version/1]).
2874 print_compile_time_flags :-
2875 compile_time_flags(list(Flags)),
2876 (Flags=[], \+ option_verbose -> true ; format(' COMPILE TIME FLAGS: ~w~N',[Flags])).
2877 print_prolog_flags(Stream) :-
2878 relevant_prolog_flags(Flags),
2879 format(Stream,' PROLOG FLAGS: ~w~N',[Flags]).
2880 print_extensions(Stream) :- findall(E,available_extension(E),Es),
2881 format(Stream,' EXTENSIONS: ~w~N',[Es]).
2882 print_cpp_version(Stream) :-
2883 available_extension(regexp_extension),!,
2884 get_cpp_version(V),
2885 format(Stream,' C++ Version for extensions: ~w~n',[V]).
2886 print_cpp_version(_).
2887 print_modules(Stream) :- findall(M,current_module(M),Ms), sort(Ms,SMs),
2888 format(Stream,' PROLOG MODULES: ~w~N',[SMs]).
2889
2890 print_logo :-
2891 % should be improved considerably; doesn't look very nice yet on macOS terminal due to line separation
2892 % â–„â–„â–„â–„ â–„â–„â–„â–„
2893 % â–ˆ â–ˆ â–ˆ â–ˆ
2894 % █▀▀▀ ▄ ▄▄▄ █▀▀▀▄
2895 % █ █ █▄█ █▄▄▄▀
2896 format_with_colour_nl(user_output,[blue],' ~s',[[9604,9604,9604,9604,32,32,32,32,32,32,32,9604,9604,9604,9604]]),
2897 format_with_colour_nl(user_output,[blue],' ~s',[[9608,32,32,32,9608,32,32,32,32,32,32,9608,32,32,32,9608]]),
2898 format_with_colour_nl(user_output,[blue],' ~s',[[9608,9600,9600,9600,32,9604,32,9604,9604,9604,32,9608,9600,9600,9600,9604]]),
2899 format_with_colour_nl(user_output,[blue],' ~s',[[9608,32,32,32,9608,32,32,9608,9604,9608,32,9608,9604,9604,9604,9600]]).
2900
2901 print_help :-
2902 print_version(full),
2903 print('Usage: probcli FILE [OPTIONS]'),nl,
2904 print(' OPTIONS are: '),nl,
2905 print(' -mc Nr model check; checking at most Nr states'),nl,
2906 print(' -model_check model check without limit on states explored'),nl,
2907 ( \+ option_verbose ->
2908 print(' -noXXX XXX=dead,inv,goal,ass (for model check)'),nl % -nodead, -noinv, -nogoal, -noass
2909 ;
2910 print(' -nodead do not look for deadlocks (for model check, animate, execute)'),nl,
2911 print(' -noinv do not look for invariant violations (for model check, animate, execute)'),nl,
2912 print(' -nogoal do not look for GOAL predicate (for model check, execute)'),nl,
2913 print(' -noass do not look for ASSERTION violations (for model check, execute)'),nl
2914 ),
2915 print(' -bf proceed breadth-first (default is mixed bf/df)'),nl,
2916 print(' -df proceed depth-first'),nl,
2917 print(' -mc_mode M M=hash,heuristic,random,dlk,breadth-first,depth-first,mixed,size'),nl, % dlk stands for out_degree_hash
2918 print(' -global_time_out N total timeout in ms for model/refinement checking and'),nl,
2919 print(' and execute steps and disprover checks'),nl,
2920 print(' -disable_timeout disable timeouts for operations, invariants,....'),nl, % speeds up mc
2921 print(' -t trace check (associated .trace file must exist)'),nl,
2922 print(' -trace_replay K F replay trace file F in format K (prolog,json,B)'),nl,
2923 print(' -init initialise specification'),nl,
2924 print(' -cbc OPNAME constraint-based invariant checking for an operation'),nl,
2925 print(' (you can also use OPNAME=all)'),nl,
2926 print(' -cbc_deadlock constraint-based deadlock checking'),nl,
2927 ( \+ option_verbose -> true ;
2928 print(' -cbc_deadlock_pred PRED as above but with additional predicate'),nl
2929 ),
2930 print(' -cbc_assertions constraint-based static assertion checking'),nl,
2931 print(' -cbc_refinement constraint-based static refinement checking'),nl,
2932 print(' -cbc_sequence S constraint-based search for sequence of operations'),nl,
2933 print(' -strict raise error if model-checking finds counter example'),nl,
2934 print(' or trace checking fails or any error state found'),nl,
2935 print(' -expcterr ERR expect error to occur (ERR=cbc,mc,ltl,...)'),nl,
2936 print(' -animate Nr random animation (max. Nr steps)'),nl,
2937 print(' -animate_all random animation until a deadlock is reached'),nl,
2938 print(' -animate_until_ltl P random animation until LTL property satisfied on trace'),nl,
2939 print(' -animate_until_ltl_state_property P until state satisfies LTL state property)'),nl,
2940 print(' -animate_stats provide feedback which operations are animated or executed'),nl,
2941 print(' -execute Nr execute specification (maximally Nr steps)'),nl,
2942 print(' in contrast to -animate: stops at first operation found, is deterministic,'),nl,
2943 print(' does not store intermediate states and does not use TIME_OUT preference'),nl,
2944 print(' -execute_all execute until a deadlock, direct loop, goal or error is reached'),nl,
2945 print(' -execute_monitor monitor performance of execute'),nl,
2946 print(' -his File write history to File'),nl,
2947 print(' -his_option O additional option when writing a history (show_init,show_states,json,trace_file)'),nl,
2948 print(' -sptxt File save constants and variable values of last discovered state to File'),nl,
2949 print(' -sstxt Dir save constants and variable values of all discovered states to files in Dir'),nl,
2950 print(' -cache Directory automatically save constants and operations to files to avoid recomputation'),nl,
2951 print(' -det_check check if animation steps are deterministic'),nl,
2952 print(' -det_constants only check if SETUP_CONSTANTS step is deterministic'),nl,
2953 ( \+ option_verbose -> true ;
2954 print(' -i interactive animation. Only for interactive sessions,'),nl,
2955 print(' the output can arbitrarily change in future versions. '),nl,
2956 print(' Do not build automatic tools using the interactive mode'),nl
2957 ),
2958 print(' -repl start interactive read-eval-loop'),nl,
2959 print(' -eval "E" evaluate expression or predicate'),nl,
2960 print(' -eval_file FILE evaluate expression or predicate from file'),nl,
2961 print(' -c print coverage statistics'),nl,
2962 print(' -cc Nr Nr print and check coverage statistics'),nl,
2963 print(' -vacuity_check look for vacuous implications in invariant'),nl,
2964 print(' -cbc_redundant_invariants Nr find redundant invariants, expecting Nr'),nl, % Nr exepcted
2965 print(' -statistics print memory and other statistics at the end'),nl,
2966 print(' -p PREF Val set preference to value'),nl,
2967 print(' -prefs FILE set preferences from Prolog file'),nl,
2968 print(' -pref_group G S set group G of preferences to predefined value set S'),nl,
2969 print(' -card GS Val set cardinality (aka scope) of B deferred set'),nl,
2970 print(' -goal "PRED" set GOAL predicate for model checker'),nl,
2971 print(' -check_goal check GOAL (after -mc, -t, or -animate)'),nl,
2972 print(' -scope "PRED" set scope predicate for model checker'),nl,
2973 print(' (only states satsifying this predicate will be examined)'),nl,
2974 print(' -property "PRED" virtually add predicate to PROPERTIES'),nl,
2975 print(' -s Port start socket server on given port'),nl,
2976 print(' -ss start socket server on port 9000'),nl,
2977 print(' -sf start socket server on some free port'),nl,
2978 print(' -l LogFile log activities in LogFile'),nl,
2979 print(' -ll log activities in /tmp/prob_cli_debug.log'),nl,
2980 print(' -logxml LogFile log activities in XML LogFile'),nl,
2981 print(' -logxml_write_ids P write variables/constants starting with P to XML LogFile'),nl,
2982 print(' -pp FILE pretty-print internal representation to file (or user_output)'), nl,
2983 print(' -ppf FILE like -pp, but force printing of all type infos'),nl,
2984 print(' -ppAB FILE like -ppf, but make output readable by Atelier-B'),nl,
2985 print(' -ppB FILE pretty-print Event-B model to file in valid B syntax'),nl,
2986 ( \+ option_verbose -> true ;
2987 print(' -ppi FILE pretty-print B model main file with indenatation'),nl,
2988 print(' -indent_b_file BFILE FILE pretty-print BFILE to FILE with indenatation'),nl,
2989 print(' -reformat_b_file BFILE FILE reformat BFILE to FILE (may insert newlines)'),nl,
2990 print(' -pp_pl_file PLFILE FILE indent Prolog PLFILE to FILE'),nl
2991 ),
2992 print(' -v verbose'),nl,
2993 ( \+ option_verbose -> true ;
2994 print(' -vv very verbose'),nl
2995 ),
2996 print(' -mc_with_tlc model check using TLC (see also TLC_WORKERS preference)'),nl,
2997 print(' -mc_with_lts_sym model check using LTSmin (symbolic)'),nl,
2998 print(' -mc_with_lts_seq model check using LTSmin (sequential)'),nl,
2999
3000 ( \+ option_verbose -> true ;
3001 print(' -ltsmin_option OPT set option for LTSmin (e.g, por)'),nl,
3002 print(' -ltsmin_ltl_output FILE set output file for LTSMin'),nl,
3003 print(' -symbolic_model_check ALGO ALGO is bmc, kinduction, ctigar, ic3'),nl,
3004 print(' -enabling_analysis_csv FILE perform operation enabling analysis'),nl,
3005 print(' -feasibility_analysis perform operation feasibility analysis'),nl,
3006 print(' -feasibility_analysis_csv FILE write feasibility result to file'),nl,
3007 print(' -read_write_matrix show read/write matrix for operations'),nl
3008 ),
3009 print(' -version print version information (-svers for short info)'),nl,
3010 print(' -check_java_version check that Java version compatible with ProB parser'),nl,
3011 print(' -assertions check ASSERTIONS'),nl,
3012 print(' -main_assertions check ASSERTIONS from main file only'),nl,
3013 print(' -properties check PROPERTIES'),nl,
3014 print(' -ccache Dir like -cache Dir but create directoy if it does not exist'),nl,
3015 print(' -show_cache show contents of cache'),nl,
3016 print(' -show_cache_verbose show contents of cache in more detail'),nl,
3017 print(' -cache_statistics show statistics about cache reuse'),nl,
3018 print(' -clear_cache clear the cache'),nl,
3019 print(' -clear_cache_for M clear the cache for machine M'),nl,
3020 print(' -show_inclusion_hierarchy useful to determine order for pre-populating cache for constants'),nl,
3021 print(' -ltlfile F check LTL formulas in file F'),nl,
3022 print(' -ltlassertions check LTL assertions (in DEFINITIONS)'),nl,
3023 print(' -ltllimit L explore at most L states when model-checking LTL or CTL'),nl,
3024 print(' -ltlformula \"F\" check the LTL formula F'),nl,
3025 print(' -ctlformula \"F\" check the CTL formula F'),nl,
3026 print(' -save File save state space for later refinement check'),nl,
3027 print(' -refchk File refinement check against previous saved state space'),nl,
3028 print(' -mcm_tests Depth MaxStates EndPredicate File'),nl,
3029 print(' generate test cases with maximum length Depth, explore'),nl,
3030 print(' maximally MaxStates, the last state satisfies EndPredicate'),nl,
3031 print(' and the test cases are written to File'),nl,
3032 print(' -mcm_cover Operation'),nl,
3033 print(' when generating MCM test cases, Operation should be covered'),nl,
3034 print(' -cbc_tests Depth EndPredicate File'),nl,
3035 print(' generate test cases by constraint solving with maximum'),nl,
3036 print(' length Depth, the last state satisfies EndPredicate'),nl,
3037 print(' and the test cases are written to File'),nl,
3038 print(' -cbc_cover Operation'),nl,
3039 print(' when generating CBC test cases, Operation should be covered'),nl,
3040 % print(' -cbc_cover_all try and cover all operations'),nl, % is now default if no cbc_cover provided
3041 print(' -test_description File'),nl,
3042 print(' read information for test generation from File'),nl,
3043 print(' -dot CMD File write a graph to a dot file, with CMD being one of:'),nl,
3044 (is_dot_command(Cmd),command_description(Cmd,_,Desc),
3045 format(' ~w : ~w~n',[Cmd,Desc]),fail
3046 ; true),
3047 print(' -dotexpr CMD Expr File write a graph for Expr to a dot file, with CMD:'),nl,
3048 (is_dot_command_for_expr(Cmd),command_description(Cmd,_,Desc),
3049 format(' ~w : ~w~n',[Cmd,Desc]),fail
3050 ; true),
3051 print(' -puml CMD File write a graph to a plantuml file, with CMD being one of:'),nl,
3052 (is_plantuml_command(Cmd),command_description(Cmd,_,Desc),
3053 format(' ~w : ~w~n',[Cmd,Desc]),fail
3054 ; true),
3055 print(' -pumlexpr CMD Expr File write a graph for Expr to a plantuml file, with CMD:'),nl,
3056 (is_plantuml_command_for_expr(Cmd),command_description(Cmd,_,Desc),
3057 format(' ~w : ~w~n',[Cmd,Desc]),fail
3058 ; true),
3059 print(' -csv CMD File write a table to a CSV file, with CMD being one of:'),nl,
3060 (is_table_command(Cmd),command_description(Cmd,_,Desc),
3061 format(' ~w : ~w~n',[Cmd,Desc]),fail
3062 ; true),
3063 print(' -csvexpr CMD Expr File write a table for Expr to a CSV file, with CMD:'),nl,
3064 (is_table_command_for_expr(Cmd),command_description(Cmd,_,Desc),
3065 format(' ~w : ~w~n',[Cmd,Desc]),fail
3066 ; true),
3067 print(' -dot_output Path generate dot files for false assertions/properties'),nl,
3068 print(' -dot_all also generate dot files for true assertions/properties'),nl,
3069 print(' -rule_report generate HTML validation report for rules machines (.rmch)'),nl,
3070 print(' -proof_export generate HTML proof export in sequent prover mode (for .probpo PO files)'),nl,
3071 print(' -csvhist E File evaluate expression over history and generate CSV file'),nl,
3072 print(' -visb JFile HFile use VisB JSON file JFILE to create HTML visualistion of history'),nl,
3073 print(' -visb_with_vars JFile HFile (similar, but also show variable values)'),nl,
3074 print(' -load_state File load state of ProB from a saved state space (generated by ProB Tcl/Tk or -save_state)'),nl,
3075 % For Eclipse Version only
3076 %% print(' -parsercp CP class path of the B Parser, this has to be a valid Java class path'),nl,
3077 %% print(' -cspm load CSP-M .csp file rather than B Machine .mch/.ref/.imp File'),nl,
3078 %% print(' -csp load CSP-M .pl file rather than B Machine File'),nl,
3079
3080 /* Options -cspref, -cspdeadlock, -cspdeterministic, and -csplivelock are deprecated, should be excluded in favor of -csp_assertion */
3081 print(' -cspref Spec [m= Impl File'),nl,
3082 print(' checks a refinement statement,'),nl,
3083 print(' where Spec and Impl are processes from File, and \'m\' the type of the refinement:'),nl,
3084 print(' \'T\' for traces, \'F\' for failures, or \'FD\' for failures-divergences.'),nl,
3085 print(' -cspdeadlock P m File'),nl,
3086 print(' checks a process for deadlock,'),nl,
3087 print(' where \'P\' is a process from File, and \'m\' the type of the model:'),nl,
3088 print(' \'F\' for failures and \'FD\' for failures-divergences.'),nl,
3089 print(' -cspdeterministic P m File'),nl,
3090 print(' checks a process for determinism,'),nl,
3091 print(' where \'P\' is a process from File, and \'m\' the type of the model:'),nl,
3092 print(' \'F\' for failures and \'FD\' for failures-divergences.'),nl,
3093 print(' -csplivelock P File'),nl,
3094 print(' checks a process for divergence,'),nl,
3095 print(' where \'P\' is a process from File.'),nl,
3096 /* Options -cspref, -cspdeadlock, -cspdeterministic, and -csplivelock are deprecated, should be excluded in favor of -csp_assertion */
3097
3098 print(' -csp_assertion \"A\" File'),nl,
3099 print(' checks the CSP assertion \'A\' on file \'File\''),nl,
3100 print(' -csp_eval "E" evaluate CSP-M expression.'),nl,
3101 print(' -csp_guide File CSP||B: Use the CSP File to control the B machine'),nl,
3102 print(' '),nl,
3103 ( \+ option_verbose -> true
3104 ;
3105 print(' -test_mode set random seed to the Prolog\'s current random state'),nl,
3106 print(' -rc runtime checking of types/pre-/post-conditions'),nl,
3107 print(' -state_trace File read a file of B predicates (one per line) and try find a matching trace.'),nl
3108
3109 ),
3110 print(' FILE extensions are: '),nl,
3111 print(' .mch for B abstract machines'),nl,
3112 print(' .ref for B refinement machines'),nl,
3113 print(' .imp for B implementation machines'),nl,
3114 print(' .sys for Event-B abstract machines'),nl,
3115 print(' .rmch for B Rule DSL machines'),nl,
3116 print(' .csp, .cspm for CSP-M files, same format as FDR'),nl,
3117 print(' .eventb for Event-B packages exported from Rodin ProB Plugin'),nl,
3118 print(' .tex, .zed for Z models'),nl,
3119 print(' .tla for TLA+ models'),nl,
3120 print(' .als for Alloy models'),nl,
3121 print(' .P for Prolog XTL models'),nl,
3122 ( option_verbose ->
3123 print(' Preferences PREF are: '),nl,
3124 print_eclipse_prefs
3125 ;
3126 print(' Use --help -v to print available preferences PREF'),nl
3127 ),
3128 print(' Set NO_COLOR environment variable to disable terminal colors'),nl,
3129 print(' More info at: https://prob.hhu.de/w/index.php/ProB_Cli'),nl,
3130 nl.
3131
3132
3133 set_argv(V) :-
3134 debug_println(20,set_argv(V)),
3135 external_functions:set_argv_from_atom(V).
3136
3137 :- use_module(b_global_sets, [set_user_defined_scope/2]).
3138 :- use_module(state_space_exploration_modes,[set_depth_breadth_first_mode/1, get_current_breadth_first_level/1]).
3139 :- use_module(tools_strings, [convert_cli_arg/2]).
3140 set_prefs :-
3141 if_option_set(cli_start_sym_mc_with_lts(_),
3142 preferences:set_preference(try_operation_reuse,false)), % LTSMIN does its own OPERATION_REUSE
3143 if_option_set(socket(_,_), % then we may need the event(.) transition_info for the Java API
3144 preferences:set_preference(store_event_transinfo,true)),
3145 option(set_prefs_from_file(File)),
3146 debug_println(20,load_preferences(File)),
3147 preferences:load_preferences(File),
3148 fail.
3149 set_prefs :-
3150 option(set_preference_group(P,V)),
3151 debug_println(20,set_preference_group(P,V)),
3152 set_preference_group(P,V),
3153 fail.
3154 % eclipse preference or 'normal preference'
3155 set_prefs :-
3156 ? option(set_pref(P,V)),
3157 set_pref(P,V),
3158 fail.
3159 set_prefs :- option(set_card(Set,V)),
3160 debug_println(20,set_card(Set,V)),
3161 convert_cli_arg(V,Value),
3162 set_user_defined_scope(Set,Value),
3163 fail.
3164 set_prefs :-
3165 ( option(breadth_first) -> set_depth_breadth_first_mode(breadth_first)
3166 ; option(depth_first) -> set_depth_breadth_first_mode(depth_first)
3167 ; option(depth_breadth_first_mode(M)) -> set_depth_breadth_first_mode(M)
3168 ; true
3169 ).
3170 :- use_module(tools_matching,[get_possible_preferences_matches_msg/2]).
3171 set_pref(P,V) :-
3172 debug_println(20,set_pref(P,V)),
3173 ? ( eclipse_preference(P,_)
3174 -> set_eclipse_preference(P,V)
3175 ; deprecated_eclipse_preference(P,_,_,_) -> set_eclipse_preference(P,V)
3176 ; obsolete_eclipse_preference(P) -> probcli_add_light_warning('Obsolete preference: ',P)
3177 ; obsolete_preference(P) -> probcli_add_light_warning('Obsolete preference: ',P)
3178 ; % might be a term if its a plugin preference
3179 atom_codes(P,Codes),
3180 append(Codes,".",Codes2), % to make term readable by read_from_codes
3181 read_from_codes(Codes2,Preference),
3182 (nonvar(Preference),preference_val_type(Preference,_)
3183 -> convert_cli_arg(V,Value),
3184 set_preference(Preference,Value)
3185 ; P=timeout ->
3186 add_error(probcli,'Unknown preference timeout. Either set preference TIME_OUT or use -gobal_time_out command','')
3187 ; get_possible_preferences_matches_msg(P,FuzzyMsg) ->
3188 ajoin(['Unknown preference: ',P,'. Did you mean:'],Msg),
3189 add_error(probcli,Msg,FuzzyMsg)
3190 ; get_possible_fuzzy_match_options(P,FuzzyMatches),
3191 % will only give perfect matches as P usually does not have the hyphen in front
3192 FuzzyMatches = [FMC|_] ->
3193 ajoin(['Unknown preference ', P, ' which looks like a probcli command! Did you want to call:'],Msg),
3194 add_error(probcli,Msg,FMC)
3195 ;
3196 add_error(probcli,'Unknown preference:',P)
3197 )
3198 ).
3199
3200 % add non severe warning:
3201 probcli_add_light_warning(Msg,Term) :- option(strict_raise_error),!,
3202 add_warning(probcli,Msg,Term). % does not write on user_error
3203 probcli_add_light_warning(Msg,Term) :- add_message(probcli,Msg,Term).
3204
3205 set_optional_errors :- % register optional/expected errors in the error_manager; avoid printing on stderr
3206 reset_optional_errors_or_warnings,
3207 (option(optional_error(Type)) ; option(expect_error(Type)) ; option(expect_error_pos(Type,_Line,_Col))),
3208 register_optional_error_or_warning(Type),
3209 fail.
3210 set_optional_errors.
3211
3212 % explicit state model checking, without LTL/CTL
3213 regular_safety_model_check_now(Nr,Runtime,WallTime,MCRes,NOW) :-
3214 statistics(runtime,[T1,_]),
3215 statistics(walltime,[W1,_]),
3216 (option(timeout(TO)) -> safe_time_out(regular_safety_model_check(Nr,Time,MCRes),TO,Res)
3217 ; regular_safety_model_check(Nr,Time,MCRes), Res=success
3218 ),
3219 statistics(runtime,[T2,_]),
3220 statistics(walltime,[W2,_]),
3221 WallTime is W2-W1,
3222 Runtime is T2-T1,
3223 (Res=time_out
3224 -> add_warning(model_check_incomplete,'Not all states examined due to -global_time_out option set by user: ',TO),
3225 writeln_log(timeout_occurred(NOW,model_check(Nr,Time,MCRes))),
3226 coverage(just_summary),
3227 MCRes=time_out
3228 ; true).
3229
3230 :- use_module(model_checker,[model_checking_is_incomplete/6]).
3231
3232 % TO DO: check for ignored states
3233 % code somewhat redundant also with model_check_incomplete below
3234 add_model_checking_warnings(FindInvViolations,FindDeadlocks,FindGoal,FindAssViolations) :-
3235 %print(check(model_checking_is_incomplete(FindInvViolations,FindDeadlocks,FindGoal,FindAssViolations,Msg,Term))),nl,
3236 model_checking_is_incomplete(FindInvViolations,FindDeadlocks,FindGoal,FindAssViolations,Msg,Term),
3237 add_warning(model_check_incomplete,Msg,Term),
3238 % TO DO: store for accumulate_infos
3239 fail.
3240 add_model_checking_warnings(_,_,_,_).
3241
3242 :- use_module(state_space,[current_state_id/1]).
3243 regular_safety_model_check(Nr,Time,ErrRes) :-
3244 statistics(runtime,[T1,_]),
3245 statistics(walltime,[W1,_]),
3246 catch(model_check_aux(Nr,T1,W1,Time,ErrRes), user_interrupt_signal, (
3247 statistics(walltime,[W2,_]), TotalWT is W2-W1,
3248 format_with_colour_nl(user_error,[red],'~nmodel checking interrupted after ~w ms by user (CTRL-C)',[TotalWT]),
3249 coverage(just_summary),
3250 perform_feedback_options_after_exception,
3251 throw(user_interrupt_signal)
3252 )).
3253
3254 % perform some important options for user feedback after CTRL-C interrupts model checking, execute, ...
3255 perform_feedback_options_after_exception :-
3256 (option(check_op_cache(_)) -> cli_check_op_cache([]) ; true),
3257 if_options_set(csv_table_command(TECommand,TableFormulas,TableOptions,TableCSVFile),
3258 csv_table_command(TECommand,TableFormulas,TableOptions,TableCSVFile)),
3259 (option(get_coverage_information(FCC)) -> pretty_print_coverage_information_to_file(FCC) ; true),
3260 (option(cli_print_statistics(X)), (cli_print_statistics(X) -> fail) ; true).
3261
3262 model_check_aux(Nr,T1,W1,Time,ErrRes) :-
3263 (option(no_deadlocks) -> FindDeadlocks=0 ; FindDeadlocks=1),
3264 (option(no_invariant_violations) -> FindInvViolations=0 ; FindInvViolations=1),
3265 (option(no_goal) -> FindGoal=0 ; FindGoal=1),
3266 (option(no_state_errors) -> FindStateErrors=0 ; FindStateErrors=1),
3267 (option(no_assertion_violations)
3268 -> FindAssViolations=0
3269 ; FindAssViolations=1
3270 ),
3271 get_preference(por,POR),
3272 StopAtFullCoverage=0,
3273 %STOPMCAFTER = 86400000, /* 86400000 = 1 day timeout */
3274 STOPMCAFTER = 1152921504606846975, /* equals 13,343,998,895 days */
3275 InspectExistingNodes = 1,
3276 write_xml_element_to_log(model_checking_options,[find_deadlocks/FindDeadlocks,
3277 find_invariant_violations/FindInvViolations, find_goal/FindGoal,
3278 find_assertion_violations/FindAssViolations,
3279 find_state_errors/FindStateErrors,
3280 partial_order_reduction/POR,
3281 inspect_existing_nodes/InspectExistingNodes]),
3282 (tcltk_interface:do_model_check(Nr,NodesAnalysed,STOPMCAFTER,ErrRes,
3283 FindDeadlocks,FindInvViolations,FindGoal,
3284 FindAssViolations,FindStateErrors,StopAtFullCoverage,POR, InspectExistingNodes)
3285 -> (statistics(runtime,[T2,_]), statistics(walltime,[W2,_]),
3286 Time1 is T2-T1, WTime is W2-W1,
3287 (model_checker: expired_static_analysis_time(AnalysisTime) ->
3288 Time is Time1 - AnalysisTime
3289 ; Time = Time1, AnalysisTime=0),
3290 formatsilent('Model checking time: ~w ms (~w ms walltime)~n',[Time,WTime]),
3291 formatsilent('States analysed: ~w~n',[NodesAnalysed]),
3292 get_state_space_stats(_,NrTransitions,_,_),
3293 printsilent('Transitions fired: '),printsilent(NrTransitions),nls,
3294 (get_current_breadth_first_level(Level)
3295 -> formatsilent('Breadth-first levels: ~w~n',[Level]) % is this the equivalent of TLC's diameter?
3296 ; true),
3297 write_xml_element_to_log(model_checking_statistics,
3298 [result/ErrRes,runtime/Time,walltime/WTime,
3299 states/NodesAnalysed,transitions/NrTransitions,staticAnalysisTime/AnalysisTime]),
3300 (ErrRes = no
3301 -> print('No counter example Found, not all states visited'),nl,
3302 add_warning(model_check_incomplete,'Not all states examined due to limit set by user: ',Nr)
3303 ; ErrRes=all
3304 -> (tcltk_find_max_reached_node
3305 -> (not_interesting(_)
3306 -> print('No counter example found. However, not all transitions were computed (and some states not satisfying SCOPE predicate were ignored) !')
3307 ; print('No counter example found. However, not all transitions were computed !')
3308 )
3309 ; not_interesting(_)
3310 -> print_green('No counter example found. ALL states (satisfying SCOPE predicate) visited.')
3311 % b_get_machine_searchscope(Scope)
3312 ; print_green('No counter example found. ALL states visited.')
3313 ),nl,
3314 add_model_checking_warnings(FindInvViolations,FindDeadlocks,FindGoal,FindAssViolations)
3315 ; % ErrRes is not no or all
3316 print_red('*** COUNTER EXAMPLE FOUND ***'),nl,
3317 debug_println(20,ErrRes),nl,
3318 tcltk_interface:translate_error_for_tclk(ErrRes,TclTkRes),
3319 print(TclTkRes),nl,
3320 print_history_as_counter_example(true),
3321 error_occurred(TclTkRes)
3322 ),nl
3323 )
3324 ; % do_model_check failed
3325 statistics(runtime,[T2,_]), Time1 is T2-T1,
3326 (model_checker: expired_static_analysis_time(AnalysisTime) -> Time is Time1 - AnalysisTime
3327 ; Time = Time1),
3328 printsilent('Model checking time: '), printsilent(Time), printsilent(' ms'),nls,
3329 print_error('*** Model checking FAILED '),nl,
3330 ErrRes=fail,
3331 definite_error_occurred
3332 ).
3333
3334 print_history_as_counter_example(CheckInv) :-
3335 (option(silent) -> true
3336 ; option(no_counter_examples) -> true % -nocounter
3337 ; cli_print_history,
3338 (silent_mode(off), CheckInv=true,
3339 current_state_id(ID),invariant_violated(ID)
3340 -> b_interpreter:analyse_invariant_for_state(ID)
3341 ; true)
3342 ).
3343
3344 cli_print_history :-
3345 tcltk_interface:tcltk_get_history(list(Hist)),
3346 length(Hist,Len),
3347 format('*** TRACE (length=~w):~n',[Len]),
3348 reverse(Hist,Trace),
3349 print_nr_list(Trace).
3350
3351 % perform all cbc checks on current machine
3352 cbc_check(_NOW) :-
3353 option(cbc_deadlock_check(DeadlockGoalPred)),
3354 cbc_deadlock_check(DeadlockGoalPred),
3355 fail.
3356 cbc_check(_NOW) :-
3357 option(constraint_based_check(OpName)),
3358 constraint_based_check(OpName),
3359 fail.
3360 cbc_check(_NOW) :- option(cbc_assertions(AllowEnumWarning,Options)),
3361 cbc_assertions(AllowEnumWarning,Options),
3362 fail.
3363 %cbc_check(NOW) :-
3364 % option(cbc_pred(TargetPredString)),
3365 % check_loaded(cbc_pred),
3366 % print('% Starting Constraint-Based Check for Predicate: '), print(TargetPredString),nl,
3367 % b_set_up_valid_state_with_pred(NormalisedState,Pred) TO DO: add this feature
3368 cbc_check(_NOW) :- option(cbc_sequence(Sequence,TargetPredString,Findall)),
3369 cbc_sequence(Sequence,TargetPredString,Findall),
3370 fail.
3371 cbc_check(_NOW) :- option(cbc_refinement),
3372 cbc_refinement,
3373 fail.
3374 cbc_check(_NOW) :- option(cbc_redundant_invariants(NrExpected)),
3375 cbc_redundant_invariants(NrExpected),
3376 fail.
3377 cbc_check(_).
3378
3379 :- use_module(tcltk_interface,[tcltk_constraint_based_check/2,
3380 tcltk_constraint_based_check_with_timeout/2,
3381 tcltk_constraint_find_deadlock_state_with_goal/3,
3382 tcltk_cbc_find_trace/4,
3383 tcltk_cbc_refinement_check/2]).
3384 :- use_module(probsrc(bmachine),[b_is_operation_name/1]).
3385
3386 constraint_based_check(all) :-
3387 check_loaded_not_empty(constraint_based_check),
3388 print_repl_prompt_s('% Starting Constraint-Based Check for all Operations: '),nl,
3389 start_xml_feature(cbc_operation_check,all_operations,true,FINFO),
3390 (tcltk_constraint_based_check(list(Result),ErrorsWereFound)
3391 -> print('% Constraint-Based Check Result: '),nl,
3392 print(Result),nl,
3393 write_result_to_file(Result),
3394 (ErrorsWereFound=true
3395 -> print_red('*** CONSTRAINT-BASED CHECK FOUND ERRORS ***'),nl, error_occurred(cbc)
3396 ; (ErrorsWereFound=false -> print_green('NO ERRORS FOUND'),nl)
3397 ; print_red('*** TIMEOUT OCCURRED ***'),nl,error_occurred(cbc)
3398 )
3399 ; write_result_to_file(cbc_check_failed), Result=internal_error, ErrorsWereFound=false,
3400 add_internal_error('ConstraintBasedCheck unexpectedly failed. ',cbc_check(all)),definite_error_occurred
3401 ),nl,
3402 write_cbc_check_result(Result,ErrorsWereFound),
3403 stop_xml_feature(cbc_operation_check,FINFO).
3404 constraint_based_check(OpName) :- OpName\=all, % -cbc OpName
3405 check_loaded_not_empty(constraint_based_check),
3406 print_repl_prompt_s('% Starting Constraint-Based Check for Operation: '), print(OpName),nl,
3407 start_xml_feature(cbc_operation_check,operation,OpName,FINFO),
3408 (tcltk_constraint_based_check_with_timeout(OpName,Result)
3409 -> print('% Constraint-Based Check Result: '),nl, print(Result),nl,
3410 write_result_to_file(Result),
3411 (Result=time_out
3412 -> print_red('*** TIMEOUT OCCURRED ***'),nl, error_occurred(cbc)
3413 ; (Result=ok -> print_green('NO ERRORS FOUND'),nl)
3414 ; print_red('*** CONSTRAINT-BASED CHECK FOUND ERRORS ***'),nl,error_occurred(cbc) )
3415 ; write_result_to_file(constraint_based_check_failed), Result=internal_error,
3416 add_error(probcli,'ConstraintBasedCheck unexpectedly failed'),
3417 (b_is_operation_name(OpName) -> true
3418 ; add_error(probcli,'Unknown Operation Name: ',OpName)),
3419 definite_error_occurred
3420 ),nl,
3421 write_cbc_check_result(Result),
3422 stop_xml_feature(cbc_operation_check,FINFO).
3423
3424 write_cbc_check_result(Result) :-
3425 functor(Result,F,_), % example result: no_counterexample_exists(Ids,Prd,Other)
3426 write_xml_element_to_log(cbc_check_result,[result/F]).
3427 write_cbc_check_result(Result,ErrorsWereFound) :- functor(Result,F,_),
3428 write_xml_element_to_log(cbc_check_result,[result/F,errors_were_found/ErrorsWereFound]).
3429
3430 cbc_deadlock_check(DeadlockGoalPred) :-
3431 print_repl_prompt_s('% Starting Constraint-Based DEADLOCK check '),nl,
3432 start_xml_feature(cbc_deadlock_check,FINFO),
3433 (tcltk_constraint_find_deadlock_state_with_goal(DeadlockGoalPred,false,Res)
3434 -> write_result_to_file(Res),
3435 (Res=time_out ->
3436 print_red('*** TIME_OUT occurred ***'),nl,
3437 error_occurred(cbc_deadlock_check_time_out)
3438 ; print_red('*** DEADLOCK state found ***'),nl,
3439 error_occurred(cbc_deadlock_check),
3440 (silent_mode(on) -> true
3441 ; print('*** STATE = '),nl,
3442 current_b_expression(DBState), translate:print_bstate(DBState),nl,
3443 print('*** END DEADLOCKING STATE '),nl
3444 )
3445 )
3446 ; write_result_to_file(no_deadlock_found), Res=no_deadlock_found,
3447 print_green('No DEADLOCK state found'),nl
3448 ),
3449 write_cbc_check_result(Res),
3450 stop_xml_feature(cbc_deadlock_check,FINFO).
3451 cbc_assertions(AllowEnumWarning,Options) :-
3452 findall(OPT,option(cbc_option(OPT)),FullOptions,Options),
3453 check_loaded_not_empty(cbc_assertions),
3454 print_repl_prompt_s('% Starting Constraint-Based static ASSERTIONS check '),nl,
3455 start_xml_feature(cbc_assertion_check,allow_enumeration_warning,AllowEnumWarning,FINFO),
3456 write_prolog_term_as_xml_to_log(options(Options)),
3457 (cbc_constraint_find_static_assertion_violation(Res,FullOptions)
3458 -> process_cbc_assertion_result(Res,AllowEnumWarning)
3459 ; write_result_to_file(cbc_assertions_failed), Res=internal_error,
3460 print_red('CBC Check failed'),nl,
3461 error_occurred(cbc_assertions_failure)
3462 ),
3463 write_cbc_check_result(Res),
3464 stop_xml_feature(cbc_assertion_check,FINFO).
3465 cbc_sequence(Sequence,TargetPredString,Findall) :-
3466 check_loaded_not_empty(cbc_sequence),
3467 print_repl_prompt_s('% Starting Constraint-Based Check for Sequence: '), print_repl_prompt_s(Sequence),
3468 start_xml_feature(cbc_sequence_check,sequence,Sequence,FINFO),
3469 (TargetPredString='' -> true ; print(' with target: '), print(TargetPredString)),
3470 nl,
3471 write_xml_element_to_log(options,[target_predicate/TargetPredString]),
3472 (tcltk_cbc_find_trace(Sequence,TargetPredString,Findall,Res)
3473 -> (Res=ok -> print_green('Sequence found and executed'),nl
3474 ; Res=time_out -> error_occurred(cbc_sequence_time_out)
3475 ; Res=no_solution_found -> print_red('*** NO SOLUTION FOUND '),error_occurred(cbc_sequence_no_solution_found)
3476 ; Res=nr_cbc_sols(NrSols) -> print('*** # SOLUTIONS FOUND: '),print(NrSols),nl
3477 ; print_red('*** Unknown result: '), print(Res),nl,
3478 error_occurred(cbc_sequence)
3479 )
3480 ; print('*** Internal error: Check failed '), error_occurred(cbc_sequence), Res=internal_error
3481 ),
3482 write_cbc_check_result(Res),
3483 stop_xml_feature(cbc_sequence_check,FINFO).
3484 cbc_refinement :-
3485 check_loaded_not_empty(cbc_refinement),
3486 print_repl_prompt_s('% Starting Constraint-Based static refinement check '),nl,
3487 start_xml_feature(cbc_refinement_check,FINFO),
3488 tcltk_cbc_refinement_check(list(Result),ErrorsWereFound),
3489 print('% Constraint-Based Refinement Check Result: '),nl,print(Result),nl,
3490 (ErrorsWereFound = time_out -> print_red('*** TIME_OUT occurred ***'),nl,error_occurred(cbc_refinement_time_out) ;
3491 ErrorsWereFound = true -> print_red('*** Refinement Violation found ***'),nl,error_occurred(cbc_refinement) ;
3492 print_green('No static Refinement Violation found'),nl
3493 ),
3494 write_xml_element_to_log(cbc_check_result,[errors_were_found/ErrorsWereFound]),
3495 stop_xml_feature(cbc_refinement_check,FINFO).
3496 :- use_module(b_state_model_check,[cbc_find_redundant_invariants/2]).
3497 cbc_redundant_invariants(NrExpected) :-
3498 check_loaded_not_empty(cbc_redundant_invariants),
3499 print_repl_prompt_s('% Starting Constraint-Based invariant redundancy check'),nl,
3500 start_xml_feature(cbc_redundant_invariants,FINFO),
3501 cbc_find_redundant_invariants(Res,TimeoutOccured),
3502 length(Res,NrInvs),
3503 (Res = [] -> print_green('No redundant invariants found'),nl
3504 ; format('*** REDUNDANT INVARIANTS (~w) ***~n',[NrInvs]),
3505 prnt(1,Res), nl
3506 ),
3507 (NrExpected = NrInvs -> true
3508 ; format_with_colour_nl(user_error,[red],'*** Expected ~w redundant invariants (instead of ~w).',[NrExpected,NrInvs]),
3509 error_occurred(cbc_redundant_invariants)),
3510 write_xml_element_to_log(cbc_redundant_invariants,[redundant_invariants/NrInvs, timeout_occured/TimeoutOccured]),
3511 stop_xml_feature(cbc_redundant_invariants,FINFO).
3512
3513 prnt(_,[]).
3514 prnt(N,[H|T]) :- format(' ~w : ~w~n',[N,H]), N1 is N+1, prnt(N1,T).
3515
3516 :- use_module(solver_interface,[predicate_uses_unfixed_deferred_set/2, unfixed_typed_id_in_list/3]).
3517 process_cbc_assertion_result(time_out,_) :- !,
3518 write_result_to_file(no_counterexample_found('"TIME_OUT"')),
3519 print_red('*** TIME_OUT occurred ***'),nl,
3520 error_occurred(cbc_assertions_time_out).
3521 process_cbc_assertion_result(no_counterexample_exists(Constants,TotPredicate,OtherInfo),AllowEnumWarning) :- !,
3522 print_green('No counter-example to ASSERTION exists '),(OtherInfo=[] -> true ; print(OtherInfo)),nl,
3523 (unfixed_typed_id_in_list(TID,CType,Constants) % TO DO: look only at component
3524 -> write_deferred_set_used(AllowEnumWarning),
3525 get_texpr_id(TID,CID),pretty_type(CType,CTypeS),
3526 format('Warning: Some constants use deferred sets (e.g., ~w:~w) which have only been checked for a single cardinality!~n',[CID,CTypeS])
3527 ; predicate_uses_unfixed_deferred_set(TotPredicate,CType)
3528 -> write_deferred_set_used(AllowEnumWarning),pretty_type(CType,CTypeS),
3529 format('Warning: Some quantified variables use deferred sets (e.g., ~w) which have only been checked for a single cardinality!~n',[CTypeS]) % happens for tests 1173, 1174
3530 ; write_result_to_file(no_counterexample_exists)
3531 %,print('Computing unsat core: '),nl,unsat_cores:unsat_core(TotPredicate,Core),print('CORE: '),translate:print_bexpr(Core),nl
3532 ). % WE HAVE A PROOF
3533 process_cbc_assertion_result(no_counterexample_found,AllowEnumWarning) :- !,
3534 write_result_to_file(no_counterexample_found('"Enumeration Warning"')),
3535 print('No counter-example for ASSERTION found (*enumeration warning occured*)'),nl,
3536 (AllowEnumWarning=true -> true ; error_occurred(cbc_assertions_enumeration_warning)).
3537 process_cbc_assertion_result(counterexample_found,_) :- !,
3538 write_result_to_file(counterexample_found),
3539 print_red('*** Counter-example for ASSERTION found ***'),nl,
3540 error_occurred(cbc_assertions),
3541 (silent_mode(on) -> true
3542 ; print('*** STATE = '),nl,
3543 current_b_expression(DBState), translate:print_bstate(DBState),nl,
3544 print('*** END ASSERTION counter-example STATE '),nl
3545 ),
3546 (get_dot_file('cbc_assertions',DFile) -> generate_dot_from_assertions(DFile) ; true).
3547 process_cbc_assertion_result(Res,A) :-
3548 write_result_to_file(Res),
3549 add_internal_error('Unknown: ',process_cbc_assertion_result(Res,A)).
3550
3551
3552 write_deferred_set_used(AllowEnumWarning) :-
3553 write_result_to_file(no_counterexample_found('"Deferred Sets Used"')),
3554 (AllowEnumWarning=true -> true ; error_occurred(cbc_assertions_enumeration_warning)).
3555
3556 :- use_module(tools_io,[safe_open_file/4]).
3557 write_result_to_file(Result) :- option(cbc_result_file(FILE)),
3558 safe_open_file(FILE,write,Stream,[encoding(utf8)]),
3559 !,
3560 write(Stream,Result),
3561 close(Stream).
3562 write_result_to_file(_).
3563
3564
3565
3566 if_option_set(Option,Call) :-
3567 if_option_set(Option,Call,true).
3568 if_option_set(Option,Then,Else) :-
3569 (option(Option) -> call_for_option(Then) ; call_for_option(Else)).
3570 ifm_option_set(Option,Call) :-
3571 ifm_option_set(Option,Call,true).
3572 ifm_option_set(Option,Then,Else) :- % can perform multiple options
3573 findall(Then,option(Option),As),
3574 (As=[] -> call_for_option(Else) ; perform(As)).
3575 perform([]).
3576 perform([A|T]) :-
3577 call_for_option(A),
3578 perform(T).
3579 call_for_option(Call) :- (call(Call) -> true ; add_internal_error('probcli option call failed: ',Call)).
3580 if_option_set_loaded(Option,Action,Call) :-
3581 ( option(Option),check_loaded_not_empty(Action) ->
3582 call_for_option(Call)
3583 ; true).
3584 ifm_option_set_loaded(Option,Action,Call) :- % can perform multiple options
3585 findall(Call,(option(Option),check_loaded_not_empty(Action)),As),
3586 perform(As).
3587
3588
3589
3590 if_options_set(Option,Call) :- % allow multiple solutions for Option
3591 option(Option),call(Call),fail.
3592 if_options_set(_,_).
3593
3594 print_options :- print('CLI OPTIONS: '),nl,
3595 option(Option), print(Option), nl, fail.
3596 print_options :- nl.
3597
3598 :- use_module(cbcsrc(enabling_analysis),[infeasible_operation_cache/1]).
3599 :- use_module(cbcsrc(sap),[explore_and_generate_testcases/7,cbc_gen_test_cases_from_string/5, tcl_get_stored_test_cases/1]).
3600 :- use_module(translate,[print_bexpr/1]).
3601
3602 mcm_test_case_generation(ADepth,AMaxStates,ATarget,Output) :-
3603 arg_is_number(ADepth,MaxDepth),
3604 arg_is_number(AMaxStates,MaxStates),
3605 bmachine:b_parse_machine_predicate(ATarget,Target),!,
3606 get_comma_or_space_separated_options(mcm_cover,Events),
3607 (option(silent) -> true
3608 ; print('mcm test case generation, maximum search depth: '),print(MaxDepth),nl,
3609 print('mcm test case generation, maximum number of states: '),print(MaxStates),nl,
3610 print('mcm test case generation, target state predicate: '),print_bexpr(Target),nl,
3611 print('mcm test case generation, output file: '),print(Output),nl,
3612 print('mcm test case generation, events to cover: '),print_list(Events),nl
3613 ),
3614 explore_and_generate_testcases(Events,Target,MaxDepth,MaxStates,Output,NumTests,Uncovered),
3615 printsilent('mcm test case generation, generated test cases: '),printsilent(NumTests),nls,
3616 print_uncovered('mcm test case generation, ',Uncovered).
3617 mcm_test_case_generation(_ADepth,_AMaxStates,_ATarget,_Output) :-
3618 print_error('MCM Test Case Generation failed'),
3619 error_occurred(mcm_tests).
3620
3621 cbc_test_case_generation(ADepth,TargetString,Output) :-
3622 arg_is_number(ADepth,MaxDepth),
3623 ( option(cbc_cover_all) -> Events=all
3624 ; (get_comma_or_space_separated_options(cbc_cover,Events), Events \= []) -> true
3625 ; Events=all ),
3626 (\+ option(cbc_cover_final) -> FEvents = Events
3627 ; Events=all -> FEvents=all,
3628 add_error(cbc_cover_final,'Option cbc_cover_final not compatible with trying to cover all events')
3629 ; FEvents = final(Events),
3630 println_silent('constraint based test case generation, target events considered final')),
3631 printsilent('constraint based test case generation, maximum search depth: '),printsilent(MaxDepth),nls,
3632 printsilent('constraint based test case generation, target state predicate: '),printsilent(TargetString),nls,
3633 printsilent('constraint based test case generation, output file: '),printsilent(Output),nls,
3634 (TargetString = '#not_invariant' -> BMC=invariant_violation
3635 ; TargetString = '#deadlock' -> BMC=deadlock
3636 ; BMC = 'none'),
3637 (BMC \= 'none' ->
3638 printsilent('constraint based test case generation, performing bounded model checking'),nls
3639 ; option(silent) -> true
3640 ; print('constraint based test case generation, events to cover: '),print_list(Events),nl),
3641 cbc_gen_test_cases_from_string(FEvents,TargetString,MaxDepth,Output,Uncovered),
3642 !,
3643 format('constraint based test case generation finished~n',[]),
3644 (BMC \= 'none'
3645 -> tcl_get_stored_test_cases(list(Tests)), %print(tests(Tests)),nl,
3646 (Tests=[] -> print_green('No counterexample found'),nl
3647 ; Tests = [_|_], BMC=deadlock -> add_error(deadlock,'Deadlock found by bmc')
3648 ; Tests = [_|_] -> add_error(invariant_violation,'Invariant violation found by bmc')
3649 ; add_internal_error('Unexpected bmc result: ',Tests)
3650 )
3651 ; Uncovered=[_|_],option(strict_raise_error)
3652 -> add_error(cbc_tests,'Uncovered events: ',Uncovered)
3653 ; print_uncovered('constraint based test case generation, ',Uncovered)
3654 ).
3655 cbc_test_case_generation(_ADepth,_ATarget,_Output) :-
3656 print_error('Constraint based test case generation failed!'),
3657 error_occurred(cbc_tests).
3658
3659 print_uncovered(Msg,Uncovered) :-
3660 include(enabling_analysis:infeasible_operation_cache,Uncovered,Infeasible),
3661 (Infeasible=[]
3662 -> format('~wuncovered events: ',[Msg]),print_list(Uncovered),nl
3663 ; format('~winfeasible uncovered events: ',[Msg]),print_list(Infeasible),nl,
3664 exclude(enabling_analysis:infeasible_operation_cache,Uncovered,Feasible),
3665 format('~wuncovered events: ',[Msg]),print_list(Feasible),nl
3666 ).
3667
3668 print_list(all) :- print('** all **').
3669 print_list(list(L)) :- print_list(L). % possibly not used
3670 print_list([]) :- print('** none **').
3671 print_list([H|T]) :- length([H|T],Len), format('(~w) ',[Len]),
3672 print(H),print(' '),print_list2(T).
3673 print_list2([]).
3674 print_list2([H|T]) :- print(H),print(' '),print_list2(T).
3675
3676 get_comma_or_space_separated_options(Option,Selection) :-
3677 functor(O,Option,1),
3678 findall(E, (option(O),arg(1,O,CommaSep),
3679 split_by_seperator(CommaSep,Es),
3680 member(E,Es)),
3681 Selection).
3682
3683 split_by_seperator(NonAtomic,Res) :- \+ atomic(NonAtomic),!, Res=[NonAtomic].
3684 split_by_seperator(String,Strings) :-
3685 atom_chars(String,Chars),
3686 split_by_seperator2(Chars,Strings).
3687 split_by_seperator2(Chars,Result) :-
3688 append(AChars,[X|B],Chars),seperator(X),!,
3689 (AChars=[] -> Result=Rest ; atom_chars(A,AChars), Result=[A|Rest]),
3690 split_by_seperator2(B,Rest).
3691 split_by_seperator2(Chars,[String]) :- atom_chars(String,Chars).
3692
3693 seperator(',').
3694 seperator(' ').
3695 seperator(';').
3696
3697 ltl_check_assertions :-
3698 (option(ltl_limit(Limit)) -> true; Limit= -1), % -1 means no limit
3699 formatsilent('Model checking LTL assertions~n',[]),
3700 ltl_check_assertions(Limit,Outcome),!,
3701 ( Outcome = pass -> print_green('LTL check passed'),nl
3702 ; Outcome = fail -> print_red('*** LTL check failed'),nl,error_occurred(ltl)
3703 ; Outcome = no_tests -> print_red('*** No LTL assertions found, test failed'),nl,definite_error_occurred
3704 ; print_red('*** An error occurred in the LTL assertion test'),nl,
3705 definite_error_occurred).
3706 ltl_check_assertions :-
3707 add_internal_error('Call failed:',ltl_check_assertions),definite_error_occurred.
3708
3709 :- use_module(probltlsrc(ltl),[parse_ltlfile/2]).
3710 ltl_check_file(Filename) :-
3711 (option(ltl_limit(Limit)) -> true; Limit= -1), % -1 means no limit
3712 ajoin(['Model checking LTL assertions from file ',Filename],Msg),
3713 print_repl_prompt_s(Msg),nl,
3714 ( parse_ltlfile(Filename, Formulas)
3715 -> ltl_check_formulas(Formulas,Limit)
3716 ; print_red('An error occurred while parsing the LTL file.\n'),
3717 definite_error_occurred
3718 ).
3719
3720 :- use_module(probltlsrc(ltl),[ltl_model_check2/4]).
3721 ltl_check_formulas([],_) :-
3722 print_green('All LTL formulas checked.\n').
3723 ltl_check_formulas([formula(Name,F)|Rest],Limit) :-
3724 print('Checking formula '),print(Name),print(':\n'),
3725 ltl_model_check2(F,Limit,init,Status),
3726 ( Status == no ->
3727 print_red('Counter-example found for formula \"'),print_red(Name),
3728 print_red('\", saving trace file.\n'),
3729 ajoin(['ltlce_', Name, '.trace'], Tracefile),
3730 tcltk_save_history_as_trace_file(prolog,Tracefile),
3731 add_error(ltl_counterexample,'Counter-example was found')
3732 ; Status == ok ->
3733 ltl_check_formulas(Rest,Limit)
3734 ; Status == incomplete ->
3735 ajoin(['Model was not completly model-checked, aborted after ',Limit,' new states'],
3736 Msg),
3737 add_error(ltl,Msg)
3738 ;
3739 ajoin(['Model checker returns unexpected result (',Status,')'],Msg),
3740 add_error(ltl,Msg)).
3741
3742 % Mode = init or specific_node(ID) or starthere
3743 cli_ltl_model_check(Formula,Mode,ExpectedStatus,Status) :-
3744 (option(ltl_limit(Max)) -> true; Max = -1), % -1 means no limit
3745 start_xml_feature(ltl_model_check,formula,Formula,FINFO),
3746 ltl_model_check(Formula,Max,Mode,Status),
3747 write_xml_element_to_log(model_check_result,[status/Status,expected_status/ExpectedStatus,(mode)/Mode]),
3748 check_status(Status,ExpectedStatus,Formula,ltl),
3749 stop_xml_feature(ltl_model_check,FINFO).
3750
3751 % Mode = init or specific_node(ID) or starthere
3752 cli_ctl_model_check(Formula,Mode,ExpectedStatus,Status) :-
3753 (option(ltl_limit(Max)) -> true; Max = -1), % -1 means no limit
3754 start_xml_feature(ctl_model_check,formula,Formula,FINFO),
3755 ctl_model_check(Formula,Max,Mode,Status),
3756 write_xml_element_to_log(model_check_result,[status/Status,expected_status/ExpectedStatus,(mode)/Mode]),
3757 check_status(Status,ExpectedStatus,Formula,ctl),
3758 stop_xml_feature(ctl_model_check,FINFO).
3759
3760 :- use_module(extension('markov/dtmc_model_checking.pl')).
3761 cli_pctl_model_check(Formula,Mode,ExpectedStatus,Status) :-
3762 % use_module(extension('markov/dtmc_model_checking.pl')),
3763 (option(ltl_limit(Max)) -> true; Max = -1), % -1 means no limit
3764 dtmc_model_checking:pctl_model_check(Formula,Max,Mode,Status),
3765 check_status(Status,ExpectedStatus,Formula,pctl).
3766
3767 check_expected(St,Exp,Mode) :-
3768 (St=Exp -> true
3769 ; ajoin(['Unexpected ',Mode,' model checking result ',St,', expected: '],Msg),
3770 add_error(Mode,Msg,Exp)).
3771
3772 check_status(ok,Expected,Formula,ltl) :- !, % TO DO: make uniform ? CTL returns true; LTL returns ok
3773 format_with_colour_nl(user_output,[green],'LTL Formula TRUE.~nNo counter example found for ~w.',[Formula]),
3774 flush_output(user_output),
3775 check_expected(true,Expected,ltl).
3776 check_status(true,Expected,Formula,ctl) :- !,
3777 format_with_colour_nl(user_output,[green],'CTL Formula TRUE.~nNo counter example found for ~w.',[Formula]),
3778 flush_output(user_output),
3779 check_expected(true,Expected,ctl).
3780 check_status(true,Expected,Formula,pctl) :- !,
3781 format_with_colour_nl(user_output,[green],'PCTL Formula TRUE: ~w~n',[Formula]),
3782 flush_output(user_output),
3783 check_expected(true,Expected,pctl).
3784 check_status(solution(Bindings),Expected,Formula,pctl) :- !,
3785 format_with_colour_nl(user_output,[green],'PCTL Formula TRUE: ~w',[Formula]),
3786 format_with_colour_nl(user_output,[green],'PCTL Solutions: ~w~n',[Bindings]),
3787 flush_output(user_output),
3788 check_expected(true,Expected,pctl).
3789 check_status(incomplete,Expected,Formula,LTLorCTL) :- !,
3790 incomplete_warning(LTLorCTL,Warning),
3791 add_warning(Warning, 'Warning: Model Check incomplete for: ', Formula),nl,
3792 format('No counter example found so far for ~w.~n',[Formula]),
3793 check_expected(incomplete,Expected,LTLorCTL).
3794 check_status(NO,Expected,Formula,LTLorCTL) :- (NO=no ; NO=false),!, % TO DO: make uniform
3795 (Expected==false
3796 -> format_with_colour_nl(user_error,[red],'Model Check Counterexample found for: ~w',[Formula])
3797 ; add_error(LTLorCTL, 'Model Check Counterexample found for: ', Formula)
3798 ),
3799 cli_print_history,
3800 print('Formula '), print('FALSE.'),nl,
3801 debug_format(19,'Use -his FILE -his_option show_states to display states of counterexample~n',[]),
3802 nl,
3803 check_expected(false,Expected,LTLorCTL).
3804 check_status(Status,Expected,Formula,LTLorCTL) :-
3805 add_internal_error('Unknown status: ', check_status(Status,Expected,Formula,LTLorCTL)).
3806
3807 incomplete_warning(ltl,ltl_incomplete) :- !.
3808 incomplete_warning(ctl,ctl_incomplete) :- !.
3809 incomplete_warning(X,X).
3810
3811 :- if(environ(prob_release,true)).
3812
3813 run_benchmark(_, _, _) :-
3814 add_message(probcli, 'Command-line argument for benchmarking is not available in release mode.').
3815
3816 :- else.
3817
3818 :- use_module('../tests/smt_solver_benchmarks/alloy2b_benchmarks').
3819 :- use_module('../tests/smt_solver_benchmarks/smt_solver_benchmarks').
3820 run_benchmark(alloy, CmdName, AlloyFilePath) :-
3821 alloy2b_benchmarks:benchmark_alloy_command(CmdName, AlloyFilePath).
3822 run_benchmark(smt, bmc, Path) :-
3823 smt_solver_benchmarks:run_additional_bmc_benchmarks(false, [Path]), halt.
3824 run_benchmark(smt, cbc_deadlock, Path) :-
3825 smt_solver_benchmarks:run_additional_deadlock_benchmarks(false, [Path]), halt.
3826 run_benchmark(smt, cbc_inv, Path) :-
3827 smt_solver_benchmarks:run_additional_inductive_inv_benchmarks(false, [Path]), halt.
3828
3829 :- endif.
3830
3831 evaluate_from_commandline :-
3832 retractall(eval_result(_,_)),
3833 option(eval_string_or_file(A,B,Q,E,Rchk)), %print(eval(A,B,Q,E)),nl,
3834 % treat eval_string and eval_file together to ensure proper order of evaluation
3835 % (only possible side-effect at the moment: formula can add new machine_string facts)
3836 eval_string_or_file(A,B,Q,E,Rchk),
3837 fail.
3838 evaluate_from_commandline :- print_eval_results,
3839 % treat -repl option or -replay File option
3840 (option(eval_repl([File1|TF]))
3841 -> (repl_evaluate_expressions([File1|TF]) -> true ; true)
3842 ; start_repl_if_required).
3843 start_repl_if_required :-
3844 (option(eval_repl([]))
3845 -> (repl_evaluate_expressions([]) -> true ; true)
3846 ; true).
3847
3848 :- dynamic eval_result/2.
3849 add_eval_result(R) :- retract(eval_result(R,N)),!,
3850 N1 is N+1, assertz(eval_result(R,N1)).
3851 add_eval_result(R) :- assertz(eval_result(R,1)).
3852 print_eval_results :- findall(R/N, eval_result(R,N), L), sort(L,SL),
3853 (SL=[] -> true ; format('Evaluation results: ~w~n',[SL])).
3854
3855 :- use_module(tools_printing,[print_error/1, format_error_with_nl/2]).
3856 %eval_string_or_file(string,_String,_,'FALSE',_Recheck) :- !. % comment in to skip evalf
3857 eval_string_or_file(string,String,_,Expected,Recheck) :-
3858 inc_counter(eval_string_nr,EvalNr),
3859 set_current_probcli_command(eval_string(String)),
3860 (option(silent),nonvar(Expected) -> true
3861 ; nonvar(Expected) -> format('eval(~w:~w): ~w~n',[EvalNr,Expected,String])
3862 ; format('eval(~w): ~w~n',[EvalNr,String])
3863 ),
3864 reset_error_spans, % avoid underlining previous errors in eval_string
3865 (eval_string_with_time_out(String,StringResult,EnumWarning,_LS) -> true
3866 ; print_error('Eval string failed: '), print_error(String),
3867 error_occurred(eval_string),
3868 StringResult='fail'
3869 ),
3870 add_eval_result(StringResult),
3871 eval_check_result(StringResult,Expected,EnumWarning,eval_string(EvalNr),String),
3872 (Recheck=recheck(Mode) -> recheck_pp_of_last_expression(Mode,_,_) ; true),
3873 unset_current_probcli_command.
3874 eval_string_or_file(file(bench),File,Quantifier,Expected,Recheck) :- !,
3875 ( member(Solver,[prob,kodkod,sat,'sat-z3','z3', 'cdclt',clingo]),
3876 (eval_string_or_file(file(Solver),File,Quantifier,Expected,Recheck) -> fail)
3877 ; true).
3878 eval_string_or_file(file(Solver),File,Quantifier,Expected,_) :-
3879 % evaluate a single formula stored in a file
3880 set_current_probcli_command(eval_file(Solver,File)),
3881 turn_show_error_source_off, % reduce clutter in user feedback; eval_file used in ProB Logic Calculator for example
3882 formatsilent('~nEvaluating file: ~w~n',[File]),
3883 error_manager:reset_error_scopes, % TO DO: avoid that exceptions mess up error scopes in eval_string/file
3884 statistics(runtime,[Start,_]),
3885 statistics(walltime,[W1,_]),
3886 (Expected=='TRUE' -> TypeInfo=predicate(_) % avoids parsing as expression
3887 ; true),
3888 (eval_file(Solver,File,Quantifier,Result,EnumWarning,TypeInfo)
3889 -> statistics(walltime,[W2,_]), WT is W2-W1,
3890 translate_solver_result(Result,Infos),
3891 accumulate_file_infos(File,Solver,[walltime-WT|Infos]),
3892 add_eval_result(Result),
3893 eval_check_result(Result,Expected,EnumWarning,eval_file,File)
3894 ; statistics(walltime,[W2,_]), WT is W2-W1,
3895 accumulate_file_infos(File,Solver,[failure-1,false-0,true-0,unknown-1,walltime-WT]),
3896 add_eval_result(eval_file_failed),
3897 print_error('Eval from file failed: '), print_error(File),
3898 error_occurred(eval_file)
3899 ),
3900 statistics(runtime,[Stop,_]), Time is Stop - Start,
3901 debug_format(19,'Time for ~w : ~w ms (~w ms walltime)~n',[File,Time,WT]),
3902 turn_show_error_source_on,
3903 unset_current_probcli_command.
3904
3905 translate_solver_result('TRUE',I) :- !, I=[false-0,true-1,unknown-0].
3906 translate_solver_result('FALSE',I) :- !, I=[false-1,true-0,unknown-0].
3907 translate_solver_result('UNKNOWN',I) :- !,I=[false-0,true-0,unknown-1].
3908 translate_solver_result('**** TIME-OUT ****',I) :- !,I=[false-0,true-0,unknown-1].
3909 translate_solver_result(_,[false-0,true-0,unknown-1]). % we could record this as error
3910
3911 eval_check_result(StringResult,Expected,_,Origin,File) :- Expected\=StringResult,!,
3912 format_error_with_nl('! Evaluation error, expected result to be: ~w (but was ~w) in ~w',[Expected,StringResult,File]),
3913 error_occurred(Origin).
3914 eval_check_result('NOT-WELL-DEFINED',Expected,_,Origin,File) :- var(Expected),!,
3915 format_error_with_nl('! Evaluation NOT-WELL-DEFINED in ~w',[File]),
3916 error_occurred(Origin).
3917 eval_check_result(_,_,EnumWarning,_,_) :- eval_gen_enum_warning(EnumWarning).
3918
3919 eval_gen_enum_warning(false) :- !.
3920 eval_gen_enum_warning(time_out) :- !,error_occurred(eval_string_time_out).
3921 eval_gen_enum_warning(_) :- print_error('Enumeration warning occurred'),
3922 error_occurred(eval_string_enum_warning,warning).
3923 %repl :- repl_evaluate_expressions([]).
3924 :- use_module(parsercall,[ensure_console_parser_launched/0]).
3925 repl_evaluate_expressions(StartFiles) :-
3926 get_errors, % first clear any errors from earlier commands
3927 nl,
3928 print('ProB Interactive Expression and Predicate Evaluator '), nl,
3929 print('Type ":help" for more information.'),nl,
3930 turn_show_error_source_off, % reduce clutter in user feedback
3931 (option(evaldot(File))
3932 -> print('Solutions written to dot file: '), print(File),nl
3933 ; true
3934 ),
3935 (ensure_console_parser_launched
3936 -> maplist(prob_cli:set_repl_input_file(verbose),StartFiles),
3937 top_level_eval
3938 ; print_repl_prompt, write('ABORTING REPL'),nl),
3939 turn_show_error_source_on.
3940
3941 :- use_module(user_interrupts,[interruptable_call/1]).
3942 top_level_eval :-
3943 catch(top_level_eval1, halt(0), (format('~s', ["Bye."]), nl)).
3944
3945 :- use_module(tools_printing,[reset_terminal_colour/1, print_red/1, print_green/1,
3946 get_repl_prompt/1, get_repl_continuation_prompt/1]).
3947 print_repl_prompt :- get_repl_prompt(Prompt), write(Prompt),reset_terminal_colour(user_output).
3948 print_repl_prompt_s(_) :- option(silent),!.
3949 print_repl_prompt_s(P) :- print_repl_prompt(P).
3950 print_repl_prompt(P) :- reset_terminal_colour(user_output), write(P).
3951 %print_repl_prompt(P) :- tools_printing:start_terminal_colour(dark_gray,user_output), write(P), reset_terminal_colour(user_output).
3952
3953 top_level_eval1 :-
3954 (interruptable_call(eval1) -> true
3955 ; print_red('Evaluation failed or interrupted'),nl,
3956 print_repl_prompt('Use :q to quit REPL'),nl),
3957 reset_errors,
3958 top_level_eval1.
3959 eval0 :- store_last_error_location_for_repl,
3960 reset_errors, % get_errors prints errors again and quits in -strict mode
3961 % However, reset_errors means that in subsequent REPL runs errors are not printed again!!
3962 garbage_collect, eval1.
3963 eval1 :- repl_multi_read_line(Expr), eval_probcli_repl_line(Expr).
3964
3965 :- dynamic last_repl_error/2.
3966 store_last_error_location_for_repl :-
3967 retractall(last_repl_error(_,_)),
3968 check_error_span_file_linecol(_,File,Line,_,_,_),!,
3969 assertz(last_repl_error(File,Line)).
3970 store_last_error_location_for_repl.
3971
3972 :- dynamic current_repl_input_stream/2.
3973 close_repl_input_stream(file_closed) :- retract(current_repl_input_stream(X,File)),!,
3974 format(":replayed ~w~n",[File]),
3975 close(X).
3976 close_repl_input_stream(no_file).
3977 :- use_module(tools_io,[safe_open_file/4]).
3978 set_repl_input_file(_,File) :- current_repl_input_stream(_,File),!,
3979 add_error(set_repl_input_file,'Cyclic file replay: ',File).
3980 set_repl_input_file(Verbose,File) :-
3981 % close_repl_input_stream, % this way we allow one REPL file to call another
3982 safe_open_file(File,read,Stream,[encoding(utf8)]),!,
3983 (Verbose=verbose -> format('Replaying REPL commands in file: ~w~n',[File]) ; true),
3984 asserta(current_repl_input_stream(Stream,File)).
3985 set_repl_input_file(_,_).
3986
3987 repl_multi_read_line(Line) :-
3988 (current_repl_input_stream(Stream,_)
3989 -> repl_multi_read_line(Stream,Line),
3990 format(user_output,'~s~n',[Line])
3991 ; repl_multi_read_line(user_input,Line)
3992 ).
3993 repl_multi_read_line(Stream,Line) :-
3994 get_repl_prompt(Prompt),
3995 repl_multi_read_line_aux(Stream,Prompt,[],Line).
3996 repl_multi_read_line_aux(Stream,Prompt,SoFar,Line) :-
3997 prompt(OldPrompt,Prompt),
3998 call_cleanup(read_line(Stream,L), prompt(_,OldPrompt)),
3999 (L=end_of_file -> close_repl_input_stream(FileC),
4000 (SoFar=[], FileC = file_closed
4001 -> repl_multi_read_line(Line) % last line of file empty; do not process
4002 ; FileC = file_closed -> Line=SoFar
4003 ; Line=end_of_file) % user pressed CTRL-D
4004 ; append(LFront,[92],L) % line ends with slash \
4005 -> append(LFront,[10],LFront2), % insert newline instead;
4006 % note cleanup_newlines in parsercall transforms this into 8232 \x2028 Unicode
4007 append(SoFar,LFront2,NewSoFar),
4008 get_repl_continuation_prompt(NewPrompt),
4009 repl_multi_read_line_aux(Stream,NewPrompt,NewSoFar,Line)
4010 ; append(SoFar,L,Line)).
4011
4012 :- use_module(eval_strings).
4013 :- dynamic trace_eval/0.
4014
4015 generate_atom_list([],[],R) :- !, R=[].
4016 generate_atom_list([],Last,[NewAtom]) :-
4017 reverse(Last,RL),
4018 atom_codes(NewAtom,RL).
4019 generate_atom_list([39|X],[],[QuotedAtom|T]) :- !,
4020 get_quoted_atom(X,[],QuotedAtom,Rest),
4021 strip_leading_ws(Rest,X2),
4022 generate_atom_list(X2,[],T).
4023 generate_atom_list([32|X],Last,[NewAtom|T]) :- !,
4024 reverse(Last,RL),
4025 atom_codes(NewAtom,RL),
4026 strip_leading_ws(X,X2),
4027 generate_atom_list(X2,[],T).
4028 generate_atom_list([H|X],Last,Res) :- generate_atom_list(X,[H|Last],Res).
4029
4030 get_quoted_atom([],Acc,QuotedAtom,[]) :- reverse(Acc,R), atom_codes(QuotedAtom,R).
4031 get_quoted_atom([39|T],Acc,QuotedAtom,T) :- !, reverse(Acc,R), atom_codes(QuotedAtom,R).
4032 get_quoted_atom([H|T],Acc,QuotedAtom,Rest) :- get_quoted_atom(T,[H|Acc],QuotedAtom,Rest).
4033
4034
4035 strip_leading_ws([32|X],R) :- !, strip_leading_ws(X,R).
4036 strip_leading_ws(X,X).
4037
4038 :- meta_predicate call_probcli_option(0).
4039 call_probcli_option(_:Option) :- just_assert_option(Option), !,
4040 (option(Option) -> true ; assert_option(Option)).
4041 call_probcli_option(_:statistics) :- !, % avoid calling SICS version
4042 cli_print_statistics(full).
4043 call_probcli_option(Option) :-
4044 catch(call(Option), error(existence_error(A,B),E), (
4045 treat_existence_error(A,B,E,Option),
4046 nl % ensure that next prompt is printed
4047 )).
4048
4049 % commands that require no execution; just asserting option(.)
4050 just_assert_option(depth_first).
4051 just_assert_option(breadth_first).
4052 just_assert_option(strict_raise_error).
4053 just_assert_option(no_deadlocks).
4054 just_assert_option(no_invariant_violations).
4055 just_assert_option(no_goal).
4056 just_assert_option(no_ltl).
4057 just_assert_option(no_assertion_violations).
4058 just_assert_option(no_state_errors).
4059 just_assert_option(no_counter_examples).
4060
4061 treat_existence_error(source_sink,File,E,Option) :- !,
4062 format_with_colour_nl(user_error,[red],
4063 '* Could not find file ~w~n* for probcli command ~w~n* Detailed error: ~w',[File,Option,E]).
4064 treat_existence_error(_,_,E,Option) :-
4065 format_with_colour_nl(user_error,[red],
4066 '* probcli command not yet supported in REPL: ~w~n* Error: ~w',[Option,E]).
4067
4068 reload_mainfile :-
4069 file_loaded(_,MainFile),
4070 reset_errors,
4071 print_repl_prompt_s('Reloading and initialising file: '), print_repl_prompt_s(MainFile),nl,
4072 clear_loaded_files,
4073 load_main_file(MainFile,0,_),
4074 get_errors,
4075 cli_start_animation(0),
4076 cli_start_initialisation(0).
4077
4078 % REPL EVAL LOOP:
4079 eval_probcli_repl_line(end_of_file) :- !, eval_line(end_of_file).
4080 eval_probcli_repl_line(Line) :- strip_ws(Line,SLine),
4081 catch(eval_line(SLine), E, (
4082 E=halt(_) -> throw(E) % e.g., coming from :quit; will be caught above
4083 ; E='$aborted' -> throw(E) % thrown by SWI-Prolog on abort by user
4084 ; add_error(repl,'Uncaught Exception in REPL: ',E),
4085 nl % ensure that next prompt is printed
4086 )).
4087
4088 % strip whitespace at end and beginning
4089 strip_ws([H|T],Res) :- is_ws(H),!, strip_ws(T,Res).
4090 strip_ws(C,Res) :- reverse(C,CR), strip_ws2(CR,SCR), reverse(SCR,Res).
4091 strip_ws2([H|T],Res) :- is_ws(H),!, strip_ws2(T,Res).
4092 strip_ws2(R,R).
4093
4094 is_ws(32).
4095
4096 :- use_module(performance_messages,[toggle_perfmessages/0]).
4097 eval_line([]) :- !, print_repl_prompt('Type :q or :quit to quit.'),nl,eval0.
4098 eval_line(end_of_file) :- !, halt_exception(0).
4099 % Haskell GHCI like syntax
4100 eval_line(":r") :- !, eval_line("--reload").
4101 eval_line(":reload") :- !, eval_line("--reload").
4102 eval_line("--reload") :- !,
4103 (reload_mainfile -> true ; get_errors,print_repl_prompt('Error(s) occured during reload (use :e to jump to first error)'),nl),
4104 eval0.
4105 % TO DO: other Haskell commands :info E :l FILE , let pattern = expression
4106 eval_line(":prefs") :- !,print_eclipse_prefs, eval0.
4107 eval_line([45|Command]) :- % -command
4108 generate_atom_list([45|Command],[],ArgV),
4109 %print(argv(ArgV)),nl,
4110 % try and parse like commands passed to probcli
4111 get_options(ArgV,recognised_cli_option,Options,[],fail),
4112 print_repl_prompt('Executing probcli command: '),print_repl_prompt(Options),nl,!,
4113 (maplist(prob_cli:call_probcli_option,Options) -> true
4114 ; print_red('Failed to execute probcli arguments'),nl),
4115 eval0.
4116 eval_line("+") :- !, add_last_expression_to_unit_tests, eval0.
4117 eval_line("$+") :- !, preferences:temporary_set_preference(expand_avl_upto,-1,CHNG),
4118 print_last_value,preferences:reset_temporary_preference(expand_avl_upto,CHNG),
4119 eval0.
4120 %eval_line("$$") :- !, print_last_expression, eval0. % now in eval_strings
4121 eval_line("$$$") :- !, % $$0 - $$9 commands to print last expression with indentation
4122 indent_print_last_expression, eval0.
4123 %eval_line("$") :- !, print_last_info, eval0. % now in eval_strings
4124 eval_line("!trace") :- !, eval_line("^").
4125 eval_line("^") :- !,
4126 (retract(trace_eval) -> print_repl_prompt('TRACING OFF'),nl
4127 ; assertz(trace_eval), print_repl_prompt('TRACING ON'),nl), eval0.
4128 eval_line("!observe") :- !, toggle_observe_evaluation.
4129 eval_line("!v") :- !, tcltk_turn_debugging_off.
4130 eval_line("!p") :- !, toggle_perfmessages.
4131 eval_line("!perf") :- !, toggle_perfmessages.
4132 eval_line("!profile") :- !, eval_line("%").
4133 eval_line("!print_profile") :- !, eval_line("%%").
4134 eval_line("%") :- !, print_repl_prompt('PROFILING : '), %spy([avl:avl_size/2]),
4135 (current_prolog_flag(profiling,on)
4136 -> set_prolog_flag(profiling,off), print('OFF') ;
4137 set_prolog_flag(profiling,on), print('ON')),
4138 nl,print_repl_prompt('USE %% to print profile info'),nl,eval0.
4139 eval_line("%%") :- !, nl,print_repl_prompt('PROLOG PROFILE INFORMATION:'), nl,
4140 catch(print_profile,
4141 error(existence_error(_,_),_),
4142 print_red('CAN ONLY BE USED WHEN RUNNING PROB FROM SOURCE')),
4143 nl,
4144 debug:timer_statistics,
4145 eval0.
4146 eval_line("!print_coverage") :- !, nl,print_repl_prompt('PROLOG COVERAGE INFORMATION:'), nl,
4147 (current_prolog_flag(source_info,on) -> true ; print_red('Only useful when current_prolog_flag(source_info,on)!'),nl),
4148 catch(print_coverage,
4149 error(existence_error(_,_),_),
4150 print_red('CAN ONLY BE USED WHEN RUNNING PROB FROM SOURCE')),
4151 nl,
4152 eval0.
4153 eval_line("!profile_reset") :- !, nl,print_repl_prompt('RESETTING PROLOG PROFILE INFORMATION'), nl,
4154 catch(profile_reset,
4155 error(existence_error(_,_),_),
4156 print_red('CAN ONLY BE USED WHEN RUNNING PROB FROM SOURCE')),
4157 eval0.
4158 eval_line("%%%") :- !, nl,print('PROFILE INFORMATION (Starting TK Viewer):'), nl,
4159 catch(
4160 (use_module(library(gauge)), gauge:view),
4161 error(existence_error(_,_),_),
4162 print_red('CAN ONLY BE USED WHEN RUNNING PROB FROM SOURCE')),
4163 nl,
4164 eval0.
4165 eval_line("!debug") :- !,
4166 print_repl_prompt('ENTERING PROLOG DEBUG MODE:'),
4167 catch(
4168 debug,
4169 error(existence_error(_,_),_),
4170 print_red('CAN ONLY BE USED WHEN RUNNING PROB FROM SOURCE')),
4171 nl,
4172 eval0.
4173 eval_line("@") :- !, get_preference(find_abort_values,OldVal),
4174 print_repl_prompt('Try more aggressively to detect ill-defined expressions: '),
4175 (OldVal=true -> Val=false ; Val=true), print(Val),nl,
4176 temporary_set_preference(find_abort_values,Val) , eval0.
4177 eval_line("!") :- !, toggle_eval_det,eval0.
4178 eval_line("!norm") :- !, toggle_normalising,eval0.
4179 eval_line(Codes) :- parse_eval_command(Codes,CommandName,Argument),!,
4180 debug_println(9,executing_eval_command(CommandName,Argument)),
4181 (exec_eval_command(CommandName,Argument) -> eval0
4182 ; format_with_colour_nl(user_error,[red,bold],'Command ~w failed',[CommandName]),
4183 eval0).
4184 eval_line(ExpressionOrPredicate) :- (trace_eval -> trace ; true),
4185 (eval_codes(ExpressionOrPredicate,exists,_,_,_,_)
4186 -> eval0
4187 ; print_red('Evaluation failed'),nl,eval0).
4188
4189 parse_eval_command([C|Rest],CommandName,Argument) :- [C]=":",
4190 eval_command(Cmd,CommandName),
4191 append(Cmd,RestArg,Rest),
4192 (RestArg = [Letter1|_] -> is_ws(Letter1) /* otherwise command name continues */ ; true),
4193 strip_ws(RestArg,Argument),
4194 (eval_command_help(CommandName,[],_), Argument = [_|_]
4195 -> format_with_colour_nl(user_error,[red],'WARNING: Command ~w does not take arguments!',[CommandName])
4196 ; eval_command_help(CommandName,[_|_],_), Argument = []
4197 -> format_with_colour_nl(user_error,[red],'WARNING: Command ~w requires arguments!',[CommandName])
4198 ; true).
4199
4200 % TO DO: some of these commands should also be made available in the Tcl/Tk Console
4201 eval_command("q",quit).
4202 eval_command("quit",quit).
4203 eval_command("halt",quit).
4204 eval_command("x",exit).
4205 eval_command("exit",exit).
4206 eval_command("f",find).
4207 eval_command("find",find).
4208 eval_command("*",apropos).
4209 eval_command("apropos",apropos).
4210 eval_command("help",help).
4211 eval_command("h",help).
4212 eval_command("?",help).
4213 eval_command("ctl",ctl(init)). % :ctl
4214 eval_command("ctlh",ctl(starthere)). % :ctlh
4215 eval_command("ltl",ltl(init)). % :ltl
4216 eval_command("ltlh",ltl(starthere)). % :ltlh
4217 eval_command("pctl",pctl(init)). % :pctl
4218 eval_command("pctlh",pctl(starthere)). % :pctlh
4219 eval_command("reset",reset_animator(hard)). % :reset
4220 eval_command("reset-history",reset_animator(history_only)). % :reset
4221 eval_command("statistics",statistics).
4222 eval_command("stats",statistics). % :stats
4223 eval_command("states",state_space_stats). % :states
4224 eval_command("state",show_state_info(2000)). % :state
4225 eval_command("statespace",state_space_display). % :statespace
4226 eval_command("u",unsat_core).
4227 %eval_command("core",unsat_core).
4228 eval_command("show",show_last_as_table). % :show
4229 eval_command("dot",show_last_as_dot(no_dot_viewing)). % :dot
4230 eval_command("dotty",show_last_as_dot(dotty)).
4231 eval_command("dotpdf",show_last_as_dot(dot)).
4232 eval_command("sfdp",show_last_as_dot(sfdp)).
4233 eval_command("browse",browse). % :browse
4234 eval_command("abstract_constants",check_abstract_constants). % :abstract_constants
4235 eval_command("det_check_constants",det_check_constants). % :det_check_constants
4236 eval_command("b",browse).
4237 eval_command("hbrowse",hbrowse). % :hbrowse browse hiearchy
4238 eval_command("hshow",hshow). % show inclusion hieararchy
4239 eval_command("comp",show_components). % :comp
4240 eval_command("replay",replay_repl_file). % :replay
4241 eval_command("trim",trimcore). % :trim
4242 eval_command("src",show_source). %:src
4243 eval_command("source",show_source). %:source
4244 eval_command("origin",show_origin). %:origin
4245 eval_command("edit",edit_main_file).
4246 eval_command("e",edit_main_file). % :e
4247 eval_command("comment",comment).
4248 eval_command("machine",show_machine_info(statistics)). %:machine
4249 eval_command("machine-stats",show_machine_info(statistics)). %:machine
4250 eval_command("files",show_machine_info(files)). %:files
4251 eval_command("syntax",syntax_help). % :syntax
4252 eval_command("open",open_file). % :open
4253
4254 available_commands(SLC) :-
4255 findall(Cmd,(eval_command(Cs,_),atom_codes(Cmd,[58|Cs])), LC),
4256 sort(LC,SLC).
4257
4258 eval_command_help(exit,[],'Exit ProB').
4259 eval_command_help(find,['P'],'Find state in state-space which makes LTL atomic proposition P true; LTL Propositions: {B-Pred}, e(Op), [Op], true, false, sink').
4260 eval_command_help(ltl(starthere),['F'],'Check LTL formula F starting from current state').
4261 eval_command_help(ltl,['F'],'Check LTL formula F; LTL Operators: G,F,X,U,W,R,not,&,or,=>; LTL Propositions: {B-Pred}, e(Op), [Op], true, false, sink; Past-LTL Operators: Y,H,O,S,T (dual to X,G,F,U,R)').
4262 eval_command_help(ctl(starthere),['F'],'Check CTL formula F starting from current state').
4263 eval_command_help(ctl(_),['F'],'Check CTL formula F in all initial states; CTL Syntax: ExUy,EXx,AXx,EFx,AGx,EX[Op]x,e(Op),{B-Pred}').
4264 eval_command_help(pctl(starthere),['F'],'Check PCTL formula F starting from current state').
4265 eval_command_help(pctl(_),['F'],'Check PCTL formula F; PCTL Operators: not, &, or, =>, {B-Pred}, e(Op), [Op], true, false, sink, P op {Exp} [PathFormula] with op in {<,<=,>=,>,=}; Path operators: X, U, F, G, U<=Bound, F<=Bound, G<=Bound').
4266 eval_command_help(browse,opt('PAT'),'Browse available constants, variables, sets and lets introduced in REPL').
4267 eval_command_help(apropos,['PAT'],'Find constant or variable whose names contains PAT').
4268 eval_command_help(hbrowse,['PAT'],'Browse machine hierarchy for all identifiers whose names contains PAT').
4269 eval_command_help(hshow,[],'Show machine inclusion hierarchy using topological sorting').
4270 eval_command_help(show_components,[],'Show components of PROPERTIES').
4271 eval_command_help(abstract_constants,[],'Show ABSTRACT_CONSTANTS and check if can be fully evaluated').
4272 eval_command_help(det_check_constants,[],'Check if values of CONSTANTS are forced and explain if they are').
4273 eval_command_help(show_last_as_table,[],'Show last evaluated expression in tabular form').
4274 eval_command_help(show_last_as_dot(_),['F'],'Show expression or predicate F as dot graph').
4275 eval_command_help(unsat_core,[],'Compute Unsatisfiable Core of last evaluated predicate').
4276 eval_command_help(help,opt('CMD'),'Provide help about REPL command CMD').
4277 eval_command_help(replay_repl_file,['FILE'],'Replay FILE of REPL commands').
4278 eval_command_help(reset_animator(_),[],'Reset history and statespace of animator').
4279 eval_command_help(show_source,['ID'],'Show origin and source code definition of identifier ID').
4280 eval_command_help(show_origin,['ID'],'Show origin of identifier ID and try opening in EDITOR').
4281 eval_command_help(show_machine_info(_),[],'Show statistics about loaded machine and files').
4282 eval_command_help(state_space_stats,[],'Show statistics about state space').
4283 eval_command_help(state_space_display,[],'Show complete state space transitions (could be very big !)').
4284 eval_command_help(show_state_info(_),[],'Show current state').
4285 eval_command_help(statistics,[],'Show statistics about last evaluation').
4286 % -machine_stats : cli_print_machine_info(statistics) -machine_files : cli_print_machine_info(files)
4287 eval_command_help(trim,[],'Trim memory usage of probcli (try and give memory back to the OS)').
4288 % implemented in eval_strings:
4289 eval_command_help(type,['E'],'Show type of expression E').
4290 eval_command_help(cvc4,['P'],'Solve predicate P using CVC4 solver').
4291 eval_command_help(kodkod,['P'],'Solve predicate P using SAT solver via Kodkod').
4292 eval_command_help(z3,['P'],'Solve predicate P using Z3 solver').
4293 eval_command_help('z3-free',['P'],'Solve predicate P using Z3 solver (ignoring current state)').
4294 eval_command_help('z3-file',['F'],'Solve predicate in File F using Z3 solver').
4295 eval_command_help('z3-free-file',['F'],'Solve predicate in File F using Z3 solver (ignoring current state)').
4296 eval_command_help(cdclt,['P'],'Solve predicate P using Prolog CDCL(T) solver').
4297 eval_command_help(cdclt-free,['P'],'Solve predicate P using Prolog CDCL(T) solver (ignoring current state)').
4298 eval_command_help(prob,['P'],'Solve predicate P using ProB solver (ignoring current state)').
4299 eval_command_help('prob-file',['F'],'Solve predicate in File F using ProB solver (ignoring current state)').
4300 eval_command_help(edit_main_file,opt('ID'),'Edit main file (or origin of identifier ID) using EDITOR (path_to_text_editor preference)').
4301 eval_command_help(comment,['STRING'],'provide STRING as a comment (mainly useful for :replay files)').
4302 eval_command_help(syntax_help,[],'Show a summary of the B syntax accepted by the REPL').
4303 eval_command_help(open_file,['FILE'],'Open FILE in preferred application.').
4304
4305 print_eval_command_help(Codes) :-
4306 eval_command(Codes,Cmd),
4307 eval_command_help(Cmd,Args,Descr),
4308 (Args = []
4309 -> format('Command ~w~n Syntax :~s~n ~w~n',[Cmd,Codes,Descr])
4310 ; Args=[Arg] -> format('Command ~w~n Syntax :~s ~w~n ~w~n',[Cmd,Codes,Arg,Descr])
4311 ; Args=opt(Arg) -> format('Command ~w~n Syntax :~s [~w]~n ~w~n',[Cmd,Codes,Arg,Descr])
4312 ; format('Command ~w~n Syntax :~s ~w~n ~w~n',[Cmd,Codes,Args,Descr])).
4313
4314 :- use_module(tools_commands,[show_dot_file/1, show_pdf_file/1, gen_dot_output/4]).
4315 :- use_module(state_space,[transition/4]).
4316 :- use_module(b_machine_hierarchy,[print_machine_topological_order/0]).
4317 exec_eval_command(quit,_) :- !, halt_exception(0).
4318 exec_eval_command(exit,_) :- !,halt.
4319 exec_eval_command(browse,CodesToMatch) :- !,
4320 (CodesToMatch=[] -> browse % maybe merge with apropos functionality
4321 ; exec_eval_command(apropos,CodesToMatch)).
4322 exec_eval_command(find,FORMULA) :-
4323 atom_codes(APF,FORMULA),cli_find_ltl_ap(APF).
4324 exec_eval_command(apropos,CodesToMatch) :- /* :* Pattern (apropos command) */
4325 browse_machine(CodesToMatch).
4326 exec_eval_command(hbrowse,CodesToMatch) :- /* :* Pattern (hbrowse command) */
4327 browse_all_machines(CodesToMatch).
4328 exec_eval_command(hshow,_) :- /* show inclusion hierarhcy */
4329 print_machine_topological_order.
4330 exec_eval_command(show_components,_) :-
4331 print_property_partitions.
4332 exec_eval_command(check_abstract_constants,_) :-
4333 check_abstract_constants.
4334 exec_eval_command(det_check_constants,_) :-
4335 det_check_constants.
4336 exec_eval_command(help,Arg) :-
4337 (Arg=[] -> eval_help
4338 ; print_eval_command_help(Arg) -> true
4339 ; (Arg=[58|RA],print_eval_command_help(RA)) -> true % remove : at front
4340 ; format('Cannot provide help about ~s~n',[Arg]),
4341 available_commands(LC), format('Available commands: ~w~n',[LC])
4342 ).
4343 exec_eval_command(ctl(Mode),FORMULA) :- % :ctl or :ctlh for ctl here
4344 atom_codes(F,FORMULA),
4345 (cli_ctl_model_check(F,Mode,_,Status)
4346 -> (Status=false -> write_history_to_user_output([show_init,show_states]) ; true)
4347 ; print('CTL Syntax: ExUy,EXx,AXx,EFx,AGx,EX[Op]x,e(Op),{B-Pred}'),nl).
4348 exec_eval_command(ltl(Mode),FORMULA) :- % :ltl or :ltlh with Mode = init or starthere
4349 atom_codes(F,FORMULA),
4350 (cli_ltl_model_check(F,Mode,_,Status)
4351 -> (Status=no -> write_history_to_user_output([show_init,show_states]) ; true)
4352 ; print('LTL Operators: G,F,X,U,W,R,not,&,or,=>,<=>'),nl,
4353 print('LTL Propositions: {B-Pred}, e(Op), [Op], true, false, sink'),nl,
4354 print('Past-LTL Operators: Y,H,O,S,T (dual to X,G,F,U,R)'),nl
4355 ).
4356 exec_eval_command(pctl(Mode),FORMULA) :- % :pctl or :pctlh with Mode = init or starthere
4357 atom_codes(F,FORMULA),
4358 (cli_pctl_model_check(F,Mode,_,Status)
4359 -> (Status=no -> write_history_to_user_output([show_init,show_states]) ; true)
4360 ; print('PCTL Propositional Operators: not, &, or, =>'),nl,
4361 print('PCTL State Formula: P op {Exp} [PathFormula] with op in {<,<=,>=,>,=}'),nl,
4362 print('PCTL Path Formulas: X phi, phi1 U phi2, F phi, G phi'),nl,
4363 print('PCTL Bounded Path Formulas: phi1 U<=Bound phi2, F<=Bound phi, G<=Bound phi'),nl,
4364 print('PCTL Propositions: {B-Pred}, e(Op), [Op], true, false, sink'),nl
4365 ).
4366 exec_eval_command(reset_animator(Hard),_) :- !,
4367 get_state_space_stats(TotalNodeSum,TotalTransSum,_,_),
4368 (Hard=hard ->
4369 format('Resetting statespace (~w states, ~w transitions)~n',[TotalNodeSum,TotalTransSum]),
4370 reset_animator
4371 ; format('Resetting animation history (keeping statespace: ~w states, ~w transitions)~n',[TotalNodeSum,TotalTransSum]),
4372 tcltk_reset % only resets animation history,...
4373 ).
4374 exec_eval_command(statistics,_) :- !, print_last_info.
4375 exec_eval_command(state_space_stats,_) :- !, % :states
4376 get_state_space_stats(TotalNodeSum,TotalTransSum,Processed,Ignored),
4377 (Ignored>0
4378 -> format('Statespace: ~w states (~w processed, ~w ignored) and ~w transitions.~n',
4379 [TotalNodeSum,Processed,Ignored,TotalTransSum])
4380 ; format('Statespace: ~w states (~w processed) and ~w transitions.~n',[TotalNodeSum,Processed,TotalTransSum])).
4381 exec_eval_command(state_space_display,_) :- !, % :statespace
4382 ( visited_expression(ID,State),
4383 functor(State,F,N),
4384 format('State ID ~w (~w/~w)~n',[ID,F,N]),
4385 transition(ID,OperationTerm,_OpID,ToID),
4386 get_operation_name(OperationTerm,OpName),
4387 format(' -> ~w (~w)~n',[ToID,OpName]),
4388 fail
4389 ;
4390 current_state_id(ID),
4391 format('Current State ID ~w~n',[ID])
4392 ).
4393 exec_eval_command(show_state_info(Limit),_) :- !, % :state
4394 (current_expression(ID,CurState)
4395 ->
4396 expand_const_and_vars_to_full_store(CurState,EState),
4397 format('Current state id ~w : ~n',[ID]), % MAX_DISPLAY_SET
4398 translate:print_bstate_limited(EState,Limit,-1),nl,
4399 (\+ not_all_transitions_added(ID),
4400 format('Outgoing transitions of state id ~w:~n',[ID]),
4401 transition(ID,OperationTerm,_OpID,ToID),
4402 get_operation_name(OperationTerm,OpName),
4403 format(' -> ~w (~w)~n',[ToID,OpName]),
4404 fail
4405 ; true)
4406 ; print_red('No current state available!'),nl
4407 ).
4408 exec_eval_command(unsat_core,_) :- !, % :core :u
4409 unsat_core_last_expression.
4410 exec_eval_command(trimcore,_) :- !, % :trim
4411 prob_trimcore_verbose.
4412 exec_eval_command(show_last_as_table,_) :- !, % :show
4413 show_last_expression_as_table.
4414 exec_eval_command(syntax_help,_) :- !, % :syntax
4415 syntax_help.
4416 exec_eval_command(show_last_as_dot(Show),Arg) :- !,
4417 (Arg = [] -> print('*** :dot requires an expression or predicate as argument.'),nl
4418 ; safe_absolute_file_name('~/probcli_repl.dot',AFile),
4419 set_eval_dot_file(AFile),
4420 format('Displaying evaluation result in: ~w~n',[AFile]),
4421 (eval_codes(Arg,exists,_,_,_,_) -> true ; true), unset_eval_dot_file,
4422 ( Show=no_dot_viewing -> true
4423 ; Show=dotty -> show_dot_file(AFile)
4424 ; safe_absolute_file_name('~/probcli_repl.pdf',PDFFile),
4425 gen_dot_output(AFile,Show,pdf,PDFFile),
4426 show_pdf_file(PDFFile)
4427 )).
4428 exec_eval_command(replay_repl_file,FILEC) :- !, % :replay
4429 atom_codes(File,FILEC),
4430 set_repl_input_file(not_verbose,File).
4431 exec_eval_command(show_source,IDC) :- !, % :src
4432 trim_id_back_quotes(IDC,TIDC),atom_codes(ID,TIDC),
4433 show_source(ID).
4434 exec_eval_command(show_origin,IDC) :- !, % :origin
4435 trim_id_back_quotes(IDC,TIDC),atom_codes(ID,TIDC),
4436 show_origin(ID).
4437 exec_eval_command(show_machine_info(X),_) :- !, % :machine
4438 cli_print_machine_info(X).
4439 exec_eval_command(edit_main_file,Arg) :- !, % :e
4440 (Arg=[] -> edit_main_file
4441 ; trim_quotes(Arg,FC), atom_codes(File,FC), file_exists(File) -> edit_file(File,unknown)
4442 ; exec_eval_command(show_origin,Arg)).
4443 exec_eval_command(open_file,FILEC) :- !, % :open
4444 (FILEC=[] -> open_file('.')
4445 ; atom_codes(File,FILEC),
4446 open_file(File)
4447 ).
4448 exec_eval_command(comment,_Arg) :- !. % do nothing; argument was a comment; mainly useful for :replay files
4449
4450
4451 trim_id_back_quotes([96|T],Res) :- append(Res,[96],T),!.
4452 trim_id_back_quotes(R,R).
4453
4454 trim_quotes([34|T],Res) :- append(Res,[34],T),!. % double quotes
4455 trim_quotes([39|T],Res) :- append(Res,[39],T),!. % single quotes
4456 trim_quotes(R,R).
4457
4458 :- use_module(tools_commands,[edit_file/2, open_file/1]).
4459 edit_main_file :- last_repl_error(File,Line),
4460 \+ functor(File,unknown,_), % File \= unknown(_),
4461 !,
4462 format('Showing first error from last command~n',[]),
4463 edit_file(File,Line).
4464 % Note: for the bbedit command we can also specify line numbers bbedit +LINE FILE
4465 edit_main_file :- file_loaded(_,MainFile), \+ empty_machine_loaded,
4466 !,edit_file(MainFile,unknown).
4467 edit_main_file :- format_with_colour_nl(user_error,[red],'No file loaded, cannot open EDITOR!',[]).
4468
4469
4470
4471 :- use_module(probsrc(error_manager),[extract_file_line_col/6]).
4472 open_file_at_position(OriginTerm) :-
4473 extract_file_line_col(OriginTerm,FILE,LINE,_COL,_Erow,_Ecol),
4474 edit_file(FILE,LINE).
4475
4476
4477 :- use_module(probsrc(bmachine),[source_code_for_identifier/6]).
4478 show_source(ID) :- source_code_for_identifier(ID,Kind,_Type,OriginStr,OriginTerm,Source),!,
4479 translate:translate_subst_or_bexpr(Source,PPS),
4480 %format('~w: ~w (Type: ~w)~norigin: ~w~nsource: ~w~n',[Kind,ID,_Type,Origin,PPS]).
4481 format('~w: ~w~norigin: ~w~nsource: ~w~n',[Kind,ID,OriginStr,PPS]),
4482 (OriginTerm=b(_,_,_),get_texpr_description(OriginTerm,Description)
4483 -> format('description: ~w~n',[Description]) ; true).
4484 show_source(ID) :- format_error_with_nl('! Could not find source for ~w',[ID]).
4485
4486 show_origin('') :- last_repl_error(_,_),!, % error occured: show error in editor like :e would
4487 edit_main_file.
4488 show_origin('') :- !,format_error_with_nl('! You need to provided an identifier',[]).
4489 show_origin(ID) :- source_code_for_identifier(ID,Kind,_Type,OriginStr,OriginTerm,_Source),!,
4490 format('~w: ~w~norigin: ~w~n',[Kind,ID,OriginStr]),
4491 open_file_at_position(OriginTerm).
4492 show_origin(ID) :- format_error_with_nl('! Could not find origin for ~w',[ID]).
4493
4494 profiling_on :- set_prolog_flag(profiling,on), print('% PROFILING ON'),nl.
4495 profiling_off :- set_prolog_flag(profiling,off), print('% PROFILING OFF'),nl.
4496
4497 % find a state satisfying LTL atomic property
4498 cli_find_ltl_ap(APF) :-
4499 if(ltl:find_atomic_property_formula(APF,ID),
4500 (format('Found state (id = ~w) satisfying LTL atomic property.~n',[ID]),
4501 tcltk_goto_state('LTL FIND',ID)),
4502 format('No explored state satsifies LTL atomic property.~n',[])).
4503
4504 eval_help :-
4505 print('ProB Interactive Expression and Predicate Evaluator '), nl,
4506 print('Type a valid B expressions or predicates, followed by RETURN or ENTER.'),nl,
4507 print('You can spread input over multiple lines by ending lines with "\\".'),nl,
4508 browse_machine([]),
4509 print('You can also type one of the following commands: '),nl,
4510 (option_verbose ->
4511 print(' + to save last expression to ProB unit tests.'),nl,
4512 print(' ! to go to deterministic propagation only mode.'),nl,
4513 print(' $ to print evaluation time for last expression.'),nl,
4514 print(' $$ to pretty-print last expression and its type.'),nl,
4515 print(' $$$ to pretty-print last expression in nested fashion.'),nl,
4516 print(' !p to toggle performance messages.'),nl,
4517 print(' !norm to toggle normalisation of results.'),nl,
4518 print(' :col to toggle colorizing of results.'),nl
4519 ; true),
4520 print(' :let x = E to define a new local variable x'),nl, % : optional for let
4521 print(' :unlet x to un-define a local variable'),nl,
4522 print(' #file=MYFILE to evaluate the formula in MYFILE'),nl,
4523 print(' @INVARIANT to evaluate or obtain invariant predicate'),nl,
4524 print(' @PROPERTIES, @GUARD-OpName ditto for properties and guards'),nl, % @FUZZ, @RANDOMISE also exist
4525 print(' :b or :b Prefix to browse the available identifiers'),nl,
4526 print(' :t E to get the type of an expression'),nl,
4527 print(' :r to reload the machine'),nl,
4528 print(' :show to display the last result as a table (if possible)'),nl,
4529 print(' :list CAT to display information with CAT : {files,variables,help,...}'),nl,
4530 print(' :* P to display constants/variables containing pattern P'),nl,
4531 print(' :core Pred to compute the unsat core for Pred'),nl,
4532 print(' :u to compute the unsat core for last evaluated result'),nl,
4533 print(' :stats to print the type and evaluation time for last query'),nl,
4534 print(' -PROBCLIARGS to pass command-line probcli arguments to the REPL'),nl,
4535 print(' (e.g., -v to switch to verbose mode or -p PREF VAL to set a preference)'),nl,
4536 print(' :ctl F or :ltl F to check a CTL or LTL formula.'),nl,
4537 print(' :f F to find a state satisfying LTL atomic property.'),nl,
4538 print(' :find-value PAT to find a value in current state matching PAT.'),nl,
4539 print(' :exec S to execute an operation or substitution S.'),nl,
4540 print(' :replay FILE to replay a file of commands.'),nl,
4541 print(' :z3 P, :cvc4 P, :kodkod P to solve predicate P using alternate solver'),nl,
4542 print(' :forall P to prove predicate P as universally quantified with default solver'),nl,
4543 print(' :prove P to prove predicate P using ProB\'s own WD prover'),nl,
4544 (option_verbose ->
4545 print(' :krt P, :pp P, :ml P to prove predicate P using Atelier-B provers if installed'),nl
4546 ; true),
4547 print(' :print P to pretty print predicate in a nested fashion'),nl,
4548 print(' :min P, :max P to find a minimal/maximal model for predicate P or %x.(P|E)'),nl,
4549 print(' :prefs to print current value of preferences'),nl,
4550 print(' :reset to reset the state space of the animator.'),nl, % :reset-history only resets history
4551 print(' :help CMD to obtain more help about a command.'),nl,
4552 print(' :state, :statespace, :states,'),nl,
4553 print(' :machine, :files, :source, :orgin, :machine-stats,'),nl,
4554 print(' :apropos, :hbrowse, :abstract_constants, :det_check_constants,'),nl,
4555 print(' :dot, :dotty, :sfdp, :trim, :comp - use :help CMD for more info'),nl,
4556 print(' :syntax to show a summary of the B syntax accepted by the REPL'),nl,
4557 print(' :q to exit.'),nl.
4558
4559 :- use_module(tools,[read_atom_from_file/3]).
4560 :- dynamic prob_summary/1.
4561
4562 :- read_atom_from_file(tclsrc('prob_summary.txt'),utf8,T), assertz(prob_summary(T)).
4563 % TODO: we could just include a shorter version with predicates and expressions
4564 % TODO: provide :syntax LTL or :syntax CTL help commands
4565 syntax_help :- prob_summary(S),
4566 format(user_output,'~w',S).
4567
4568
4569 browse :- browse_machine([]), browse_repl_lets.
4570
4571 :- use_module(bmachine,[get_machine_identifiers/2]).
4572 % the CodesToMatch parameters mimics the apropos command of the Clojure-REPL
4573 browse_machine(CodesToMatch) :-
4574 get_machine_identifiers(machines,MN), display_match('MACHINES',CodesToMatch,MN),
4575 (CodesToMatch =[] -> print_sets
4576 ; get_machine_identifiers(sets,SN), display_match('SETS',CodesToMatch,SN),
4577 get_machine_identifiers(set_constants,SCN), display_match('SETS-ELEMENTS',CodesToMatch,SCN)
4578 ),
4579 get_machine_identifiers(definition_files,DFN),
4580 (DFN=[] -> true ; display_match('DEFINITIONS FILES',CodesToMatch,DFN)),
4581 get_machine_identifiers(definitions,DN),
4582 (DN=[] -> true ; display_match('DEFINITIONS',CodesToMatch,DN)),
4583 get_machine_identifiers(constants,CN),
4584 display_match('CONSTANTS',CodesToMatch,CN),
4585 get_machine_identifiers(variables,VN),
4586 display_match('VARIABLES',CodesToMatch,VN),
4587 get_machine_identifiers(operations,Ops),
4588 display_match('OPERATIONS',CodesToMatch,Ops).
4589
4590 display_match(KIND,CodesToMatch,Ids) :- display_match(KIND,CodesToMatch,Ids,show_empty).
4591 display_match(KIND,CodesToMatch,Ids,ShowEmpty) :-
4592 include(prob_cli:atom_contains_codes(CodesToMatch),Ids,MatchingIds),
4593 length(MatchingIds,LenMIds),
4594 (LenMIds=0, ShowEmpty=show_only_if_match -> true
4595 ; sort(MatchingIds,SMatchingIds),
4596 (CodesToMatch=[]
4597 -> format(' ~w: ~w ~w~n',[KIND,LenMIds,SMatchingIds])
4598 ; length(Ids,LenIds),
4599 format('Matching ~w: ~w/~w ~w~n',[KIND,LenMIds,LenIds,SMatchingIds]))
4600 ).
4601
4602 % check if an atom contains a list of codes in its name
4603 atom_contains_codes([],_) :- !.
4604 atom_contains_codes(Codes,Name) :- atom_codes(Name,NC),
4605 append([_,Codes,_],NC).
4606
4607 :- use_module(b_global_sets,[b_global_set/1]).
4608 print_sets :- print('Available SETS: '), b_global_set(GS), print_set(GS),fail.
4609 print_sets :- nl.
4610
4611 :- use_module(probsrc(b_global_sets),[is_b_global_constant/3]).
4612 print_set(GS) :- print(GS), \+ is_b_global_constant(GS,_,_),!, print(' ').
4613 print_set(GS) :- print(' = {'), is_b_global_constant(GS,_,Cst), print(Cst), print(' '),fail.
4614 print_set(_) :- print(' } ').
4615
4616 :- use_module(b_machine_hierarchy,[get_machine_identifier_names/7]).
4617 % browse all machines, shows identifiers maybe not visible at top-level
4618 browse_all_machines(CodesToMatch) :-
4619 format('Searching machine hierarchy for identifiers matching ~s~n',[CodesToMatch]),
4620 get_machine_identifier_names(Name,Params,Sets,AVars,CVars,AConsts,CConsts),
4621 format('~nMACHINE ~w~n',[Name]),
4622 display_match('PARAMS',CodesToMatch,Params,show_only_if_match),
4623 display_match('SETS',CodesToMatch,Sets,show_only_if_match),
4624 display_match('ABSTRACT_VARIABLES',CodesToMatch,AVars,show_only_if_match),
4625 display_match('CONCRETE_VARIABLES',CodesToMatch,CVars,show_only_if_match),
4626 display_match('ABSTRACT_CONSTANTS',CodesToMatch,AConsts,show_only_if_match),
4627 display_match('CONCRETE_CONSTANTS',CodesToMatch,CConsts,show_only_if_match),
4628 fail.
4629 browse_all_machines(_).
4630
4631
4632 :- use_module(bmachine,[b_get_properties_from_machine/1]).
4633 print_property_partitions :- print('PARTITIONS OF PROPERTIES'),nl,
4634 b_get_properties_from_machine(Properties),
4635 predicate_components(Properties,Comp),
4636 length(Comp,Len), print(Len), print(' components found in PROPERTIES'),nl,
4637 nth1(Nr,Comp,component(P,Vars)),
4638 format('~n& // Component ~w/~w over identifiers ~w~n',[Nr,Len,Vars]),
4639 translate:print_bexpr(P),nl,fail.
4640 print_property_partitions :- nl, print(' ============== '),nl.
4641
4642 :- use_module(store,[lookup_value_for_existing_id/3]).
4643 :- use_module(b_machine_hierarchy,[abstract_constant/2]).
4644 check_abstract_constants :-
4645 format('Checking whether abstract constants can be expanded:~n',[]),
4646 current_expression(_ID,CurState),
4647 expand_const_and_vars_to_full_store(CurState,EState),
4648 abstract_constant(AID,_),
4649 lookup_value_for_existing_id(AID,EState,Val),
4650 get_value_type(Val,VF),
4651 format(user_output,'~n*** Evaluating ABSTRACT_CONSTANT (stored value: ~w):~n',[VF]),
4652 format_with_colour_nl(user_output,[blue],' ~w',[AID]),
4653 (debug_mode(off) -> true
4654 ; translate:translate_bvalue(Val,VS), format_with_colour_nl(user_output,[blue],' Stored value = ~w',[VS])),
4655 atom_codes(AID,C),
4656 % TO DO: provide info if value symbolic and can be expanded fully + add timing
4657 % term_size, unique in state space
4658 % this command is deprecated compared to -csv constants_analysis (i.e., tcltk_analyse_constants)
4659 eval_codes(C,exists,_,_EnumWarning,_LS,_),nl, % TO DO: call try_expand_and_convert_to_avl_with_check(Val)
4660 fail.
4661 check_abstract_constants.
4662
4663 :- use_module(probsrc(custom_explicit_sets),[is_interval_closure/3]).
4664 get_value_type(CS, Res) :- is_interval_closure(CS,_,_),!, Res = 'interval closure'.
4665 get_value_type(closure(_,_,_),Res) :- !, Res= 'symbolic closure'.
4666 get_value_type(avl_set(_), Res) :- !, Res= 'explicit AVL set'.
4667 get_value_type(Val,VF) :- functor(Val,VF,_).
4668
4669 :- use_module(b_state_model_check,[cbc_constants_det_check/1]).
4670 det_check_constants :- \+ current_state_corresponds_to_setup_constants_b_machine, !,
4671 format_with_colour_nl(user_error,[red],'This command requires to setup the constants first!',[]).
4672 det_check_constants :-
4673 current_state_id(ID),
4674 %format('Checking whether constants are forced in state ~w:~n',[ID]),
4675 cbc_constants_det_check(ID).
4676
4677 % showing relations as tables:
4678
4679 :- use_module(extrasrc(table_tools),[print_value_as_table/2]).
4680 show_last_expression_as_table :- \+ last_expression(_,_Expr),!,
4681 print_red('Please evaluate an expression or predicate first.'),nl.
4682 show_last_expression_as_table :-
4683 get_last_result_value(Expr,_,Value),
4684 print_value_as_table(Expr,Value).
4685
4686
4687 % a few definitions so that probcli commands work in REPL:
4688 :- use_module(specfile,[get_internal_representation/1]).
4689 :- use_module(tools_files,[write_to_utf8_file_or_user_output/2]).
4690 :- use_module(translate,[set_unicode_mode/0, unset_unicode_mode/0, set_atelierb_mode/1, unset_atelierb_mode/0, with_translation_mode/2]).
4691 :- public pretty_print_internal_rep/4, pretty_print_internal_rep_to_B/1.
4692 pretty_print_internal_rep(PPFILE,MachName,TYPES,TransMode) :-
4693 b_or_z_mode, !,
4694 pretty_print_internal_rep_b(PPFILE,MachName,TYPES,TransMode).
4695 pretty_print_internal_rep(PPFILE,_MachName,_TYPES,TransMode) :-
4696 with_translation_mode(TransMode,get_internal_representation(PP)),
4697 write_to_utf8_file_or_user_output(PPFILE,PP).
4698
4699 pretty_print_internal_rep_b(PPFILE,MachName,TYPES,unicode) :- !,
4700 set_unicode_mode,
4701 call_cleanup(b_write_machine_representation_to_file(MachName,TYPES,PPFILE),unset_unicode_mode).
4702 pretty_print_internal_rep_b(PPFILE,'$auto',_TYPES,atelierb) :- animation_minor_mode(eventb),!,
4703 b_write_eventb_machine_to_classicalb_to_file(PPFILE). % old -ppB option:
4704 pretty_print_internal_rep_b(PPFILE,MachName,TYPES,atelierb) :- !,
4705 set_atelierb_mode(native),
4706 call_cleanup(b_write_machine_representation_to_file(MachName,TYPES,PPFILE),unset_atelierb_mode).
4707 pretty_print_internal_rep_b(PPFILE,MachName,TYPES,_) :- b_write_machine_representation_to_file(MachName,TYPES,PPFILE).
4708
4709 % -ppB option:
4710 pretty_print_internal_rep_to_B(PPFILE) :- b_write_eventb_machine_to_classicalb_to_file(PPFILE).
4711
4712 :- use_module(tools_printing,[tcltk_nested_read_prolog_file_as_codes/2]).
4713 % -pppl option: internal developer utility to pretty-print a Prolog file in nested fashion
4714 % can be useful to inspecting .prob AST files or .P XTL files
4715 pretty_print_prolog_file(PPFILE) :-
4716 file_loaded(_,MainFile),
4717 (loaded_main_file(Ext,_), \+( (Ext='P' ; Ext='prob' ; Ext= 'pl') )
4718 -> add_warning(probcli,'The -pppl command is designed to work with Prolog files (.P, .prob or .pl), not with: ',Ext) ; true),
4719 pretty_print_prolog_file(MainFile,PPFILE).
4720
4721 pretty_print_prolog_file(File,File) :- !,
4722 add_error(probcli,'Output file must be different from input Prolog file:',File).
4723 pretty_print_prolog_file(MainFile,PPFILE) :-
4724 format('Pretty-Printing Prolog file ~w to ~w~n',[MainFile,PPFILE]),
4725 tcltk_nested_read_prolog_file_as_codes(MainFile,list(Codes)),
4726 safe_intelligent_open_file(PPFILE,write,Stream),
4727 format(Stream,'~s~n',[Codes]),
4728 close(Stream).
4729
4730 :- use_module(extrasrc(source_indenter),[indent_b_file/3]).
4731 indent_main_b_file(PPFILE) :-
4732 file_loaded(_,MainFile),
4733 indent_b_file_to_file(MainFile,PPFILE,[]).
4734
4735 indent_b_file_to_file(File,File,_) :- !,
4736 add_error(probcli,'Output file must be different from input B file:',File).
4737 indent_b_file_to_file(MainFile,PPFILE,Options) :-
4738 format('Indenting B file ~w to ~w~n',[MainFile,PPFILE]), flush_output,
4739 safe_intelligent_open_file(PPFILE,write,OutStream),
4740 call_cleanup(indent_b_file(MainFile,OutStream,Options),close(OutStream)).
4741
4742
4743 % Simple Animator
4744
4745 interactive_animate_machine :-
4746 nl,print('IMPORTANT: Do not use this mode for automatic tools.'),nl,
4747 print('The output format can change arbitrarily in future versions.'),nl,
4748 print('Please terminate your input with a dot (.) and then type return.'),nl,nl,
4749 animate_machine2.
4750 animate_machine2 :-
4751 print_current_state,
4752 cli_computeOperations(Ops),
4753 length(Ops,Max),
4754 print('Enabled Operations: '),nl,
4755 print_options(Ops,1),
4756 print(' ==> '),!,
4757 read(Nr),
4758 (number(Nr),Nr>0,Nr=<Max
4759 -> cli_animateOperationNr(Nr,Ops,0)
4760 ; fail
4761 ),!,
4762 animate_machine2.
4763 animate_machine2.
4764
4765 print_current_state :- current_state_id(CurID), print('ID ==> '), print(CurID),nl,
4766 getStateValues(CurID,State),
4767 print_bindings(State),
4768 (specfile:b_or_z_mode,\+is_initialised_state(CurID)
4769 -> print_red(' Not yet initialised.'),print_mode_info, debug_println(10,state(State)) ; nl).
4770
4771 print_mode_info :- animation_mode(M), (animation_minor_mode(MM) -> true ; MM=''),
4772 format('Animation Mode = ~w [~w]~n',[M,MM]).
4773
4774 cli_computeOperations(Ops) :- option(animate_stats),!, % provide statistics about the animation
4775 nl,
4776 start_probcli_timer(Timer),
4777 current_state_id(CurID),
4778 tcltk_get_options(list(Ops)),
4779 ajoin(['Time to compute all operations in state ',CurID,': '],Msg),
4780 stop_probcli_timer(Timer,Msg).
4781 cli_computeOperations(Ops) :- tcltk_get_options(list(Ops)).
4782
4783 cli_animateOperationNr(Nr,Options,StepNr) :-
4784 (option(animate_stats)
4785 -> nth1(Nr,Options,Action),
4786 truncate_animate_action(Action,TA),
4787 (StepNr>1 -> format('performing step ~w : ~w~n',[StepNr,TA])
4788 ; format('performing ~w~n',[TA]))
4789 ; true),
4790 tcltk_perform_nr(Nr).
4791
4792 :- use_module(tools_strings,[truncate_atom/3]).
4793 % optionally truncate animation action atom for printing:
4794 truncate_animate_action(Action,TA) :-
4795 (option_verbose -> TA = Action
4796 ; \+ atom(Action) -> TA = Action
4797 ; truncate_atom(Action,100,TA)).
4798
4799 perform_random_step(StepNr) :- perform_random_step(_Ops,_Len,_RanChoice,StepNr).
4800 perform_random_step(Ops,Len,RanChoice,StepNr) :-
4801 cli_computeOperations(Ops),
4802 current_state_id(CurID), check_for_errors(CurID,StepNr),
4803 length(Ops,Len), Len>0,
4804 debug_println(20,perform_random_step(Len,StepNr)),
4805 L1 is Len+1,
4806 (do_det_checking, Len>1
4807 -> print_error('Non-deterministic step in animate or init'),
4808 print_error('State:'),
4809 print_current_state, print_error('Enabled Operations: '), print_options(Ops,1),
4810 error_occurred(det_check)
4811 ; true),
4812 random(1,L1,RanChoice),
4813 debug_println(20,random(L1,RanChoice)),
4814 cli_animateOperationNr(RanChoice,Ops,StepNr).
4815
4816 :- use_module(state_space,[visited_expression/2]).
4817 check_for_errors(CurID,StepNr) :- invariant_violated(CurID),
4818 \+ option(no_invariant_violations),
4819 get_preference(do_invariant_checking,true),
4820 ajoin(['INVARIANT VIOLATED after ',StepNr,' steps (state id ',CurID,').'],ErrMsg),
4821 format('~w~n',[ErrMsg]),
4822 visited_expression(CurID,CurState), print_state_silent(CurState),
4823 error_occurred_with_msg(invariant_violation,ErrMsg),
4824 fail.
4825 check_for_errors(CurID,_) :- get_state_errors(CurID).
4826 % TO DO: also check for assertion errors, goal, state_errors with abort
4827
4828 :- use_module(bmachine,[b_machine_has_constants_or_properties/0]).
4829 do_det_checking :- option(det_check),!.
4830 do_det_checking :- option(det_constants_check),current_state_id(root),
4831 b_or_z_mode, b_machine_has_constants_or_properties.
4832
4833 perform_random_steps(Nr,_) :- \+ number(Nr),!,
4834 print_error('Argument to animate not a number'), print_error(Nr),error_occurred(animate).
4835 perform_random_steps(Nr,_) :- Nr<0, !,
4836 print_error('Argument to animate is a negative number'), print_error(Nr),error_occurred(animate).
4837 perform_random_steps(0,_) :- !.
4838 perform_random_steps(Nr,ErrorOnDeadlock) :-
4839 (perform_random_initialisation_if_necessary(Steps) % if Nr=1 we currently will also execute the INITIALISATION ! TO DO: fix
4840 -> perform_random_steps_aux(Steps,Nr,ErrorOnDeadlock)
4841 ; % we have setup_constants_fails or initialisation_fails
4842 print_error('Could not initialise model for animation')
4843 ).
4844
4845 perform_random_steps_aux(Nr,Max,_) :- Nr >= Max,!, debug_println(9,performed_random_steps(Nr)).
4846 perform_random_steps_aux(Nr,Max,ErrorOnDeadlock) :-
4847 N1 is Nr+1,
4848 (perform_random_step(N1)
4849 -> perform_random_steps_aux(N1,Max,ErrorOnDeadlock)
4850 ; /* deadlock */
4851 write_xml_element_to_log(deadlock_found,[step/Nr]),
4852 (ErrorOnDeadlock=true, \+ option(no_deadlocks)) ->
4853 print_error('Deadlock occurred during -animate, at step number:'), print_error(Nr),
4854 error_occurred(animate)
4855 ; print('% Deadlock occurred during -animate, at step number:'), print(Nr),nl
4856 ).
4857
4858 perform_random_initialisation_if_necessary(Steps) :-
4859 b_or_z_mode, current_state_id(State), State=root,!, perform_random_initialisation(Steps).
4860 perform_random_initialisation_if_necessary(0).
4861
4862 perform_random_initialisation :- perform_random_initialisation(_).
4863 perform_random_initialisation(Steps) :- current_state_id(State), State \= root, !,
4864 print_error('init can only be used in initial state'), print_error(State),error_occurred(initialisation),
4865 Steps=0.
4866 perform_random_initialisation(Steps) :- b_mode, b_machine_has_constants_or_properties,!,
4867 (perform_random_step(Ops,_Len,RanChoice,1)
4868 -> nth1(RanChoice,Ops,Choice), %print(Choice),nl,
4869 (Choice = 'PARTIAL_SETUP_CONSTANTS'
4870 -> error_occurred(setup_constants_inconsistent)
4871 ; true)
4872 ; error_occurred(setup_constants_fails),fail), % $setup_constants TODO: properties unknown or unsat
4873 perform_random_init_after_setup_constants, Steps=2. % $initialise_machine
4874 perform_random_initialisation(Steps) :- (perform_random_step(1) -> Steps=1 ; error_occurred(initialisation_fails),fail).
4875
4876
4877 perform_random_init_after_setup_constants :- \+ option(initialise), we_need_only_static_assertions(_),!,
4878 printsilent('% NOT INITIALISING MACHINE (not required)'),nls.
4879 % debug_println(20,'% NOT INITIALISING MACHINE (not required)').
4880 perform_random_init_after_setup_constants :-
4881 (perform_random_step(2) % 2 is the step nr not the number of steps
4882 -> true
4883 ; error_occurred(initialisation_fails),
4884 fail).
4885
4886 :- use_module(cbcsrc(enabling_analysis),[tcltk_cbc_enabling_analysis/1, print_enable_table/1, is_timeout_enabling_result/1]).
4887 do_enabling_analysis_csv(EnablingCsvFile,NOW) :-
4888 start_probcli_timer(Timer1),
4889 start_xml_feature(enabling_analysis,file,EnablingCsvFile,FINFO),
4890 tcltk_cbc_enabling_analysis(list(R)),
4891 stop_probcli_timer(Timer1,'% Finished CBC Enabling Analysis',_TotWallTime),
4892 print_cbc_stats(R,NOW),
4893 debug_println(9,writing_to_file(EnablingCsvFile)),
4894 my_tell(EnablingCsvFile),
4895 print_enable_table(R),
4896 told,!,
4897 stop_xml_feature(enabling_analysis,FINFO).
4898 do_enabling_analysis_csv(EnablingCsvFile,_) :-
4899 add_error(enabling_analysis,'Enabling analysis failed',EnablingCsvFile),
4900 stop_xml_group_in_log(enabling_analysis).
4901
4902 print_cbc_stats(Res,_NOW) :- length(Res,Len), Ops is Len-2, % Header + Init
4903 CBC_Calls is Ops*(Ops+1), % +1 for INITIALISATION
4904 findall(TO,(member(list([_|T]),Res), member(TO,T),is_timeout_enabling_result(TO)),TOS),
4905 length(TOS,NrTOS),
4906 format('% CBC Enabling Stats:~n% Nr of events: ~w~n% Nr of cbc calls: ~w, Timeout results: ~w~n',[Ops,CBC_Calls,NrTOS]),
4907 write_xml_element_to_log(cbc_enabling_stats,[nr_events/Ops,cbc_calls/CBC_Calls,nr_timeouts/NrTOS]).
4908
4909
4910 :- use_module(cbcsrc(enabling_analysis),[feasible_operation_with_timeout/3]).
4911 do_feasibility_analysis(ATimeOut,EnablingCsvFile) :-
4912 arg_is_number(ATimeOut,TimeOut),
4913 start_xml_feature(feasibility_analysis,file,EnablingCsvFile,FINFO),
4914 findall(list([Op,Res]),feasible_operation_with_timeout(Op,TimeOut,Res),R),
4915 debug_println(9,writing_to_file(EnablingCsvFile)),
4916 my_tell(EnablingCsvFile),
4917 print_enable_table([list(['Event','Feasibility'])|R]),
4918 told,!,
4919 stop_xml_feature(feasibility_analysis,FINFO).
4920 do_feasibility_analysis(_,EnablingCsvFile) :-
4921 add_error(feasibility_analysis,'Feasibility analysis failed',EnablingCsvFile),
4922 stop_xml_group_in_log(feasibility_analysis).
4923
4924 :- use_module(b_read_write_info,[tcltk_read_write_matrix/1]).
4925 generate_read_write_matrix(CsvFile) :-
4926 tcltk_read_write_matrix(list(Matrix)),
4927 my_tell(CsvFile),
4928 print_enable_table(Matrix),
4929 told,!.
4930 generate_read_write_matrix(CsvFile) :-
4931 add_error(read_write_matrix,'Generating Read-Write-Matrix failed',CsvFile).
4932
4933
4934 my_tell(File) :-
4935 catch(
4936 tell(File),
4937 error(_E,_), % existence_error(_,_)
4938 add_error_fail(tell,'File cannot be written to: ',File)).
4939
4940 print_options([],_).
4941 print_options([H|T],N) :-
4942 print(' '), print(N), print(':'), print(H),nl,
4943 N1 is N+1,
4944 print_options(T,N1).
4945
4946 print_nr_list(List) :- print_nr_list(List,0,1,no_repeats).
4947
4948 print_nr_list([],NM1,_,Repeats) :- !, print_repeats(NM1,Repeats).
4949 print_nr_list([H|T],_,N,repeated(H,SinceN)) :- !, N1 is N+1,
4950 print_nr_list(T,N,N1,repeated(H,SinceN)).
4951 print_nr_list([H|T],NM1,N,Repeats) :- !,
4952 print_repeats(NM1,Repeats),
4953 N1 is N+1,
4954 print_nr_list(T,N,N1,repeated(H,N)).
4955 print_nr_list(X,_,_,_) :- print('### not a list: '), print(X),nl.
4956
4957 print_repeats(N,repeated(H,N)) :- !,
4958 format(' ~w: ~w~n',[N,H]).
4959 print_repeats(N,repeated(H,Since)) :- !, Repeats is 1+N-Since,
4960 format(' ~w - ~w: ~w (~w repetitions)~n',[Since,N,H,Repeats]).
4961 print_repeats(_,_).
4962
4963 print_bindings([]) :- !.
4964 print_bindings([binding(Var,_,PPV)|T]) :- !, print(Var),print('='),print(PPV),
4965 (T=[] -> true ; print(', '), print_bindings(T)).
4966 print_bindings([binding(Var,_,PPV,_Tag)|T]) :- !, print(Var),print('='),print(PPV),
4967 (T=[] -> true ; print(', '), print_bindings(T)).
4968 print_bindings(X) :- print('### Internal Error: illegal binding list: '), print(X),nl.
4969
4970 :- dynamic expected_error_occurred/1.
4971 :- dynamic error_did_not_occur/1.
4972 reset_expected_error_occurred :- retractall(expected_error_occurred(_)).
4973 check_all_expected_errors_occurred(NOW) :-
4974 %error_manager:display_error_statistics,
4975 get_errors, get_state_space_errors,
4976 retractall(error_did_not_occur(_)),
4977 expected_error(Type),
4978 \+ expected_error_occurred(Type),
4979 format_with_colour_nl(user_error,[red],'*** Expected Error of following type to occur: ~w',[Type]),
4980 writeln_log_time(expected_error_did_not_occur(NOW,Type)),
4981 assertz(error_did_not_occur(Type)),
4982 (option(strict_raise_error) -> definite_error_occurred ; fail).
4983 check_all_expected_errors_occurred(_NOW) :-
4984 findall(1,expected_error(_),EE), length(EE,NrExpected),
4985 (NrExpected>0
4986 -> findall(1,error_did_not_occur(_),EDNO), length(EDNO,NrNotOcc),
4987 (NrNotOcc>0
4988 -> format_with_colour_nl(user_error,[red],'*** Some expected errors (~w/~w) did NOT occur!',[NrNotOcc,NrExpected])
4989 ; format_with_colour_nl(user_output,[green],'All expected errors (~w) occurred.',[NrExpected])
4990 )
4991 ; true).
4992
4993 expected_error(Type) :- option(expect_error(Type)).
4994 expected_error(Type) :- option(expect_error_pos(Type,_Line,_Col)).
4995
4996 error_occurred(warning(Type)) :- !, error_occurred(Type,warning).
4997 error_occurred(Type) :- error_occurred(Type,error).
4998
4999 get_error_category_and_type(warning(Cat),Category,Type) :- !, Category=Cat,Type=warning.
5000 get_error_category_and_type(C,C,error).
5001
5002 error_occurred_with_msg(Type,Msg) :- error_occurred_with_msg(Type,Msg,not_yet_extracted).
5003 error_occurred_with_msg(warning(Type),Msg,Span) :- !, error_occurred(Type,warning,Span,Msg).
5004 error_occurred_with_msg(Type,Msg,Span) :- error_occurred(Type,error,Span,Msg).
5005
5006 error_occurred(Type,ErrOrWarn) :- error_occurred(Type,ErrOrWarn,not_yet_extracted,'').
5007
5008 error_occurred(Type,ErrOrWarning,ExtractedSpan,Msg) :-
5009 option(expect_error_pos(Type,Line,Col)),!,
5010 write_xml_element_to_log(expected_error_occurred,[category/Type, (type)/ErrOrWarning, message/Msg]),
5011 assertz(expected_error_occurred(Type)),
5012 (get_error_or_warning_span(ExtractedSpan,Type,EL,EC)
5013 -> (option(expect_error_pos(Type,EL,EC))
5014 -> debug_println(9,expect_error_pos_ok(Type,EL,EC))
5015 ; format('*** Unexpected line ~w and column ~w for error ~w!~n*** Expected line ~w and column ~w.~n',[EL,EC,Type,Line,Col]),
5016 definite_error_occurred
5017 )
5018 ; format('*** Could not obtain position information for error ~w! Expected line ~w and column ~w.~n',[Type,Line,Col]),
5019 %display_error_statistics,
5020 definite_error_occurred).
5021 error_occurred(Type,ErrOrWarning,ExtractedSpan,Msg) :-
5022 functor(Type,FType,_),
5023 option(expect_error(FType)),!,
5024 inc_counter(cli_expected_errors),
5025 get_xml_span(ExtractedSpan,XML),
5026 write_xml_element_to_log(expected_error_occurred,[category/Type, (type)/ErrOrWarning, message/Msg|XML]),
5027 assertz(expected_error_occurred(FType)).
5028 error_occurred(Type,ErrOrWarning,ExtractedSpan,Msg) :-
5029 (probcli_time_stamp(NOW) -> true ; NOW=unknown),
5030 writeln_log(error_occurred(NOW,Type)),
5031 get_xml_span(ExtractedSpan,XML),
5032 (functor(Type,FType,_),option(optional_error(FType)) ->
5033 write_xml_element_to_log(optional_error_occurred,[category/FType, (type)/ErrOrWarning, message/Msg|XML]),
5034 formatsilent('% Optional error occured: ~w~n',[Type])
5035 ;
5036 write_xml_element_to_log(error_occurred,[category/Type, (type)/ErrOrWarning, message/Msg|XML]),
5037 (ErrOrWarning = warning -> safe_inc_counter(cli_warnings) ; safe_inc_counter(cli_errors)),
5038 flush_output, % ensure we can later associate position of error message
5039 (option(strict_raise_error) ->
5040 print_error('*** Unexpected error occurred ***'),
5041 print_error(Type),
5042 findall(Err,option(expect_error(Err)),Ls), (Ls=[] -> true ; print_error(expected(Ls))),
5043 definite_error_occurred
5044 ; ErrOrWarning=error,serious_error(Type)
5045 -> print_error('*** Serious error occurred ***'),
5046 print_error(Type),
5047 definite_error_occurred
5048 ; print_probcli_error_non_strict(Type,ErrOrWarning)
5049 )
5050 ).
5051
5052 safe_inc_counter(Counter) :-
5053 catch(inc_counter(Counter), E,
5054 format(user_error,'~n*** Exception in counter library, probably not yet initialized: ~w.~n~n',[E])).
5055
5056
5057 get_xml_span(Span,XML) :- extract_file_line_col(Span,FullFilename,Line,Col,EndLine,EndCol),!,
5058 XML = [file/FullFilename,start_line/Line,end_line/EndLine,start_col/Col,end_col/EndCol|XT],
5059 get_xml_add_description(Span,XT).
5060 get_xml_span(Span,XML) :- get_xml_add_description(Span,XML).
5061
5062 get_xml_add_description(Span,XML) :-
5063 extract_additional_description(Span,Msg),!,
5064 XML = [additional_description/Msg].
5065 get_xml_add_description(_,[]).
5066
5067 get_error_or_warning_span(not_yet_extracted,Type,EL,EC) :- check_error_span_file_linecol(Type,_File,EL,EC,_,_).
5068 get_error_or_warning_span(not_yet_extracted,Type,EL,EC) :- check_error_span_file_linecol(warning(Type),_File,EL,EC,_,_).
5069 get_error_or_warning_span(Span,_,EL,EC) :- Span \= not_yet_extracted, extract_line_col(Span,EL,EC,_,_).
5070
5071
5072 % a list of serious errors: if these occur; then return code different from 0 even in non-strict mode
5073 serious_error(get_java_command_path).
5074 serious_error(internal_error(_)).
5075
5076 print_probcli_error_non_strict(parse_machine_predicate_error,_) :-
5077 !. % have already been reported
5078 print_probcli_error_non_strict(Type,ErrOrWarning) :-
5079 (ErrOrWarning=warning -> print_error('*** warning occurred ***')
5080 ; print_error('*** error occurred ***')),
5081 print_error(Type).
5082
5083 definite_error_occurred :- print_error('*** Abnormal termination of probcli !'),
5084 (file_loaded(_,File) -> print_error('*** for_file'(File)) ; true),
5085 (current_probcli_command(Cmd) -> print_error('*** for_command'(Cmd)) ; true),
5086 (probcli_time_stamp(NOW) -> halt_prob(NOW,1)
5087 ; writeln_log(halt(1)),
5088 halt_exception(1)
5089 ).
5090
5091 :- dynamic current_probcli_command/1.
5092 set_current_probcli_command(X) :- retractall(current_probcli_command(_)),
5093 assertz(current_probcli_command(X)).
5094 unset_current_probcli_command :- retractall(current_probcli_command(_)).
5095
5096 halt_prob(ExitCode) :-
5097 (probcli_time_stamp(NOW) -> halt_prob(NOW,ExitCode) ; halt_prob(0,ExitCode)).
5098 halt_prob(NOW,ExitCode) :-
5099 write_xml_element_to_log(probcli_halted_prematurely,[now/NOW]),
5100 close_all_xml_groups_in_log_until('probcli-run'),
5101 stop_xml_probcli_run(NOW),
5102 halt_exception(ExitCode).
5103
5104
5105 :- dynamic accumulated_infos/3, individual_file_infos/3, merged_individual_file_infos/3.
5106 accumulate_infos(Context,Infos) :- option(benchmark_info_csv_output(_,_,_)), % -bench_csv
5107 file_loaded(_,File),
5108 get_additional_infos(Infos,Infos2), % additional infos if -machine_stats provided
5109 sort(Infos2,SInfos), % infos is a list of the form Info-Value
5110 debug_println(19,assert_file_infos(File,Context,SInfos)),
5111 assertz(individual_file_infos(File,Context,SInfos)), % store for later csv summary printing
5112 fail.
5113 accumulate_infos(Context,Infos) :- accumulate_infos_2(Context,Infos).
5114
5115 % useful if this is not related to a loaded file, like -eval_file:
5116 accumulate_file_infos(File,Context,Infos) :-
5117 get_additional_stats(Infos,Infos2),
5118 sort(Infos2,SInfos), % infos is a list of the form Info-Value
5119 assertz(individual_file_infos(File,Context,SInfos)).
5120
5121 % join/merge accumulated infos for multiple runs (benchmarking) for a particular context/category
5122 % currently we support this for model-checking
5123 merge_accumulated_infos(Context) :- individual_file_infos(File,Context,_),!,
5124 findall(Infos,individual_file_infos(File,Context,Infos),[Infos1|RestInfos]),
5125 merge_acc(Infos1,RestInfos,1,Result),
5126 assertz(merged_individual_file_infos(File,Context,Result)).
5127
5128 merge_acc(Cur,[],_,Cur).
5129 merge_acc(Cur,[Next|T],Nr,Res) :-
5130 N1 is Nr+1,
5131 merge_acc_infos(Cur,Next,N1,NextCur),
5132 merge_acc(NextCur,T,N1,Res).
5133
5134 % merge two accumulated infos lists
5135 merge_acc_infos([],S,_,Res) :- !, Res=S.
5136 merge_acc_infos(S,[],_,Res) :- !, Res=S.
5137 merge_acc_infos([C1|T1],[C2|T2],Nr,[Cat-ResVal|MT]) :-
5138 get_info(C1,Cat,Val1), get_info(C2,Cat,Val2),
5139 merge_value(Cat,Val1,Val2,Nr,ResVal),!,
5140 merge_acc_infos(T1,T2,Nr,MT).
5141 merge_acc_infos([C1|T1],T2,Nr,[C1|MT]) :-
5142 add_warning(merge_acc_infos,'Missing value: ',C1),
5143 merge_acc_infos(T1,T2,Nr,MT).
5144
5145 % merge individual values
5146 merge_value(Cat,Val1,_Val2,_,ResVal) :- keep_first_value(Cat),!, ResVal=Val1.
5147 merge_value(_,Val,Val,_,ResVal) :- !, ResVal=Val.
5148 merge_value(Cat,Val1,Val2,Nr,ResVal) :- compute_average(Cat),!, ResVal is (Val1*(Nr-1)/Nr) + (Val2 / Nr).
5149 merge_value(Cat,Val1,Val2,Nr,ResVal) :-
5150 add_warning(merge_value,'Differing values: ',val(Cat,Val1,Val2)),
5151 ResVal is (Val1*(Nr-1)/Nr) + (Val2 / Nr).
5152
5153 compute_average(runtime).
5154 compute_average(total_runtime).
5155 compute_average(walltime).
5156
5157 keep_first_value(memory_used). % memory consumption of the first run is relevant
5158
5159
5160 % also store additional infos if -machine_stats provided; useful for benchmarking/articles
5161 :- use_module(covsrc(hit_profiler),[retract_profile_stats/2]).
5162 get_additional_infos(I,Res) :- option(cli_print_machine_info(statistics)),!,
5163 findall(Key-Nr,b_machine_statistics(Key,Nr),I2,I),
5164 get_additional_stats(I2,Res).
5165 get_additional_infos(I,Res) :- get_additional_stats(I,Res).
5166 get_additional_stats(I,Res) :-
5167 findall(Key-Nr,retract_profile_stats(Key,Nr),Res,I). % include additional profiling stats and retract/reset them
5168
5169 accumulate_infos_2(_,[]).
5170 accumulate_infos_2(Context,[Info|T]) :- get_info(Info,FF,Nr),
5171 (number(Nr) -> Nr>0 ; add_internal_error('Can only accumulate numbers:',FF-Nr),fail), !,
5172 (retract(accumulated_infos(Context,FF,OldNr)) ->true ; OldNr=0),
5173 N1 is OldNr+Nr,
5174 assertz(accumulated_infos(Context,FF,N1)),
5175 accumulate_infos_2(Context,T).
5176 accumulate_infos_2(Context,[_|T]) :- accumulate_infos_2(Context,T).
5177 get_info(FF-Nr,FF,Nr).
5178 get_info(FF/Nr,FF,Nr).
5179
5180 :- use_module(tools_io,[safe_intelligent_open_file/3]).
5181 print_accumulated_infos(NrFilesProcessed) :-
5182 (option(benchmark_info_csv_output(File,FileMode,CSVMode)) % TODO: allow multiple entries
5183 -> safe_intelligent_open_file(File,FileMode,Stream) % FileMode is write or append
5184 ; Stream=user_output, CSVMode=csv
5185 ),
5186 call_cleanup(pr_acc_infos_aux(Stream,NrFilesProcessed,FileMode,CSVMode),
5187 close(Stream)), !.
5188 print_accumulated_infos(NrFilesProcessed) :-
5189 add_internal_error('Call failed:',print_accumulated_infos(NrFilesProcessed)).
5190
5191 get_csv_mode(csv,csv).
5192 get_csv_mode(tex,latex).
5193 get_csv_mode(latex,latex).
5194
5195 %:- use_module(library(system),[ datime/1]).
5196 pr_acc_infos_aux(Stream,NrFilesProcessed,FileMode,CSVMode) :-
5197 (NrFilesProcessed>1,accumulated_infos(_,_,_) -> true ; option(benchmark_info_csv_output(_,_,_))),!,
5198 print_individual_file_infos_csv(Stream,FileMode,CSVMode),
5199 start_xml_group_in_log(summary,files_processed,NrFilesProcessed),
5200 ((FileMode = append ; NrFilesProcessed = 1)
5201 -> true % do not print accumulated info line
5202 ; format(Stream,'Analysis summary (~w files processed): ',[NrFilesProcessed]),
5203 findall(Context-F-Nr,accumulated_infos(Context,F,Nr),L), sort(L,SL),
5204 maplist(prob_cli:pracc(Stream),SL),nl(Stream)
5205 ),
5206 % TO DO: write infos to XML log
5207 (option(print_version(VERSIONKIND)) ->
5208 datime(datime(Year,Month,Day,Hour,Min,_Sec)),
5209 format(Stream,'CSV file generated at ~w:~w on the date ~w/~w/~w using probcli:~n',[Hour,Min,Year,Month,Day]),
5210 print_version(VERSIONKIND,Stream),
5211 print_csv_prefs(Stream)
5212 ; true),
5213 (option(cli_print_statistics(memory)) -> print_memory_statistics(Stream) ; true),
5214 stop_xml_group_in_log_no_statistics(summary).
5215 pr_acc_infos_aux(_,_NrFilesProcessed,_Mode,_).
5216
5217 print_csv_prefs(Stream) :- \+ \+ option(set_preference_group(_,_)),
5218 format(Stream,'PREFERENCE GROUP,Setting~n',[]),
5219 option(set_preference_group(P,V)),
5220 format(Stream,'~w,~w~n',[P,V]),
5221 fail.
5222 print_csv_prefs(Stream) :- \+ \+ option(set_pref(_,_)),
5223 format(Stream,'PREFERENCE,Value~n',[]),
5224 option(set_pref(P,V)),
5225 format(Stream,'~w,~w~n',[P,V]),
5226 fail.
5227 print_csv_prefs(_).
5228
5229 pracc(Stream,Context-F-Nr) :- format(Stream,'~w:~w:~w ',[Context,F,Nr]).
5230 :- use_module(probsrc(tools),[gen_relative_path_to_cur_dir/2]).
5231 % print CSV summary of run
5232 print_individual_file_infos_csv(Stream,FileMode,CSVMode) :-
5233 findall(C,individual_file_infos(_,C,_),All), sort(All,AllContexts),
5234 member(Context,AllContexts), % iterate over all Contexts
5235 (individual_file_infos(_,Context,HInfos) -> true), % pick one as header
5236 (FileMode=append
5237 -> true % do not print header line, we append to an existing table
5238 ; format(Stream,'~nFILE,ANALYSIS,',[]),
5239 print_titles(HInfos,CSVMode,Stream),nl(Stream)
5240 ),
5241 % TO DO: ensure Infos and SHInfos identical, else add 0 for missing categories
5242 (merged_individual_file_infos(File,Context,Infos)
5243 -> true % just print averages
5244 ; individual_file_infos(File,Context,Infos)
5245 ),
5246 gen_relative_path_to_cur_dir(File,RelFile),
5247 format(Stream,'~w,~w,',[RelFile,Context]),
5248 print_vals(Infos,HInfos,CSVMode,Stream),nl(Stream),
5249 fail.
5250 print_individual_file_infos_csv(_,_,_).
5251
5252
5253
5254 print_vals(_,[],_,_) :- !.
5255 print_vals([H|T],[Header|HT],Mode,Stream) :- get_info(Header,Title,_),
5256 get_info(H,Title,Nr), !,
5257 write_atom(Mode,Stream,Nr),
5258 (T=[] -> write_csv_terminator(Mode,Stream) ; write_csv_sep(Mode,Stream), print_vals(T,HT,Mode,Stream)).
5259 print_vals(Vals,[_|HT],Mode,Stream) :- % a value is missing for this file
5260 write(Stream,'-'),
5261 (HT=[] -> write_csv_terminator(Mode,Stream) ; write_csv_sep(Mode,Stream), print_vals(Vals,HT,Mode,Stream)).
5262 print_titles([],_,_).
5263 print_titles([H|T],Mode,Stream) :- get_info(H,FF,_),
5264 write_atom(Mode,Stream,FF),
5265 (T=[] -> write_csv_terminator(Mode,Stream) ; write_csv_sep(Mode,Stream), print_titles(T,Mode,Stream)).
5266
5267 :- use_module(probsrc(tools),[latex_escape_atom/2]).
5268 write_atom(latex,Stream,Atom) :- atom(Atom), latex_escape_atom(Atom,EAtom),!,
5269 write(Stream,EAtom).
5270 write_atom(_,Stream,Term) :- write(Stream,Term).
5271
5272 write_csv_sep(latex,Stream) :- !,write(Stream,' & ').
5273 write_csv_sep(_,Stream) :- write(Stream,',').
5274 write_csv_terminator(latex,Stream) :- !,write(Stream,' \\\\').
5275 write_csv_terminator(_,_).
5276
5277 write_important_xml_element_to_log(Category,Infos) :-
5278 include(prob_cli:important_info,Infos,II),
5279 write_xml_element_to_log(Category,II).
5280 important_info(FF/Nr) :-
5281 \+ irrelevant_xml_info(FF),
5282 (Nr=0 -> \+ irrelevant_xml_if_zero(FF) ; true).
5283 irrelevant_xml_info(true_after_expansion).
5284 irrelevant_xml_info(false_after_expansion).
5285 irrelevant_xml_info(unknown_after_expansion).
5286 irrelevant_xml_info(total_after_expansion).
5287 irrelevant_xml_if_zero(timeout).
5288 irrelevant_xml_if_zero(enum_warning).
5289
5290
5291 % check_required_infos(ExpectedInfos,ActualInfos,ErrType)
5292 check_required_infos([],_,_).
5293 check_required_infos([H|T],Infos,ErrType) :-
5294 (check_single_info(H,Infos)
5295 -> check_required_infos(T,Infos,ErrType)
5296 ; translate_err_type(ErrType,ES),
5297 format_with_colour_nl(user_error,[red],
5298 '*** Unexpected result while checking: ~w~n*** expected : ~w~n*** in : ~w',
5299 [ES,H,Infos]),
5300 error_occurred(ErrType)).
5301 translate_err_type(check_assertions,'ASSERTIONS') :- !.
5302 translate_err_type(cli_check_assertions,'ASSERTIONS') :- !.
5303 translate_err_type(check_goal,'GOAL') :- !.
5304 translate_err_type(load_po_file,'PROOF OBLIGATIONS') :- !.
5305 translate_err_type(cli_wd_check,'WD PROOF OBLIGATIONS') :- !.
5306 translate_err_type(check_cache_stats,'CACHE STATISTICS') :- !.
5307 translate_err_type(X,X).
5308
5309 check_single_info(Label-Nr,Infos) :- !, member(Label-ActualNr,Infos),
5310 match_info(Nr,ActualNr).
5311 check_single_info(H,List) :- member(H,List).
5312 match_info(X,X).
5313 match_info(comparison_operator(Comp,Nr),ActualNr) :-
5314 number(Nr), number(ActualNr),call(Comp,ActualNr,Nr).
5315
5316 :- use_module(tools_platform, [max_tagged_integer/1]).
5317 :- public mc_ok_arg/2.
5318 mc_ok_arg(Arg,X) :- Arg==all,!,max_tagged_integer(X).
5319 mc_ok_arg(Arg,N) :- arg_is_number(Arg,N).
5320
5321
5322 :- dynamic option/1.
5323 assert_all_options([]).
5324 assert_all_options([Opt|T]) :- assert_option(Opt),
5325 assert_all_options(T).
5326
5327 :- use_module(pathes_extensions_db,[probcli_command_requires_extension/2]).
5328 cli_option_not_available(Opt,ProBExtension,Reason) :-
5329 probcli_command_requires_extension(Opt,ProBExtension),
5330 unavailable_extension(ProBExtension,Reason).
5331
5332 check_unavailable_options :-
5333 ? option(Opt),
5334 cli_option_not_available(Opt,ProBExtension,Reason),
5335 (recognised_option(Name,Opt,_,_) -> true ; Name=Opt),
5336 ajoin(['probcli command ', Name,' cannot be performed because extension not available (',Reason,'):'],Msg),
5337 add_error(probcli,Msg,ProBExtension),
5338 fail.
5339 check_unavailable_options.
5340
5341 assert_option(silent) :- option(force_no_silent),!. % ignoring silent flag
5342 assert_option(Opt) :- assertz(option(Opt)), treat_option(Opt).
5343
5344 :- use_module(tools_printing,[set_no_color/1, reset_no_color_to_default/0]).
5345 treat_option(silent) :- !, set_silent_mode(on),set_error_manager_silent_mode(on).
5346 treat_option(force_no_silent) :- !, set_silent_mode(off),set_error_manager_silent_mode(off).
5347 treat_option(no_color) :- !, set_no_color(true).
5348 treat_option(_).
5349
5350 reset_options :- retractall(option(_)),
5351 set_silent_mode(off), set_error_manager_silent_mode(off),
5352 reset_no_color_to_default.
5353
5354 % replace a leading double-dash -- by a single dash and replace inner dashes by underscores
5355 normalise_option_atom(X,RX) :- atom(X),!,
5356 atom_codes(X,CodesX),
5357 % remove leading dash
5358 (CodesX=[45,45,H|T], H\=45 % Double dash --Option
5359 -> maplist(prob_cli:convert_dash_to_underscore,[H|T],HT2),
5360 RXCodes=[45|HT2]
5361 ; CodesX = [Dash|T], is_dash(Dash) % single dash
5362 -> maplist(prob_cli:convert_dash_to_underscore,T,T2),
5363 RXCodes=[45|T2]
5364 ; maplist(prob_cli:convert_dash_to_underscore,CodesX,RXCodes)
5365 ),
5366 atom_codes(RX,RXCodes).
5367 normalise_option_atom(T,T).
5368
5369 is_dash(45). % regular dash
5370 is_dash(8212). % Unicode double dash; sometimes automatically generated from -- by e.g., macOS Mail program
5371
5372 :- public normalise_pref_name/2. % called via recognised_option
5373 % replace dashes by underscores
5374 normalise_pref_name(X,RX) :- atom(X),!,
5375 atom_codes(X,CodesX),
5376 maplist(prob_cli:convert_dash_to_underscore,CodesX,C2),
5377 atom_codes(RX,C2).
5378 normalise_pref_name(T,T).
5379
5380 convert_dash_to_underscore(45,R) :- !, R=95.
5381 convert_dash_to_underscore(X,X).
5382
5383 recognised_cli_option(X,Opt,Args,Condition) :- normalise_option_atom(X,RX),
5384 ? recognised_option(RX,Opt,Args,Condition).
5385
5386 % get a list of all options
5387 get_all_options(SOpts) :-
5388 findall(O, recognised_option(O,_,_,_), Opts),
5389 sort(Opts,SOpts).
5390
5391 :- use_module(tools_matching,[fuzzy_match_codes_lower_case/2]).
5392 % compute a set of possible fuzzy matches
5393 get_possible_fuzzy_match_options(Option,FuzzyMatches) :-
5394 normalise_option_atom(Option,RX),
5395 atom_codes(RX,OCodes),
5396 get_all_options(SOpts),
5397 findall(Target,(member(Target,SOpts),atom_codes(Target,TargetCodes),
5398 fuzzy_match_codes_lower_case(OCodes,TargetCodes)),FuzzyMatches).
5399
5400 :- use_module(tools_matching,[get_possible_completions_msg/3]).
5401 get_possible_options_completion_msg(Option,Msg) :-
5402 normalise_option_atom(Option,RX),
5403 get_all_options(SOpts),
5404 get_possible_completions_msg(RX,SOpts,Msg).
5405
5406 recognised_option(X,Opt,[],true) :- recognised_option(X,Opt). % options without arguments
5407 recognised_option(X,Opt,Args,true) :- recognised_option(X,Opt,Args). % options with arguments but no code needed to check arguments
5408
5409 recognised_option('-mc',cli_mc(N,[]),[Arg],prob_cli:mc_ok_arg(Arg,N)).
5410 recognised_option('-bench_model_check',cli_mc(LimitNr,[reset_state_space,repeat(Rep)]),[Arg],tools:arg_is_number(Arg,Rep)) :- max_tagged_integer(LimitNr).
5411 recognised_option('-model_check',cli_mc(LimitNr,[]),[],true) :- max_tagged_integer(LimitNr).
5412 recognised_option('-timeout',timeout(N),[Arg],tools:arg_is_number(Arg,N)). % for model checking, refinement checking and for disprover per PO
5413 recognised_option('-time_out',timeout(N),[Arg],tools:arg_is_number(Arg,N)).
5414 recognised_option('-global_time_out',timeout(N),[Arg],tools:arg_is_number(Arg,N)). % better name, to avoid conflict with -p timeout N which also works
5415 recognised_option('-s',socket(S,true),[Arg],tools:arg_is_number(Arg,S)).
5416 recognised_option('-cc',coverage(N,N2,just_check_stats),[Arg,Arg2],
5417 (arg_is_number_or_wildcard(Arg,N),arg_is_number_or_wildcard(Arg2,N2))).
5418 recognised_option('-csp_guide',add_csp_guide(File),[File],
5419 prob_cli:check_file_arg(File,'csp_guide')).
5420 recognised_option('-prologOut',csp_translate_to_file(PlFile),[PlFile],
5421 prob_cli:check_file_arg(PlFile,'prologOut')).
5422 recognised_option('-load_state',load_state(Filename),[Filename],
5423 prob_cli:check_file_arg(Filename,'load_state')).
5424 recognised_option('-refchk',refinement_check(Filename,trace,100000),[Filename],
5425 prob_cli:check_file_arg(Filename,'refchk')).
5426 recognised_option('-ref_check',refinement_check(Filename,FailuresModel,100000),[Shortcut,Filename],
5427 (prob_cli:check_file_arg(Filename,'ref_check'),
5428 prob_cli:check_failures_mode(Shortcut,FailuresModel))).
5429 recognised_option('-refinement_check',Option,Args,Code) :- recognised_option('-refchk',Option,Args,Code).
5430 recognised_option('-hash',check_statespace_hash(H,_),[Arg],tools:arg_is_number(Arg,H)).
5431 recognised_option('-hash64',check_statespace_hash(H,'64bit'),[Arg],tools:arg_is_number(Arg,H)).
5432 recognised_option('-hash32',check_statespace_hash(H,'32bit'),[Arg],tools:arg_is_number(Arg,H)).
5433 recognised_option('-check_op_cache_stats',
5434 check_op_cache([next_state_calls-H1,inv_check_calls-H2,
5435 operations_cached-H3,invariants_cached-H4]),[Arg1,Arg2,Arg3,Arg4],
5436 (tools:arg_is_number_or_wildcard(Arg1,H1), tools:arg_is_number_or_wildcard(Arg2,H2),
5437 tools:arg_is_number_or_wildcard(Arg3,H3), tools:arg_is_number_or_wildcard(Arg4,H4))).
5438 recognised_option('-ltllimit',ltl_limit(Nr),[Arg], tools:arg_is_number(Arg,Nr)).
5439 recognised_option('-ltlfile',ltl_file(Filename),[Filename],
5440 prob_cli:check_file_arg(Filename,'ltlfile')).
5441 recognised_option('-check_disprover_result',cli_check_disprover_result([true-TNr,false-FNr,unknown-UNr,failure-0]),[T,F,U],
5442 (arg_is_number_or_wildcard(T,TNr),arg_is_number_or_wildcard(F,FNr),arg_is_number_or_wildcard(U,UNr))).
5443 recognised_option('-aa',cli_check_assertions(all,[true/TNr,false/FNr,unknown/UNr]),[T,F,U],
5444 (arg_is_number_or_wildcard(T,TNr),arg_is_number_or_wildcard(F,FNr),arg_is_number_or_wildcard(U,UNr))).
5445 recognised_option('-ma',cli_check_assertions(main,[true/TNr,false/FNr,unknown/UNr]),[T,F,U],
5446 (arg_is_number_or_wildcard(T,TNr),arg_is_number_or_wildcard(F,FNr),arg_is_number_or_wildcard(U,UNr))).
5447 recognised_option('-wd',cli_wd_check(DNr,TNr),[D,T],
5448 (arg_is_number_or_wildcard(T,TNr),arg_is_number_or_wildcard(D,DNr))).
5449 recognised_option('-check_cache_stats',cli_cache_stats_check([value_persistance_reused_transitions-RNr,
5450 value_persistance_stored_transitions-SNr]),[R,S],
5451 (arg_is_number_or_wildcard(S,SNr),arg_is_number_or_wildcard(R,RNr))).
5452 recognised_option('-kodkod_comparision',kodkod_comparision(Nr),[Arg],tools:arg_is_number(Arg,Nr)).
5453 recognised_option('-kodkod_performance',kodkod_performance(File,Nr),[File,Arg],tools:arg_is_number(Arg,Nr)).
5454 recognised_option('-animate',cli_random_animate(N,true),[Steps],tools:arg_is_number(Steps,N)).
5455 recognised_option('-simulate',cli_simulate(File,1,N,[]),[File,Steps],tools:arg_is_number(Steps,N)).
5456 recognised_option('-rt_simulate',cli_simulate(File,1,N,[simulation_speed/1]),[File,Steps],tools:arg_is_number(Steps,N)).
5457 recognised_option('-mc_simulate',cli_simulate(File,R,N,[]),[File,Reps,Steps],(tools:arg_is_number(Steps,N),tools:arg_is_number(Reps,R))).
5458 recognised_option('-simb_profile',cli_print_statistics(simb_profile),[],true).
5459 recognised_option('-simulate_until_ltl_ap',simb_ltl_stop_condition(LTL_Stop_AsAtom),[LTL_Stop_AsAtom],true).
5460 recognised_option('-simulate_until_time',simb_option(max_simulation_time(T)),[Time],tools:arg_is_number(Time,T)).
5461 recognised_option('-execute',execute(N,true,current_state(1)),[Steps],tools:arg_is_number(Steps,N)).
5462 recognised_option('-execute_repeat',execute(N,true,current_state(R)),[Steps,Rep],
5463 (tools:arg_is_number(Steps,N),tools:arg_is_number(Rep,R))).
5464 recognised_option('-execute_expect_steps',execute_expect_steps(N),[Steps],tools:arg_is_number(Steps,N)).
5465 recognised_option('-logxml_write_vars',logxml_write_ids(variables,Prefix),[Prefix],true).
5466 recognised_option('-logxml_write_ids',logxml_write_ids(all,Prefix),[Prefix],true).
5467 recognised_option('-zmq_master',zmq_master(Identifier),[Identifier], true).
5468 recognised_option('-cbc_tests', cbc_tests(Depth,EndPred,Output),[Depth,EndPred,Output],
5469 prob_cli:check_file_arg(Output,'cbc_tests')).
5470 recognised_option('-mcm_tests', mcm_tests(Depth,MaxStates,EndPred,Output),[Depth,MaxStates,EndPred,Output],
5471 prob_cli:check_file_arg(Output,'mcm_tests')).
5472 recognised_option('-test_description', test_description(File), [File],
5473 prob_cli:check_file_arg(File,'test_description')).
5474 recognised_option('-all_paths', all_deadlocking_paths(File), [File],
5475 prob_cli:check_file_arg(File,'all_paths')).
5476 recognised_option('-dot',dot_command(Category,File,default),[Category,File],
5477 prob_cli:check_file_arg(File,'dot')).
5478 recognised_option('-spdot',dot_command(state_space,File,default),[File], prob_cli:check_file_arg(File,'spdot')). % we keep this : it is shown in Wiki
5479 % recognised_option('-spmdot',dot_command(signature_merge,File,default),[File], prob_cli:check_file_arg(File,'spmdot')).
5480 % recognised_option('-spddot',dot_command(dfa_merge,File,default),[File], prob_cli:check_file_arg(File,'spddot')).
5481 % recognised_option('-sgdot',dot_command(state_as_graph,File,default),[File], prob_cli:check_file_arg(File,'sgdot')).
5482 recognised_option('-dotexpr',dot_command_for_expr(Category,Expr,File,[],default),[Category,Expr,File],
5483 prob_cli:check_file_arg(File,'dotexpr')).
5484 recognised_option('-dot_expr',Opt,Args,Call) :- recognised_option('-dotexpr',Opt,Args,Call).
5485 %recognised_option('-sgedot',dot_command_for_expr(expr_as_graph,Expr,File,[],default),[Expr,File], prob_cli:check_file_arg(File,'sgedot')).
5486 % recognised_option('-sptdot',dot_command_for_expr(transition_diagram,Expr,File,[],default),[Expr,File],prob_cli:check_file_arg(File,'sptdot')).
5487 %recognised_option('-invdot',dot_command(invariant,File,default),[File], prob_cli:check_file_arg(File,'invdot')).
5488 %recognised_option('-propdot',dot_command(properties,File,default),[File], prob_cli:check_file_arg(File,'propdot')).
5489 %recognised_option('-assdot',dot_command(assertions,File,default),[File], prob_cli:check_file_arg(File,'assdot')).
5490 %recognised_option('-deaddot',dot_command(deadlock,File,default)(File),[File], prob_cli:check_file_arg(File,'deaddot')).
5491 recognised_option('-puml',plantuml_command(Category,File),[Category,File],
5492 prob_cli:check_file_arg(File,'plantuml')).
5493 recognised_option('-pumlexpr',plantuml_command(Category,File,[Expr]),[Category,Expr,File],
5494 prob_cli:check_file_arg(File,'plantuml')).
5495 recognised_option('-puml_expr',Opt,Args,Call) :- recognised_option('-pumlexpr',Opt,Args,Call).
5496 recognised_option('-csv',csv_table_command(Category,[],[],File),[Category,File],
5497 prob_cli:check_file_arg(File,'csv')).
5498 recognised_option('-csvexpr',csv_table_command(Category,[Expr],[],File),[Category,Expr,File],
5499 prob_cli:check_file_arg(File,'csvexpr')).
5500 recognised_option('-csv_expr',Opt,Args,Call) :- recognised_option('-csvexpr',Opt,Args,Call).
5501 recognised_option('-csv_hist',Opt,Args,Call) :- recognised_option('-csvhist',Opt,Args,Call).
5502 recognised_option('-csvhist',evaluate_expression_over_history_to_csv_file(Expr,File),[Expr,File],
5503 prob_cli:check_file_arg(File,'csvhist')).
5504 %recognised_option('-get_min_max_coverage',csv_table_command(minmax_table,[],[text_output],File),[File]). % deprecated
5505 recognised_option('-min_max_coverage',csv_table_command(minmax_table,[],[text_output],File),[File],
5506 prob_cli:check_file_arg(File,'min_max_coverage')).
5507 recognised_option('-get_coverage_information',get_coverage_information(File),[File],
5508 prob_cli:check_file_arg(File,'get_coverage_information')).
5509 %recognised_option('-vc',csv_table_command(minmax_table,[],[text_output],user_output)).
5510 recognised_option('-read_write_matrix_csv',generate_read_write_matrix_csv(CsvFile),
5511 [CsvFile],
5512 prob_cli:check_file_arg(CsvFile,'read_write_matrix_csv')).
5513 recognised_option('-feasibility_analysis_csv',feasibility_analysis_csv(TimeOut,EnablingCsvFile),
5514 [TimeOut,EnablingCsvFile],
5515 prob_cli:check_file_arg(EnablingCsvFile,'feasibility_analysis_csv')).
5516 recognised_option('-l',log(Log,prolog),[Log],
5517 prob_cli:check_file_arg(Log,'l')).
5518 recognised_option('-log',log(Log,prolog),[Log],
5519 prob_cli:check_file_arg(Log,'log')).
5520 recognised_option('-logxml',log(Log,xml),[Log],
5521 prob_cli:check_file_arg(Log,'logxml')). % see cli_start_logging
5522 recognised_option('-logtlc',logtlc(Log),[Log],
5523 prob_cli:check_file_arg(Log,'logtlc')).
5524 recognised_option('-pp',pretty_print_internal_rep(File,'$auto',needed,ascii),[File],
5525 prob_cli:check_file_arg(File,'pp')).
5526 recognised_option('-ppunicode',pretty_print_internal_rep(File,'$auto',needed,unicode),[File],
5527 prob_cli:check_file_arg(File,'pp')).
5528 recognised_option('-ppf',pretty_print_internal_rep(File,'$auto',all,ascii),[File],
5529 prob_cli:check_file_arg(File,'ppf')).
5530 recognised_option('-ppAB',pretty_print_internal_rep(File,'$auto',all,atelierb),[File],
5531 prob_cli:check_file_arg(File,'ppAB')).
5532 recognised_option('-pp_with_name',pretty_print_internal_rep(File,MachName,all,ascii),[MachName,File],
5533 prob_cli:check_file_arg(File,'pp_with_name')). % provide explicit machine name
5534 recognised_option('-ppB',pretty_print_internal_rep_to_B(File),[File],
5535 prob_cli:check_file_arg(File,'ppB')). % deprecated; is now superseded by ppAB for Event-B machines
5536 recognised_option('-pppl',pretty_print_prolog_file(File),[File],
5537 prob_cli:check_file_arg(File,'pppl')).
5538 recognised_option('-pp_pl_file',pretty_print_prolog_file(File,OutFile),[File,OutFile],
5539 (prob_cli:check_file_arg(File,'pp_pl_file'),prob_cli:check_file_arg(OutFile,'pp_pl_file'))).
5540 recognised_option('-ppi',indent_main_b_file(File),[File],
5541 prob_cli:check_file_arg(File,'ppi')).
5542 recognised_option('-indent_b_file',indent_b_file_to_file(BFile,OutFile,[]),[BFile,OutFile], % indent some other file
5543 (prob_cli:check_file_arg(BFile,'indent_b_file'),prob_cli:check_file_arg(OutFile,'indent_b_file'))).
5544 recognised_option('-reformat_b_file',indent_b_file_to_file(BFile,OutFile,
5545 [insert_new_lines_before_keywords,insert_new_lines_after_keywords]),[BFile,OutFile], % reformat some other file
5546 (prob_cli:check_file_arg(BFile,'indent_b_file'),prob_cli:check_file_arg(OutFile,'indent_b_file'))).
5547 recognised_option('-save_state',save_state_space(Filename),[Filename],
5548 prob_cli:check_file_arg(Filename,'save_state')). % possibly save_state_space would be a better name
5549 recognised_option('-save',save_state_for_refinement(Filename),[Filename],
5550 prob_cli:check_file_arg(Filename,'save')).
5551 recognised_option('-sptxt',print_values(Filename),[Filename],
5552 prob_cli:check_file_arg(Filename,'sptxt')).
5553 recognised_option('-sstxt',print_all_values(Dirname),[Dirname],
5554 prob_cli:check_file_arg(Dirname,'sstxt')).
5555 recognised_option('-latex',process_latex_file(In,Out),[In,Out],
5556 (prob_cli:check_file_arg(In,'latex'),prob_cli:check_file_arg(Out,'latex'))).
5557 recognised_option('-bench_csv',benchmark_info_csv_output(File,write,csv),[File],prob_cli:check_file_arg(File,'bench_csv')).
5558 recognised_option('-bench_csv_append',benchmark_info_csv_output(File,append,csv),[File],prob_cli:check_file_arg(File,'bench_csv')).
5559 recognised_option('-bench_tex',benchmark_info_csv_output(File,write,latex),[File],prob_cli:check_file_arg(File,'bench_tex')).
5560 recognised_option('-trace_replay',trace_check(Style,File,default_trace_replay),[Style,File],prob_cli:check_file_arg(File,'trace_replay')). % Style can be json, prolog or B
5561 recognised_option('-det_trace_replay',trace_check(Style,File,deterministic_trace_replay),[Style,File],prob_cli:check_file_arg(File,'det_trace_replay')).
5562 recognised_option('-replay',eval_repl([File]),[File],prob_cli:check_file_arg(File,'replay')). % used to be -eval
5563 recognised_option('-state_trace',state_trace(File),[File],prob_cli:check_file_arg(File,'state_trace')).
5564 recognised_option('-typecheckertest',typechecker_test(File),[File],prob_cli:check_file_arg(File,'typecheckertest')).
5565 recognised_option('-enabling_analysis_csv',enabling_analysis_csv(EnablingCsvFile),[EnablingCsvFile],
5566 prob_cli:check_file_arg(EnablingCsvFile,'enabling_analysis_csv')).
5567 recognised_option('-dot_output',dot_analyse_output_prefix(Path),[Path],prob_cli:check_file_arg(Path,'dot_output')).
5568 recognised_option('-evaldot',evaldot(File),[File],prob_cli:check_file_arg(File,'evaldot')).
5569 recognised_option('-his',history(File),[File],prob_cli:check_file_arg(File,'his')).
5570 recognised_option('-visb_click',visb_click(SVGID),[SVGID],true).
5571 recognised_option('-visb',visb_history(JSONFile,HTMLFile,[]),[JSONFile,HTMLFile],
5572 (prob_cli:check_file_arg(JSONFile,'visb'),prob_cli:check_file_arg(HTMLFile,'visb'))).
5573 recognised_option('-visb_with_vars',
5574 visb_history(JSONFile,HTMLFile,[show_constants(all),show_sets(all),show_variables(all)]),
5575 [JSONFile,HTMLFile],
5576 (prob_cli:check_file_arg(JSONFile,'visb_with_vars'),prob_cli:check_file_arg(HTMLFile,'visb_with_vars'))).
5577 recognised_option('-rule_report',rule_report(File), [File], prob_cli:check_file_arg(File,'rule_report')).
5578 recognised_option('-proof_export',proof_export(Style,File), [Style,File], prob_cli:check_file_arg(File,'proof_export')). % Style can be html, bpr or a dot output format
5579 recognised_option('-bench_alloy_cmd',run_benchmark(alloy,CmdNames,AlloyFilePath),[CmdNames,AlloyFilePath],prob_cli:check_file_arg(AlloyFilePath,'bench_alloy_cmd')).
5580 recognised_option('-bench_smt_cbc_inv',run_benchmark(smt,cbc_inv,Folder),[Folder],prob_cli:check_file_arg(Folder,'bench_smt_cbc_inv')).
5581 recognised_option('-bench_smt_cbc_deadlock',run_benchmark(smt,cbc_deadlock,Folder),[Folder],prob_cli:check_file_arg(Folder,'bench_smt_cbc_deadlock')).
5582 recognised_option('-bench_smt_bmc',run_benchmark(smt,bmc,Folder),[Folder],prob_cli:check_file_arg(Folder,'bench_smt_bmc')).
5583 recognised_option('-eval_file',eval_string_or_file(file(default),F,exists,_ANY,norecheck),[F],prob_cli:check_file_arg(F,'eval_file')).
5584 recognised_option('-evalt_file',eval_string_or_file(file(default),F,exists,'TRUE',norecheck),[F],prob_cli:check_file_arg(F,'evalt_file')).
5585 recognised_option('-eval_rule_file',eval_string_or_file(file(default),F,forall,_ANY,norecheck),[F],prob_cli:check_file_arg(F,'eval_rule_file')).
5586 recognised_option('-solve_file',eval_string_or_file(file(Solver),F,exists,_ANY,norecheck),[Solver,F],prob_cli:check_file_arg(F,'eval_file')).
5587
5588 recognised_option('-zmq_assertions',zmq_assertion(Identifier),[Identifier],true).
5589 recognised_option('-zmq_worker',zmq_worker(Identifier),[Identifier], true).
5590 %recognised_option('-zmq_worker2',zmq_worker2(MasterIP, Port, ProxyID, Logfile),[MasterIP, SPort, SProxyID, Logfile],
5591 % tools:(arg_is_number(SPort,Port), arg_is_number(SProxyID, ProxyID))).
5592 recognised_option('-p',set_pref(NPREF,PREFVAL),[PREF,PREFVAL],prob_cli:normalise_pref_name(PREF,NPREF)).
5593 recognised_option('-pref',set_pref(NPREF,PREFVAL),[PREF,PREFVAL],prob_cli:normalise_pref_name(PREF,NPREF)).
5594 recognised_option('-prob_application_type',set_application_type(T),[T],true).
5595 recognised_option('-cbc_redundant_invariants',cbc_redundant_invariants(Nr),[X],tools:arg_is_number(X,Nr)).
5596 recognised_option('-expcterrpos',expect_error_pos(Type,LNr,CNr),[Type,Line,Col],
5597 (tools:arg_is_number(Line,LNr),tools:arg_is_number(Col,CNr))).
5598 recognised_option('-pref_group',set_preference_group(NGroup,Val),[Group,Val],
5599 (prob_cli:normalise_option_atom(Group,NGroup))).
5600 recognised_option('-save_all_traces_until',generate_all_traces_until(Formula,FilePrefix),
5601 [Formula,FilePrefix],
5602 true). % we could check LTL formula and FilePrefix
5603 recognised_option('-check_machine_file_sha',check_machine_file_sha(FILE,SHA1),[FILE,SHA1],
5604 prob_cli:check_file_arg(FILE,'check_machine_file_sha')).
5605 recognised_option('-sha1sum',Command,Args,Call) :-
5606 recognised_option('-check_machine_file_sha',Command,Args,Call).
5607 recognised_option('-animate_until_ltl_steps',animate_until_ltl(Formula,no_loop,ltl_found,Steps),[Formula,A],
5608 tools:arg_is_number(A,Steps)).
5609 recognised_option('-gc_margin',set_gc_margin(Nr),[X], tools:arg_is_number(X,Nr)).
5610
5611 % recognised_option/3
5612 recognised_option('-prefs',set_prefs_from_file(PREFFILE),[PREFFILE]).
5613 %recognised_option('-plugin',plugin(Plugin), [Plugin]).
5614 recognised_option('-card',set_card(SET,SCOPE),[SET,SCOPE]).
5615 recognised_option('-argv',set_argv(ARGV),[ARGV]).
5616 recognised_option('-goal',set_goal(GOAL),[GOAL]).
5617 recognised_option('-property',add_additional_property(PRED),[PRED]).
5618 recognised_option('-scope',set_searchscope(GOAL),[GOAL]).
5619 recognised_option('-searchscope',set_searchscope(GOAL),[GOAL]).
5620 recognised_option('-search_scope',set_searchscope(GOAL),[GOAL]).
5621 recognised_option('-eval',eval_string_or_file(string,E,exists,_,norecheck),[E]).
5622 recognised_option('-evalt',eval_string_or_file(string,E,exists,'TRUE',norecheck),[E]).
5623 recognised_option('-evalf',eval_string_or_file(string,E,exists,'FALSE',norecheck),[E]).
5624 recognised_option('-evalt_rc',eval_string_or_file(string,E,exists,'TRUE',recheck(ascii)),[E]).
5625 recognised_option('-evalf_rc',eval_string_or_file(string,E,exists,'FALSE',recheck(ascii)),[E]).
5626 recognised_option('-evalu',eval_string_or_file(string,E,exists,'UNKNOWN',norecheck),[E]).
5627 recognised_option('-evalnwd',eval_string_or_file(string,E,exists,'NOT-WELL-DEFINED',norecheck),[E]).
5628 recognised_option('-parsercp',parsercp(L),[L]). % deprecated
5629 recognised_option('-parserport',parserport(L),[L]).
5630 recognised_option('-expcterr',expect_error(Type),[Type]).
5631 recognised_option('-expecterr',expect_error(Type),[Type]).
5632 recognised_option('-expect',expect_error(Type),[Type]).
5633 recognised_option('-opterr',optional_error(Type),[Type]).
5634 recognised_option('-his_option',history_option(Option),[Option]). % trace_file, json, show_init, show_states
5635 recognised_option('-cache',cache_storage(D,strict),[D]). % for value_persistance caching
5636 recognised_option('-ccache',cache_storage(D,create_if_needed),[D]). % ditto
5637 recognised_option('-show_cache',show_cache(default),[]).
5638 recognised_option('-show_cache_verbose',show_cache(verbose),[]).
5639 recognised_option('-cache_statistics',cli_print_statistics(value_persistance_stats),[]).
5640 recognised_option('-cache_stats',cli_print_statistics(value_persistance_stats),[]). % synonym
5641 % see also -check_cache_stats
5642 recognised_option('-clear_cache',clear_value_persistance_cache,[]).
5643 recognised_option('-clear_cache_for',clear_value_persistance_cache(Machine),[Machine]).
5644 recognised_option('-hshow',cli_print_statistics(hshow),[]). % machine inclusion hierarchy
5645 recognised_option('-show_inclusion_hierarchy',cli_print_statistics(hshow),[]). % machine inclusion hierarchy
5646
5647 recognised_option('-MAIN',csp_main(ProcessName),[ProcessName]).
5648
5649 recognised_option('-ltlformula',ltl_formula_model_check(Formula,_),[Formula]).
5650 recognised_option('-ltlformulat',ltl_formula_model_check(Formula,true),[Formula]).
5651 recognised_option('-ltlformulaf',ltl_formula_model_check(Formula,false),[Formula]).
5652 recognised_option('-ctlformula',ctl_formula_model_check(Formula,_),[Formula]).
5653 recognised_option('-ctlformulat',ctl_formula_model_check(Formula,true),[Formula]).
5654 recognised_option('-ctlformulaf',ctl_formula_model_check(Formula,false),[Formula]).
5655 recognised_option('-pctlformula',pctl_formula_model_check(Formula,_),[Formula]).
5656 recognised_option('-pctlformulat',pctl_formula_model_check(Formula,true),[Formula]).
5657 recognised_option('-pctlformulaf',pctl_formula_model_check(Formula,false),[Formula]).
5658 recognised_option('-animate_until_ltl',animate_until_ltl(Formula,no_loop,_,_),[Formula]).
5659 recognised_option('-animate_until_ltl_state_property',animate_until_ltl(Formula,ltl_state_property,_,_),[Formula]).
5660
5661
5662 %recognised_option('-cspref',csp_in_situ_refinement_check(assertRef('False',val_of(AbsP1,no_loc_info_available),Type,val_of(ImplP2,no_loc_info_available),no_loc_info_available),'False'),[AbsP1,Type,ImplP2]).
5663 recognised_option('-cspref',csp_in_situ_refinement_check(AbsP1,Type,ImplP2),[AbsP1,Type,ImplP2]).
5664 % -cspref R [F= Q
5665 recognised_option('-cspdeadlock',csp_checkAssertion(Proc,Model,'deadlock free'),[Proc,Model]).
5666 % -cspdeadlock R F
5667 recognised_option('-cspdeterministic',csp_checkAssertion(Proc,Model,'deterministic'),[Proc,Model]).
5668 % -cspdeterministic R F
5669 recognised_option('-csplivelock',csp_checkAssertion(Proc,'FD','livelock free'),[Proc]).
5670 % -csplivelock R
5671 % -csp_assertion "P [F= Q"
5672 recognised_option('-csp_assertion',check_csp_assertion(Assertion),[Assertion]).
5673 recognised_option('-csp_eval', eval_csp_expression(Expr),[Expr]).
5674 recognised_option('-get_csp_assertions_as_string',csp_get_assertions,[]).
5675
5676 recognised_option('-variable_coverage',csv_table_command(variable_coverage,[],[text_output],user_output),[]).
5677 recognised_option('-vacuity_check',vacuity_check,[]).
5678 recognised_option('-wd_check',cli_wd_check(_,_),[]).
5679 recognised_option('-wd_check_all',cli_wd_check(X,X),[]).
5680 recognised_option('-well_definedness_check',cli_wd_check(_,_),[]).
5681 recognised_option('-wd_inv_proof',cli_wd_inv_proof(_,_,_),[]).
5682 recognised_option('-lint',cli_lint,[]). % extended static check (ESC, esc)
5683 recognised_option('-lint_operations',cli_lint(operations),[]).
5684 recognised_option('-lint_variables',cli_lint(variables),[]).
5685 recognised_option('-cbc',constraint_based_check(OpName),[OpName]). % cbc invariant checking
5686 recognised_option('-cbc_invariant',constraint_based_check(OpName),[OpName]).
5687 recognised_option('-cbc_deadlock',cbc_deadlock_check(true),[]).
5688 recognised_option('-cbc_assertions',cbc_assertions(true,[]),[]).
5689 recognised_option('-cbc_main_assertions',cbc_assertions(true,[main_assertions]),[]).
5690 recognised_option('-cbc_assertions_proof',cbc_assertions(false,[]),[]). % do not allow enumeration warnings
5691 recognised_option('-cbc_assertions_tautology_proof',cbc_assertions(false,[tautology_check]),[]). % do not allow enumeration warnings + disregard PROPERTIES, used for Atelier-B proof/disproof; TO DO: also call WD prover
5692 recognised_option('-cbc_assertions_tautology_proof_check',cbc_assertions(false,[tautology_check,contradiction_check]),[]).
5693 recognised_option('-cbc_option',cbc_option(OPT),[OPT]). % should be tautology_check,contradiction_check, unsat_core
5694 recognised_option('-cbc_result_file',cbc_result_file(FILE),[FILE]). % write result to FILE
5695 recognised_option('-cbc_refinement',cbc_refinement,[]).
5696 recognised_option('-cbc_deadlock_pred',cbc_deadlock_check(GoalPred),[GoalPred]).
5697 recognised_option('-cbc_sequence',cbc_sequence(OpSequence,'',single_solution),[OpSequence]).
5698 recognised_option('-cbc_sequence_all',cbc_sequence(OpSequence,'',findall),[OpSequence]).
5699 recognised_option('-cbc_sequence_with_target',cbc_sequence(OpSequence,TargetPredString,single_solution),[OpSequence,TargetPredString]).
5700 recognised_option('-cbc_sequence_with_target_all',cbc_sequence(OpSequence,TargetPredString,findall),[OpSequence,TargetPredString]).
5701 recognised_option('-comment',comment(UserComment),[UserComment]). % not processed by tool, but will be stored in log-file and used by log_analyser
5702 recognised_option('-junit',junit(Dir),[Dir]).
5703 recognised_option('-mcm_cover', mcm_cover(Event),[Event]).
5704 recognised_option('-cbc_cover', cbc_cover(Event),[Event]).
5705 recognised_option('-cbc_cover_match', cbc_cover(match_event(Event)),[Event]). % find events which have Event String occuring somewhere in name
5706 recognised_option('-cbc_cover_all', cbc_cover_all,[]). % is now default if no cbc_cover provided
5707 recognised_option('-cbc_cover_final', cbc_cover_final,[]).
5708 recognised_option('-bmc', cbc_tests(Depth,'#not_invariant',''),[Depth]).
5709 recognised_option('-bdc', cbc_tests(Depth,'#deadlock',''),[Depth]).
5710 recognised_option('-enabling_analysis',enabling_analysis_csv(user_output),[]).
5711 recognised_option('-feasibility_analysis',feasibility_analysis_csv(1000,user_output),[]).
5712 recognised_option('-read_write_matrix',generate_read_write_matrix_csv(user_output),[]).
5713 recognised_option('-scc_trace',check_scc_for_ltl_formula(LtlFormula,SCC),[LtlFormula,SCC]).
5714 recognised_option('-selfcheck_module',selfcheck(M,[]),[M]).
5715 recognised_option('-mc_mode',depth_breadth_first_mode(M),[M]). % can be mixed, hash, heuristic
5716 recognised_option('-assertion',cli_check_assertions(specific(X),[false/0,unknown/0]),[X]).
5717 recognised_option('-cbc_assertion',cbc_assertions(true,[specific(X)]),[X]). % check only a specific assertion
5718 recognised_option('-symbolic_model_check', cli_symbolic_model_check(Algorithm), [Algorithm]).
5719 recognised_option('-ltsmin2',ltsmin2(EndpointPath), [EndpointPath]).
5720 recognised_option('-ltsmin_ltl_output',ltsmin_ltl_output(Path), [Path]).
5721 recognised_option('-ltsmin_option', ltsmin_option(X),[X]).
5722 recognised_option('-machine_hash_check',cli_print_machine_info(hash(X)),[X]).
5723 recognised_option('-install',install_prob_lib(X,[]),[X]).
5724 recognised_option('-install_dry_run',install_prob_lib(X,[dryrun]),[X]).
5725
5726
5727 recognised_option('-dot_all',dot_generate_for_all_formulas). % generate dot also for true formulas
5728 recognised_option('-animate_all',cli_random_animate(2147483647,false)).
5729 recognised_option('-execute_all',execute(2147483647,false,current_state(1))).
5730 recognised_option('-execute_all_inits',execute(2147483647,false,from_all_initial_states)).
5731 recognised_option('-animate_stats',animate_stats).
5732 recognised_option('-execute_monitor',execute_monitoring).
5733 recognised_option('-check_goal',check_goal).
5734 recognised_option('-ltlassertions',ltl_assertions).
5735 recognised_option('-assertions',cli_check_assertions(all,[false/0,unknown/0])).
5736 recognised_option('-main_assertions',cli_check_assertions(main,[false/0,unknown/0])).
5737 recognised_option('-properties',cli_check_properties).
5738 recognised_option('-properties_core',cli_core_properties(_)). % variable as arg: try various algorithms in order
5739 recognised_option('-properties_core_wd',cli_core_properties(wd_prover)).
5740 recognised_option('-properties_core_z2',cli_core_properties(z3_bup(2))).
5741 recognised_option('-properties_core_z3',cli_core_properties(z3_bup(3))).
5742 recognised_option('-selfcheck',selfcheck(_,[])).
5743 recognised_option('-pacheck',pa_check). % predicate analysis for Kodkod
5744 recognised_option('-det_check',det_check). % check if animation is deterministic
5745 recognised_option('-det_constants',det_constants_check). % check if animation for setup_constants is deterministic
5746 recognised_option('-bf',breadth_first).
5747 recognised_option('-breadth',breadth_first).
5748 recognised_option('-df',depth_first).
5749 recognised_option('-depth',depth_first).
5750 recognised_option('-strict',strict_raise_error).
5751 recognised_option('-silent',silent).
5752 recognised_option('-quiet',silent).
5753 recognised_option('-q',silent).
5754 recognised_option('-force_no_silent',force_no_silent). % override provided silent flag; useful for gitlab test debugging
5755 recognised_option('-statistics',cli_print_statistics(full)).
5756 recognised_option('-stats',cli_print_statistics(full)).
5757 recognised_option('-memory_stats',cli_print_statistics(memory)).
5758 recognised_option('-memory_statistics',cli_print_statistics(memory)).
5759 recognised_option('-memory',cli_print_statistics(memory)).
5760 recognised_option('-profile_stats',cli_print_statistics(sicstus_profile)).
5761 recognised_option('-profile_statistics',cli_print_statistics(sicstus_profile)).
5762 recognised_option('-op_cache_profile',cli_print_statistics(op_cache_profile)).
5763 recognised_option('-hit_profile',cli_print_statistics(hit_profile)). % mainly for ProB developers
5764 recognised_option('-reset_profile_statistics',reset_profiler). % mainly for use in REPL
5765 recognised_option('-nodead',no_deadlocks).
5766 recognised_option('-no_dead',no_deadlocks).
5767 recognised_option('-no_deadlocks',no_deadlocks).
5768 recognised_option('-noinv',no_invariant_violations).
5769 recognised_option('-no_inv',no_invariant_violations).
5770 recognised_option('-no_invariant_violations',no_invariant_violations).
5771 recognised_option('-nogoal',no_goal).
5772 recognised_option('-no_goal',no_goal).
5773 recognised_option('-noltl',no_ltl). % just used for TLC at the moment
5774 recognised_option('-no_ltl',no_ltl).
5775 recognised_option('-noass',no_assertion_violations).
5776 recognised_option('-no_ass',no_assertion_violations).
5777 recognised_option('-no_assertion_violations',no_assertion_violations).
5778 recognised_option('-no_state_errors',no_state_errors). % disable checking for general_errors and transition related state_errors
5779 recognised_option('-nocounter',no_counter_examples).
5780 recognised_option('-no_counter_examples',no_counter_examples).
5781 recognised_option('-nocolor',no_color).
5782 recognised_option('-no_color',no_color).
5783 recognised_option('-no_colour',no_color).
5784 recognised_option('-disable_time_out',set_preference_group(time_out,disable_time_out)).
5785 recognised_option('-disable_timeout',set_preference_group(time_out,disable_time_out)).
5786 %recognised_option('-POR',with_reduction).
5787 recognised_option('-i',animate).
5788 recognised_option('-repl',eval_repl([])). % used to be -eval
5789 recognised_option('-c',coverage(false)).
5790 recognised_option('-cs',coverage(just_summary)).
5791 recognised_option('-coverage',coverage(false)).
5792 recognised_option('-coverage_summary',coverage(just_summary)).
5793 recognised_option('-machine_stats',cli_print_machine_info(statistics)).
5794 recognised_option('-machine_statistics',cli_print_machine_info(statistics)).
5795 recognised_option('-machine_files',cli_print_machine_info(files(no_sha))).
5796 recognised_option('-machine_files_sha',cli_print_machine_info(files(with_sha))).
5797 recognised_option('-machine_hash',cli_print_machine_info(hash(_))).
5798 recognised_option('-check_abstract_constants',check_abstract_constants).
5799 recognised_option('-op_cache_stats',check_op_cache([])).
5800 recognised_option('-op_cache_statistics',check_op_cache([])).
5801 recognised_option('-cv',coverage(true)).
5802 recognised_option('-v',verbose(19)).
5803 recognised_option('-vv',verbose(5)).
5804 recognised_option('-vvv',verbose(1)).
5805 recognised_option('-verbose',verbose(19)).
5806 recognised_option('-debug',verbose(19)).
5807 recognised_option('-verbose_off',verbose_off). % mainly useful in REPL
5808 recognised_option('-voff',verbose_off). % mainly useful in REPL
5809 recognised_option('-very_verbose',verbose(5)).
5810 recognised_option('-gc_trace',set_gc_trace(verbose)). % gc_info
5811 recognised_option('-gc_off',set_gc_on_off(off)).
5812 recognised_option('-gc_on',set_gc_on_off(on)).
5813 recognised_option('-profiling_on',profiling_on). % Prolog profiling
5814 recognised_option('-profile',cli_print_statistics(prob_profile)). % ProB Operation profiling
5815 recognised_option('-prob_profile',cli_print_statistics(prob_profile)). % ProB Operation profiling
5816 recognised_option('-prob_statistics',cli_print_statistics(prob_profile)). % synonym
5817 recognised_option('-prob_stats',cli_print_statistics(prob_profile)). % synonym
5818 recognised_option('-version',print_version(full)).
5819 recognised_option('-cpp_version',print_version(cpp)).
5820 recognised_option('-V',print_version(full)).
5821 recognised_option('-svers',print_version(short)).
5822 recognised_option('-short_version',print_version(short)).
5823 recognised_option('-check_lib',print_version(lib)).
5824 recognised_option('-check_java_version',check_java_version).
5825 recognised_option('-java_version',print_version(java)).
5826 recognised_option('-release_java_parser',release_java_parser).
5827 recognised_option('-fast_read_prob',fast_read_prob).
5828 recognised_option('-file_info',file_info).
5829 recognised_option('-t',default_trace_check).
5830 recognised_option('-init',initialise).
5831 recognised_option('-initialise',initialise).
5832 recognised_option('-ll',log('/tmp/prob_cli_debug.log',prolog)). % see cli_start_logging
5833 recognised_option('-ss',socket(9000,true)). % standard socket 9000
5834 recognised_option('-sf',socket(_,true)). % free socket
5835 recognised_option('-local_socketserver',socket(_,true)). % do not allow remote socket connections
5836 recognised_option('-remote_socketserver',socket(_,false)). % allow remote socket connections
5837 recognised_option('-help',help).
5838 recognised_option('-h',help).
5839 recognised_option('-rc',runtimechecking).
5840 recognised_option('-test_mode',test_mode).
5841 recognised_option('-check_complete',check_complete).
5842 recognised_option('-check_complete_operation_coverage', check_complete_operation_coverage).
5843 recognised_option('-mc_with_tlc', cli_start_mc_with_tlc).
5844 recognised_option('-mc_with_lts_sym', cli_start_sym_mc_with_lts(symbolic)).
5845 recognised_option('-mc_with_lts_seq', cli_start_sym_mc_with_lts(sequential)).
5846 recognised_option('-core',disprover_options([disprover_option(unsat_core),unsat_core_algorithm/linear])).
5847 recognised_option('-export_po',disprover_options([disprover_option(export_po_as_machine(user_output))])).
5848 recognised_option('-ltsmin',ltsmin).
5849 recognised_option('-trace',prolog_trace). % enter Prolog debugger on development system after starting up ProB
5850
5851 % some utilities to be able to call the above options directly from repl:
5852 :- public silent/0, coverage/1, help/0.
5853 % predicate to set_verbose_mode
5854 %verbose :- tcltk_turn_debugging_on(19).
5855 %very_verbose :- tcltk_turn_debugging_on(5).
5856 verbose(Nr) :- tcltk_turn_debugging_on(Nr),
5857 (Nr<10 -> set_gc_trace(verbose) ; true). % terse is another option for gc_trace
5858 verbose_off :- set_gc_trace(off), tcltk_turn_debugging_off.
5859 file_info :- file_loaded(true,MainFile), print_file_info(MainFile).
5860 coverage(ShowEnabledInfo) :- probcli_time_stamp(NOW), cli_show_coverage(ShowEnabledInfo,NOW).
5861
5862 % Governs global stack garbage collection trace messages
5863 set_gc_trace(X) :- member(X,[off,terse,verbose]),!,set_prolog_flag(gc_trace,X).
5864 set_gc_trace(X) :- add_error(prob_cli,'Illegal value for gc_trace:',X).
5865
5866 % At least Margin kilobytes of free global stack space are guaranteed to exist after a garbage collection
5867 set_gc_margin(Margin) :- set_prolog_flag(gc_margin,Margin).
5868 set_gc_on_off(OnOff) :- set_prolog_flag(gc,OnOff).
5869
5870 silent :- (option(silent) -> true ; assert_option(silent)).
5871 help :- eval_help.
5872 dot_command(DCommand,DotFile,DotEngine) :- call_dot_command_with_engine(DCommand,DotFile,[],DotEngine).
5873 dot_command_for_expr(DECommand,Expr,DotFile,Opts,DotEngine) :-
5874 call_dot_command_with_engine_for_expr(DECommand,Expr,DotFile,Opts,DotEngine).
5875
5876 plantuml_command(PCommand,UmlFile) :- call_plantuml_command(PCommand,UmlFile).
5877 plantuml_command_for_expr(PECommand,Expr,UmlFile,Opts) :-
5878 call_plantuml_command_for_expr(PECommand,Expr,UmlFile,Opts).
5879
5880 :- use_module(tools_io,[safe_intelligent_open_file/3]).
5881 csv_table_command(TCommand,Formulas,Options,CSVFile) :-
5882 append(Formulas,[TableResult],ActualArgs),
5883 OptionalArgs=[],
5884 format_with_colour_nl(user_output,[blue],'Calling table command ~w',[TCommand]),
5885 call_command(table,TCommand,_,ActualArgs,OptionalArgs),
5886 write_table_to_csv_file(CSVFile,Options,TableResult),
5887 format_with_colour_nl(user_output,[blue],'Finished exporting ~w to ~w',[TCommand,CSVFile]).
5888
5889
5890 save_state_space(StateFile) :- debug_println(20,'% Saving state space to file'),
5891 state_space:tcltk_save_state_space(StateFile).
5892 :- public load_state/1. % for REPL
5893 load_state(StateFile) :- debug_println(20,'% Loading state space from file'),
5894 state_space:tcltk_load_state(StateFile).
5895 :- public execute/3. % for REPL
5896 execute(ESteps,ErrOnDeadlock,From) :- cli_execute(ESteps,ErrOnDeadlock,From).
5897
5898 option_verbose :- option(verbose(_)).
5899 option_very_verbose :- debug_level_active_for(5).
5900
5901 set_random_seed_to_deterministic_start_seed :-
5902 % in test_mode we do not change the random number generator's initial seed
5903 true. %getrand(CurrState),setrand(CurrState). % this seems to be a no-op
5904
5905 :- if(predicate_property(set_random(_), _)).
5906 % SWI-Prolog's native API for reinitializing the RNG state.
5907 % The equivalent of this call is also performed automatically by SWI
5908 % when a random number is requested for the first time.
5909 set_new_random_seed :- set_random(seed(random)).
5910 :- else.
5911 % SICStus way of (re)initializing the RNG state.
5912 % Note that on SICStus, the initial RNG state after startup is always the same,
5913 % so it *must* be manually reinitialized like this to get actually random results!
5914 %:- use_module(library(random),[setrand/1]).
5915 set_new_random_seed :-
5916 now(TimeStamp), % getting the unix time
5917 setrand(TimeStamp). % setting new random seed by every execution of probcli
5918 :- endif.
5919
5920 halt_exception :- halt_exception(0).
5921 halt_exception(Code) :- throw(halt(Code)).
5922
5923 % -----------------
5924
5925 start_xml_feature(FeatureName,[CErrs1,CWarns1,CEErrs1]) :-
5926 debug_format(20,'% Starting ~w~n',[FeatureName]),
5927 get_counter(cli_errors,CErrs1), get_counter(cli_warnings,CWarns1), get_counter(cli_expected_errors,CEErrs1),
5928 start_xml_group_in_log(FeatureName).
5929
5930 start_xml_feature(FeatureName,Attr,Value,[CErrs1,CWarns1,CEErrs1]) :-
5931 debug_format(20,'% Starting ~w (~w=~w)~n',[FeatureName,Attr,Value]),
5932 get_counter(cli_errors,CErrs1), get_counter(cli_warnings,CWarns1), get_counter(cli_expected_errors,CEErrs1),
5933 start_xml_group_in_log(FeatureName,Attr,Value).
5934
5935 stop_xml_feature(FeatureName,[CErrs1,CWarns1,CEErrs1]) :-
5936 get_counter(cli_errors,CErrs2), get_counter(cli_warnings,CWarns2), get_counter(cli_expected_errors,CEErrs2),
5937 CErrs is CErrs2-CErrs1, CWarns is CWarns2-CWarns1, CEErrs is CEErrs2-CEErrs1,
5938 (CEErrs>0
5939 -> write_xml_element_to_log('probcli-errors',[errors/CErrs,warnings/CWarns,expected_errors/CEErrs])
5940 ; write_xml_element_to_log('probcli-errors',[errors/CErrs,warnings/CWarns])
5941 ),
5942 debug_format(20,'% Finished ~w (errors=~w, warnings=~w, expected_errors=~w)~n',[FeatureName,CErrs,CWarns,CEErrs]),
5943 stop_xml_group_in_log(FeatureName),
5944 !.
5945 stop_xml_feature(FeatureName,L) :-
5946 add_internal_error('Illegal or failed call:',stop_xml_feature(FeatureName,L)).
5947
5948 %(CErrs>0 -> (file_loaded(_,MainFile) -> true ; MainFile=unknown), Time=unknown, % TO DO: determine time
5949 % create_and_print_junit_result(['Feature',MainFile], FeatureName, Time, error) ; true).
5950 % Note: call stop_xml_group_in_log if the feature stops unexpectedly and you do not have the Info list available
5951
5952 % -----------------
5953
5954 :- public user:runtime_entry/1.
5955 user:runtime_entry(start) :- go_cli.
5956
5957 %save :- save_program('probcli.sav').
5958
5959 :- use_module(eventhandling,[announce_event/1]).
5960 :- announce_event(compile_prob).