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