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