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