1 % (c) 2009-2019 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 :- module(specfile, [
6 specfile_possible_trans_name/2, specfile_possible_trans_name_for_successors/2,
7 specfile_trans/6,
8 prepare_state_for_specfile_trans/2, prepare_state_for_specfile_trans/3,
9
10 property/2, elementary_prop/2,
11
12 partial_trans/4, specfile_trans_or_partial_trans/6,
13
14 animation_mode/1, set_animation_mode/1, add_animation_minor_mode/1,
15 animation_minor_mode/1, set_animation_minor_mode/1, remove_animation_minor_mode/0,
16 unset_animation_minor_modes/1, reset_animation_minor_modes/1,
17 b_mode/0, z_mode/0, b_or_z_mode/0, b_or_z_mode/1, eventb_mode/0,
18 csp_mode/0, csp_mode/1,
19 csp_with_bz_mode/0, z_or_tla_minor_mode/0,
20 process_algebra_mode/0,
21
22 type_check_csp_and_b/0,
23
24 currently_opened_file/1, % only true for successfully opened files
25 currently_opened_file_status/2, % second parameter: success or failure
26 reset_currently_opened_file/0,set_currently_opened_file/1, set_failed_to_open_file/1,
27 set_currently_opened_package/1,
28 spec_file_has_been_successfully_loaded/0,
29
30 state_corresponds_to_initialised_b_machine/1, state_corresponds_to_initialised_b_machine/2,
31 state_corresponds_to_fully_setup_b_machine/1, state_corresponds_to_fully_setup_b_machine/2,
32 state_corresponds_to_set_up_constants/1, state_corresponds_to_set_up_constants/2, state_corresponds_to_set_up_constants_only/2,
33 current_b_expression/1,
34
35 get_operation_name/2, get_operation_internal_name/2,
36 translate_operation_name/2,
37 get_operation_arguments/2, get_operation_return_values_and_arguments/3,
38 build_up_b_real_operation/2,
39 expand_const_and_vars/3, expand_const_and_vars_to_full_store/2,
40 expand_to_constants_and_variables/3,
41
42 compute_operation_effect_max/6, % has replaced compute_operation_effect/5
43 create_setup_constants_operation/2,
44 get_internal_representation/1, get_internal_representation/2,
45 get_possible_event/1, get_possible_language_specific_top_level_event/3,
46 get_specification_description/2
47 ]).
48
49 :- use_module(tools).
50
51 :- use_module(module_information).
52 :- module_info(group,animator).
53 :- module_info(description,'This module computes transitions and properties depending on the current animator mode.').
54
55 :- use_module(library(lists)).
56 %:- use_module(library(avl)).
57 %:- use_module(library(clpfd)).
58
59 :- use_module(debug).
60 :- use_module(b_interpreter).
61 :- use_module(preferences).
62 :- use_module(self_check).
63 :- use_module(error_manager).
64 :- use_module(translate).
65 :- use_module(succeed_max,[succeed_max_call_id/3]).
66
67 :- use_module(store,[empty_state/1]).
68 :- use_module(bmachine).
69 :- use_module(bsyntaxtree).
70
71
72 %% :- use_module(delay).
73
74 :- use_module(value_persistance, [load_constants/2]).
75
76 /* --------------------------------- */
77
78
79
80
81 /* --------------------------------- */
82 /* ANIMATION & TEMPORAL VERIFICATION */
83 /* --------------------------------- */
84
85
86 :- dynamic animation_mode/1, animation_minor_mode/1.
87 % not marking as volatile; otherwise we startup with no animation_mode set
88 % not all parts of ProB can deal with this at the moment
89 %:- volatile animation_mode/1, animation_minor_mode/1.
90
91 animation_mode(b).
92 /* possible values: b, csp, xtl, z, csp_and_b, promela */
93
94 ?b_mode :- animation_mode(X), (X=b ; X=csp_and_b).
95 z_mode :- animation_mode(X), (X=b ; X=csp_and_b), animation_minor_mode(z).
96 eventb_mode :- animation_mode(X), (X=b ; X=csp_and_b), animation_minor_mode(eventb).
97 csp_with_bz_mode :- animation_mode(csp_and_b).
98 z_or_tla_minor_mode :- animation_minor_mode(X), (X=tla ; X=z).
99
100 csp_mode :- animation_mode(X), csp_mode(X).
101 csp_mode(cspm).
102 csp_mode(csp_and_b).
103
104 b_or_z_mode :-
105 (animation_mode(X) -> (X=b -> true ; X=csp_and_b)). % basically the same as b_mode
106 b_or_z_mode(b). b_or_z_mode(csp_and_b).
107
108 process_algebra_mode :-
109 (animation_mode(X) -> \+ X=b, \+X=z).
110
111 set_animation_mode(X) :-
112 retractall(animation_mode(_)),
113 remove_animation_minor_mode,
114 assert(animation_mode(X)).
115
116 set_animation_minor_mode(X) :-
117 remove_animation_minor_mode,
118 assert(animation_minor_mode(X)).
119 remove_animation_minor_mode :-
120 retractall(animation_minor_mode(_)).
121
122 % use to temporarily unset animation minor mode:
123 :- use_module(library(lists),[maplist/2]).
124 unset_animation_minor_modes(L) :- findall(X,retract(animation_minor_mode(X)),L).
125 reset_animation_minor_modes(L) :- maplist(add_animation_minor_mode,L).
126
127 add_animation_minor_mode(X) :-
128 (animation_minor_mode(X) -> true ; assert(animation_minor_mode(X))).
129
130
131 :- dynamic currently_opened_file_status/2.
132 :- volatile currently_opened_file_status/2.
133 %currently_opened_file(none).
134
135 reset_currently_opened_file :- retractall(currently_opened_file_status(_,_)).
136 :- use_module(eventhandling,[register_event_listener/3]).
137 :- register_event_listener(clear_specification,reset_currently_opened_file,
138 'Reset Specfile Currently Opened File.').
139
140 % call if a spec was not loaded from file but from package (e.g., via socket / prob2)
141 set_currently_opened_package(Type) :-
142 set_currently_opened_file(package(Type)).
143
144 set_currently_opened_file(File) :-
145 reset_currently_opened_file,
146 assert(currently_opened_file_status(File,success)).
147
148 set_failed_to_open_file(File) :-
149 reset_currently_opened_file,
150 assert(currently_opened_file_status(File,failure)).
151
152 currently_opened_file(File) :- currently_opened_file_status(File,success).
153
154 spec_file_has_been_successfully_loaded :- currently_opened_file(_).
155
156 :- use_module(bmachine,[b_machine_has_variables/0]).
157 % true if state corresponds to an initialised B machine
158 state_corresponds_to_initialised_b_machine(const_and_vars(_,_)) :- !,
159 b_or_z_mode.
160 state_corresponds_to_initialised_b_machine([]).
161 state_corresponds_to_initialised_b_machine([_|_]).
162 state_corresponds_to_initialised_b_machine(csp_and_b(_,BState)) :-
163 csp_with_bz_mode,
164 state_corresponds_to_initialised_b_machine(BState).
165
166
167 % check if state corresponds to an initialised B machine, and if so return expanded State
168 state_corresponds_to_initialised_b_machine(const_and_vars(ConstID,Vars),State) :- !,
169 b_or_z_mode, expand_const_and_vars(ConstID,Vars,State).
170 state_corresponds_to_initialised_b_machine(expanded_const_and_vars(_ConstID,_Vars,FullStore),State) :- !,
171 % generated by prepare_state_for_specfile_trans
172 State=FullStore.
173 state_corresponds_to_initialised_b_machine([],[]).
174 state_corresponds_to_initialised_b_machine([H|T],[H|T]).
175 state_corresponds_to_initialised_b_machine(csp_and_b(_,BState),State) :-
176 csp_with_bz_mode,
177 state_corresponds_to_initialised_b_machine(BState,State).
178
179 % check if all variables, constants setup; also allows concrete_constants if no variables exist
180 state_corresponds_to_fully_setup_b_machine(concrete_constants(_)) :- !, b_or_z_mode,
181 \+ b_machine_has_variables.
182 state_corresponds_to_fully_setup_b_machine(X) :- state_corresponds_to_initialised_b_machine(X).
183
184 state_corresponds_to_fully_setup_b_machine(concrete_constants(Constants),State) :- !, b_or_z_mode,
185 \+ b_machine_has_variables, State=Constants.
186 state_corresponds_to_fully_setup_b_machine(X,State) :- state_corresponds_to_initialised_b_machine(X,State).
187
188 % check if we only have constants, no variable values yet
189 state_corresponds_to_set_up_constants_only(root,State) :- !, animation_mode(b),
190 \+ b_machine_has_constants_or_properties, State=[]. % relevant for test 960
191 state_corresponds_to_set_up_constants_only(concrete_constants(Constants),State) :- !,
192 b_or_z_mode, State=Constants.
193 state_corresponds_to_set_up_constants_only(csp_and_b(_,BState),State) :- !,
194 csp_with_bz_mode,
195 state_corresponds_to_set_up_constants_only(BState,State).
196
197 state_corresponds_to_set_up_constants(const_and_vars(_,_)) :- !. % avoid expansion
198 state_corresponds_to_set_up_constants(X) :- state_corresponds_to_set_up_constants(X,_).
199
200 state_corresponds_to_set_up_constants(const_and_vars(ConstID,Vars),State) :- !,
201 b_or_z_mode, expand_const_and_vars(ConstID,Vars,State).
202 state_corresponds_to_set_up_constants(expanded_const_and_vars(_ConstID,_Vars,FullStore),State) :- !,
203 % generated by prepare_state_for_specfile_trans
204 State=FullStore.
205 state_corresponds_to_set_up_constants(concrete_constants(Constants),State) :- !,
206 b_or_z_mode, State=Constants.
207 state_corresponds_to_set_up_constants(csp_and_b(_,BState),State) :- !,
208 csp_with_bz_mode,
209 state_corresponds_to_set_up_constants(BState,State).
210 state_corresponds_to_set_up_constants([],State) :- !, State=[],
211 animation_mode(b).
212 state_corresponds_to_set_up_constants(State,RState) :-
213 animation_mode(b),
214 (State = root -> \+ b_machine_has_constants_or_properties,RState=[] ; RState=State).
215
216 :- use_module(state_space,[current_expression/2]).
217 current_b_expression(CurBState) :-
218 current_expression(_CurID,CurState),
219 state_corresponds_to_set_up_constants(CurState,CurBState).
220
221 /* TRANSITIONS */
222
223 :- use_module(xtl_interface).
224 :- use_module(tools_meta,[call_residue/2]).
225 % ---------------------------------------------------
226
227
228 % Tries to find successor state for Op in State DB. Fails, if no solution is possible
229 % Input: State DB, Operation Op
230 % Output: DB2 the sucessor state
231 % Residue: Unfinished co-routines (should not happen!)
232 %specfile_trans(DB,Op,DB2,[]) :- !, specfile:i_transition(DB,Op,DB2).
233 specfile_trans(DB,OpName,Op,DB2,TransInfo,Residue) :-
234 % i_transition(DB,OpName,Op,DB2,TransInfo), Residue = []. % is faster, but no residue checking
235 ? animation_mode(MODE),
236 ? call_residue(i_transition(MODE,DB,OpName,Op,DB2,TransInfo),Residue).
237
238 ?i_transition(b,State,OpName,Op,NewState,TransInfo) :- !,
239 ? b_trans(State,OpName,Op,NewState,TransInfo).
240 i_transition(xtl,State,OpName,Op,NewState,[]) :- !,
241 xtl_transition(State,Op,NewState), functor(Op,OpName,_).
242 i_transition(cspm,State,_OpName,Op,NewState,[]) :- !,
243 % Note: the OpName is ignored: we cannot make use of it
244 cspm_transition(State,Op,NewState).
245 %i_transition(promela,State,_OpName,Op,NewState,[]) :- !,
246 % promela_transition(State,Op,NewState).
247 % ; MODE=smv -> smv_transition(State,Op,NewState),TransInfo=[]
248 i_transition(csp_and_b,State,OpName,Op,NewState,TransInfo) :- !, %% print(cspB(OpName,Op,State)),nl, %trace,
249 % Note: the OpName is either the name of a B operation or '$CSP' (or a variable)
250 csp_and_b_transition(State,OpName,Op,NewState,TransInfo).
251
252
253 % if you call specfile_trans multiple times for the same state, it is
254 % more efficient to call this predicate first once
255 prepare_state_for_specfile_trans(const_and_vars(ConstID,Vars),R) :- !, %print(expanding_const(ConstID)),nl,
256 R = expanded_const_and_vars(ConstID,Vars,FullStore),
257 expand_const_and_vars(ConstID,Vars,FullStore). %, print(full(FullStore)),nl.
258 % TO DO: also expand for csp_and_b
259 prepare_state_for_specfile_trans(X,X).
260
261 % a version with a memo argument to store expanded constants
262 prepare_state_for_specfile_trans(const_and_vars(ConstID,Vars),MEMO,R) :- !, %print(expanding_const(ConstID)),nl,
263 R = expanded_const_and_vars(ConstID,Vars,FullStore),
264 (nonvar(MEMO),MEMO = [ConstID/ConstantsStore]
265 -> %tools_printing:print_term_summary(memo(ConstID,ConstantsStore)),nl,
266 append(ConstantsStore,Vars,FullStore) % simply reuse expanded constants in MEMO
267 ; % expand_const_and_vars inlined (so as to obtain ConstantsStore
268 state_space:visited_expression(ConstID,concrete_constants(ConstantsStore)), %% This can take a while if the Constants are big !
269 % print(no_memo(ConstID,MEMO)),tools_printing:print_term_summary(ConstantsStore),nl,
270 append(ConstantsStore,Vars,FullStore),
271 (var(MEMO) -> MEMO=[ConstID/ConstantsStore] ; true)
272 ). %, print(full(FullStore)),nl.
273 % TO DO: also expand for csp_and_b
274 prepare_state_for_specfile_trans(X,_,X).
275
276
277 /* can be attempted if trans fails to attempt to use partially computed transitions */
278 partial_trans(DB,Op,DB2,Residue) :-
279 call_residue(partial_i_transition(DB,Op,DB2),Residue).
280
281 partial_i_transition(root,'$partial_setup_constants',concrete_constants(ConstantsStore)) :-
282 animation_mode(b),
283 set_error_context(operation('$partial_setup_constants',root)),
284 b_interpreter:b_partial_set_up_concrete_constants(ConstantsStore).
285
286 % a predicate which automatically calls partial_trans :
287 specfile_trans_or_partial_trans(DB,OpName,Op,DB2,TransInfo,Residue) :-
288 if(specfile_trans(DB,OpName,Op,DB2,TransInfo,Residue),true,
289 (OpName='$setup_constants', TransInfo=[],
290 partial_trans(DB,Op,DB2,Residue))).
291
292 /* build up skeletons of possible operations; to be used before time_out call is made */
293 specfile_possible_trans_name(State,OpName) :- animation_mode(MODE),
294 (MODE=b -> b_possible_trans_name(State,OpName)
295 ; MODE = csp_and_b -> csp_b_possible_trans_name(State,OpName)
296 ; setup_transition_skeleton(MODE,OpName) /* TO DO: add more possible skeletons */
297 ).
298
299 % only set up skeletons if it is worth it for computing all successors
300 % e.g., currently it is not worth it to setup skeletons for either CSP or CSP||B (due to renaming,... we cannot predict which parts of a CSP process can be excluded)
301 ?specfile_possible_trans_name_for_successors(State,OpName) :- animation_mode(MODE),
302 ? (MODE=b -> b_possible_trans_name(State,OpName)
303 ; setup_transition_skeleton(MODE,OpName)
304 ).
305
306 setup_transition_skeleton(_,_). /* TO DO: add more possible skeletons ? */
307
308 :- use_module(library(random)).
309 b_possible_trans_name(root,OpName) :- !,
310 (b_machine_has_constants_or_properties
311 -> OpName = '$setup_constants'
312 ; OpName = '$initialise_machine').
313 b_possible_trans_name(concrete_constants(_),OpName) :- !, OpName = '$initialise_machine'.
314 b_possible_trans_name(_State,OpName) :-
315 ? (preferences:preference(randomise_operation_order,true),random(1,3,1)
316 -> b_machine_operation_names_in_reverse_order(OpName) ; true),
317 %b_get_machine_operation(OpName,_Res,_Params,_,_,_).
318 ? b_top_level_operation(OpName).
319 % we could check: b_operation_cannot_modify_state(OpName) given a preference
320
321 csp_b_possible_trans_name(csp_and_b_root,OpName) :- !,
322 (b_machine_has_constants_or_properties
323 -> OpName = 'tau($setup_constants)'
324 ; OpName = 'tau($initialise_machine)').
325 csp_b_possible_trans_name(concrete_constants(_),OpName) :- !,
326 OpName = 'tau($initialise_machine)'.
327 csp_b_possible_trans_name(State,OpName) :-
328 b_possible_trans_name(State,OpName).
329 % TO DO: add non-synchronised channels
330
331 % --------------
332
333 :- use_module(probcspsrc(haskell_csp),[channel_type_list/2]).
334 :- use_module(debug).
335 % check whether a currently open CSP is type compatible with a loaded B machine
336 type_check_csp_and_b :- animation_mode(csp_and_b), debug_println(9,type_check_csp_and_b),
337 b_get_machine_operation(ChannelOpName,Res,Params,_,_,_), append(Params,Res,ParamsRes),
338 channel_type_list(ChannelOpName,CSPTypeList),
339 % TO DO: also check B variable names which match channel name
340 debug_println(9,checking_synchronised_channel(ChannelOpName,ParamsRes,CSPTypeList)),
341 l_check_compatibility(ParamsRes,CSPTypeList,ChannelOpName),
342 fail.
343 type_check_csp_and_b.
344
345 %convert_csp_type_to_list(type(T),R) :- convert_csp_type_to_list2(T,R).
346 %convert_csp_type_to_list2(dotUnitType,[]).
347 %convert_csp_type_to_list2(dotTupleType(T),T).
348
349 l_check_compatibility([],[],_) :- !.
350 l_check_compatibility([B|BT],[CSP|CSPT],ChannelOpName) :- !, check_compatibility(B,CSP,ChannelOpName),
351 l_check_compatibility(BT,CSPT,ChannelOpName).
352 l_check_compatibility([],CSP,ChannelOpName) :- !,
353 add_error(type_check_csp_and_b,'CSP Channel has too many parameters: ', ChannelOpName:CSP).
354 l_check_compatibility(B,[],ChannelOpName) :- !,
355 print('* CSP Channel has too few parameters: '), print(ChannelOpName),nl,
356 print('* B Arguments will be ignored: '), l_print_bexpr_or_subst(B),nl.
357 %add_error(type_check_csp_and_b,'CSP Channel has too few parameters: ', ChannelOpName:B).
358
359 check_compatibility(b(identifier(ID),TYPE,INFO),CSP_TYPE,ChannelOpName) :- !,
360 (type_ok(TYPE,CSP_TYPE) -> true ;
361 % TO DO: pretty print B and CSP Types
362 add_error(type_check_csp_and_b,'Incompatible types between B and CSP: ',ChannelOpName:ID:(TYPE:CSP_TYPE),b(identifier(ID),TYPE,INFO))
363 ).
364 check_compatibility(B,CSP,ChannelOpName) :- !,
365 add_internal_error('Illegal types: ',check_compatibility(B,CSP,ChannelOpName)).
366
367 % TO DO: needs to be refined much more;
368 type_ok(Type,CSPType) :-
369 (type_ok2(Type,CSPType) -> true
370 ; add_error(type_check_csp_and_b,'Cannot be converted (B:CSP): ',Type:CSPType),fail).
371 type_ok2(boolean,X) :- !, is_csp_boolean_type(X).
372 type_ok2(integer,X) :- !, is_csp_integer_type(X).
373 type_ok2(string,CSP) :- !,is_csp_global_set_type(CSP,string).
374 type_ok2(set(T),CSP) :- !, is_csp_set_type(CSP,T).
375 % TO DO: what if we have set(couple(integer,T)) instead of seq(T) ?
376 % rye
377 % check set(couple(integer,T)) (seq type) in B
378 type_ok2(seq(T),CSP) :- !, is_csp_seq_type(CSP,T).
379 type_ok2(couple(A,B),CSP) :- !, is_csp_couple_type(CSP,A,B).
380 type_ok2(global(GS),CSP) :- !,is_csp_global_set_type(CSP,GS).
381 type_ok2(X,Y) :- print(unkown(X,Y)),nl.
382
383 is_csp_couple_type(setValue([na_tuple([A|Rest])|_]),TA,TB) :- type_ok(TA,setValue([A])),
384 check_rest_couple_els(Rest,TB).
385 is_csp_couple_type(typeTuple([A|Rest]),TA,TB) :- type_ok(TA,A), check_rest_couple(Rest,TB).
386
387 check_rest_couple_els([B],TB) :- !, type_ok(TB,setValue([B])).
388 check_rest_couple_els([B1|BRest],couple(TB1,TBRest)) :- type_ok(TB1,setValue([B1])),
389 check_rest_couple_els(BRest,TBRest).
390 check_rest_couple([B],TB) :- !, type_ok(TB,B).
391 check_rest_couple([B1|BRest],couple(TB1,TBRest)) :- type_ok(TB1,B1),
392 check_rest_couple(BRest,TBRest).
393
394 % rye
395 % check if it is couple(integer, T) type and return T in 2nd arguments
396 couple_int(couple(integer, T), T). % possible sequence
397
398 % rye: it's not correct to check only Head
399 % % for example, for CSP type, {{}, {(1,2),(2,3)}}. Its head is emptyset, but the second one is set of tuple
400 is_csp_set_type('Set'([H|_]),Type) :- type_ok(Type,H). % just check Head
401 % check the 2nd element in set in case the 1st is emptyset
402 is_csp_set_type(setValue([_|T]),Type) :-
403 T = [H1 | _], !,
404 % if it is set(couple(integer, T)), it can be a sequence type
405 (couple_int(Type, TH1) -> is_csp_seq_type(setValue(T), TH1)
406 ; type_ok(Type,H1)
407 ). % check the 2nd
408 % if it is only one element in set, just check the head
409 is_csp_set_type(setValue([H|T]),Type) :-
410 (couple_int(Type, TH1) -> is_csp_seq_type(setValue([H|T]), TH1)
411 ; type_ok(Type,H)
412 ). % just check Head
413
414 is_csp_seq_type('Seq'(H),Type) :- type_ok(Type,H).
415 is_csp_seq_type(setValue([H|_]),Type) :- H=list(L), is_csp_list(L,Type).
416 is_csp_list([],_).
417 is_csp_list([H|_],Type) :- type_ok(Type,setValue([H])).
418
419 is_csp_boolean_type(boolType).
420 is_csp_boolean_type(setValue([H|_])) :- is_csp_boolean_value(H).
421 is_csp_boolean_value(true).
422 is_csp_boolean_value(false).
423
424 is_csp_integer_type(intType).
425 is_csp_integer_type(setFromTo(_,_)).
426 is_csp_integer_type(setFrom(_)).
427 is_csp_integer_type(setValue([int(_)|_])).
428
429 is_csp_global_set_type(dataType(_),_GS). % TO DO CHECK MEMBERS
430 is_csp_global_set_type(setValue([]),_GS). % TO DO CHECK MEMBERS
431 is_csp_global_set_type(setValue([_|_]),_GS). % TO DO CHECK MEMBERS
432
433 % --------------
434
435
436 :- use_module(bmachine,[b_get_machine_operation/4]).
437 :- use_module(bsets_clp,[tuple_of/3]).
438 % compute transitions for a CSP || B specification
439 % Note: the OpName is either the name of a B machine operation (even if hidden) or '$CSP' (useful for ltsmin)
440 csp_and_b_transition(root,OpName,Op,NewState,TransInfo) :- !,
441 Op = start_cspm_MAIN, OpName=Op, NewState = csp_and_b_root,TransInfo = [].
442 csp_and_b_transition(csp_and_b_root,OpName,Trans,NewState,TransInfo) :- !,
443 Trans = tau(Op), OpName = '$CSP',
444 b_trans(root,_,Op,InitialBState,TransInfo),
445 (InitialBState = concrete_constants(_)
446 -> NewState = InitialBState
447 ; csp_initialisation_for_b(InitialCSPState),
448 NewState = csp_and_b(InitialCSPState,InitialBState)
449 ).
450 csp_and_b_transition(concrete_constants(C),OpName,Trans,NewState,TransInfo) :- !,
451 Trans = tau(Op), OpName = '$CSP',
452 b_trans(concrete_constants(C),_,Op,InitialBState,TransInfo),
453 csp_initialisation_for_b(InitialCSPState),
454 NewState = csp_and_b(InitialCSPState,InitialBState).
455 csp_and_b_transition(csp_and_b(CSPState,BState),OpName,EventVisibleToUser,csp_and_b(NewCSP,NewB),TransInfo) :-
456 !,
457 csp_transition_for_b(CSPState,ChOpName,ChArgs,CSPAction,NewCSP),
458 % TO DO: split up csp_transition_for_b: into two parts; second part converts datatypes and only called if linking op exists
459 %% print(csp_trans(ChOpName,ChArgs)),nl, %%
460 length(ChArgs,Len), length(OpArgs,Len),
461 b_transition_for_csp(ChOpName,CSPAction,ChArgs,OpArgs,BState,OpName,Operation,NewB,TransInfo),
462 hide_csp_event(CSPAction,Operation,EventVisibleToUser).
463 csp_and_b_transition(State,'$CSP',Op,NewState,[]) :-
464 % we have a pure CSP state: use CSP-M transition
465 cspm_transition(State,Op,NewState).
466
467 :- use_module(bmachine,[b_is_variable/1,b_is_constant/1]).
468 % compute the B counterpart for a CSP transition:
469 b_transition_for_csp(ChOpName,_CSPAction,ChArgs,OpArgs,BState,OpName,Operation,NewB,TransInfo) :-
470 build_up_b_operation_for_csp(ChOpName,OpArgs,Operation),
471 !,
472 OpName = ChOpName,
473 %% print_message(trying_b_trans(Operation,ChArgs,OpArgs)), %%
474 generate_b_operationargs_from_csp(ChArgs,OpArgs),
475 %% print(trying_b_trans(Operation)),nl, %%
476 b_trans(BState,_,Operation,NewB,TransInfo).
477 %%, print_message(csp_btrans(Operation)), %%.
478 b_transition_for_csp(ChOpName,_CSPAction,ChArgs,OpArgs,BState,OpName,Operation,NewB,TransInfo) :-
479 OpName = ChOpName,
480 (b_is_variable(ChOpName) ; b_is_constant(ChOpName)),
481 %% print(probing(ChOpName)),nl,
482 expand_const_and_vars_to_full_store(BState,FBState),
483 try_lookup_value_in_store_and_global_sets(ChOpName,FBState,IdValue),
484 !,
485 NewB=BState,TransInfo=[],
486 /* interpret as probing operation: get value of var,cst,SET */
487 generate_b_operationargs_from_csp(ChArgs,OpArgs),
488 (OpArgs=[SingleVal]
489 -> SingleVal = IdValue, Operation='-->'(ChOpName,[IdValue])
490 ; OpArgs=[Val1,Val2],
491 tuple_of(Val1,Val2,IdValue), /* from bsets_clp, use exact_element_of ??? */
492 OpCall =.. [ChOpName,Val1],
493 Operation='-->'(OpCall,[Val2])
494 ).
495 b_transition_for_csp(_ChOpName,CSPAction,_ChArgs,_OpArgs,BState,OpName,Operation,NewB,TransInfo) :-
496 OpName = '$CSP', % all CSP events grouped together
497 NewB=BState,TransInfo=[],
498 /* no B operation of the name; could be tau or tick or extra comm channel */
499 %Op1 =.. [ChOpName|OpArgs],
500 Operation = CSPAction. % removed csp(.) wrapper [for LTL model checker]
501
502 hide_csp_event(CSPAction,_,EventVisibleToUser) :-
503 haskell_csp:symbol('HIDE_CSPB',_,Span,_),!, % if there is a HIDE_CSPB definition then we do MAIN [{| HIDE_CSPB |}] B_MACHINE \ {| HIDE_CSPB |}
504 haskell_csp:evaluate_argument(val_of('HIDE_CSPB',Span),EvCList),
505 % print(hide(EvCList,CSPAction)),nl,
506 ~~mnf(haskell_csp:expand_channel_pattern_expression(EvCList,ECList,no_loc_info_available)),
507 haskell_csp:cspm_hide_action(CSPAction,omega,ECList, Span, EventVisibleToUser,_).
508 hide_csp_event(_CSPAction,Operation,EventVisibleToUser) :-
509 % get_preference(csp_event_visible_to_user,true) -> EventVisibleToUser = CSPAction
510 EventVisibleToUser = Operation.
511
512 build_up_b_operation_for_csp(OpName,OpArgs,Operation) :- %print(csp(OpName,OpArgs,Operation)),nl,
513 nonvar(OpName),
514 b_get_machine_operation(OpName,Res,Params,_), %print(get_machine_op(OpName,Res,Params)),nl,
515 specfile:generate_args(OpArgs,Params,Res, BArgs,BResults,OpName), %print(gen_args(BArgs,BResults)),nl,
516 % TO DO: either also extract types from Params, Res or better write a static checker that tests that the B operation and CSP channel types are compatible
517 safe_univ(Op1,[OpName|BArgs]), %print(op1(Op1)),nl,
518 (BResults = [] -> Operation = Op1 ; Operation =.. ['-->',Op1,BResults]).
519
520 build_up_b_real_operation(OpName,Operation) :-
521 b_get_machine_operation_for_animation(OpName,Res,Params,_,_,true), %true==TopLevel
522 length(Params,Len), length(OpArgs,Len),
523 length(Res,RLen), length(BResults,RLen),
524 safe_univ(Op1,[OpName|OpArgs]),
525 (BResults = [] -> Operation = Op1 ; Operation =.. ['-->',Op1,BResults]).
526
527 generate_args([],[],Res,[],BRes,_) :- length(Res,L), length(BRes,L).
528 generate_args([],[_Param|T],Res,[_|TA],BRes,OpName) :-
529 generate_args([],T,Res,TA,BRes,OpName).
530 generate_args([CSPArg|TC],[Param|T],Res,[CSPArg|TA],BRes,OpName) :- check_type_for_id(CSPArg,Param,OpName),
531 generate_args(TC,T,Res,TA,BRes,OpName).
532 generate_args([CSPArg|TC],[],[ReturnParam|TRes],[],[CSPArg|TBRes],OpName) :-
533 check_type_for_id(CSPArg,ReturnParam,OpName),
534 generate_args(TC,[],TRes,[],TBRes,OpName).
535 generate_args([H|T],[],[],[],[],OpName) :-
536 add_error(specfile,'CSP provides extra arguments: ',OpName:[H|T]).
537
538 check_type_for_id(Val,TID,OpName) :- get_texpr_type(TID,Type),
539 check_type(Type,Val,OpName:TID).
540
541 :- block check_type(?,-,?).
542 check_type(boolean,pred_true,_) :- !.
543 check_type(boolean,pred_false,_) :- !.
544 check_type(integer,int(_),_) :- !.
545 check_type(string,string(_),_) :- !.
546 check_type(global(GS),fd(_,GS),_) :- !.
547 check_type(couple(A,B),(VA,VB),OID) :- !, check_type(A,VA,OID), check_type(B,VB,OID).
548 check_type(set(_T),[],_) :- !.
549 check_type(set(_T),closure(_,_,_),_) :- !. % TO DO: check type signature of closure
550 check_type(set(T),[H|_],OID) :- !, check_type(T,H,OID).
551 check_type(set(T),avl_set((node(Y,_,_,_L,_R))),OID) :- !, check_type(T,Y,OID).
552 check_type(seq(T),V,OID) :- !, check_type(set(couple(integer,T)),V,OID).
553 % TO DO: record, freetype ; but do not appear in translation from CSP to B yet
554 check_type(Type,Value,OpName:TID) :-
555 def_get_texpr_id(TID,ID),
556 add_error(check_type_for_id,'Illegal CSP value for argument: ',OpName:ID:type(Type):value(Value)),
557 fail.
558
559 get_operation_internal_name(Op,Name) :- var(Op),!,
560 add_error(get_operation_internal_name,'Variable Transition: ',Op), Name=Op.
561 get_operation_internal_name('$initialise_machine',N) :- !, N='$initialise_machine'.
562 get_operation_internal_name('$setup_constants',N) :- !, N='$setup_constants'.
563 get_operation_internal_name('$partial_setup_constants',N) :- !, N='$partial_setup_constants'.
564 get_operation_internal_name(Op,Name) :- get_operation_name(Op,Name).
565
566 % tool to get the basic operation/channel/event name of a transition:
567 get_operation_name(Op,Name) :- var(Op),!, add_error(get_operation_name,'Variable Transition: ',Op), Name=Op.
568 get_operation_name('-->'(F,_),N) :- !, functor(F,N,_).
569 %get_operation_name(io([Action|_],proc(_Nr,_PROC),_SPAN),F) :-
570 % animation_mode(promela),!,functor(Action,F,_).
571 get_operation_name(io(_V,Ch,_SPAN),N) :- csp_mode,!, functor(Ch,N,_).
572 get_operation_name(FullOperation,Name) :- functor(FullOperation,Functor,_),
573 translate_operation_name(Functor,Name).
574
575 get_operation_arguments(Op,Args) :- var(Op),!, add_error(get_operation_arguments,'Variable Transition: ',Op), Args=[].
576 get_operation_arguments('-->'(F,_ReturnValues),Args) :- !, F =.. [_|Args].
577 %get_operation_arguments(io([_Action|V],proc(_Nr,_PROC),_SPAN),Args) :-
578 % animation_mode(promela),!,Args=V.
579 get_operation_arguments(io(V,_Ch,_SPAN),Args) :- csp_mode,!, Args = V.
580 get_operation_arguments(FullOperation,Args) :- FullOperation =.. [_|Args].
581
582 get_operation_return_values_and_arguments('-->'(F,ReturnValues),ReturnValues,Args) :- !,
583 F =.. [_|Args].
584 get_operation_return_values_and_arguments(Op,[],Args) :- get_operation_arguments(Op,Args).
585
586 translate_operation_name('$initialise_machine',T) :- !,T='INITIALISATION'.
587 translate_operation_name('$setup_constants',T) :- !,T='SETUP_CONSTANTS'.
588 translate_operation_name('$partial_setup_constants',T) :- !,T='PARTIAL_SETUP_CONSTANTS'.
589 %translate_operation_name(InternalName,Res) :- !, Res=InternalName.
590 translate_operation_name(X,X).
591
592
593
594
595
596 :- use_module(state_space,[visited_expression/2]).
597 :- use_module(library(between),[between/3]).
598
599 b_trans(State,OpName,Operation,NewState,PathInfo) :-
600 ? compute_operation_effect_max(State,OpName,Operation,NewState,PathInfo,_Max).
601
602 compute_operation_effect_max([],OpName,Operation,NewState,PathInfo,Max) :-
603 compute_operation_on_expanded_store([],OpName,Operation,Updates,PathInfo,Max),
604 store:store_updates_and_normalise(Updates,[],NewState).
605 compute_operation_effect_max([H|T],OpName,Operation,NewState,PathInfo,Max) :-
606 compute_operation_on_expanded_store([H|T],OpName,Operation,Updates,PathInfo,Max),
607 store:store_updates_and_normalise(Updates,[H|T],NewState).
608 compute_operation_effect_max(const_and_vars(ConstID,Vars),OpName,Operation,ResultingStore,PathInfo,Max) :-
609 prepare_state_for_specfile_trans(const_and_vars(ConstID,Vars),R),
610 %print(expanded_const_and_vars(ConstID)),nl,
611 compute_operation_effect_max(R,OpName,Operation,ResultingStore,PathInfo,Max).
612 compute_operation_effect_max(concrete_constants(ConstantsStore),'$initialise_machine',OpInit,ResultingStore,PathInfo,Max) :-
613 ? get_max_enablings_for_init(Max,'$initialise_machine',MaxForCall),
614 ? succeed_max_call_id('$initialise_machine',
615 b_interpreter:b_initialise_machine(ConstantsStore,InitialVars,InitialStore,PathInfo),MaxForCall),
616 create_initialisation_operation(InitialVars,OpInit),
617 %user:do_one_gui_event,
618 ? (\+ preferences:preference(symmetry_mode,flood), /* TO DO : improve permutation to allow using const_and_vars optimisation */
619 ? visited_expression(ConstID,concrete_constants(ConstantsStore))
620 -> ResultingStore = const_and_vars(ConstID,InitialVars) /* avoid storing constant values again */
621 ; ResultingStore = InitialStore).
622 compute_operation_effect_max(expanded_const_and_vars(ConstID,Vars,FullStore),OpName,Operation,ResultingStore,PathInfo,Max) :-
623 %print(const_and_vars(ConstID,Vars)),nl,
624 ? compute_operation_on_expanded_store(FullStore,OpName,Operation,Updates,PathInfo,Max),
625 ResultingStore = const_and_vars(ConstID,NewVars),
626 store:store_updates_and_normalise(Updates,Vars,NewVars).
627 %store:store_updates(Updates,Vars,NewVars). % we could use this when operation re-used / cached
628 %ErrorMsg = compute_operation_effect(const_and_vars(ConstID,Vars),Operation,ResultingStore,PathInfo),
629 %reconstruct_constants_store(ConstID,ConstantsStore,NewState,ErrorMsg,ResultingStore).
630 compute_operation_effect_max(root,'$setup_constants',OpSetup,concrete_constants(FilteredConstantsStore),[],Max) :-
631 ? b_machine_has_constants_or_properties,
632 ? get_max_enablings_for_init(Max,'$setup_constants',MaxForCall),
633 ? compute_constants(ConstantsStore,MaxForCall),
634 create_setup_constants_operation(ConstantsStore,OpSetup),
635 %%print_message('FOUND_CONSTANTS'(OpName)),
636 (get_preference(filter_unused_constants,true)
637 -> exclude(unused_binding,ConstantsStore,FilteredConstantsStore)
638 ; FilteredConstantsStore=ConstantsStore).
639 %user:do_one_gui_event.
640 compute_operation_effect_max(root,'$initialise_machine',OpInit,InitialStore,PathInfo,Max) :-
641 \+ b_machine_has_constants_or_properties,
642 get_max_enablings_for_init(Max,'$initialise_machine',MaxForCall),
643 %user:do_one_gui_event, user:do_one_gui_event, user:do_one_gui_event,
644 empty_state(EmptyState),
645 succeed_max_call_id('$initialise_machine',
646 b_interpreter:b_initialise_machine(EmptyState,InitialVars,InitialStore,PathInfo),MaxForCall),
647 create_initialisation_operation(InitialVars,OpInit).
648 %user:do_one_gui_event.
649
650 unused_binding(bind(C,_)) :- bmachine:b_is_unused_constant(C).
651
652 compute_constants(ConstantsStore,_Max) :-
653 % check if values have been computed and stored into a file before -- if yes, use them
654 load_constants(Stores,MaxReached),!,
655 choose_loaded_solution(Stores,ConstantsStore,MaxReached).
656 compute_constants(ConstantsStore,Max) :-
657 % print('Searching for valid CONSTANTS'),nl,!,
658 ? succeed_max_call_id('$setup_constants',b_interpreter:b_set_up_concrete_constants(ConstantsStore),Max).
659
660 choose_loaded_solution(Stores,ConstantsStore,_MaxReached) :-
661 member(ConstantsStore,Stores).
662 choose_loaded_solution(_Stores,_ConstantsStore,true) :-
663 % provoke the setting of the "maximum reached flag"
664 succeed_max_call_id('$setup_constants',member(_,_),1),fail.
665
666 expand_const_and_vars_to_full_store(root,R) :- !,R=[].
667 expand_const_and_vars_to_full_store(concrete_constants(ConstantsStore),FullStore) :- !,
668 ConstantsStore = FullStore.
669 expand_const_and_vars_to_full_store(const_and_vars(ConstID,Vars),FullStore) :- !,
670 expand_const_and_vars(ConstID,Vars,FullStore).
671 expand_const_and_vars_to_full_store(expanded_const_and_vars(_ConstID,_Vars,ExpStore),FullStore) :- !,
672 FullStore = ExpStore.
673 expand_const_and_vars_to_full_store(R,R).
674
675 expand_const_and_vars(ConstID,Vars,FullStore) :-
676 state_space:visited_expression(ConstID,concrete_constants(ConstantsStore)), %% This can take a while if the Constants are big !
677 % print('exp: '),tools_printing:print_term_summary(ConstantsStore),nl,
678 append(ConstantsStore,Vars,FullStore).
679
680 expand_to_constants_and_variables(root,[],[]).
681 expand_to_constants_and_variables(concrete_constants(ConstStore),ConstStore,[]).
682 expand_to_constants_and_variables(const_and_vars(ConstID,VarStore),ConstStore,VarStore) :-
683 state_space:visited_expression(ConstID,concrete_constants(ConstStore)).
684 expand_to_constants_and_variables([],[],[]).
685 expand_to_constants_and_variables([H|T],[],[H|T]).
686
687 :- use_module(b_operation_cache,[compute_operation_on_expanded_store_cache/5]).
688
689 % compute operation effect on a store where all constants have been put into the environment
690 compute_operation_on_expanded_store(InState,OpName,Operation,NewState,PathInfo,Max) :-
691 get_preference(try_operation_reuse,full),
692 animation_mode(b), % doesn't seem to work with CSP||B yet; see CSPB/LTSMin/Counters.mch + .csp
693 \+ animation_minor_mode(eventb), % projection seems to confuse Event-B interpreter, see e.g. prob_examples/public_examples/EventBPrologPackages/ABZ_Landing_Gear/Ref3_ControllerSensors_mch.eventb
694 % TO DO: fix
695 !,
696 get_max_enablings_per_operation(Max,OpName,MaxForCall),
697 succeed_max_call_id(OpName,
698 compute_operation_on_expanded_store_cache(OpName,Operation,InState,NewState,PathInfo),
699 MaxForCall).
700 compute_operation_on_expanded_store(InState,OpName,Operation,NewState,PathInfo,Max) :-
701 ? get_max_enablings_per_operation(Max,OpName,MaxForCall),
702 ? succeed_max_call_id(OpName,
703 b_interpreter:b_execute_top_level_operation_update(OpName,Operation,InState,NewState,PathInfo),
704 MaxForCall).
705
706
707 create_initialisation_operation(_InitialVars,'$initialise_machine').
708
709 create_setup_constants_operation(_ConstantVars,'$setup_constants').
710
711 :- use_module(bmachine,[b_get_machine_operation_max/2]). % MAX_OPERATIONS_... DEFINITIONS
712 get_max_enablings_per_operation_aux(OpName,RMax,RandomisedRestart) :-
713 b_get_machine_operation_max(OpName,Max),
714 !,
715 (Max<0 -> RMax is -Max, RandomisedRestart=true ; RMax=Max, RandomisedRestart=false).
716 get_max_enablings_per_operation_aux(_OpName,Max,false) :-
717 preferences:preference(maxNrOfEnablingsPerOperation,Max).
718
719
720 get_max_enablings_per_operation(Max,OpName,MaxForCall) :-
721 (var(Max) -> get_max_enablings_per_operation_aux(OpName,Max,RandomisedRestart) ; RandomisedRestart=false),
722 (RandomisedRestart=true,
723 get_preference(randomise_enumeration_order,true)
724 -> % we succeed Max times with the value 1, thus forcing a randomised restart
725 MaxForCall=1, between(1,Max,Retry), format('Randomised Restart ~w for ~w~n',[Retry,OpName])
726 ; % we succeed once with the value Max
727 MaxForCall is Max).
728
729 get_max_enablings_for_init(Max,Op,MaxForCall) :-
730 (var(Max) -> get_preference(maxNrOfInitialisations,Max) ; true),
731 (Max>1,
732 get_preference(randomisedRestartInitalisations,true),
733 get_preference(randomise_enumeration_order,true)
734 -> % we succeed Max times with the value 1, thus forcing a randomised restart
735 MaxForCall=1, between(1,Max,Retry), format('Randomised Restart ~w for ~w~n',[Retry,Op])
736 ; % we succeed once with the value Max
737 MaxForCall=Max).
738
739 /* PROPERTIES */
740
741 property(const_and_vars(ConstID,Vars),Property) :- b_or_z_mode,
742 expand_const_and_vars(ConstID,Vars,FullStore),!,
743 property(FullStore,Property).
744 property(csp_and_b(CSPState,BState),Property) :- animation_mode(csp_and_b),!,
745 %% print(checking_csp_and_b(CSPState)),nl,
746 expand_const_and_vars_to_full_store(BState,FBState),
747 (xtl_interface:cspm_property(CSPState,Property) ;
748 b_property(FBState,Property)).
749 property(State,Property) :- animation_mode(AM),
750 (AM = b -> b_property(State,Property)
751 ; AM=xtl -> xtl_interface:xtl_property(State,Property)
752 ; AM=cspm -> xtl_interface:cspm_property(State,Property)
753 ; AM=csp_and_b -> b_property(State,Property) % State should be root
754 ).
755
756 %b_property(const_and_vars(ConstID,Vars),Prop) :- !,
757 % expand_const_and_vars(ConstID,Vars,FullStore),
758 % b_property(FullStore,Prop).
759 b_property(root,Prop) :- !, b_preference_par(PARA,Op,VAL), Prop=.. [Op,PARA,VAL].
760 b_property([H|T],non_ground(Var)) :- debug:debug_mode(on),
761 member(bind(Var,Val),[H|T]),\+(ground(Val)).
762 b_property([H|T],Prop) :- elementary_prop([H|T],Prop).
763 b_property([],Prop) :- elementary_prop([],Prop).
764 b_property(concrete_constants(DB),Prop) :- elementary_prop(DB,Prop).
765
766
767
768 :- use_module(preferences).
769 :- use_module(b_global_sets,[b_global_set/1, b_get_fd_type_bounds/3,inferred_minimum_global_set_cardinality/2,
770 inferred_maximum_global_set_cardinality/2, unfixed_deferred_set/1]).
771
772 b_preference_par('MAXINT','=',MaxInt) :- get_preference(maxint,MaxInt).
773 b_preference_par('MININT','=',MinInt) :- get_preference(minint,MinInt).
774 b_preference_par(card(GlobalSet),Op,Card) :-
775 b_global_set(GlobalSet),
776 b_get_fd_type_bounds(GlobalSet,Low,Up), RCard is Up-Low+1,
777 % provide feedback if unfixed_deferred_set
778 (inferred_maximum_global_set_cardinality(GlobalSet,MaxCard),
779 (inferred_minimum_global_set_cardinality(GlobalSet,MinCard) -> true ; MinCard=1),
780 MinCard \= MaxCard,
781 Op = ':', Card = '..'(MinCard,MaxCard)
782
783 ;
784
785 inferred_minimum_global_set_cardinality(GlobalSet,MinCard),
786 \+ (inferred_maximum_global_set_cardinality(GlobalSet,_)),
787 Op='>=',Card=MinCard % show minimum cardinality info
788
789 ;
790
791 Op= '=', (unfixed_deferred_set(GlobalSet)
792 -> ajoin([RCard,' (assumed for deferred set)'],Card) ; Card=RCard)
793 ).
794
795 /* --------------------------------------------------------- */
796
797
798 elementary_prop(DB,Prop) :-
799 member(bind(Var,Val),DB), %print(var_prop(Var)),nl_time,
800 elementary_prop3(Val,Var,Prop).
801
802 :- use_module(custom_explicit_sets,[is_avl_relation/1,is_avl_partial_function/1,get_first_avl_elements/4, avl_approximate_size/3]).
803 elementary_prop3(Val,Var,Prop) :- var(Val),!, Prop = '='(Var,'_VAR_').
804 elementary_prop3(avl_set(Avl),Var,Prop) :- !,
805 (show_avl_set(Avl) % \+ custom_explicit_sets:is_avl_sequence(Avl))
806 -> elementary_fun_prop(avl_set(Avl),Var,Prop)
807 ; elementary_var_prop(avl_set(Avl),Var,Prop)).
808 elementary_prop3([H|T],Var,Prop) :- H=(_,_),
809 get_preference(show_function_tuples_in_property,true),!,
810 elementary_fun_prop([H|T],Var,Prop).
811 elementary_prop3(Val,Var,Prop) :- elementary_var_prop(Val,Var,Prop).
812
813 show_avl_set(AVL) :- get_preference(show_function_tuples_in_property,true),
814 is_avl_relation(AVL),
815 avl_approximate_size(AVL,0,Size), Size < 257, % only the first 30 will be shown by get_relation_element anyway
816 is_avl_partial_function(AVL).
817
818
819 :- use_module(bmachine,[b_is_variable/2]).
820 elementary_var_prop(Val,Var,Prop) :-
821 % TODO: use translate:translate_bvalue_for_expression/3
822 animation_minor_mode(tla),!,
823 ( identifier_has_tla_type(Var,TlaType) ->
824 translate_bvalue_with_tlatype(Val,TlaType,Text)
825 ; otherwise ->
826 translate_bvalue(Val,Text)),
827 Prop = '='(Var,Text).
828 elementary_var_prop(Val,Var,Prop) :-
829 (b_is_variable(Var,Type) % what about constants
830 -> translate_bvalue_with_type_and_limit(Val,Type,320,Text)
831 ; translate_bvalue_with_type_and_limit(Val,any,320,Text)), % translate_properties_with_limit uses 320 Limit
832 Prop = '='(Var,Text).
833
834 identifier_has_tla_type(Id,Type) :-
835 get_texpr_id(TId,Id),
836 (b_get_machine_constants(Ids)
837 ;b_get_machine_variables(Ids)),
838 member(TId,Ids),!,
839 get_texpr_info(TId,Infos),
840 memberchk(tla_type(Type),Infos).
841 % to do: use b_is_variable + translate_bvalue_with_type
842 elementary_fun_prop(Val,Var,Prop) :-
843 nonvar(Val),
844 get_relation_element(Val,X,Y), % Show value in form: Var(X) = Y
845 create_texpr(identifier(Var),any,[],Fun),
846 create_texpr(value(X),any,[],Arg),
847 create_texpr(function(Fun,Arg),any,[],Lhs),
848 create_texpr(value(Y),any,[],Rhs),
849 create_texpr(equal(Lhs,Rhs),pred,[],Expr),
850 translate_bexpression_with_limit(Expr,80,Prop).
851
852 get_relation_element(avl_set(A),X,Y) :- custom_explicit_sets:is_avl_relation(A),
853 !, %preferences:preference(expand_avl_upto,Limit),
854 Limit=30, % reduced limit, as now we can inspect with evaluation view
855 get_first_avl_elements(A,Limit,Els,CutOff),
856 (member((X,Y),Els), X\=term(_)
857 ;
858 CutOff=not_all, X='...', Y='...').
859 get_relation_element(Value,X,Y) :-
860 member((X,Y),Value). /* otherwise we have a record structure */
861
862
863 :- use_module(bmachine,[b_show_machine_representation/3]).
864 :- use_module(probcspsrc(haskell_csp_analyzer),[get_internal_csp_representation/1]).
865 get_internal_representation(X) :- get_internal_representation(X,false).
866 get_internal_representation(X,UnsetMinorMode) :- animation_mode(AM), get_internal_aux(AM,X,UnsetMinorMode).
867 get_internal_aux(b,X,UnsetMinorMode) :- !, b_show_machine_representation(X,true,UnsetMinorMode). % UnsetMinorMode=true means we try and generate classical B syntax
868 get_internal_aux(cspm,X,_) :- !, get_internal_csp_representation(X).
869 get_internal_aux(csp_and_b,Res,UnsetMinorMode) :- !, append("CSP||B - B Part only",X,Res),
870 b_show_machine_representation(X,true,UnsetMinorMode).
871 get_internal_aux(_,X,_) :- X="Internal representation only available in B or CSP mode".
872
873
874 :- use_module(probcspsrc(haskell_csp),[channel/2]).
875 :- use_module(bmachine,[b_top_level_operation/1]).
876 get_possible_event(OpName) :- b_or_z_mode,
877 %b_is_operation_name(OpName).
878 b_top_level_operation(OpName).
879 get_possible_event(Channel) :- csp_mode,
880 channel(Channel,_).
881 % what about csp_and_b mode ?
882
883
884 get_possible_language_specific_top_level_event(OpName,ResultNames,ParameterNames) :-
885 b_or_z_mode,!,
886 get_possible_b_top_level_event(OpName,ResultNames,ParameterNames).
887 get_possible_language_specific_top_level_event(Channel,unknown,unknown) :- csp_mode,
888 channel(Channel,_).
889
890 get_possible_b_top_level_event('$setup_constants',[],Ids) :-
891 b_machine_has_constants_or_properties,
892 b_get_machine_constants(TIds), maplist(get_texpr_id,TIds,Ids).
893 get_possible_b_top_level_event('$initialise_machine',[],Ids) :-
894 b_get_machine_variables(TIds), maplist(get_texpr_id,TIds,Ids).
895 get_possible_b_top_level_event(OpName,ResultNames,ParameterNames) :-
896 b_top_level_operation(OpName),
897 b_get_machine_operation(OpName,Results,RealParameters,_RealBody,_OType,_OpPos),
898 maplist(get_texpr_id,Results,ResultNames),
899 maplist(get_texpr_id,RealParameters,ParameterNames).
900
901 % obtain a textual description of specification category names
902 get_specification_description(Category,Name) :-
903 animation_mode(Mode),
904 (animation_minor_mode(Minor) -> true ; Minor = none), % there could be several minor modes !
905 (get_specific_description(Mode,Minor,Category,N) -> Name=N
906 ; get_default_description(Category,N) -> Name = N
907 ; add_error(get_specification_description,'Unknown category: ',Category),
908 Name=Category).
909
910 get_specific_description(cspm,_,C,N) :- get_csp_description(C,N).
911 get_specific_description(b,eventb,C,N) :- get_eventb_description(C,N).
912 get_specific_description(b,tla,C,N) :- get_tla_description(C,N).
913
914 get_csp_description(operations,'CHANNELS').
915 get_csp_description(operation,'CHANNEL').
916 get_csp_description(assertions,'CSP_ASSERTIONS').
917 get_csp_description(machine,'CSP_SPECIFICATION').
918 get_csp_description(operations_lc,'events').
919
920 get_tla_description(properties,'ASSUME').
921 get_tla_description(machine,'MODULE').
922 get_tla_description(operation,'ACTION'). % no key word
923 get_tla_description(operations,'ACTIONS'). % no key word
924 get_tla_description(operations_lc,'actions').
925
926 get_eventb_description(properties,'AXIOMS').
927 get_eventb_description(assertions,'THEOREMS').
928 get_eventb_description(operations,'EVENTS').
929 get_eventb_description(operation,'EVENT').
930 get_eventb_description(operations_lc,'events').
931 get_eventb_description(machine,'MODEL').
932
933 get_default_description(properties,'PROPERTIES').
934 get_default_description(assertions,'ASSERTIONS').
935 get_default_description(invariant,'INVARIANT').
936 get_default_description(invariants,'INVARIANTS').
937 get_default_description(operations,'OPERATIONS').
938 get_default_description(operation,'OPERATION').
939 get_default_description(operations_lc,'operations').
940 get_default_description(machine,'MACHINE').
941 get_default_description(constants,'CONSTANTS').
942 get_default_description(variables,'VARIABLES').
943 get_default_description(initialisation,'INITIALISATION').
944 get_default_description(sets,'SETS').
945 get_default_description(goal,'GOAL').
946 get_default_description(definition,'DEFINITION').
947 get_default_description(definitions,'DEFINITIONS').
948 get_default_description(variants,'VARIANTS').