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