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(bmachine_eventb,[check_event_b_project/4
6 ,prime_variable/2
7 ,prime_variables/2
8 ,deferred_set_equality_without_enumeration_axioms/2
9 ,is_eventb_additional_info/1
10 ,raw_event/10
11 ,is_primed_id/1
12 ]).
13
14 :- use_module(library(lists)).
15 :- use_module(library(ordsets)).
16 :- use_module(library(avl)).
17 :- use_module(library(codesio),[read_from_codes/2]).
18
19 :- use_module(error_manager).
20 :- use_module(tools,[remove_all/3,foldl/4,foldl/5,foldl/6,ajoin_with_sep/3,unique_id/2]).
21 :- use_module(self_check).
22 :- use_module(btypechecker).
23 :- use_module(b_ast_cleanup).
24 :- use_module(bsyntaxtree).
25 :- use_module(debug).
26 :- use_module(bmachine_construction).
27 :- use_module(preferences,[get_preference/2]).
28 :- use_module(input_syntax_tree,[extract_raw_identifiers/2,create_fresh_identifier/3]).
29 :- use_module(translate,[translate_bexpression/2]).
30 :- use_module(pragmas,[extract_pragmas_from_event_b_extensions/2,apply_pragmas_to_event_b_machine/3]).
31
32 :- use_module(module_information,[module_info/2]).
33 :- module_info(group,typechecker).
34 :- module_info(description,'This module contains the rules for loading a Event-B machine or context. ').
35
36 :- use_module(specfile,[eventb_mode/0]).
37 deferred_set_equality_without_enumeration_axioms(Set,ExtSet) :-
38 eventb_mode,
39 deferred_set_eq_wo_enumeration_axioms(Set,ExtSet),
40 % there is a single equality Set = {id1,...,idn} and no partition or not enough disequalities
41 % quite often the user forgot to add those disequalities
42 \+ (deferred_set_eq_wo_enumeration_axioms(Set,ExtS2), ExtS2 \= ExtSet).
43
44 :- dynamic deferred_set_eq_wo_enumeration_axioms/2.
45
46 check_event_b_project(RawModels,RawContextes,Extensions,MachineWithPragmas) :-
47 retractall(deferred_set_eq_wo_enumeration_axioms(_,_)),
48 catch( check_event_b_project1(RawModels,RawContextes,Extensions,MachineWithPragmas),
49 typecheck_errors(Errors),
50 ( add_all_perrors(Errors),fail )).
51 check_event_b_project1([],RawContextes,Extensions,MachineWithPragmas) :-
52 !,
53 check_extensions(Extensions,Freetypes,Ops,InitEnv), % Theories
54 check_contextes(InitEnv,RawContextes,Contextes),
55 convert_event_b(context,Freetypes,Ops,Contextes,[],[],Machine),
56 extract_pragmas_from_event_b_extensions(Extensions,Pragmas),
57 apply_pragmas_to_event_b_machine(Pragmas,Machine,MachineWithPragmas).
58 check_event_b_project1(RawModels,RawContextes,Extensions,MachineWithPragmas) :-
59 compute_animation_chain(RawModels,AnimationChain),
60 check_event_b_project2(RawModels,RawContextes,Extensions,
61 AnimationChain,Machine),
62 extract_pragmas_from_event_b_extensions(Extensions,Pragmas),
63 apply_pragmas_to_event_b_machine(Pragmas,Machine,MachineWithPragmas).
64
65 check_event_b_project2(RawModels,RawContextes,Extensions,AnimationChain,Machine) :-
66 RawModels=[event_b_model(_,Main,_)|_],
67 check_extensions(Extensions,Freetypes,Ops,InitEnv), % related to Theory plugin
68 % generate type-checked contextes
69 check_contextes(InitEnv,RawContextes,Contextes),
70 % generate type-checked models
71 check_models(InitEnv,RawModels,Contextes,Models),
72 % merge all the constants/vars/predicates and events into one machine
73 convert_event_b(Main,Freetypes,Ops,Contextes,Models,AnimationChain,Machine).
74
75 % the filter chain contains the name of all models that
76 % should be contained in the animation
77 compute_animation_chain(Models,AnimationChain) :-
78 get_preference(number_animated_abstractions,N),
79 debug_println(9,compute_animation_chain(N)),
80 length(Models,L),
81 N1 is min(N+1,L),
82 prefix_length(Models, AnimatedModels, N1),
83 extract_model_names(AnimatedModels,AnimationChain).
84 extract_model_names([],[]).
85 extract_model_names([event_b_model(_,Name,_)|MRest],[Name|NRest]) :-
86 extract_model_names(MRest,NRest).
87
88 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
89 % context
90
91 check_contextes(InitEnv,RawContextes,Contextes) :-
92 debug_println(9,'Checking Contextes'),
93 % make sure that a extended context is treated before
94 % the extending context
95 topological_sort(RawContextes,SortedContextes),
96 check_contextes2(SortedContextes,InitEnv,[],Contextes).
97 check_contextes2([],_,_,[]).
98 check_contextes2([RawContext|Rrest],InitEnv,PrevContextes,[Context|Crest]) :-
99 check_context(RawContext,InitEnv,PrevContextes,Context),
100 check_contextes2(Rrest,InitEnv,[Context|PrevContextes],Crest).
101
102 check_context(RawContext,InitEnv,PrevContextes,Context) :-
103 extract_ctx_sections(RawContext,Name,Extends,
104 RawSets,RawConstants,RawAbstractConstants,RawAxioms,RawTheorems),
105 Context = context(Name,Extends,Sets,Constants,AbstractConstants,Axioms,Theorems),
106
107 % create deferred sets
108 create_sets(RawSets,Name,Sets),
109 % and constants
110 IdInfos = [loc(Name,constants),section(Name)],
111 create_identifiers(RawConstants,IdInfos,Constants),
112 create_identifiers(RawAbstractConstants,IdInfos,AbstractConstants),
113
114 % with the constants and set of seen contextes,
115 create_ctx_env(Extends,PrevContextes,InitEnv,PrevEnv),
116 % and the sets and constants
117 add_unique_variables(Sets,PrevEnv,SetEnv),
118 add_unique_variables(Constants,SetEnv,EnvT),
119 add_unique_variables(AbstractConstants,EnvT,Env),
120
121 % now typecheck the axioms and theorems,
122 % this should determine the constant's types
123 typecheck_together([RawAxioms,RawTheorems],Env,[Axioms,Theorems],axioms).
124
125 extract_ctx_sections(RawContext,Name,Extends,RawSets,RawConstants,RawAbstractConstants,RawAxioms,RawTheorems) :-
126 RawContext = event_b_context(_Pos,Name,Sections),
127 optional_rawmachine_section(extends,Sections,[],Extends),
128 optional_rawmachine_section(sets,Sections,[],RawSets),
129 optional_rawmachine_section(constants,Sections,[],RawConstants),
130 optional_rawmachine_section(abstract_constants,Sections,[],RawAbstractConstants),
131 optional_rawmachine_section(axioms,Sections,[],RawAxioms),
132 optional_rawmachine_section(theorems,Sections,[],RawTheorems).
133
134
135 create_sets([],_,[]).
136 create_sets([RawSet|RSrest],CtxName,[Set|Srest]) :-
137 ext2int(RawSet,deferred_set(SetName),_,set(global(SetName)),
138 identifier(SetName),[section(CtxName),given_set],Set),
139 create_sets(RSrest,CtxName,Srest).
140
141 create_identifiers([],_,[]).
142 create_identifiers([RawIdentifier|RIrest],Infos,[Identifier|Irest]) :-
143 ext2int(RawIdentifier,I,_,_,I,Infos,Identifier),
144 I=identifier(_),
145 create_identifiers(RIrest,Infos,Irest).
146
147 create_ctx_env(Extends, Contextes, Old, New) :-
148 % find all seen contextes (and their extended contextes,
149 % and again their extended contextes, ...)
150 transitive_contextes(Extends,Contextes,TransExt),
151 % and all variables of extended machines
152 add_env_vars_for_extended2(TransExt,Contextes,Old,New).
153 transitive_contextes(Extends,Contextes,All) :-
154 findall(E, transext(Extends,Contextes,E), All1), sort(All1, All).
155 transext(Extends,_,E) :- member(E,Extends).
156 transext(Extends,Contextes,E) :-
157 member(Name,Extends),
158 internal_context_extends(Context,Name,NewExtends),
159 member(Context,Contextes),
160 transext(NewExtends,Contextes,E).
161 % add_env_vars_for_extended2(Names,Contextes,OldEnv,NewEnv):
162 % Names: a list of the names of the contextes whose constants and sets
163 % should be added to the type environment
164 % Contextes: a list of all existing contextes
165 % OldEnv: the input environment
166 % NewEnv: the input environment plus the constants and sets
167 add_env_vars_for_extended2([],_,Env,Env).
168 add_env_vars_for_extended2([Name|Erest],Contextes,Old,New) :-
169 internal_context_sets(Context,Name,Sets),
170 internal_context_constants(Context,Name,Constants),
171 internal_context_abstract_constants(Context,Name,AbstractConstants),
172 member(Context,Contextes),!,
173 add_unique_variables(Sets,Old,Env1),
174 add_unique_variables(Constants,Env1,Env2),
175 add_unique_variables(AbstractConstants,Env2,Env),
176 add_env_vars_for_extended2(Erest,Contextes,Env,New).
177
178 % copy&paste from bmachine_construction
179 add_unique_variables([],Env,Env).
180 add_unique_variables([Var|Rest],Old,New) :-
181 def_get_texpr_id(Var,Name),
182 get_texpr_type(Var,Type),
183 get_texpr_info(Var,Infos),
184 ( env_lookup_type(Name,Old,_) ->
185 add_error(bmachine_eventb,'Identifier declared twice',Name),
186 fail
187 ; otherwise -> true),
188 env_store(Name,Type,Infos,Old,Env),
189 add_unique_variables(Rest,Env,New).
190
191 % add the primed (') versions of the variables to the
192 % type environment
193 add_primed_variables(Variables,OrigEnv,NewEnv) :-
194 prime_variables(Variables,Primed),
195 add_unique_variables(Primed,OrigEnv,NewEnv).
196
197
198 :- use_module(btypechecker,[prime_identifiers/2,prime_identifier/2,prime_identifiers0/2]).
199
200 % add a prime (') to each typed identifier
201 prime_variables(V,PV) :- prime_identifiers(V,PV).
202 % add a prime (') to a typed identifier
203 prime_variable(V,P) :- prime_identifier(V,P).
204 % add (or remove) a prime (') to a plain identifier (without syntax structure)
205 prime_id(UnPrimed,Primed) :-
206 atom_concat(UnPrimed,'\'',Primed).
207
208 % unprime_id( ListoPrimedIds, CorrespondingIds, PossiblyPrimedID, UnprimedID)
209 unprime_id(AtomicIds0,AtomicIds,Id0,Id) :- nth1(N,AtomicIds0,Id0),!, nth1(N,AtomicIds,Id).
210 unprime_id(_,_,Id,Id).
211
212 check_for_errors(Errors) :-
213 % TO DO: extract and add warnings in list
214 Errors = [_|_],!,throw(typecheck_errors(Errors)).
215 check_for_errors([]).
216
217 typecheck_l(Untyped,Env,Type,Typed,Context) :-
218 all_same(Untyped,Type,Types),
219 btype_ground_dl(Untyped,Env,[],Types,Typed1,Errors,[]),
220 check_for_errors(Errors),
221 clean_up_l_with_optimizations(Typed1,[],Typed,Context),!.
222 typecheck_l(Untyped,Env,Type,Typed,Context) :-
223 add_failed_call_error(typecheck_l(Untyped,Env,Type,Typed,Context)),fail.
224 all_same([],_,[]).
225 all_same([_|R],E,[E|T]) :- all_same(R,E,T).
226
227 typecheck(Untyped,Env,Type,Typed) :-
228 typecheck_with_freevars(Untyped,Env,[],Type,Typed).
229 typecheck_with_freevars(Untyped,Env,Freevars,Type,Typed) :-
230 btype_ground_dl([Untyped],Env,Freevars,[Type],[Typed1],Errors,[]),
231 clean_up_pred_or_expr(Freevars,Typed1,Typed),
232 check_for_errors(Errors).
233
234
235
236
237
238 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
239 % models
240
241 check_models(InitEnv,RawModels,Contextes,Models) :-
242 debug_println(9,'CHECKING MODELS'),
243 topological_sort(RawModels,SortedModels),
244 check_models2(SortedModels,InitEnv,[],Contextes,Models).
245
246 check_models2([],_,_,_,[]).
247 check_models2([RawModel|RMrest],InitEnv,PrevModels,Contextes,[Model|Mrest]) :-
248 (check_model(RawModel,InitEnv,PrevModels,Contextes,Model) -> true
249 ; add_failed_call_error(check_model(RawModel,InitEnv,PrevModels,Contextes,Model)),
250 fail),
251 check_models2(RMrest,InitEnv,[Model|PrevModels],Contextes,Mrest).
252
253 check_model(RawModel,InitEnv,PrevModels,Contextes,Model) :-
254 extract_model_sections(RawModel,Name,Refines,Sees,
255 RawVariables,RawInvariant,
256 RawTheorems,RawVariant,RawEvents),
257 Model = model(Name,Refines,Sees,ConcreteVariables,NewVariables,Invariant,Theorems,Events),
258 get_refined_model(Refines,PrevModels,RefinedModel),
259
260 get_all_abstract_variables(Refines,PrevModels,AbstractionVariables),
261 length(PrevModels,Level),
262 IdInfos = [loc(Name,variables),section(Name),level(Level)],
263 create_identifiers(RawVariables,IdInfos,ConcreteVariables),
264 split_abstract_vars(AbstractionVariables,ConcreteVariables,
265 NewVariables,DroppedAbstractVars),
266
267 create_ctx_env(Sees,Contextes,InitEnv,CtxEnv),
268 add_unique_variables(ConcreteVariables,CtxEnv,ModelEnv),
269 add_unique_variables(DroppedAbstractVars,ModelEnv,InvEnv),
270 % add primed versions of the concrete variables to
271 % permit before-after predicates in the witnesses
272 add_primed_variables(ConcreteVariables,InvEnv,BeforeAfterEnv),
273
274 typecheck_together([RawInvariant,RawTheorems],InvEnv,[Invariant,Theorems],invariant),
275
276 typecheck_variant(RawVariant,InvEnv,Variant),
277
278 get_abstract_events(RefinedModel,AbstractEvents),
279
280 check_events(RawEvents,Name,ModelEnv,BeforeAfterEnv,InvEnv,
281 DroppedAbstractVars,ConcreteVariables,AbstractEvents,
282 NewVariables,Variant,Events).
283
284 % Context is just an information term about the context (axioms, ...)
285 typecheck_together(Raws,Env,Typed,Context) :-
286 maplist(same_length, Raws, Typed),
287 append(Raws,RawL), append(Typed,TypedL),
288 typecheck_l(RawL,Env,pred,TypedL,Context).
289
290 typecheck_variant(-, _Env, -) :- !.
291 typecheck_variant(RawVariant, Env, Variant) :-
292 typecheck(RawVariant, Env, Type, Variant),
293 ( Type==integer -> true
294 ; functor(Type,set,1) -> true
295 ; otherwise ->
296 add_error(bmachine_eventb,'Invalid type of variant ',Type),
297 fail).
298
299 remove_linking_parts([],_AnimationChain,[]).
300 remove_linking_parts([Inv|Irest],AnimationChain,Invariants) :-
301 ( abstraction_var_occures(Inv,AnimationChain) ->
302 Invariants = RestInvariants
303 ; otherwise ->
304 Invariants = [Inv|RestInvariants]),
305 remove_linking_parts(Irest,AnimationChain,RestInvariants).
306
307 abstraction_var_occures(TExpr,AnimationChain) :-
308 get_texpr_expr(TExpr,identifier(_)),!,
309 get_texpr_section(TExpr,Section),
310 \+ member(Section,AnimationChain).
311 abstraction_var_occures(TExpr,AnimationChain) :-
312 syntaxtraversion(TExpr,_,_,_,Subs,_),
313 abstraction_var_occures_l(Subs,AnimationChain).
314 abstraction_var_occures_l([Sub|_],AnimationChain) :-
315 abstraction_var_occures(Sub,AnimationChain),!.
316 abstraction_var_occures_l([_|Srest],AnimationChain) :-
317 abstraction_var_occures_l(Srest,AnimationChain).
318
319 get_texpr_section(TExpr,Section) :-
320 get_texpr_info(TExpr,Info),member(section(Section),Info),!.
321
322 extract_model_sections(RawModel,Name,Refines,Sees,Variables,Invariant,Theorems,Variant,Events) :-
323 RawModel = event_b_model(_Pos,Name,Sections),
324 optional_rawmachine_section(refines,Sections,-,Refines),
325 optional_rawmachine_section(sees,Sections,[],Sees),
326 optional_rawmachine_section(variables,Sections,[],Variables),
327 optional_rawmachine_section(invariant,Sections,[],Invariant),
328 optional_rawmachine_section(theorems,Sections,[],Theorems),
329 optional_rawmachine_section(variant,Sections,-,Variant),
330 optional_rawmachine_section(events,Sections,[],Events).
331
332 %get_abstraction_variables(-,[]).
333 %get_abstraction_variables(Model,Variables) :-
334 % internal_model_vars(Model,_Name,Variables).
335
336 get_abstract_events(-,[]).
337 get_abstract_events(Model,Events) :- internal_model_events(Model,_Name,Events).
338
339 get_refined_model(-,_Models,-) :- !.
340 get_refined_model(Name,Models,Model) :-
341 internal_model(M,Name),
342 ( memberchk(M,Models) ->
343 M=Model
344 ; otherwise ->
345 add_error(bmachine_eventb,'Unable to find refined model ',Name),
346 fail).
347
348 split_abstract_vars(AbstractVars,ConcreteVars,NewVars,DroppedVars) :-
349 split_abstract_vars2(AbstractVars,ConcreteVars,DroppedVars),
350 find_new_variables(ConcreteVars,AbstractVars,NewVars).
351 split_abstract_vars2([],_,[]).
352 split_abstract_vars2([AbstractVar|AVrest],ConcreteVars,Dropped) :-
353 ( find_identifier_in_list(AbstractVar,ConcreteVars,ConcreteVar) ->
354 % Both variables have the same type
355 get_texpr_type(AbstractVar,Type),
356 get_texpr_type(ConcreteVar,Type),
357 Dropped = DroppedRest
358 ; otherwise ->
359 Dropped = [AbstractVar|DroppedRest]),
360 split_abstract_vars2(AVrest,ConcreteVars,DroppedRest).
361 find_new_variables([],_,[]).
362 find_new_variables([ConcreteVar|CVrest],AbstractVars,NewVars) :-
363 ( find_identifier_in_list(ConcreteVar,AbstractVars,_AbstractVar) -> NewVars = Nrest
364 ; otherwise -> NewVars = [ConcreteVar|Nrest]),
365 find_new_variables(CVrest,AbstractVars,Nrest).
366
367 % find_identifier_in_list(TypedIdToFind,List,Elem):
368 % search for a typed identifier Elem in List wich
369 % has the same id as TypedIdToFind, but type and informations
370 % may be different
371 find_identifier_in_list(TypedIdToFind,List,Found) :-
372 def_get_texpr_id(TypedIdToFind,Id),
373 get_texpr_id(Found,Id),
374 member(Found,List).
375
376 get_all_abstract_variables(Refines,AbstractModels,AbstractVariables) :-
377 get_all_abstract_variables2(Refines,AbstractModels,_EncounteredIds,AbstractVariables,[]).
378 get_all_abstract_variables2(-,_AbstractModels,EncounteredIds) -->
379 {!,empty_avl(EncounteredIds)}.
380 get_all_abstract_variables2(Name,AbstractModels,EncounteredIds) -->
381 {get_refined_model(Name,AbstractModels,Model),
382 internal_model_refines(Model,_,Refines)},
383 get_all_abstract_variables2(Refines,AbstractModels,EncounteredIdsAbs),
384 get_all_abstract_variables3(Model,EncounteredIdsAbs,EncounteredIds).
385 get_all_abstract_variables3(Model,EncounteredIdsIn,EncounteredIdsOut,
386 FoundVarsIn,FoundVarsOut) :-
387 internal_model_vars(Model,_,Vars),
388 extract_new_variables(Vars,EncounteredIdsIn,NewVars),
389 get_texpr_ids(NewVars,NewIds),
390 add_all_to_avl(NewIds,EncounteredIdsIn,EncounteredIdsOut),
391 add_all(NewVars,FoundVarsIn,FoundVarsOut).
392 add_all_to_avl([],Avl,Avl).
393 add_all_to_avl([H|T],In,Out) :-
394 avl_store(H,In,1,Inter),
395 add_all_to_avl(T,Inter,Out).
396 add_all([],L,L).
397 add_all([H|T],[H|L1],L2) :- add_all(T,L1,L2).
398 extract_new_variables([],_EncounteredIdsIn,[]).
399 extract_new_variables([Var|Vrest],EncounteredIds,NewVars) :-
400 get_texpr_id(Var,Id),
401 ( avl_fetch(Id,EncounteredIds) ->
402 NewVars = NewRest
403 ; otherwise ->
404 NewVars = [Var|NewRest]),
405 extract_new_variables(Vrest,EncounteredIds,NewRest).
406
407
408
409
410
411 check_events([],_ModelName,_Env,_GEnv,_InvEnv,_Dropped,_ConcreteVars,_AbstractEvents,_NewVars,_Variant,[]).
412 check_events([RawEvent|RawRest],ModelName,Env,GEnv,InvEnv,DroppedVars,ConcreteVars,AbstractEvents,NewVars,Variant,[Event|Erest]) :-
413 (check_event(RawEvent,ModelName,Env,GEnv,InvEnv,DroppedVars,ConcreteVars,AbstractEvents,NewVars,Variant,Event)
414 -> true
415 ; add_failed_call_error(check_event(RawEvent,ModelName,Env,GEnv,InvEnv,DroppedVars,ConcreteVars,AbstractEvents,NewVars,Variant,Event))),
416 check_events(RawRest,ModelName,Env,GEnv,InvEnv,DroppedVars,ConcreteVars,AbstractEvents,NewVars,Variant,Erest).
417
418
419 check_event(RawEvent,ModelName,Env,GEnv,InvEnv,DroppedVars,ConcreteVars,AbstractEvents,NewVariables,Variant,
420 event(EvName,ModelName,Status,TParameters,TGuard,TTheorems,MActions,TVarWitnesses,TParamWitnesses,Unmodifiables,Refines)) :-
421
422 raw_event(RawEvent,_,EvName,RawStatus,Refines,Params,Guards,Theorems,Actions,Witnesses),
423 check_status(RawStatus, Variant, Status, Refines, AbstractEvents, eventlocation(ModelName,EvName)),
424 get_abstract_parameters(Refines,AbstractEvents,AbstractParameters),
425 create_identifiers(Params,[loc(ModelName,event(EvName))],TParameters),
426 split_abstract_vars(AbstractParameters,TParameters,
427 _NewParameters,DroppedParameters1),
428 annotate_dropped_parameters(DroppedParameters1,Refines,AbstractEvents,DroppedParameters),
429 conjunct_guards(Guards,Guard),
430 maplist(adapt_becomes_such,Actions,Actions1),
431 % add new parameters to the typing environments:
432 add_identifiers_to_environment(TParameters,Env,Subenv),
433 add_identifiers_to_environment(TParameters,GEnv,SubGenv),
434 add_identifiers_to_environment(TParameters,InvEnv,SubTheoremsEnv), % theorems can access dropped abstract variables; just like the invariant
435 typecheck(Guard,Subenv,pred,TGuard),
436 typecheck_l(Theorems,SubTheoremsEnv,pred,TTheorems,theorems),
437 typecheck_l(Actions1,Subenv,subst,TActions,actions),
438 check_witnesses(Witnesses,SubGenv,DroppedParameters,DroppedVars,TVarWitnesses,TParamWitnesses),
439 % add checks that some variables may not be modified, e.g
440 % if skip is refined
441 get_abstract_actions(Refines,AbstractEvents,AbstractActions),
442 ~~mnf( add_modified_vars_to_actions(TActions,MActions1) ),
443 add_unmodified_assignments(AbstractActions,MActions1,ConcreteVars,MActions),
444 add_equality_check(MActions,AbstractActions,NewVariables,ConcreteVars,Unmodifiables).
445
446 % add assignments of the form x:=x if a not dropped abstract variable
447 % is modified by the abstract event, but not the dropped event
448 add_unmodified_assignments(AbstractActions,ConcreteActions,ConcreteVars,NewActions) :-
449 get_modified_vars_of_actions(AbstractActions,AbstractModified),
450 get_modified_vars_of_actions(ConcreteActions,ConcreteModified),
451 remove_all(AbstractModified,ConcreteModified,OnlyAbstractModified),
452 findall( Var,
453 ( member(Id,OnlyAbstractModified), get_texpr_id(Var,Id), memberchk(Var,ConcreteVars)),
454 ToKeep),
455 ( ToKeep = [] -> NewActions = ConcreteActions
456 ; ToKeep = [_|_] ->
457 create_texpr(assign(ToKeep,ToKeep),subst,[],Action1),
458 add_modified_vars_to_action(Action1,Action),
459 NewActions = [Action|ConcreteActions]).
460
461 check_status(RawStatus, Variant, TConv, Refines, AbstractEvents, Location) :-
462 remove_pos(RawStatus,Status),
463 check_status2(Status, Variant, Refines, AbstractEvents, Location, Conv, Infos),
464 create_texpr(Conv, status, Infos, TConv).
465 check_status2(ordinary, _Variant, _Refines, _AbstractEvents, _Location, ordinary, []).
466 check_status2(convergent, _Variant, Refines, AbstractEvents, _Location, ordinary, [convergence_proved]) :-
467 % if the refined event is also convergent, we can (or must because the
468 % variant may be missing in the refinement) omit the check for decreasing the
469 % variant. We do this by treating the event as ordinary.
470 convergence_ensured_by_abstract_event(Refines, AbstractEvents),!.
471 check_status2(convergent, Variant, _Refines, _AbstractEvents, Location, convergent(RVariant), [convergence_proved]) :-
472 variant_must_be_set(Variant,Location,RVariant).
473 check_status2(anticipated, Variant, _Refines, _AbstractEvents, _Location, anticipated(RVariant), []) :-
474 get_variant(Variant,RVariant).
475
476 :- use_module(tools_strings,[ajoin/2]).
477 variant_must_be_set(-,Location,RVariant) :- !,
478 Location = eventlocation(Model,Name),
479 ajoin(['No variant defined for ', Name, ' in model ', Model],Msg),
480 add_error(bmachine_eventb,Msg),
481 get_variant(-,RVariant).
482 % removed fail to allow animation
483 variant_must_be_set(V,_,V).
484
485 % get_variant(ModelVariant,Variant) checks profides a default variant (0) if
486 % the model does not have a variant
487 get_variant(-,V) :- !, create_texpr(integer(0),integer,[default_variant],V).
488 get_variant(V,V).
489
490 convergence_ensured_by_abstract_event(Refines, AbstractEvents) :-
491 % find a refined event which status is convergent
492 internal_event_status(Event,Ref,Status),
493 get_texpr_info(Status,StatusInfo),
494 member(Event, AbstractEvents),
495 member(Ref, Refines),
496 member(convergence_proved,StatusInfo),!.
497
498 annotate_dropped_parameters([],_,_,[]).
499 annotate_dropped_parameters([P|PRest],Refines,AbstractEvents,[A|ARest]) :-
500 def_get_texpr_id(P,Id),
501 add_texpr_infos(P,[droppedby(DropList)],A),
502 findall(Event, event_drops_param(Event,Refines,AbstractEvents,Id), DropList),
503 annotate_dropped_parameters(PRest,Refines,AbstractEvents,ARest).
504 event_drops_param(Event,Refines,AbstractEvents,Id) :-
505 get_texpr_id(Pattern,Id),
506 member(Event,Refines),
507 get_event_parameters(Event,AbstractEvents,AbParams),
508 member(Pattern,AbParams).
509
510 get_abstract_parameters([],_,R) :- !,R=[].
511 get_abstract_parameters([Refines|Rest],Events,Params) :- !,
512 get_event_parameters(Refines,Events,LocalParams),
513 append(LocalParams,RestParams,Params),
514 get_abstract_parameters(Rest,Events,RestParams).
515 get_abstract_parameters(Refines,_,Params) :- add_error(get_abstract_parameters,'Illegal Refines List: ',Refines),
516 Params=[].
517 get_event_parameters(Refines,Events,Params) :-
518 internal_event_params(Event,Refines,Params),
519 member(Event,Events),!.
520
521 get_abstract_actions([],_,[]).
522 get_abstract_actions([Refines|Rest],Events,Actions) :-
523 get_event_action(Refines,Events,LocalActions),
524 append(LocalActions,RestActions,Actions),
525 get_abstract_actions(Rest,Events,RestActions).
526 get_event_action(Refines,Events,Actions) :-
527 internal_event_actions(Event,Refines,Actions),
528 member(Event,Events),!.
529
530 check_witnesses([],_Env,_DroppedParams,_DroppedVars,[],[]).
531 check_witnesses([Witness|Rest],Env,DroppedParams,DroppedVars,TVarWitnesses,TParamWitnesses) :-
532 check_witness(Witness,Env,DroppedParams,DroppedVars,TWitness,WType),
533 ( WType = droppedvar ->
534 TVarWitnesses = [TWitness|TWVRest],
535 TParamWitnesses = TWPRest
536 ; WType = droppedparam(_DropList) ->
537 TVarWitnesses = TWVRest,
538 TParamWitnesses = [TWitness|TWPRest]),
539 check_witnesses(Rest,Env,DroppedParams,DroppedVars,TWVRest,TWPRest).
540 check_witness(witness(_Pos,RawId,Pred),Env,DroppedParams,DroppedVars,TWitness,WType) :-
541 RawId = identifier(_,WitnessId),
542 get_witness_identifier(WitnessId,DroppedParams,DroppedVars,TId,Info,WType),
543 get_texpr_type(TId,Type),
544 env_store(WitnessId,Type,Info,Env,Subenv),
545 typecheck(Pred,Subenv,pred,TPred),
546 create_texpr(witness(TId,TPred),witness,[],TWitness).
547 get_witness_identifier(PrimedId,_DroppedParams,DroppedVars,TPrimeId,[],droppedvar) :-
548 prime_id(Id,PrimedId),
549 get_texpr_id(TId,Id),
550 member(TId,DroppedVars),!,
551 prime_variables([TId],[TPrimeId]).
552 get_witness_identifier(Id,DroppedParams,_DroppedVars,TId,Info,droppedparam(DropList)) :-
553 get_texpr_id(TId,Id),
554 member(TId,DroppedParams),!,
555 get_texpr_info(TId,Info),
556 member(droppedby(DropList),Info),!.
557
558 conjunct_guards([],truth(none)).
559 conjunct_guards([H|T],Result) :- conjunct_guards2(T,H,Result).
560 conjunct_guards2([],G,G).
561 conjunct_guards2([H|T],G,Result) :- conjunct_guards2(T,conjunct(none,G,H),Result).
562
563 /*
564 parallel_actions(Actions,Pos,Action) :-
565 ( Actions = [] -> Action = skip(Pos)
566 ; Actions = [S] -> Action = S
567 ; otherwise -> Action = parallel(Pos,Actions)).
568 */
569
570 % eventb becomes_such uses primed identifiers: distinguish it from normal becomes_such
571 % ast_cleanup will translate it back to becomes_such, but with $0 instead of primes (so that it conforms to classical B)
572 adapt_becomes_such(becomes_such(Pos,Ids,Pred),evb2_becomes_such(Pos,Ids,Pred)) :- !.
573 adapt_becomes_such(Subst,Subst).
574
575 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
576 % convert B project to classical B machine
577
578 :- use_module(bmachine_structure,[create_machine/2]).
579
580 convert_event_b(Main,Freetypes,Ops,Contextes,Models,AnimationChain,Machine) :-
581 debug_println(9,'Converting to classical B'),
582 select_models(AnimationChain,Models,AnimatedModels),
583 % todo: access to private elements of bmachine_construction
584 create_machine(Main,Empty),
585 convert_event_b2(Freetypes,Ops,AnimatedModels,Contextes,AnimationChain,
586 Empty,Machine),!.
587 convert_event_b(Main,Freetypes,Ops,Contextes,Models,AnimationChain,Machine) :-
588 add_failed_call_error(convert_event_b(Main,Freetypes,Ops,Contextes,Models,AnimationChain,Machine)),
589 fail.
590 convert_event_b2(Freetypes,Ops,AnimatedModels,Contextes,AnimationChain) -->
591 append_to_section(freetypes,Freetypes),
592 append_to_section(operators,Ops),
593 create_constants(AnimatedModels,Contextes,AnimatedContextNames),
594 {append(AnimatedContextNames,AnimationChain,AnimatedSectionNames)},
595 create_variables(AnimatedModels,AnimatedSectionNames),
596 create_events(AnimatedModels,AnimatedSectionNames),
597 create_animated_section_info(AnimatedContextNames,AnimationChain).
598
599 create_animated_section_info(Contextes,Models) -->
600 {reverse(Models,FromAbstractToConcrete),
601 maplist(mark_as_model,FromAbstractToConcrete,MarkedModels),
602 maplist(mark_as_context,Contextes,MarkedContextes),
603 append(MarkedContextes,MarkedModels,Sections)},
604 append_to_section(meta,[animated_sections(Sections)]).
605
606 mark_as_model(Name,model(Name)).
607 mark_as_context(Name,context(Name)).
608
609 /*
610 get_operation_identifiers([],[]).
611 get_operation_identifiers([TExpr|Rest],[Id|IdRest]) :-
612 get_texpr_expr(TExpr,operation(Id,_,_,_)),
613 get_operation_identifiers(Rest,IdRest).
614 */
615
616 create_variables(Models,AnimatedSectionNames) -->
617 {collect_model_infos(Models,AnimatedSectionNames,Variables,Invariants,Theorems)},
618 append_to_section(abstract_variables,Variables),
619 conjunct_to_section(invariant,Invariants),
620 append_to_section(assertions,Theorems).
621
622 select_contexts([],_Contexts,[]).
623 select_contexts([Name|NRest],Contexts,[Context|CRest]) :-
624 internal_context(Context,Name),
625 memberchk(Context,Contexts),
626 select_contexts(NRest,Contexts,CRest).
627
628 select_models([],_Models,[]).
629 select_models([Name|NRest],Models,[Model|MRest]) :-
630 internal_model(Model,Name), memberchk(Model,Models),
631 select_models(NRest,Models,MRest).
632
633 % collect_model_infos(Models,Variables,Invariants,Theorems):
634 % collect all variables, invariants and theorems of the given models
635 collect_model_infos([],_,[],[],[]) :- !.
636 collect_model_infos(Models,AnimatedSectionNames,Vars,Invs,Thms) :-
637 collect_model_infos2(Models,AnimatedSectionNames,AllVars,Vars1,Invs,Thms),
638 % add to every variable the information in which models
639 % it is present
640 add_var_model_occurrences(Vars1,AllVars,Vars).
641 collect_model_infos2([],_,[],[],[],[]).
642 collect_model_infos2([Model|MRest],AnimatedSectionNames,Vars,NewVars,Invs,Thms) :-
643 internal_model_vars(Model,_,LVars), append(LVars,RVars,Vars),
644 % use only newly introduced variables of a model, to prevent
645 % double declarations
646 % in case of a limited animation chain, it is important to introduce
647 % all variables for the most abstract model
648 ( MRest == [] -> LNewVars = LVars
649 ; otherwise -> internal_model_newvars(Model,_,LNewVars)),
650 append(LNewVars,RNewVars,NewVars),
651 internal_model_invs(Model,_,LInvs1), append_stripped_predicates(LInvs1,AnimatedSectionNames,RInvs,Invs),
652 internal_model_thms(Model,_,LThms1), append_stripped_predicates(LThms1,AnimatedSectionNames,RThms,Thms),
653 collect_model_infos2(MRest,AnimatedSectionNames,RVars,RNewVars,RInvs,RThms).
654 add_var_model_occurrences([],_,[]).
655 add_var_model_occurrences([Var|Vrest],AllVars,[MVar|Mrest]) :-
656 add_var_model_occurrence(Var,AllVars,MVar),
657 add_var_model_occurrences(Vrest,AllVars,Mrest).
658 add_var_model_occurrence(Var,AllVars,MVar) :-
659 findall(Section,
660 ( find_identifier_in_list(Var,AllVars,M),
661 get_texpr_info(M,Infos),
662 member(section(Section),Infos)),
663 Sections),
664 reverse(Sections,FromAbstractToConcrete),
665 add_texpr_infos(Var,[occurrences(FromAbstractToConcrete)],MVar).
666 append_stripped_predicates(PredsIn,AnimatedSectionNames,RestPreds,Preds) :-
667 remove_linking_parts(PredsIn,AnimatedSectionNames,LPreds),
668 append(LPreds,RestPreds,Preds).
669
670 all_used_contextes(AnimatedModels,Contextes,Sees) :-
671 ( AnimatedModels = [] ->
672 all_context_names(Contextes,Sees)
673 ; otherwise ->
674 collect_sees(AnimatedModels,Sees)).
675 all_context_names([],[]).
676 all_context_names([Context|Crest],[Name|Nrest]) :-
677 internal_context(Context,Name),
678 all_context_names(Crest,Nrest).
679 collect_sees([],[]).
680 collect_sees([Model|MRest],Sees) :-
681 internal_model_sees(Model,_,LocalSees), append(LocalSees,RestSees,Sees),
682 collect_sees(MRest,RestSees).
683
684 create_constants(AnimatedModels,Contextes,AnimatedContextNames) -->
685 {all_used_contextes(AnimatedModels,Contextes,Sees),
686 get_constants(Sees,Contextes,DefSets,EnumSets,EnumElems,Constants,AbstractConstants,Axioms,Theorems,AnimatedContextNames)},
687 append_to_section(deferred_sets,DefSets),
688 append_to_section(enumerated_sets,EnumSets),
689 append_to_section(enumerated_elements,EnumElems),
690 append_to_section(concrete_constants,Constants),
691 append_to_section(abstract_constants,AbstractConstants),
692 conjunct_to_section(properties,Axioms),
693 append_to_section(assertions,Theorems).
694
695 get_constants(Sees,Contextes,DefSets,EnumSets,EnumElems,Constants,AbstractConstants,Axioms,Theorems,AllContextNames) :-
696 transitive_contextes(Sees,Contextes,AllContextNames),
697 select_contexts(AllContextNames,Contextes,AllContextes),
698 collect_context_infos(AllContextes,Sets,Constants1,AbstractConstants,Axioms1,Theorems),
699 enumerated_deferred_sets(Sets,Constants1,Axioms1,DefSets,Constants,Axioms,
700 EnumSets,EnumElems).
701
702 collect_context_infos([],[],[],[],[],[]).
703 collect_context_infos([context(Name,_Ex,LSets1,LCsts1,LAbsCsts1,LAxms,LThms)|Rest],Sets,Constants,AbstractConstants,Axioms,Theorems) :-
704 add_context_occurrences(LSets1,Name,LSets),
705 add_context_occurrences(LCsts1,Name,LCsts),
706 add_context_occurrences(LAbsCsts1,Name,LAbsCsts),
707 append(LSets,RSets,Sets),
708 append(LCsts,RCsts,Constants),
709 append(LAbsCsts,RAbsCsts,AbstractConstants),
710 append(LAxms,RAxms,Axioms),
711 append(LThms,RThms,Theorems),
712 collect_context_infos(Rest,RSets,RCsts,RAbsCsts,RAxms,RThms).
713 add_context_occurrences([],_,[]).
714 add_context_occurrences([Constant|Crest],Name,[CC|CCrest]) :-
715 add_texpr_infos(Constant,[occurrences([Name])],CC),
716 add_context_occurrences(Crest,Name,CCrest).
717
718
719 % merge the events and write them to a machine
720 create_events(AnimatedModels,AnimatedSectionNames) -->
721 {get_events(AnimatedModels,AnimatedSectionNames,Events,Initialisation,Promoted)},
722 append_to_section(operation_bodies,Events),
723 bmachine_construction:write_section(initialisation,Initialisation),
724 append_to_section(promoted,Promoted).
725
726 % merge the events of multiple refinement levels
727 get_events([],_,[],Initialisation,[]) :- !,
728 create_texpr(skip,subst,[],Initialisation).
729 get_events(AnimatedModels,AnimatedSectionNames,Events,Initialisation,Promoted) :-
730 get_events_to_animate(AnimatedModels,AnimEvents),
731 merge_refinement_levels(AnimEvents,AnimatedModels,AnimatedSectionNames,MergedEvents,Promoted1),
732 remove_initialisation(Promoted1,Promoted2),
733 add_op_parenthesis(Promoted2,Promoted),
734 select_initialisation(MergedEvents,PreOps,Initialisation),
735 create_operations(PreOps,Events).
736 remove_initialisation(In,Out) :-
737 get_texpr_id(Expr,'INITIALISATION'),
738 select(Expr,In,Out),!.
739 remove_initialisation(In,Out) :-
740 % add_error(check_event_b_project,'Model has no INITIALISATION'), %err msg already generated below
741 Out=In.
742 add_op_parenthesis([],[]).
743 add_op_parenthesis([Old|ORest],[New|NRest]) :-
744 def_get_texpr_id(Old,Id),
745 rename_bt(Old,[rename(Id,op(Id))],New),
746 add_op_parenthesis(ORest,NRest).
747
748 select_initialisation(In,Ops,Init) :-
749 select(eventop('INITIALISATION',Section,[],Init1,op([],[]),_),In,Ops),!,
750 add_texpr_infos(Init1,[eventb(Section)],Init).
751 select_initialisation(In,Ops,Init) :-
752 add_error(select_initialisation,'Model has no INITIALISATION'),
753 Init = b(skip,subst,[]), % replace skip by non-det assign
754 Ops=In.
755 create_operations([],[]).
756 create_operations([E|ERest],[O|ORest]) :-
757 create_operation(E,O),
758 create_operations(ERest,ORest).
759 create_operation(eventop(Name,Section,Parameters,Subst,Type,Refines),Operation) :-
760 create_texpr(identifier(op(Name)),Type,[],Id),
761 get_texpr_info(Subst,SubstInfo),
762 Mod=modifies(_),memberchk(Mod,SubstInfo),
763 Reads=reads(_),memberchk(Reads,SubstInfo),
764 ( Refines == [] -> RefInfo = []
765 ; otherwise -> RefInfo = [refines(Refines)]),
766 create_texpr(operation(Id,[],Parameters,Subst),Type,[eventb(Section),Mod,Reads|RefInfo],Operation).
767
768 get_events_to_animate([Model|_],Events) :- internal_model_events(Model,_,Events).
769
770 merge_refinement_levels([],_,_,[],[]).
771 merge_refinement_levels([Event|ERest],AnimModels,AnimatedSectionNames,[Merged|MRest],[Prom|PRest]) :-
772 merge_refinement_levels2(Event,AnimModels,AnimatedSectionNames,Merged,Prom),
773 merge_refinement_levels(ERest,AnimModels,AnimatedSectionNames,MRest,PRest).
774
775 merge_refinement_levels2(Event,AnimatedLevels,AnimatedSectionNames,
776 eventop(Name,Section,Parameters,Subst,OpType,Refines),Prom) :-
777 AnimatedLevels = [CurrentLevel|_Abstractions],
778 internal_model(CurrentLevel,Section),
779 internal_event_params(Event,Name,Parameters),
780 internal_event_refined(Event,Name,Refines),
781 %merge_parameters(Refines,Parameters,_Abstractions,MergedParameters),
782 merge_events_to_subst(Name,AnimatedLevels,AnimatedSectionNames,[],Subst1),
783 optimise_events(Subst1,Subst),
784 get_texpr_types(Parameters,Types),OpType = op(Types,[]),
785 create_texpr(identifier(Name),OpType,[],Prom).
786 merge_events_to_subst(Name,[CurrentLevel|Abstractions],AnimatedSectionNames,RefinedParameters,TEvent) :-
787 create_texpr(RefLevelEvent,subst,[modifies(Vars),reads(Reads)],TEvent),
788 RefLevelEvent = rlevent(Name,Section,Status,Params,Guard,Theorems,Actions,VWitnesses,PWitnesses,Unmodifiables,AbstractEvents),
789 InternalEvent = event(Name,Section,Status,AllParams,Guard,Theorems,Actions,VWitnesses1,PWitnesses1,Unmodifiables,Refines),
790 get_event_from_model(Name,CurrentLevel,InternalEvent),
791 strip_witnesses(VWitnesses1,AnimatedSectionNames,VWitnesses),
792 strip_witnesses(PWitnesses1,AnimatedSectionNames,PWitnesses),
793 remove_refined_parameters(AllParams,RefinedParameters,Params),
794 ( Abstractions = [] ->
795 AbstractEvents = []
796 ; otherwise ->
797 append(RefinedParameters,Params,NewRefinedParameters),
798 merge_events_to_subst_l(Refines,Abstractions,AnimatedSectionNames,NewRefinedParameters,AbstractEvents1),
799 normalise_merged_events(AbstractEvents1,AbstractEvents)),
800 collect_modified_vars(Actions,AbstractEvents,Vars),
801 collect_read_vars(AllParams,Guard,Theorems,Actions,VWitnesses,PWitnesses,AbstractEvents,Reads).
802 merge_events_to_subst_l([],_,_,_,[]).
803 merge_events_to_subst_l([Name|NRest],Abstractions,AnimatedSectionNames,RefinedParameters,[TEvent|TRest]) :-
804 merge_events_to_subst(Name,Abstractions,AnimatedSectionNames,RefinedParameters,TEvent),
805 merge_events_to_subst_l(NRest,Abstractions,AnimatedSectionNames,RefinedParameters,TRest).
806
807 % removes a witness completely if the witnessed variable belongs
808 % to a refinement level that is not animated or removes part of the
809 % witness-predicate if references to not animated levels are made.
810 strip_witnesses([],_AnimatedSectionNames,[]).
811 strip_witnesses([Witness|WRest],AnimatedSectionNames,Result) :-
812 strip_witness(Witness,AnimatedSectionNames,StrippedWitness),
813 append(StrippedWitness,SWRest,Result),
814 strip_witnesses(WRest,AnimatedSectionNames,SWRest).
815 strip_witness(Witness,AnimatedSectionNames,StrippedWitness) :-
816 get_texpr_expr(Witness,witness(W,P)),
817 ( abstraction_var_occures(W,AnimatedSectionNames) ->
818 % The abstract variable is not animated, skip the complete witness
819 StrippedWitness = []
820 ; otherwise ->
821 conjunction_to_list(P,Preds),
822 remove_linking_parts(Preds,AnimatedSectionNames,SPreds),
823 conjunct_predicates(SPreds,SP),
824 get_texpr_type(Witness,Type),
825 get_texpr_info(Witness,Info),
826 create_texpr(witness(W,SP),Type,Info,TWitness),
827 StrippedWitness = [TWitness]).
828
829 remove_refined_parameters([],_RefinedParameters,[]).
830 remove_refined_parameters([Param|APRest],RefinedParameters,Parameters) :-
831 ( find_identifier_in_list(Param,RefinedParameters,_RefParam) ->
832 Parameters = PRest
833 ; otherwise ->
834 Parameters = [Param|PRest]),
835 remove_refined_parameters(APRest,RefinedParameters,PRest).
836
837 /* currently commented out :
838 merge_parameters([],Parameters,_Abstractions,Parameters).
839 merge_parameters([_|_],Parameters,[],Parameters) :- !.
840 merge_parameters([Refines|Rest],OldParameters,Abstractions,Parameters) :-
841 Abstractions = [Abstract|FurtherAbstractions],
842 get_event_from_model(Refines,Abstract,Event),
843 internal_event_params(Event,_,NewParameters),
844 internal_event_refined(Event,_,NewRefines),
845 add_unique_parameters(NewParameters,OldParameters,Parameters2),
846 merge_parameters(NewRefines,Parameters2,FurtherAbstractions,Parameters3),
847 merge_parameters(Rest,Parameters3,Abstractions,Parameters).
848 add_unique_parameters([],Parameters,Parameters).
849 add_unique_parameters([P|PRest],InParameters,OutParameters) :-
850 ( find_identifier_in_list(P,InParameters,_) ->
851 !,Parameters = InParameters
852 ; otherwise ->
853 Parameters = [P|InParameters]),
854 add_unique_parameters(PRest,Parameters,OutParameters).
855 */
856
857 get_event_from_model(Name,Model,Event) :-
858 internal_model_events(Model,_,Events),
859 internal_event(Event,Name),
860 member(Event,Events),!.
861
862 collect_modified_vars(Actions,Events,Vars) :-
863 ~~mnf( get_modified_vars_of_actions(Actions,M1) ),
864 append_modified_vars_of_events(Events,M2),
865 append(M1,M2,M3),sort(M3,Vars).
866 get_modified_vars_of_actions([],[]).
867 get_modified_vars_of_actions([Action|Arest],Vars) :-
868 get_modified_vars_of_action(Action,Vlocal),
869 append(Vlocal,Vrest,Vars),
870 get_modified_vars_of_actions(Arest,Vrest).
871 get_modified_vars_of_action(Action,Vars) :-
872 get_texpr_info(Action,Infos),
873 member(modifies(Vars), Infos),!.
874
875 add_modified_vars_to_actions([],[]).
876 %add_modified_vars_to_actions([TAction|ARest],MRest) :-
877 % get_texpr_expr(TAction,skip),!, % remove skip actions % for Daniel: is this better than keeping them ??
878 % add_modified_vars_to_actions(ARest,MRest).
879 add_modified_vars_to_actions([TAction|ARest],[MAction|MRest]) :-
880 (add_modified_vars_to_action(TAction,MAction) ->true
881 ; add_internal_error('Call failed: ',add_modified_vars_to_action(TAction,MAction)),
882 MAction = TAction),
883 add_modified_vars_to_actions(ARest,MRest).
884 add_modified_vars_to_action(TAction,MAction) :-
885 get_lhs_ids(TAction,Vars),
886 maplist(prime_id,Vars,Primed),
887 add_texpr_infos(TAction,[assigned_after(Primed),modifies(Vars)],MAction).
888
889 get_lhs_ids(TAction,Ids) :-
890 get_lhs_tids(TAction,Vars),
891 get_texpr_ids(Vars,Ids).
892 get_lhs_tids(TAction,Vars) :-
893 get_texpr_expr(TAction,Action),
894 split_lhs_rhs(Action,Lhs,_),
895 extract_lhs_ids(Lhs,Vars).
896
897 split_lhs_rhs(skip,[],[]). % not needed as skip removed above
898 split_lhs_rhs(assign(Ids,Exprs),Ids,Exprs).
899 split_lhs_rhs(assign_single_id(Id,Expr),[Id],[Expr]).
900 split_lhs_rhs(becomes_element_of(Ids,Expr),Ids,[Expr]).
901 split_lhs_rhs(becomes_such(Ids,Pred),Ids,[Pred]).
902 split_lhs_rhs(evb2_becomes_such(Ids,Pred),Ids,[Pred]).
903 extract_lhs_ids([],[]).
904 extract_lhs_ids([TId|TRest],[Var|VRest]) :-
905 extract_lhs_id(TId,Var),
906 extract_lhs_ids(TRest,VRest).
907 extract_lhs_id(Id,Var) :-
908 get_texpr_id(Id,_),!,Var=Id.
909 extract_lhs_id(Func,Var) :-
910 get_texpr_expr(Func,function(Id,_)),
911 get_texpr_id(Id,Var).
912
913 append_modified_vars_of_events(Events,Vars) :-
914 append_modified_vars_of_events2(Events,Unsorted),
915 sort(Unsorted,Vars).
916 append_modified_vars_of_events2([],[]).
917 append_modified_vars_of_events2([TEvent|ERest],Vars) :-
918 get_modified_vars_of_event(TEvent,Local),
919 append(Local,VRest,Vars),
920 append_modified_vars_of_events2(ERest,VRest).
921 get_modified_vars_of_event(TEvent,Local) :-
922 get_texpr_info(TEvent,Info),
923 memberchk(modifies(Local),Info).
924
925 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
926 % get all the variables that are accessed in an event
927 collect_read_vars(AllParams,Guard,Theorems,Actions,VWitnesses,PWitnesses,AbstractEvents,Reads) :-
928 get_texpr_ids(AllParams,Params), % access to parameters is not reading a variable
929 find_identifier_uses(Guard,Params,GrdVars),
930 find_identifier_uses_l(Theorems,Params,ThmVars),
931 maplist(find_all_action_reads(Params),Actions,ActVars0), ord_union(ActVars0, ActVars),
932 maplist(find_all_witness_reads(Params),VWitnesses,VWitVars0), ord_union(VWitVars0,VWitVars),
933 maplist(find_all_witness_reads(Params),PWitnesses,PWitVars0), ord_union(PWitVars0,PWitVars),
934 join_abstract_reads(AbstractEvents,AbstrVars),
935 ord_union([GrdVars,ThmVars,ActVars,VWitVars,PWitVars,AbstrVars],Reads).
936 %find_all_identifiers(Ignore,Expr,Vars) :-
937 % find_identifier_uses(Expr,Ignore,Vars). % Just switch arguments to allow the use of maplist
938 find_all_action_reads(Ignore,TAction,Res) :-
939 get_texpr_expr(TAction,Action),
940 (find_action_reads2(Action,Ignore,Vars) -> Res=Vars
941 ; add_internal_error('Illegal action: ',find_action_reads2(Action,Ignore,_)),Res=[]).
942 find_action_reads2(skip,_,Vars) :- Vars=[].
943 find_action_reads2(assign(_,Exprs),Ignore,Vars) :- find_identifier_uses_l(Exprs,Ignore,Vars).
944 find_action_reads2(assign_single_id(_,Expr),Ignore,Vars) :- find_identifier_uses(Expr,Ignore,Vars).
945 find_action_reads2(becomes_element_of(_,Expr),Ignore,Vars) :- find_identifier_uses(Expr,Ignore,Vars).
946 find_action_reads2(becomes_such(Ids,Pred),Ignore,Vars1) :-
947 % all references to Ids are to the state after: not a read
948 get_texpr_ids(Ids,AtomicIds),
949 append(AtomicIds,Ignore,Ignore0),sort(Ignore0,Ignore1),
950 find_identifier_uses(Pred,Ignore1,Vars),
951 prime_identifiers0(Ids,Ids0), % Ids with $0 afterwards
952 get_texpr_ids(Ids0,AtomicIds0),
953 maplist(unprime_id(AtomicIds0,AtomicIds),Vars,Vars1).
954 %find_action_reads2(evb2_becomes_such(Ids,Pred),Ignore,Vars) :-
955 % prime_variables(Ids,PIds),get_texpr_ids(PIds,Primes),
956 % append(Primes,Ignore,Ignore0),sort(Ignore0,Ignore1),
957 % find_identifier_uses(Pred,Ignore1,Vars).
958 find_all_witness_reads(Ignore,Witness,Vars) :-
959 get_texpr_expr(Witness,witness(I,P)),
960 get_texpr_id(I,Id),
961 sort([Id|Ignore],Ignore2),
962 find_identifier_uses(P,Ignore2,Vars1),
963 % a small hack to remove the primed variables that refer to the after-state
964 % without the need to put all variables in the Ingore list:
965 exclude(is_primed_id,Vars1,Vars).
966 is_primed_id(Id) :- atom_codes(Id,Codes),[Prime]="'",last(Codes,Prime).
967 join_abstract_reads([],[]) :- !.
968 join_abstract_reads(AbstractEvents,Reads) :-
969 maplist(get_read_from_info,AbstractEvents,AbsReads),
970 ord_union(AbsReads,ReadBySome),
971 maplist(get_modifies_from_info,AbstractEvents,AbsModifies),
972 ord_union(AbsModifies,ModifiedBySome),
973 ord_intersection(AbsModifies,ModifiedByAll),
974 ord_subtract(ModifiedBySome,ModifiedByAll,ModifiedByNotAll),
975 ord_union(ReadBySome,ModifiedByNotAll,Reads).
976 get_read_from_info(AbstrEvents,Reads) :-
977 get_texpr_info(AbstrEvents,Info),memberchk(reads(Reads),Info).
978 get_modifies_from_info(AbstrEvents,Modifies) :-
979 get_texpr_info(AbstrEvents,Info),memberchk(modifies(Modifies),Info).
980
981 add_equality_check(Actions,AbstractActions,NewVars,Variables,Unmodifiables) :-
982 get_modified_vars_of_actions(Actions,Modified),
983 get_modified_vars_of_actions(AbstractActions,AbstractModified),
984 unmodifiables(Modified,AbstractModified,NewVars,Variables,Unmodifiables).
985 unmodifiables([],_AbstractModified,_NewVars,_Variables,[]).
986 unmodifiables([UM|Modified],AbstractModified,NewVars,Variables,Unmodifiables) :-
987 ( is_modifiable(UM,AbstractModified,NewVars) ->
988 Unmodifiables = UMrest
989 ; otherwise ->
990 get_texpr_id(TUM,UM),
991 member(TUM,Variables),!,
992 Unmodifiables = [TUM|UMrest]),
993 unmodifiables(Modified,AbstractModified,NewVars,Variables,UMrest).
994 % the abstract event modifies it, so we can do it, too
995 is_modifiable(UM,AbstractModified,_NewVars) :- member(UM,AbstractModified),!.
996 % the variables is newly introduced, so we can modifiy it
997 is_modifiable(UM,_AbstractModified,NewVars) :-
998 get_texpr_id(TUM,UM), member(TUM,NewVars).
999
1000 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1001 % normalising merged events means that if two refined events A and B
1002 % change a different set of variables then the event A gets an additional
1003 % assignment of the form x:=x with x as a variable that is changed in B
1004 % but not in A.
1005 % This can happen even though merged events have the same assignments because
1006 % they again can refine events that have different assignments.
1007
1008 % None or one refined event do not have to be normalised
1009 normalise_merged_events([],[]) :- !.
1010 normalise_merged_events([E],[E]) :- !.
1011 normalise_merged_events(Events,Normalised) :-
1012 append_modified_vars_of_events(Events,AllModifiedVars),
1013 find_typed_version_in_events(AllModifiedVars,Events,TypedVars),
1014 normalise_merged_events2(Events,AllModifiedVars,TypedVars,Normalised).
1015 normalise_merged_events2([],_AllModifiedVars,_TypedVars,[]).
1016 normalise_merged_events2([Event|Erest],AllModifiedVars,TypedVars,[Normalised|Nrest]) :-
1017 normalise_merged_event(Event,AllModifiedVars,TypedVars,Normalised),
1018 normalise_merged_events2(Erest,AllModifiedVars,TypedVars,Nrest).
1019 normalise_merged_event(Event,AllModifiedVars,TypedVars,Normalised) :-
1020 get_modified_vars_of_event(Event,Modified),
1021 remove_all(AllModifiedVars,Modified,MissingVars),
1022 add_missing_assignments(MissingVars,Event,AllModifiedVars,TypedVars,Normalised).
1023 add_missing_assignments([],Event,_,_,Event) :- !.
1024 add_missing_assignments(MissingVars,TEvent,AllModifiedVars,TypedVars,Normalised) :-
1025 get_texpr_expr(TEvent,Event),
1026 get_texpr_type(TEvent,Type),
1027 get_texpr_info(TEvent,Infos),
1028 selectchk(modifies(_),Infos,RestInfos), % TO DO: also add reads Information
1029 create_texpr(NewEvent,Type,[modifies(AllModifiedVars)|RestInfos],Normalised),
1030 Event = rlevent(Name,Sec,St,Prm,Grd,Thm,Actions,VWit,PWit,Unmod,AbsEvents),
1031 NewEvent = rlevent(Name,Sec,St,Prm,Grd,Thm,NewActions,VWit,PWit,Unmod,AbsEvents),
1032 append(Actions,NewAssignments,NewActions),
1033 create_missing_assignments(MissingVars,TypedVars,NewAssignments).
1034 create_missing_assignments([],_TypedVars,[]).
1035 create_missing_assignments([MissingVar|Mrest],TypedVars,[Assign|Arest]) :-
1036 create_missing_assignment(MissingVar,TypedVars,Assign),
1037 create_missing_assignments(Mrest,TypedVars,Arest).
1038 create_missing_assignment(Var,TypedVars,Assignment) :-
1039 get_texpr_id(TId,Var),
1040 memberchk(TId,TypedVars),
1041 prime_id(Var,Primed),
1042 create_texpr(assign([TId],[TId]),subst,[assigned_after(Primed),modifies(Var)],Assignment).
1043
1044 find_typed_version_in_events([],_Events,[]).
1045 find_typed_version_in_events([Name|Nrest],Events,[Typed|Trest]) :-
1046 find_typed_version_in_events2(Name,Events,Typed),
1047 find_typed_version_in_events(Nrest,Events,Trest).
1048 find_typed_version_in_events2(Name,Events,Typed) :-
1049 get_texpr_id(Typed,Name),
1050 member(Event,Events),
1051 get_texpr_expr(Event,rlevent(_Name,_Sec,_St,_Prm,_Grd,_Thm,Actions,_VWit,_PWit,_Unmod,AbsEvents)),
1052 find_typed_version_in_events3(Name,Actions,AbsEvents,Typed),!.
1053 find_typed_version_in_events3(_Name,Actions,_AbsEvents,Typed) :-
1054 member(Action,Actions),
1055 get_lhs_tids(Action,Vars),
1056 member(Typed,Vars),!.
1057 find_typed_version_in_events3(Name,_Actions,AbsEvents,Typed) :-
1058 find_typed_version_in_events2(Name,AbsEvents,Typed).
1059
1060 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1061 % optimisation of guards:
1062 % A guard in a refinement does not need to be evaluated in in an abstract event
1063 % again. This happens quiet frequently, especially if "extends" is used.
1064 % The same applies for assignments: If in a refinement an action is performed,
1065 % we do not have to check if the same action can be performed in a more abstract
1066 % level.
1067 optimise_events(TEvent,NTEvent) :-
1068 empty_avl(Empty),
1069 optimise_events2(Empty,TEvent,NTEvent).
1070 optimise_events2(KnownElements,TEvent,NTEvent) :-
1071 create_texpr(Event,Type,Infos,TEvent),
1072 create_texpr(NewEvent,Type,Infos,NTEvent),
1073 Event = rlevent(Name,Section,Status,Params,OldGuard,OldTheorems,OldActions,
1074 VWitnesses,PWitnesses,Unmodifiables,OldAbstractEvents),
1075 NewEvent = rlevent(Name,Section,Status,Params,NewGuard,NewTheorems,NewActions,
1076 VWitnesses,PWitnesses,Unmodifiables,NewAbstractEvents),
1077 optimise_guards(OldGuard,OldTheorems,KnownElements,NewGuard,NewTheorems,KnownElements1),
1078 optimise_formulas(OldActions,KnownElements1,NewActions,NewKnownElements),
1079 maplist(optimise_events2(NewKnownElements),OldAbstractEvents,NewAbstractEvents).
1080 optimise_guards(OldGuard,OldTheorems,KnownElements,NewGuard,NewTheorems,NewKnownElements) :-
1081 conjunction_to_list(OldGuard,OldGuards),
1082 optimise_formulas(OldGuards,KnownElements,NewGuards,KnownElements1),
1083 % If no elements were removed, we just use the old guard
1084 ( OldGuards=NewGuards -> OldGuard=NewGuard
1085 ; otherwise -> conjunct_predicates(NewGuards,NewGuard)
1086 ),
1087 optimise_formulas(OldTheorems,KnownElements1,NewTheorems,NewKnownElements).
1088 % optimise_formulas(+AllFormulas,+KnownElements,-NewFormulas,-NewNormed)
1089 % AllFormulas: A list of formulas
1090 % KnownElementes: A list of normed versions of already encountered elements
1091 % NewFormulas: A sub-list of AllFormulas which are new (not in KnownElements)
1092 % NewKnownElements: The updated list of already encountered elements
1093 % If no formulas are removed, it is guaranteed that NewFormulas=AllFormulas
1094 optimise_formulas(AllFormulas,KnownElements,NewFormulas,NewKnownElements) :-
1095 % convert formulas to a list: Formula/Normed where Normed is a normalised form
1096 maplist(add_stripped_ast,AllFormulas,AllFormNormed),
1097 % remove the already known formulas
1098 exclude(is_duplicate_formula(KnownElements),AllFormNormed,NewFormNormed),
1099 % split the list [Form/Normed] into [Form] and [Normed]
1100 maplist(unzipslash,NewFormNormed,NewFormulas1,NewNormed),
1101 ( AllFormNormed = NewFormNormed -> % No formulas removed, keep everything as it is
1102 NewFormulas = AllFormulas
1103 ; otherwise ->
1104 NewFormulas = NewFormulas1
1105 ),
1106 foldl(add_to_known_elements,NewNormed,KnownElements,NewKnownElements).
1107 add_stripped_ast(Formula,Formula/Stripped) :-
1108 strip_and_norm_ast(Formula,Stripped).
1109 is_duplicate_formula(KnownElements,_Formula/Stripped) :-
1110 avl_fetch(Stripped,KnownElements). % remark: if some ast_cleanup operations introduce fresh identifiers (e.g., comp_result) then we may not detect formulas as identical here !
1111 unzipslash(A/B,A,B).
1112 add_to_known_elements(New,In,Out) :-
1113 avl_store(New,In,true,Out).
1114
1115 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1116 % internal event handling (just data structure)
1117 internal_event(event(Name,_Section,_Status,_Params,_Grd,_Thm,_Act,_VWit,_PWit,_Unmod,_Ref),Name).
1118 internal_event_status(event(Name,_Section,Status,_Params,_Grd,_Thm,_Act,_VWit,_PWit,_Unmod,_Ref),Name,Status).
1119 internal_event_params(event(Name,_Section,_Status,Params,_Grd,_Thm,_Act,_VWit,_PWit,_Unmod,_Ref),Name,Params).
1120 internal_event_actions(event(Name,_Section,_Status,_Params,_Grd,_Thm,Act,_VWit,_PWit,_Unmod,_Ref),Name,Act).
1121 internal_event_refined(event(Name,_Section,_Status,_Params,_Grd,_Thm,_Act,_VWit,_PWit,_Unmod,Ref),Name,Ref).
1122
1123 internal_context(context(Name,_Extends,_Sets,_Constants,_AbstractConstants,_Axioms,_Theorems),Name).
1124 internal_context_extends(context(Name,Extends,_Sets,_Constants,_AbstractConstants,_Axioms,_Theorems),Name,Extends).
1125 internal_context_sets(context(Name,_Extends,Sets,_Constants,_AbstractConstants,_Axioms,_Theorems),Name,Sets).
1126 internal_context_constants(context(Name,_Extends,_Sets,Constants,_AbstractConstants,_Axioms,_Theorems),Name,Constants).
1127 internal_context_abstract_constants(context(Name,_Extends,_Sets,_Constants,AbstractConstants,_Axioms,_Theorems),Name,AbstractConstants).
1128
1129 internal_model(model(Name,_Refines,_Sees,_Variables,_NewVariables,_Invariants,_Theorems,_Events),Name).
1130 internal_model_refines(model(Name,Refines,_Sees,_Variables,_NewVariables,_Invariants,_Theorems,_Events),Name,Refines).
1131 internal_model_sees(model(Name,_Refines,Sees,_Variables,_NewVariables,_Invariants,_Theorems,_Events),Name,Sees).
1132 internal_model_vars(model(Name,_Refines,_Sees,Variables,_NewVariables,_Invariants,_Theorems,_Events),Name,Variables).
1133 internal_model_newvars(model(Name,_Refines,_Sees,_Variables,NewVariables,_Invariants,_Theorems,_Events),Name,NewVariables).
1134 internal_model_invs(model(Name,_Refines,_Sees,_Variables,_NewVariables,Invariants,_Theorems,_Events),Name,Invariants).
1135 internal_model_thms(model(Name,_Refines,_Sees,_Variables,_NewVariables,_Invariants,Theorems,_Events),Name,Theorems).
1136 internal_model_events(model(Name,_Refines,_Sees,_Variables,_NewVariables,_Invariants,_Theorems,Events),Name,Events).
1137
1138 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1139 % analyse deferred sets and generate enumerated sets if possible
1140
1141
1142
1143
1144 %% :- include(bmachine_eventb_common).
1145 %% code below used to be in separate file, as there was the single-level and multi-level mode:
1146
1147
1148
1149 extract_name(event_b_model(_,Name,_Sections),Res) :- !, Res=Name.
1150 extract_name(event_b_context(_,Name,_Sections),Res) :- !, Res=Name.
1151 extract_name(MODEL,_) :- add_error(extract_name,'Could not extract model name: ',MODEL),fail.
1152
1153 extract_sections(event_b_model(_,_Name,Sections),Sections).
1154 extract_sections(event_b_context(_,_Name,Sections),Sections).
1155
1156 % topological sort
1157
1158 topological_sort(List,Sorted) :-
1159 get_dependencies(List,Dependencies),
1160 topolsort(Dependencies,[],SortedNames),
1161 get_sorted(SortedNames,List,Sorted),!.
1162 topological_sort(List,Sorted) :- add_failed_call_error(topological_sort(List,Sorted)),fail.
1163
1164 get_dependencies([],[]).
1165 get_dependencies([E|Rest],[dep(Name,Deps)|Drest]) :-
1166 extract_name(E,Name),
1167 findall(D,dependency(E,D),Deps1),
1168 sort(Deps1,Deps),
1169 get_dependencies(Rest,Drest).
1170
1171 dependency(Elem,Dependend) :-
1172 extract_sections(Elem,Sections),
1173 ( rawmachine_section(extends,Sections,Extends),
1174 member(Dependend,Extends)
1175 ; rawmachine_section(refines,Sections,Dependend)).
1176
1177 topolsort([],_,[]) :- !.
1178 topolsort(Deps,Fulfilled,[First|Rest]) :-
1179 select(dep(First,Before),Deps,Drest),
1180 is_sublist(Before,Fulfilled),!,
1181 sort([First|Fulfilled],NewFulfilled),
1182 topolsort(Drest,NewFulfilled,Rest).
1183 is_sublist([],_).
1184 is_sublist([H|T],[F|R]) :-
1185 ( H=F -> is_sublist(T,R)
1186 ; otherwise -> is_sublist([H|T],R)).
1187
1188 get_sorted([],_,[]).
1189 get_sorted([Name|Nrest],Elems,[First|Srest]) :-
1190 member(First,Elems),
1191 extract_name(First,Name),!,
1192 get_sorted(Nrest,Elems,Srest).
1193
1194 % copy&paste from bmachine_construction
1195 rawmachine_section(Elem,List,Result) :-
1196 functor(Pattern,Elem,2),
1197 arg(2,Pattern,Result),
1198 member(Pattern,List),!.
1199
1200 optional_rawmachine_section(Elem,List,Default,Result) :-
1201 ( rawmachine_section(Elem,List,Result1) -> true
1202 ; Result1=Default),
1203 Result1=Result.
1204
1205 % ----------------------------------------
1206
1207
1208 % older versions of the .eventb files do not have a status included
1209 raw_event(event(Pos,Name,RawRefines,Params,Guards,Actions,Witnesses),
1210 Pos,Name,ordinary(none),Refines,Params,Guards,[],Actions,Witnesses) :-
1211 (\+((RawRefines==[] ; RawRefines=[_|_]))
1212 -> add_error(b_machine_eventb,'Outdated .eventb format, ignoring refines:',RawRefines),
1213 Refines = []
1214 ; Refines=RawRefines).
1215 raw_event(event(Pos,Name,Status,Refines,Params,Guards,Actions,Witnesses),
1216 Pos,Name,Status,Refines,Params,Guards,[],Actions,Witnesses).
1217 raw_event(event(Pos,Name,Status,Refines,Params,Guards,Theorems,Actions,Witnesses),
1218 Pos,Name,Status,Refines,Params,Guards,Theorems,Actions,Witnesses).
1219
1220 % code common to bmachine_eventb.pl and bmachine_eventb_ml.pl
1221
1222 :- use_module(bmachine_structure,[select_section/5]).
1223 append_to_section(Section,List,Old,New) :-
1224 % todo: access to private elements of bmachine_construction
1225 select_section(Section,OldList,NewList,Old,New),
1226 append(OldList,List,NewList).
1227 conjunct_to_section(Section,Preds,Old,New) :-
1228 % todo: access to private elements of bmachine_construction
1229 select_section(Section,OldPred,NewPred,Old,New),
1230 conjunct_predicates([OldPred|Preds],NewPred).
1231
1232 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1233 % analyse Event-B deferred sets and generate enumerated sets if possible
1234
1235 enumerated_deferred_sets(Sets,Constants,Axioms,NewSets,NewConstants,NewAxioms,TSet,TElements) :-
1236 conjunct_predicates(Axioms,Axiom),
1237 conjunction_to_list(Axiom,Axiom2),
1238 enumerated_deferred_sets2(Sets,Constants,Axiom2,NewSets,NewConstants,NewAxioms,TSet,TElements).
1239
1240 enumerated_deferred_sets2([],Csts,Axioms,[],Csts,Axioms,[],[]).
1241 enumerated_deferred_sets2([Set|SetRest],Csts,Axioms,NewSets,NewCsts,NewAxioms,[TSet|TSetRest],TElementsAll) :-
1242 % case 1: the set is an enumerated set
1243 enumerated_deferred_set(Set,Csts,Axioms,ICsts,IAxioms,TSet,TElements),!,
1244 append(TElements,TElementsRest,TElementsAll),
1245 enumerated_deferred_sets2(SetRest,ICsts,IAxioms,NewSets,NewCsts,NewAxioms,TSetRest,TElementsRest).
1246 enumerated_deferred_sets2([Set|SetRest],Csts,Axioms,[Set|NewSets],NewCsts,NewAxioms,TSets,TElements) :-
1247 % case 2: the set is a normal deferred set
1248 enumerated_deferred_sets2(SetRest,Csts,Axioms,NewSets,NewCsts,NewAxioms,TSets,TElements).
1249
1250 enumerated_deferred_set(Set,Constants,Axioms,NewConstants,NewAxioms,Set,TElements) :-
1251 %% print(checking_for_enumerated_deferred_sets(Axioms)),nl,
1252 has_enumeration_axioms(Set,Elements,Axioms,NewAxioms),
1253 %% print(found_enumerated_set(Set)),nl, %%
1254 % remove Elem1,...,ElemN from the constants
1255 remove_constants(Elements,Constants,NewConstants),
1256 % add enumerated set information to the elements
1257 get_texpr_type(Set,SType),
1258 (SType=set(global(Type)) -> true
1259 ; add_error_and_fail(enumerated_deferred_set,'Unexpected Set: ',(Set:SType))),
1260 (typeset_enumerated(Elements,Type,TElements) -> true
1261 ; add_error_and_fail(enumerated_deferred_set,'Could not typeset: ',(Type,Elements))).
1262
1263
1264 has_enumeration_axioms(Set,Elements,AxiomsIn,AxiomsOut) :-
1265 has_partition_axioms(Set,Elements,AxiomsIn,AxiomsOut),!.
1266 has_enumeration_axioms(Set,Elements,AxiomsIn,AxiomsOut) :-
1267 % there in an axiom Set = {Elem1,...,ElemN}
1268 select_equal_extension_set_of_ids(Set,AxiomsIn,Axioms1,ExtSet,Elements),
1269 % check if all axioms needed for an enumeration are
1270 % present, and remove them
1271 % second case: All elements of the set are mutually unequal
1272
1273 % generate the unequalities we have to check for
1274 generate_unequals(Elements,Unequals),
1275 % check if they are all in the axioms, and remove them from the axioms
1276 (all_unequals_present(Unequals,Axioms1,AxiomsOut) -> true
1277 ; assert(deferred_set_eq_wo_enumeration_axioms(Set,ExtSet)),
1278 print('Deferred set with equality but *not* recognized as enumerated set: '),
1279 translate:print_bexpr(Set), print(' = '), translate:print_bexpr(ExtSet),nl,
1280 fail
1281 ).
1282
1283 has_partition_axioms(Set,PartitionElements,AxiomsIn,AxiomsOut) :-
1284 % print(checking_for_enumeration_axioms(Set)),nl,
1285 % first case: A partion predicate is present with
1286 % all elements of the set as its arguments
1287 % ( e.g. partition(S,{a},{b},...) )
1288
1289 % create a pattern for the partition:
1290 get_texpr_id(Set,SetId),get_texpr_id(SetRef,SetId),
1291 create_texpr(partition(SetRef,Singletons),pred,_,Partition),
1292 % remove the partition from the axioms
1293 % print(looking_for_partition(SetId,Partition)),nl,nl,
1294 select(Partition,AxiomsIn,AxiomsOut1),
1295 %%print(found_partition(SetID,Partition)),nl,
1296 % check if all arguments are singletons and get the
1297 % singleton elements
1298 all_singletons(Singletons,PartitionElements,AxiomsOut1,AxiomsOut2,Recursive),
1299 (Recursive==true
1300 -> AxiomsOut=AxiomsIn /* then we still need the partition axioms */
1301 ; AxiomsOut=AxiomsOut2).
1302 %% ,print(all_singletons(Singletons)),nl.
1303 %% print(singletons(PartitionElements)),nl,
1304 % check if all arguments and the identifiers
1305 % of the set are the same
1306 % same_elements(Elements,PartitionElements).
1307
1308
1309 % all elements of a list are singletons, the second argument
1310 % returns the list of elements without the set around it
1311 all_singletons([],[],Ax,Ax,_).
1312 all_singletons([Set|SRest],[Expr|ERest],AxiomsIn,AxiomsOut,Recursive) :-
1313 get_texpr_expr(Set,set_extension([Expr])),!,
1314 all_singletons(SRest,ERest,AxiomsIn,AxiomsOut,Recursive).
1315 all_singletons([ID1|SRest],Result,AxiomsIn,AxiomsOut,Recursive) :-
1316 ID1 = b(identifier(_ID),set(global(_)),_Info),
1317 Recursive=true,
1318 % print(trying_to_look_for_recursive_partition(_ID)),nl, %%
1319 has_enumeration_axioms(ID1,PartitionElements,AxiomsIn,AxiomsOut1),
1320 % print(recursive_partition(ID,PartitionElements)),nl,
1321 append(PartitionElements,ERest,Result),
1322 all_singletons(SRest,ERest,AxiomsOut1,AxiomsOut,_).
1323
1324 % the two lists of typed identifiers have the same identifiers
1325 %same_elements(ElemsA,ElemsB) :-
1326 % get_texpr_ids(ElemsA,IdsA),sort(IdsA,A),
1327 % get_texpr_ids(ElemsB,IdsB),sort(IdsB,B),
1328 % A=B.
1329
1330 typeset_enumerated([],_Type,[]).
1331 typeset_enumerated([Elem|Erest],Type,[TElem|Trest]) :-
1332 create_texpr(identifier(Id),global(Type),Infos,Elem),
1333 create_texpr(identifier(Id),global(Type),[enumerated_set_element|Infos],TElem),
1334 typeset_enumerated(Erest,Type,Trest).
1335
1336 remove_constants([],Cst,Cst).
1337 remove_constants([TId|Erest],In,Out) :-
1338 get_texpr_id(TId,Id),
1339 get_texpr_id(Pattern,Id),
1340 select(Pattern,In,Env),
1341 remove_constants(Erest,Env,Out).
1342
1343 % find an equality Set = {id1,...,idk}
1344 select_equal_extension_set_of_ids(Set,In,Out,Ext,Elements) :-
1345 get_texpr_id(Set,SetId),
1346 get_texpr_id(Expr,SetId),
1347 create_texpr(set_extension(Elements),_,_,Ext),
1348 create_texpr(Equal,_,_,TEqual),
1349 ( Equal = equal(Expr,Ext); Equal = equal(Ext,Expr) ),
1350 select(TEqual,In,Out),!.
1351
1352 generate_unequals(Elements,Unequals) :-
1353 get_texpr_ids(Elements,Ids),
1354 findall(unequal(A,B),two_ids(Ids,A,B),Unequals).
1355 two_ids([A|Rest],A,B) :- member(B,Rest).
1356 two_ids([_|Rest],A,B) :- two_ids(Rest,A,B).
1357
1358 all_unequals_present([],Axioms,Axioms).
1359 all_unequals_present([unequal(A,B)|Rest],InAxioms,OutAxioms) :-
1360 remove_unequalities(InAxioms,A,B,IntAxioms,0,N), N>0,!, % at least one occurrence
1361 all_unequals_present(Rest,IntAxioms,OutAxioms).
1362
1363 remove_unequalities([],_,_,[],N,N).
1364 remove_unequalities([TAxiom|T],A,B,Rest,NrRemoved,R) :-
1365 get_texpr_id(AExpr,A), get_texpr_id(BExpr,B),
1366 get_texpr_expr(TAxiom,Axiom),
1367 is_unequality(Axiom,AExpr,BExpr),!, N1 is NrRemoved+1,
1368 remove_unequalities(T,A,B,Rest,N1,R).
1369 remove_unequalities([Axiom|T],A,B,[Axiom|TR],N,R) :- % not an unequality between A and B
1370 remove_unequalities(T,A,B,TR,N,R).
1371
1372 is_unequality(not_equal(A,B),A,B) :- !.
1373 is_unequality(not_equal(B,A),A,B) :- !.
1374 is_unequality(negation(TEqual),A,B) :-
1375 get_texpr_expr(TEqual,Equal),
1376 is_equality(Equal,A,B).
1377 is_equality(equal(A,B),A,B) :- !.
1378 is_equality(equal(B,A),A,B) :- !.
1379
1380 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1381 % creating a type environment with information about theories inside
1382
1383 check_extensions(Infos,Freetypes,Ops,TheoryEnv) :-
1384 findall( T, (member(T,Infos),is_eventb_additional_info(T)), Theories),
1385 default_theory_ops(InitialEnv),
1386 foldl(check_theory,Theories,FreetypesL,OpsL,InitialEnv,TheoryEnv),
1387 append(FreetypesL,Freetypes),append(OpsL,Ops).
1388 is_eventb_additional_info(Term) :-
1389 nonvar(Term),functor(Term,theory,Arity),
1390 memberchk(Arity,[3,4,5,7]).
1391 default_theory_ops(Env) :-
1392 env_empty(Empty),
1393 cond_operator(Id,Op),
1394 env_store_operator(Id,Op,Empty,Env).
1395 cond_operator('COND',bmachine_eventb:direct_definition(Params,DirectDef,[PT])) :-
1396 PT = '__IFTHENELSETYPE',
1397 TypeExpr = identifier(none,PT),
1398 Params = [argument('THEN',TypeExpr),
1399 argument('ELSE',TypeExpr),
1400 argument('IF',set_extension(none,[truth(none)]))],
1401 DirectDef = if_then_else(none,identifier(none,'IF'),
1402 identifier(none,'THEN'),identifier(none,'ELSE')).
1403 check_theory(Theory,Freetypes,Ops,Env,OutEnv) :-
1404 (check_theory2(Theory,Env,Freetypes,Ops) -> true
1405 ; add_internal_error('Theory check failed:',Theory),fail),
1406 store_operator_list(Ops,Env,OutEnv).
1407 store_operator_list(Ops,Env,OutEnv) :-
1408 keys_and_values(Ops,Ids,Operators),
1409 foldl(env_store_operator,Ids,Operators,Env,OutEnv).
1410 check_theory2(theory(PT,Datatypes,OP),Env,Freetypes,Ops) :-
1411 % just to be backward-compatible to a version without axiomatic definitions
1412 check_theory2(theory(PT,Datatypes,OP,[]),Env,Freetypes,Ops).
1413 check_theory2(theory(PT,Datatypes,OP,AxDefs),Env,Freetypes,Ops) :-
1414 % just to be backward-compatible to a version without operator mapping
1415 % definitions
1416 check_theory2(theory(PT,Datatypes,OP,AxDefs,[]),Env,Freetypes,Ops).
1417 check_theory2(theory(PT,Datatypes,OP,AxDefs,Mappings),Env,Freetypes,Ops) :-
1418 check_theory2(theory(unknown,unknown,PT,Datatypes,OP,AxDefs,Mappings),Env,Freetypes,Ops).
1419 check_theory2(theory(_Id,_Imported,PT,Datatypes,OP,AxDefs,Mappings),Env,Freetypes,AllOps) :-
1420 extract_freetypes(Env,Datatypes,Freetypes,FreetypeOps),
1421 (Mappings=none -> ML=[] ; ML=Mappings), % some older .eventb files seem to have none here, e.g., Theory/SumProduct_m1_mch.eventb
1422 foldl(handle_mappings(PT),ML,MappedOpsL,OP/AxDefs,OP1/AxDefs1),
1423 append(MappedOpsL,MappedOps),
1424 maplist(store_operator(PT),OP1,DefinedOps),
1425 maplist(store_axiomatic_operator(PT),AxDefs1,AxOpsL),
1426 append(AxOpsL,AxOps),
1427 append([FreetypeOps,MappedOps,DefinedOps,AxOps],AllOps1),
1428 % The operators are used for call-backs, a module prefix is mandatory
1429 maplist(prefix_with_module,AllOps1,AllOps).
1430 prefix_with_module(Id-Op,Id-(bmachine_eventb:Op)).
1431
1432 store_operator(PT,operator(Id,Parameters,_WD,DirectDef,RecursiveDef),Id-Op) :-
1433 store_operator2(DirectDef,RecursiveDef,Parameters,PT,Op).
1434 store_operator2(_,RecursiveDef,Parameters,PT,Op) :-
1435 RecursiveDef=[_|_],!,Op=recursive_operator(Parameters,RecursiveDef,PT).
1436 store_operator2([Def],_,Parameters,PT,Op) :- !,
1437 Op=direct_definition(Parameters,Def,PT).
1438 store_operator2(_,_,_,_,Op) :-
1439 Op = unsupported_operator('Operators without direct definition are currently unsupported').
1440
1441 extract_freetypes(ParamEnv,DataTypes,Freetypes,FreetypeOps) :-
1442 maplist(extract_freetype(DataTypes,ParamEnv),DataTypes,Freetypes,FreetypeOpsL),
1443 append(FreetypeOpsL,FreetypeOps).
1444 extract_freetype(AllDataTypes,Env,
1445 datatype(Id,TypeParams,Constructors),
1446 freetype(FreetypeId,Cases),
1447 [Id-freetype_operator(FreetypeId,Types,TypeParams,Usage)|CaseOps]) :-
1448 foldl(add_datatype_to_env,AllDataTypes,Env,Env1),
1449 foldl(add_type_parameter,TypeParams,Types,Env1,ParamEnv),
1450 create_freetype_typeid(Id,Types,FreetypeId),
1451 Type = freetype(FreetypeId),
1452 extract_used_type_parameters(Constructors,TypeParams,Usage),
1453 store_eventb_operator(Id,freetype_operator_as_identifier(Id),ParamEnv,ParamEnv2),
1454 maplist(extract_case(ParamEnv2,Type,Types),Constructors,Cases,CaseOpsL),
1455 append(CaseOpsL,CaseOps).
1456 add_datatype_to_env(datatype(Id,Params,_),In,Out) :-
1457 length(Params,NumberOfParams),
1458 functor(FreetypeId,Id,NumberOfParams),
1459 env_store(Id,set(freetype(FreetypeId)),[],In,Out).
1460 add_type_parameter(TypeParam,Type,In,Out) :-
1461 extract_id(TypeParam,ParameterId),
1462 env_store(ParameterId,set(Type),[],In,Out).
1463 extract_id(identifier(_,Id),Id).
1464 % constructor without parameters
1465 extract_case(_ParamEnv,freetype(TypeId),_Types, constructor(Id,[]),
1466 case(Id,constant([Id])),Ops) :- !,
1467 Ops=[Id-constructor_operator(TypeId,[])].
1468 % constructor with parameters
1469 extract_case(ParamEnv,Freetype,ParamTypes,constructor(Id,Destructors),
1470 case(Id,Type),
1471 [Id-constructor_operator(FreetypeId,Types)|DestructOps]) :-
1472 maplist(extract_destructor(ParamEnv,Freetype,ParamTypes,Id,Type),
1473 Destructors,Projections,TypesAndOps),
1474 maplist(split_type_and_op,TypesAndOps,Types,DestructOps),
1475 Freetype=freetype(FreetypeId),
1476 combine_typelist_with_prj(Types,Type,Projections).
1477 extract_destructor(Env,freetype(FreetypeId),ParamTypes,Case,CType,
1478 destructor(Name,TypeExpr),Projection,Type-Name-Op) :-
1479 typecheck_with_freevars(TypeExpr,Env,ParamTypes,set(Type),_),
1480 Op = destructor_operator(FreetypeId,Projection,Case,CType).
1481 split_type_and_op(Type-Name-Op,Type,Name-Op).
1482
1483 create_freetype_typeid(Id,Types,FreetypeId) :-
1484 FreetypeId =.. [Id|Types].
1485
1486 :- assert_must_succeed(( combine_typelist_with_prj([a,b],T,P),
1487 T == couple(a,b), P == [[prj1],[prj2]] )).
1488 :- assert_must_succeed(( combine_typelist_with_prj([a,b,c],T,P),
1489 T == couple(a,couple(b,c)),
1490 P == [[prj1],[prj2,prj1],[prj2,prj2]] )).
1491 :- assert_must_succeed(( combine_typelist_with_prj([a,b,c,d],T,P),
1492 T == couple(couple(a,b),couple(c,d)),
1493 P == [[prj1,prj1],[prj1,prj2],[prj2,prj1],[prj2,prj2]] )).
1494 combine_typelist_with_prj([T],R,Projections) :- !,R=T,Projections=[[]].
1495 combine_typelist_with_prj(Types,couple(TypeL,TypeR),Projections) :-
1496 split_list_in_middle(Types,TypesLeft,TypesRight),
1497 same_length(TypesLeft,PrjLeft),same_length(TypesRight,PrjRight),
1498 append(PrjLeft,PrjRight,Projections),
1499 maplist(cons(prj1),PrjLeft1,PrjLeft),
1500 maplist(cons(prj2),PrjRight1,PrjRight),
1501 combine_typelist_with_prj(TypesLeft,TypeL,PrjLeft1),
1502 combine_typelist_with_prj(TypesRight,TypeR,PrjRight1).
1503 split_list_in_middle(List,Left,Right) :-
1504 length(List,N),
1505 Half is floor(N / 2),
1506 append_length(Left,Right,List,Half).
1507
1508 combine_exprlist_to_couple([T],R) :- !,T=R.
1509 combine_exprlist_to_couple(Exprs,R) :-
1510 split_list_in_middle(Exprs,ExprsLeft,ExprsRight),
1511 combine_exprlist_to_couple(ExprsLeft,TL),
1512 combine_exprlist_to_couple(ExprsRight,TR),
1513 get_texpr_types([TL,TR],[TypeL,TypeR]),
1514 create_texpr(couple(TL,TR),couple(TypeL,TypeR),[],R).
1515
1516 combine_exprlist_to_cprod([T],R) :- !,T=R.
1517 combine_exprlist_to_cprod(Exprs,R) :-
1518 split_list_in_middle(Exprs,ExprsLeft,ExprsRight),
1519 combine_exprlist_to_cprod(ExprsLeft,TL),
1520 combine_exprlist_to_cprod(ExprsRight,TR),
1521 get_texpr_types([TL,TR],[set(TypeL),set(TypeR)]),
1522 create_texpr(cartesian_product(TL,TR),set(couple(TypeL,TypeR)),[],R).
1523
1524 extract_used_type_parameters(Constructors,TypeParams,Usages) :-
1525 maplist(extract_id,TypeParams,TypeParamIds),
1526 convlist(used_type_parameters_of_constructor(TypeParamIds),Constructors,Usages).
1527 used_type_parameters_of_constructor(TypeParamIds,constructor(Id,Destructors),
1528 used_param_types(Id,UsedParamTypes,DestructorExprs)) :-
1529 maplist(destructor_expr,Destructors,DestructorExprs),
1530 maplist(used_type_parameters_of_destructor(TypeParamIds),
1531 DestructorExprs,UsedParamTypeL),
1532 UsedParamTypeL = [_|_], % store the information only for constructors that actually use
1533 % type parameters
1534 ord_union(UsedParamTypeL,UsedParamTypes).
1535 used_type_parameters_of_destructor(TypeParamIds,TypeExpr,UsedTypes) :-
1536 extract_raw_identifiers(TypeExpr,UsedIds),
1537 findall( N, (nth1(N,TypeParamIds,T),memberchk(T,UsedIds)), UsedTypes1),
1538 sort(UsedTypes1,UsedTypes).
1539 destructor_expr(destructor(_,Expr),Expr).
1540 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1541 % callback predicates for operators
1542
1543 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1544
1545 :- public unsupported_operator/9.
1546 unsupported_operator(Msg,Id,_Args,Pos,_Env,ExPr,Result,TRin,TRout) :-
1547 store_typecheck_error(Msg,Pos,TRin,TRout),
1548 failure_syntax_element(ExPr,Id,F,Type), % just to make sure that the result
1549 create_texpr(F,Type,[],Result). % is nonvar, to prevent later errors
1550 failure_syntax_element(expr,Id,identifier(Id),_).
1551 failure_syntax_element(pred,_Id,falsity,pred).
1552
1553 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1554
1555 :- use_module(prozsrc(z_tools),[create_z_let/6]).
1556
1557 % Theory plug-in: direct definitions
1558 :- public direct_definition/11.
1559 direct_definition(Params, % e.g. [argument(a,bool_set(none))]
1560 DirectDef, % Raw AST of DirectDefinition Body, e.g., convert_bool(none,negation(none,equal(none,identifier(none,a),boolean_true(none))))
1561 PT, _Id, TArgs, Pos,
1562 Env, % environment of operators
1563 ExPr,Result,TRin,TRout) :-
1564 (Params,DirectDef) = (NewParams,NewDirectDefBody), %gen_fresh_params(Params,DirectDef,NewParams,NewDirectDefBody),
1565 apply_direct_definition(TArgs,NewParams,NewDirectDefBody,PT,Env,Pos,TLetIds,TLetValues,TDef,TRin,TRout),
1566 create_z_let(ExPr,TLetIds,TLetValues,TDef,[],Result).
1567
1568 % Example: ddef([argument(R,pow_subset(none,identifier(none,T)))],seq(none,identifier(none,R)),[T],seq)
1569
1570 % this code not needed as we now systematically rename in create_z_let
1571 %:- use_module(input_syntax_tree,[raw_replace/3]).
1572 %gen_fresh_params(Params,DirectDef,NewParams,NewDirectDefBody) :-
1573 % maplist(alpha_rename,Params,NewParams,RenameList), %print(replaces(RenameList)),nl,
1574 % raw_replace(DirectDef,RenameList,NewDirectDefBody).
1575 %:- use_module(gensym,[gensym/2]).
1576 %alpha_rename(argument(OldID,Type),argument(FreshID,Type),replace(OldID,identifier(none,FreshID))) :-
1577 % gensym(OldID,FreshID).
1578
1579 % Args are the arguments of the operator where it is used
1580 % Params are the parameters in the operator definition
1581 :- public apply_direct_definition/11.
1582 apply_direct_definition(TArgs,Params,DirectDef,PT,Env,_Pos,
1583 TLetIds,TLetValues,TDef,TRin,TRout) :-
1584 same_length(TArgs,Params),!,
1585 maplist(create_typed_id,PT,ParametricTypes,TPT),
1586 add_identifiers_to_environment(TPT,Env,SubEnv),
1587 % type check the arguments given in the operator usage
1588 get_texpr_types(TArgs,ArgTypes),
1589 typecheck_arguments(Params,SubEnv,ArgTypes,TParams,TRin,TR2),
1590 % type check the direct definition of the operator. To do this we need the parameters of the operators
1591 % in the type environment. Their type is determined by the arguments of the operator call.
1592 add_identifiers_to_environment(TParams,SubEnv,DefEnv),
1593 btype(apply_direct_definition,DirectDef,DefEnv,_Type,TDef,TR2,TRout),
1594 append(TParams,TPT,TLetIds),
1595 maplist(create_typeset,ParametricTypes,TypeValues),
1596 append(TArgs,TypeValues,TLetValues).
1597 apply_direct_definition(_TArgs,_Arguments,_DirectDef,_PT,_Env,Pos,
1598 _TParams,_,_TDef,TRin,TRout) :-
1599 store_typecheck_error('Wrong number of operator arguments',Pos,TRin,TRout).
1600
1601 split_arg_and_typedef(argument(Id,TypeExpr),Id,TypeExpr).
1602 map_to_set_type(Type,set(Type)).
1603 typecheck_arguments(Params,Env,ArgTypes,TParams,TRin,TRout) :-
1604 % type check the parameters' type expressions of the operator definition, they should have the same type
1605 % as the arguments (except being a set)
1606 % E.g. an operator "o" has one argument "arg" and type expression "T**BOOL" (with T being a parameter type of the theory),
1607 % then for "o(5|->TRUE)" we have "couple(integer,boolean)" as the argument's type,
1608 % we add "T" to the type environment (with type set(_)),
1609 % then we type check the parameter expression "T**BOOL", expecting the type set(coule(integer,boolean)),
1610 % the type check results in T being of type set(integer).
1611 maplist(split_arg_and_typedef,Params,ParamIds,ParamTypeExprs),
1612 same_length(Params,ArgTypes),
1613 maplist(map_to_set_type,ArgTypes,SetArgTypes),
1614 btype_l(ParamTypeExprs,Env,SetArgTypes,_TParamTypeExprs,TRin,TRout),
1615 maplist(create_typed_id,ParamIds,ArgTypes,TParams).
1616 create_typeset(Type,TExpr) :- create_texpr(typeset,Type,[],TExpr).
1617
1618
1619
1620 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1621 :- public choose_operator/8.
1622 % Theory plug-in: CHOOSE operator
1623 % Maybe the use of the direct_definition operator would be possible but it turned out
1624 % that constructing the necessary parameters was quite tricky.
1625 choose_operator(Id,[TArg],Pos,_Env,ExPr,Result,TRin,TRout) :- !,
1626 ( get_texpr_type(TArg,set(Type)) ->
1627 create_texpr(external_function_call('CHOOSE',[TArg]),Type,[],Result),
1628 TRin = TRout
1629 ; otherwise ->
1630 failure_syntax_element(ExPr,Id,Expression,Type),
1631 create_texpr(Expression,Type,[],Result), % just to avoid free variables in the AST
1632 store_typecheck_error('Expected set for choose operator argument',Pos,TRin,TRout)
1633 ).
1634 choose_operator(_Id,_TArgs,Pos,_Env,_ExPr,_Result,TRin,TRout) :-
1635 store_typecheck_error('Wrong number of operator arguments',Pos,TRin,TRout).
1636
1637
1638 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1639 % Theory plug-in: Recursive operators
1640 :- public recursive_operator/11.
1641 recursive_operator(Arguments,Cases,PT,
1642 Id,TArgs,_Pos,Env,ExPr,Result,TRin,TRout) :-
1643 % parameter types
1644 maplist(create_typed_id,PT,ParametricTypes,TPT),
1645 add_identifiers_to_environment(TPT,Env,Env1),
1646 maplist(create_typeset,ParametricTypes,LetValues), % needed for the LET
1647 typecheck_arguments(Arguments,Env1,ArgTypes,TParamIds,TRin,TR1),
1648 % TArgs: A,B,Cf
1649 % TArg: A|->B|->C
1650 get_texpr_types(TArgs,ArgTypes),
1651 create_couple(TArgs,TArg),
1652 length(TArgs,NumberOfArgs),OpInfo = [theory_operator(Id,NumberOfArgs)],
1653 unique_id("opresult.",ResultId),create_typed_id(ResultId,Type,TResultId),
1654 ( ExPr=expr -> % Result: Comp(x|->y|->z)
1655 % we need to append a result parameter in the comprehension set
1656 create_texpr(function(TCompSet,TArg),Type,OpInfo,InnerResult),
1657 append(TParamIds,[TResultId],CompSetIds),append(ArgTypes,[Type],CompSetTypes),
1658 % make sure that we do not run into an infinite loop
1659 store_eventb_operator(Id,freetype_operator_as_function(RecId,Type),Env1,Env2)
1660 ; ExPr=pred -> % Result: x|->y|->z : Comp
1661 create_texpr(member(TArg,TCompSet),pred,OpInfo,InnerResult),
1662 CompSetIds = TParamIds,ArgTypes=CompSetTypes,
1663 % make sure that we do not run into an infinite loop
1664 store_eventb_operator(Id,freetype_operator_as_set(RecId),Env1,Env2)
1665 ),
1666 couplise_list(CompSetTypes,CompSetType),
1667 % Comp: {i,r| Cond}
1668 create_recursive_compset(CompSetIds,Cond,set(CompSetType),[],RecId,TCompSet),
1669 % Params: a,b,c
1670 % i = a|->b|->c
1671 add_identifiers_to_environment(TParamIds,Env2,Subenv),
1672 foldl(recursive_operator_case(Subenv,TResultId),Cases,TCases,TR1,TRout),
1673 conjunct_predicates(TCases,Cond),
1674 create_z_let(ExPr,TPT,LetValues,InnerResult,OpInfo,Result).
1675
1676
1677 recursive_operator_case(Env,TResultId,case(ParamId,_,Expression,Formula),Cond,TRin,TRout) :-
1678 % Add free identifiers of case to environment
1679 extract_free_identifiers(Expression,TFreeIdentifiers,Env,Subenv),
1680 % IsCase => CaseCheck
1681 create_texpr(implication(IsCase,TCaseCheck),pred,[],Cond),
1682 % IsCase: ParamId = constructor(x,y,z)
1683 typecheck_parameter(ParamId,Env,TParamId),
1684 recop_create_is_case(Expression,Subenv,IsCase,TParamId,FT,Case,TRin,TR1),
1685 % CaseCheck: #x,y,z | Destruction & Predicate
1686 recop_create_in_case(Formula,TParamId,TResultId,Subenv,TFreeIdentifiers,FT,Case,TCaseCheck,TR1,TRout).
1687 extract_free_identifiers(typeof(_Pos,ExtExpr,_TypeExpr),TIds,In,Out) :-
1688 extract_free_identifiers(ExtExpr,TIds,In,Out).
1689 extract_free_identifiers(extended_expr(_Pos,_Case,Exprs,Preds),TIds,In,Out) :-
1690 append(Exprs,Preds,Ids),
1691 maplist(extract_free_identifier,Ids,TIds),
1692 add_identifiers_to_environment(TIds,In,Out).
1693 extract_free_identifier(identifier(_Pos,Id),TId) :-
1694 create_typed_id(Id,_,TId).
1695 typecheck_parameter(ParamId,Env,TParamId) :-
1696 env_lookup_type(ParamId,Env,ParamType),
1697 create_typed_id(ParamId,ParamType,TParamId).
1698 %env_store_type(Id,Type,In,Out) :-
1699 % % Version without Info field
1700 % env_store(Id,Type,[],In,Out).
1701 recop_create_is_case(typeof(_,Expr,_TypeExpr),Env,IsCase,TParamId,FT,Case,TRin,TRout) :-
1702 recop_create_is_case(Expr,Env,IsCase,TParamId,FT,Case,TRin,TRout).
1703 recop_create_is_case(Expression,Env,IsCase,TParamId,FT,Case,TRin,TRout) :-
1704 Expression = extended_expr(_,Case,_,_),
1705 get_texpr_type(TParamId,freetype(FT)),
1706 btype(recop_create_is_case,Expression,Env,freetype(FT),_TCons,TRin,TRout),
1707 create_texpr(freetype_case(FT,Case,TParamId),pred,[],IsCase).
1708 recop_create_in_case(Formula,TParamId,TResultId,Subenv,TFreeIdentifiers,FT,Case,Cond,TRin,TRout) :-
1709 % Predicate
1710 btype(recop_create_in_case,Formula,Subenv,Type,TFormula,TRin,TRout),
1711 ( Type=pred -> Predicate = TFormula
1712 ; otherwise ->
1713 get_texpr_types([TResultId,TFormula],[TypeA,TypeB]),
1714 unify_types_strict(TypeA,TypeB),
1715 create_texpr(equal(TResultId,TFormula),pred,[],Predicate)),
1716 % Destruction: x->y|->z = destructor(ParamId)
1717 ( TFreeIdentifiers = [] ->
1718 Cond = Predicate
1719 ; TFreeIdentifiers = [_|_] ->
1720 get_texpr_types(TFreeIdentifiers,FTypes),
1721 combine_typelist_with_prj(FTypes,FType,Projections),
1722 unique_id("destructed",DId),create_typed_id(DId,FType,TDId),
1723 create_texpr(freetype_destructor(FT,Case,TParamId),FType,[],Destructor),
1724 maplist(create_inner_let(TDId),Projections,TLetExpressions),
1725 create_z_let(pred,TFreeIdentifiers,TLetExpressions,Predicate,[],InnerLets),
1726 create_z_let(pred,[TDId], [Destructor], InnerLets,[],Cond)
1727 ).
1728
1729 create_inner_let(TOrig,Projections,TExpr) :-
1730 apply_projections(Projections,TOrig,TExpr).
1731
1732 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1733 % Theory plug-in: datatype sets
1734 :- public freetype_operator/12.
1735 freetype_operator(FreetypeId1,Types1,TypeParams1,Usage1,
1736 Id,TArgs,_Pos,Env,_ExPr,Result,TR,TR) :-
1737 % make a fresh copy to prevent that several instances of the freetype propagate
1738 % their types to each other (resulting in spurious typing errors)
1739 copy_term(freetype(FreetypeId1,Types1,TypeParams1,Usage1),
1740 freetype(FreetypeId, Types, TypeParams, Usage)),
1741 maplist(map_to_set_type,Types,SetTypes),
1742 get_texpr_types(TArgs,SetTypes),
1743 create_freetype_compset(TArgs,Id,FreetypeId,TypeParams,Usage,Env,Result).
1744 create_freetype_compset(TArgs,SetId,FreetypeId,TypeParams,Usage,Env,Result) :-
1745 find_constructors_with_complex_types(TArgs,Usage,Constructors),
1746 ( Constructors = [] ->
1747 create_texpr(freetype_set(FreetypeId),set(freetype(FreetypeId)),[],Result)
1748 ; otherwise ->
1749 create_freetype_compset2(TArgs,SetId,Constructors,FreetypeId,TypeParams,Env,Result)).
1750 create_freetype_compset2(TArgs,SetId,Constructors,FreetypeId,TypeParams,Env,Result) :-
1751 btypechecker:add_ext_variables(TypeParams,Env,TParams,Subenv,TRin,TRout),
1752 get_texpr_types(TParams,Types),get_texpr_types(TArgs,Types),
1753 Type=freetype(FreetypeId),
1754 create_texpr(identifier(freetype_element),Type,[],TId),
1755 do_prettyprint_freetype(FreetypeId,TArgs,PP),
1756 create_recursive_compset([TId],Let,set(Type),[freetype(PP)],RecId,Result),
1757 store_eventb_operator(SetId,freetype_operator_as_identifier(RecId),Subenv,Subenv2),
1758 foldl(create_cons_check(FreetypeId,Subenv2,TId),Constructors,Checks,TRin,TRout),
1759 conjunct_predicates(Checks,Cond),
1760 create_z_let(pred,TParams,TArgs,Cond,[],Let).
1761 create_cons_check(FreetypeId,Env,TId,cons(Case,Exprs),Check,TRin,TRout) :-
1762 btype_l(Exprs,Env,_Types,TExprs,TRin,TRout),
1763 combine_exprlist_to_cprod(TExprs,Set),
1764 get_texpr_type(Set,set(Type)),
1765 create_texpr(freetype_case(FreetypeId,Case,TId),pred,[],CheckCase),
1766 create_texpr(freetype_destructor(FreetypeId,Case,TId),Type,[],Value),
1767 create_texpr(member(Value,Set),pred,[],Membercheck),
1768 create_texpr(implication(CheckCase,Membercheck),pred,[],Check).
1769 % this is used to pretty-print the resulting comprehension set
1770 do_prettyprint_freetype(Id,Params,R) :-
1771 maplist(translate_bexpression,Params,Strs),
1772 ajoin_with_sep(Strs,',',S),
1773 functor(Id,I,_),
1774 ajoin([I,'(',S,')'],R).
1775
1776 find_constructors_with_complex_types(TArgs,Usage,Constructors) :-
1777 find_complex_type_params(TArgs,ComplexTP),
1778 findall(cons(Id,DestructorExprs),
1779 ( member(used_param_types(Id,UsedParamTypes,DestructorExprs),Usage),
1780 ord_intersect(UsedParamTypes,ComplexTP)),
1781 Constructors).
1782 % returns the indeces of the type arguments that are not only types
1783 find_complex_type_params(TArgs,ComplexTP) :-
1784 findall(N,(nth1(N,TArgs,TArg),\+ is_just_type(TArg)),ComplexTP1),
1785 sort(ComplexTP1,ComplexTP).
1786
1787 :- public freetype_operator_as_identifier/9.
1788 freetype_operator_as_identifier(RecId,Id,TArgs,_Pos,_Env,_ExPr,Result,TR,TR) :-
1789 get_texpr_types(TArgs,SetTypes),
1790 maplist(map_to_set_type,Types,SetTypes),
1791 create_freetype_typeid(Id,Types,FreetypeId),
1792 create_recursion_ref(RecId,set(freetype(FreetypeId)),Result).
1793
1794 :- public freetype_operator_as_function/10.
1795 freetype_operator_as_function(RecId,RType,_Id,TArgs,_Pos,_Env,_ExPr,Result,TR,TR) :-
1796 create_couple(TArgs,TArg), get_texpr_type(TArg,Type),
1797 create_recursion_ref(RecId,set(couple(Type,RType)),TFunction),
1798 create_texpr(function(TFunction,TArg),RType,[],Result).
1799
1800 :- public freetype_operator_as_set/9.
1801 freetype_operator_as_set(RecId,_Id,TArgs,_Pos,_Env,_ExPr,Result,TR,TR) :-
1802 create_couple(TArgs,TArg), get_texpr_type(TArg,Type),
1803 create_recursion_ref(RecId,set(Type),TSet),
1804 create_texpr(member(TArg,TSet),pred,[],Result).
1805
1806 create_recursion_ref(RecId,Type,TId) :-
1807 create_texpr(identifier(RecId),Type,[for_recursion],TId).
1808
1809 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1810 % Theory plug-in: datatype constructors
1811 :- public constructor_operator/10. % TO DO: ensure by another mechanism that Spider detects that this is called
1812 constructor_operator(FreetypeId1,[],Id,[],_Pos,_Env,_ExPr,Result,TRin,TRout) :-
1813 !, copy_term(FreetypeId1,FreetypeId),
1814 create_texpr(value(freeval(FreetypeId,Id,term(Id))),
1815 freetype(FreetypeId),[],Result),
1816 TRin = TRout.
1817 constructor_operator(FreetypeId1,ParamTypes1,
1818 Id,TArgs,_Pos,_Env,_ExPr,Result,TR,TR) :-
1819 copy_term(constructor(FreetypeId1,ParamTypes1),constructor(FreetypeId,ParamTypes)),
1820 get_texpr_types(TArgs,ParamTypes),
1821 combine_exprlist_to_couple(TArgs,TArg),
1822 create_texpr(freetype_constructor(FreetypeId,Id,TArg),freetype(FreetypeId),[],Result).
1823
1824 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1825 % Theory plug-in: datatype destructors
1826 :- public destructor_operator/12. % TO DO: ensure by another mechanism that Spider detects that this is called
1827 destructor_operator(FreetypeId1,Projections,Case,CType1,
1828 _Id,[TArg],_Pos,_Env,_ExPr,Result,TR,TR) :-
1829 copy_term(destructor(FreetypeId1,CType1),destructor(FreetypeId,CType)),
1830 get_texpr_type(TArg,freetype(FreetypeId)),
1831 create_texpr(freetype_destructor(FreetypeId,Case,TArg),CType,[],Destructed),
1832 apply_projections(Projections,Destructed,Result).
1833
1834 % create an projection expression (or a combination of arbitrary many) to
1835 % access a part of a couple. The input is a list of prj1/prj2 atoms,
1836 % e.g. [prj1,prj1,prj2]: Take the first of the first of the second element.
1837 apply_projections(Projections,Expr,Result) :-
1838 reverse(Projections,Prjs),
1839 apply_projections1(Prjs,Expr,Result).
1840 apply_projections1([],Expr,Expr).
1841 apply_projections1([P|Rest],Expr,Result) :-
1842 get_texpr_type(Inner,couple(A,B)),
1843 apply_projections2(P,A,B,Result,Inner),
1844 apply_projections1(Rest,Expr,Inner).
1845 apply_projections2(prj1,A,_B,Result,Inner) :-
1846 create_texpr(first_of_pair(Inner),A,[],Result).
1847 apply_projections2(prj2,_A,B,Result,Inner) :-
1848 create_texpr(second_of_pair(Inner),B,[],Result).
1849
1850 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1851 % Theory plug-in: axiomatic definitions of operators
1852 store_axiomatic_operator(_PT,axiomatic_def_block(_Id,_Types,OpDefs,_Axioms),Ops) :-
1853 % in case we do not recognize the operator, we store an error message
1854 % that is shown as soon the operator is used somewhere
1855 maplist(store_axdef_error,OpDefs,Ops).
1856 store_axdef_error(opdef(Id,_Arguments,_WD),Id-unsupported_operator(Msg)) :-
1857 ajoin(['Axiomatic defined operator \"',Id,'\" not recognized. Be sure to add a .ptm file to your Theory project.'],Msg).
1858
1859
1860 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1861 % Theory plug-in: Tagged operators that can be replaced by internal constructs
1862 handle_mappings(PT,tag(Opname,Tag),Ops,OPin/AxDefsin,OPout/AxDefsOut) :- !,
1863 ( extract_operator(Opname,Operator,OPin/AxDefsin,OPout/AxDefsOut) ->
1864 (debug:debug_mode(on) -> format("Mapping Theory Operator ~s -> ~w~n",[Tag,Opname]) ; true),
1865 (store_operator_by_tag(Tag,Opname,Operator,PT,Ops) -> true
1866 ; add_internal_error('Error mapping Theory Operator (the *.ptm file maybe incorrect or you need a newer version of ProB): ',Tag:Opname))
1867 ; otherwise ->
1868 ajoin(['ProB theory mapping: operator ',Opname,' not found, mapping entry ignored.'],Msg),
1869 add_error(bmachine_eventb,Msg),
1870 OPin/AxDefsin=OPout/AxDefsOut,Ops=[]
1871 ).
1872 handle_mappings(_PT,Mapping,[],X,X) :-
1873 functor(Mapping,Functor,Arity),
1874 ajoin(['ProB theory mapping: unexpected entry of type ',Functor,'/',Arity,', entry ignored.'],Msg),
1875 add_error(bmachine_eventb,Msg).
1876
1877 extract_operator(Opname,Operator,OPin/AxDefs,OPout/AxDefs) :-
1878 Operator = operator(Opname,_Parameters,_WD,_DirectDef,_RecursiveDef),
1879 selectchk(Operator,OPin,OPout),!.
1880 extract_operator(Opname,Operator,OP/AxDefsIn,OP/AxDefsOut) :-
1881 Operator = axdef(Opname,Parameters,WD,block(Id,Types,Axioms)),
1882 select(axiomatic_def_block(Id,Types,OpDefsIn,Axioms),AxDefsIn,axiomatic_def_block(Id,Types,OpDefsOut,Axioms),AxDefsOut),
1883 select(opdef(Opname,Parameters,WD),OpDefsIn,OpDefsOut),!.
1884
1885 % two versions are supported: The older one expects an atom Tag, the new one a string
1886 % The string version is then parsed as a Prolog term.
1887 store_operator_by_tag(Tag,Opname,Operator,PT,Ops) :-
1888 is_list(Tag),!, % A string
1889 append(Tag,".",Tag1), % read_from_codes/2 needs a full-stop at the end
1890 read_from_codes(Tag1,Term),
1891 store_operator_by_tag(Term,Opname,Operator,PT,Ops).
1892 store_operator_by_tag(Tag,Opname,Operator,PT,Ops) :-
1893 store_operator_by_tag1(Tag,Opname,Operator,PT,Ops).
1894 store_operator_by_tag1(Tag,Opname,Operator,PT,Ops) :-
1895 % SIGMA or PI
1896 aggregation_operator(Tag,Functor),!,
1897 get_operator_parameters(Operator,Parameters),
1898 ( Parameters = [Arg] ->
1899 create_raw_aggregation_op(Functor,Arg,ClassicalBOp),
1900 Ops=[Opname-direct_definition([Arg],ClassicalBOp,PT)]
1901 ; otherwise ->
1902 parameter_error(Parameters,1,Opname),Ops=[]
1903 ).
1904 store_operator_by_tag1(mkinat,OpName,Operator,PT,Ops) :- !,
1905 store_operator_by_tag1(mkinat(iZero,iSucc),OpName,Operator,PT,Ops).
1906 store_operator_by_tag1(mkinat(ZeroOp,SuccOp),OpName,Operator,_PT,Ops) :- !,
1907 get_operator_parameters(Operator,Parameters),
1908 ( Parameters = [argument(Arg,_ArgType)] ->
1909 Ops=[OpName-make_inductive_natural(Arg,ZeroOp,SuccOp)]
1910 ; otherwise ->
1911 parameter_error(Parameters,1,OpName),Ops=[]
1912 ).
1913 store_operator_by_tag1(choose,OpName,Operator,_PT,Ops) :- !,
1914 get_operator_parameters(Operator,Parameters),
1915 ( Parameters = [argument(_Arg,_ArgType)] ->
1916 Ops=[OpName-choose_operator]
1917 ; otherwise ->
1918 parameter_error(Parameters,1,OpName),Ops=[]
1919 ).
1920 store_operator_by_tag1(BOperator,Opname,Operator,PT,Ops) :- unary_operator_raw_term(BOperator,Arg,Expr), !,
1921 get_operator_parameters(Operator,Parameters),
1922 ( Parameters = [argument(Arg,_ArgType)] ->
1923 Ops=[Opname-direct_definition(Parameters,Expr,PT)]
1924 ; otherwise ->
1925 parameter_error(Parameters,1,Opname),Ops=[]
1926 ).
1927 store_operator_by_tag1(BOperator,Opname,Operator,PT,Ops) :- %print(try(BOperator,Opname,Operator,PT,Ops)),nl,
1928 binary_operator_raw_term(BOperator,Arg1,Arg2,Expr), !,
1929 get_operator_parameters(Operator,Parameters),
1930 ( Parameters = [argument(Arg1,_ArgType1), argument(Arg2,_ArgType2)] ->
1931 Ops=[Opname-direct_definition(Parameters,Expr,PT)]
1932 ; otherwise ->
1933 parameter_error(Parameters,1,Opname),Ops=[]
1934 ).
1935
1936 % TO DO ternary operator ?? son/3
1937
1938 % construct a raw term with arguments for replacement in AST
1939 % first argument is functor name as it appears in the theory mapping file *.ptm
1940 binary_operator_raw_term(Functor,Arg1,Arg2,Term) :- binary_operator_to_ast(Functor,ASTFunctor),
1941 Term =.. [ASTFunctor,none,identifier(none,Arg1),identifier(none,Arg2)].
1942 binary_operator_to_ast('^',concat).
1943 binary_operator_to_ast(concat,concat).
1944 binary_operator_to_ast(div,floored_div).
1945 binary_operator_to_ast(restrict_front,restrict_front).
1946 binary_operator_to_ast(restrict_tail,restrict_tail).
1947 % binary tree operators
1948 binary_operator_to_ast(arity,arity).
1949 binary_operator_to_ast(bin,bin).
1950 binary_operator_to_ast(const,const).
1951 binary_operator_to_ast(father,father).
1952 binary_operator_to_ast(rank,rank).
1953 binary_operator_to_ast(subtree,subtree).
1954
1955 % construct a raw term with argument for replacement in AST
1956 % first argument is functor name as it appears in the theory mapping file *.ptm
1957 unary_operator_raw_term(Functor,Arg,Term) :- unary_operator_to_ast(Functor,ASTFunctor),
1958 Term =.. [ASTFunctor,none,identifier(none,Arg)].
1959 unary_operator_to_ast(closure,reflexive_closure). % reflexive_closure corresponds to closure B operator !
1960 unary_operator_to_ast(closure1,closure).
1961 unary_operator_to_ast(conc,general_concat).
1962 unary_operator_to_ast(fnc,trans_function).
1963 unary_operator_to_ast(rel,trans_relation).
1964 unary_operator_to_ast(succ,successor). % also exist in Event-B
1965 unary_operator_to_ast(pred,predecessor). % also exist in Event-B
1966 unary_operator_to_ast(bool,convert_bool). % also exist in Event-B
1967 unary_operator_to_ast(id,identity). % exists in similar way in Event-B
1968 unary_operator_to_ast(union,general_union).
1969 unary_operator_to_ast(inter,general_intersection).
1970 unary_operator_to_ast(F,F) :- unary_operator(F). % operators that have same name in B and AST
1971
1972 % sequence operators
1973 unary_operator(seq).
1974 unary_operator(seq1).
1975 unary_operator(iseq).
1976 unary_operator(iseq1).
1977 unary_operator(perm).
1978 unary_operator(first).
1979 unary_operator(size).
1980 unary_operator(front).
1981 unary_operator(tail).
1982 unary_operator(rev).
1983 unary_operator(last).
1984 unary_operator(mu).
1985 % tree operators
1986 unary_operator(tree).
1987 unary_operator(btree).
1988 unary_operator(top).
1989 unary_operator(sons).
1990 unary_operator(bin).
1991 unary_operator(left).
1992 unary_operator(right).
1993 unary_operator(sizet).
1994 unary_operator(prefix).
1995 unary_operator(postfix).
1996 %unary_operator(infix). % not yet supported
1997 %unary_operator(mirror). % not yet supported
1998 % general operators
1999 unary_operator(min). % also exist in Event-B
2000 unary_operator(max). % also exist in Event-B
2001 unary_operator(domain).
2002 unary_operator(range).
2003 % z operators
2004 unary_operator(compaction).
2005 unary_operator(bag_items).
2006
2007 aggregation_operator('SIGMA',general_sum).
2008 aggregation_operator('PI',general_product).
2009
2010 create_raw_aggregation_op(Op,argument(Arg,_ArgType),Result) :-
2011 % this construction will immediately wrap _agg_op1/2 inside Sigma or Pi, and thus _agg_op1/2 will not be visibile outside
2012 A = identifier(none,Arg), % User-given argument
2013 create_fresh_identifier('_agg_op1',[A],I1), % starting with _ ensures user cannot create such an id
2014 create_fresh_identifier('_agg_op2',[A],I2),
2015 I = identifier(none,I1), % I is the (not used) index variable
2016 N = identifier(none,I2), % N is the integer to sum or multiply
2017 Pred = member(none,couple(none,I,N),A), % I|->N : Arg
2018 Result =.. [Op,none,[I,N],Pred,N]. % SIGMA(I,N . I|->N:Arg | N) (or PI)
2019
2020 parameter_error(Parameters,Expected,Opname) :-
2021 length(Parameters,N),
2022 ajoin(['ProB theory mapping: Expected ',Expected,' parameter for operator ',
2023 Opname,' but found ',N],Msg),
2024 add_error(bmachine_eventb,Msg).
2025
2026 get_operator_parameters(operator(_Opname,Parameters,_WD,_DirectDef,_RecursiveDef),Parameters).
2027 get_operator_parameters(axdef(_Opname,Parameters,_WD,_Block),Parameters).
2028
2029 store_eventb_operator(Id,Op,Ein,Eout) :-
2030 env_store_operator(Id,bmachine_eventb:Op,Ein,Eout).
2031
2032
2033 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2034 % Operator for constructing inductive natural numbers
2035 :- public make_inductive_natural/11.
2036 make_inductive_natural(ArgId,ZeroOp,SuccOp,
2037 Id,[TParam],_Pos,Env,expr,Result,TRin,TRout) :-
2038 unique_id("opresult.",ResultId),
2039 create_typed_id(ResultId,NatType,TResult),
2040 create_typed_id(ArgId,integer,TArgId),
2041 % prepare environment:
2042 add_identifiers_to_environment([TArgId,TResult],Env,Env1),
2043 % we create a recursive function by using a (as recursive annotated) comprehension
2044 % set. We can refer to the compset with RecId.
2045 create_recursive_compset([TArgId,TResult],Cond,set(couple(integer,NatType)),[],RecId,TCompSet),
2046 % used for recursive call:
2047 env_store(RecId,set(couple(integer,NatType)),[],Env1,SubEnv),
2048 % just type iZero to retrieve its type:
2049 IZero=extended_expr(none,ZeroOp,[],[]),
2050 btype(make_inductive_natural,IZero,SubEnv,NatType,_,TRin,TR1),
2051 % Arg=0 => Result=iZero
2052 RawCase1=implication(none,
2053 equal(none,identifier(none,ArgId),integer(none,0)),
2054 equal(none,identifier(none,ResultId),IZero)),
2055 btype(make_inductive_natural,RawCase1,SubEnv,pred,Case1,TR1,TR2),
2056 % Arg>0 => Result=iSucc( recursive_call(Arg-1) )
2057 RawCase2=implication(none,
2058 greater(none,identifier(none,ArgId),integer(none,0)),
2059 equal(none,identifier(none,ResultId),extended_expr(none,SuccOp,[Minus1],[]))),
2060 Minus1=function(none,identifier(none,RecId),minus(none,identifier(none,ArgId),integer(none,1))),
2061 btype(make_inductive_natural,RawCase2,SubEnv,pred,Case2,TR2,TRout),
2062 % {Arg,Result | Arg=0=>Result=iZero & Arg>0=>Result=iSucc( RC(Arg-1) )}
2063 conjunct_predicates([Case1,Case2],Cond),
2064 % {Arg,Result | Arg=0=>Result=iZero & Arg>0=>Result=iSucc( RC(Arg-1) )}(TParam)
2065 create_texpr(function(TCompSet,TParam),NatType,[theory_operator(Id,1)],Result).