1 % (c) 2014-2015 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(before_after_predicates, [tcltk_before_after_predicate_for_operation/2,
6 before_after_predicate_for_operation/2,
7 before_after_predicate_with_equalities/3,
8 before_after_predicate_list_conjunct_with_equalities/3,
9 before_after_predicate_list_disjunct_with_equalities/3,
10 list_renamings_to_primed_vars/2]).
11
12 :- use_module(library(lists)).
13
14 :- use_module(bsyntaxtree, [get_texpr_expr/2,
15 get_texpr_id/2,
16 is_truth/1,
17 safe_create_texpr/3,
18 get_texpr_type/2,
19 conjunct_predicates/2,
20 conjunction_to_list/2,
21 create_implication/3,
22 create_couple/3,
23 disjunct_predicates/2,
24 find_typed_identifier_uses/2,
25 remove_all_infos/2,
26 rename_bt/3,
27 create_exists/3,
28 create_negation/2]).
29 :- use_module(error_manager, [add_error_fail/3]).
30 :- use_module(bmachine_eventb, [prime_variable/2,
31 prime_variables/2,
32 is_primed_id/1]).
33 :- use_module(bmachine,[b_get_machine_operation/4,
34 b_get_machine_variables/1,
35 b_get_machine_constants/1]).
36 %:- use_module(specfile,[animation_minor_mode/1]).
37 :- use_module(translate,[translate_bexpression/2]).
38
39 :- use_module(module_information,[module_info/2]).
40 :- module_info(group,misc).
41 :- module_info(description,'This module computes before-after-predicates of B and Event-B actions.').
42
43 tcltk_before_after_predicate_for_operation(OpName,list(Res)) :-
44 before_after_predicate_for_operation(OpName,BAPredicate),
45 %translate:print_bexpr(BAPredicate),nl,
46 conjunction_to_list(BAPredicate,LP),
47 maplist(translate:translate_bexpression,LP,Res).
48
49 before_after_predicate_for_operation(OpName,BAPredicate) :-
50 b_get_machine_operation(OpName,_Results,_Parameters,OpBody),
51 %print(op(OpName)),nl,
52 b_get_machine_variables(Variables),
53 b_get_machine_constants(Constants),
54 append(Variables,Constants,VarsAndConsts),
55 before_after_predicate_with_equalities(OpBody,VarsAndConsts,BAPredicate).
56
57 :- mode before_after_predicate_with_equalities(+Action,+AllIdentifiers,-Predicate).
58 % these add missing y' = y equalities for unchanged variables
59 before_after_predicate_with_equalities(Action,AllIdentifiers,Predicate) :-
60 before_after_predicate_list_conjunct_with_equalities([Action],AllIdentifiers,Predicate).
61 before_after_predicate_list_conjunct_with_equalities(Actions,AllIdentifiers,BAPredicateWithEq) :-
62 maplist(before_after_predicate_no_equalities_tl(top_level),Actions,AllPredicates),
63 conjunct_predicates(AllPredicates,BAPredicate),
64 add_missing_equalities(AllIdentifiers,BAPredicate,BAPredicateWithEq).
65 before_after_predicate_list_disjunct_with_equalities(Actions,AllIdentifiers,BAPredicate) :-
66 maplist(before_after_predicate_no_equalities_tl(top_level),Actions,AllPredicates),
67 maplist(add_missing_equalities(AllIdentifiers),AllPredicates,BAPredicates),
68 disjunct_predicates(BAPredicates,BAPredicate).
69
70 % does not add missing y' = y equalities for unchanged variables
71 % top-level version: has a special rule for PRE
72 before_after_predicate_no_equalities_tl(TopLevel,Action,Predicate) :-
73 get_texpr_expr(Action,Expr),
74 before_after_predicate_no_equalities_top_level_aux(Expr,Predicate,TopLevel).
75
76 :- use_module(preferences,[get_preference/2]).
77 before_after_predicate_no_equalities_top_level_aux(precondition(Pre,Body),Predicate,top_level) :-
78 get_preference(treat_outermost_pre_as_select,true),
79 !,
80 before_after_predicate_no_equalities(Body,BABody,_),
81 conjunct_predicates([Pre,BABody],Predicate). % May sometimes have to be an implication (depending on how BA-predicate is used) !
82 before_after_predicate_no_equalities_top_level_aux(Expr,Pred,_) :-
83 before_after_predicate_no_equalities_aux(Expr,Pred,_).
84
85 % does not add missing y' = y equalities for unchanged variables
86 before_after_predicate_no_equalities(Action,Predicate,ChangedIDs) :-
87 get_texpr_expr(Action,Expr),
88 before_after_predicate_no_equalities_aux(Expr,Predicate,ChangedIDs).
89
90 get_changed_id(b(function(FUN,_),_,_),ID) :- !, get_changed_id(FUN,ID).
91 get_changed_id(ID,ID).
92
93 before_after_predicate_no_equalities_aux(assign_single_id(Id,Pred),Predicate,ChangedIDs) :- !,
94 before_after_predicate_no_equalities_aux(assign([Id],[Pred]),Predicate,ChangedIDs).
95 before_after_predicate_no_equalities_aux(assign(Ids,Preds),Predicate,ChangedIds) :- !,
96 maplist(get_changed_id,Ids,ChangedIds),
97 maplist(ba_predicate_equal,Ids,Preds,Predicates),
98 conjunct_predicates(Predicates,Predicate).
99 before_after_predicate_no_equalities_aux(becomes_element_of(Ids,Set),Predicate,Ids) :- !,
100 maplist(ba_predicate_member(Set),Ids,Predicates),
101 conjunct_predicates(Predicates,Predicate). % should we generate Set /= {} => Predicate
102 before_after_predicate_no_equalities_aux(becomes_such(Ids,Pred),Predicate,Ids) :- !,
103 ba_predicate_becomes_such(Ids,Pred,Predicate).
104 before_after_predicate_no_equalities_aux(choice(Choices),Predicate,ChangedIDs) :- !,
105 maplist(before_after_predicate_no_equalities,Choices,BAChoices,Changes),
106 append(Changes,ChangedIDs),
107 maplist(add_missing_equalities(ChangedIDs),BAChoices,BAChoicesWithEqualities),
108 disjunct_predicates(BAChoicesWithEqualities,Predicate).
109 before_after_predicate_no_equalities_aux(precondition(Pre,Body),Predicate,ChangedIDs) :- !,
110 before_after_predicate_no_equalities(Body,BABody,ChangedIDs),
111 create_implication(Pre,BABody,Predicate).
112 before_after_predicate_no_equalities_aux(assertion(Pre,Body),Predicate,ChangedIDs) :-
113 !,
114 before_after_predicate_no_equalities(Body,BABody,ChangedIDs),
115 create_implication(Pre,BABody,Predicate1),
116 create_negation(Pre,NotPre),
117 add_missing_equalities(ChangedIDs,b(truth,pred,[]),NotPrePredicate),
118 create_implication(NotPre,NotPrePredicate,Predicate2),
119 conjunct_predicates([Predicate1,Predicate2],Predicate).
120 before_after_predicate_no_equalities_aux(select_when(Pre,Body),Predicate,ChangedIDs) :- !,
121 before_after_predicate_no_equalities(Body,BABody,ChangedIDs),
122 conjunct_predicates([Pre,BABody],Predicate).
123 before_after_predicate_no_equalities_aux(select(Whens),Predicate,ChangedIDs) :- !,
124 maplist(before_after_predicate_no_equalities,Whens,WhensPredicates,Changes),
125 append(Changes,ChangedIDs),
126 maplist(add_missing_equalities(ChangedIDs),WhensPredicates,WhensPredicatesWithEqualities),
127 disjunct_predicates(WhensPredicatesWithEqualities,Predicate).
128 before_after_predicate_no_equalities_aux(select(Whens,Else),Predicate,ChangedIDs) :- !,
129 maplist(before_after_predicate_no_equalities,Whens,WhensPredicates,Changes),
130 maplist(add_missing_equalities(ChangedIDs),WhensPredicates,WhensPredicatesWithEqualities),
131 maplist(get_select_conditions,Whens,SelectConditions),
132 disjunct_predicates(SelectConditions,ElseTemp),
133 create_negation(ElseTemp,ElseLHS),
134 before_after_predicate_no_equalities(Else,ElseRHS,ElseChangedIDs),
135 append([ElseChangedIDs|Changes],ChangedIDs),
136 conjunct_predicates([ElseLHS,ElseRHS],ElsePred),
137 add_missing_equalities(ChangedIDs,ElsePred,ElsePredWithEqualities),
138 disjunct_predicates([ElsePredWithEqualities|WhensPredicatesWithEqualities],Predicate).
139 % TODO: case, handle while
140 before_after_predicate_no_equalities_aux(sequence(ListOfSteps),Predicate,ChangedIDs) :- !,
141 ba_predicate_sequence(ListOfSteps,Predicate,ChangedIDs).
142 before_after_predicate_no_equalities_aux(if(IfList),Predicate,ChangedIDs) :- !,
143 ba_predicate_if(IfList,Predicate,ChangedIDs).
144 before_after_predicate_no_equalities_aux(let(P,D,B),Predicate,ChangedIDs) :- !,
145 before_after_predicate_no_equalities_aux(any(P,D,B),Predicate,ChangedIDs).
146 before_after_predicate_no_equalities_aux(any(Parameters,PreCond,Body),Predicate,ChangedIDs) :- !,
147 before_after_predicate_no_equalities(Body,BABody,ChangedIDs),
148 conjunct_predicates([PreCond,BABody],Inner),
149 create_exists(Parameters,Inner,Predicate).
150 before_after_predicate_no_equalities_aux(parallel(P),Predicate,ChangedIDs) :- !,
151 maplist(before_after_predicate_no_equalities,P,Preds,Changes),
152 append(Changes,ChangedIDs),
153 conjunct_predicates(Preds,Predicate).
154 before_after_predicate_no_equalities_aux(skip,Predicate,[]) :- !,
155 Predicate = b(truth,pred,[]).
156 before_after_predicate_no_equalities_aux(var(Parameters,Body),Predicate,ChangedIDs) :- !,
157 before_after_predicate_no_equalities(Body,BABody,ChangedIDs),
158 create_exists(Parameters,BABody,Predicate).
159 before_after_predicate_no_equalities_aux(rlevent(_Name,_Section,_Stat,_Parameters,Guards,_Thm,Actions,_VWit,_PWit,_Unmod,_AbsEvents),Predicate,ChangedIDs) :- !,
160 maplist(before_after_predicate_no_equalities,Actions,BAActions,Changes),
161 append(Changes,ChangedIDs),
162 conjunct_predicates([Guards|BAActions],Predicate). % should probably be an implication? see precondition.
163 before_after_predicate_no_equalities_aux(operation_call(OpId,[],[]),Predicate,ChangedIDs) :- !,
164 get_texpr_id(OpId,op(OpName)),
165 b_get_machine_operation(OpName,[],[],OpBody),
166 before_after_predicate_no_equalities(OpBody,Predicate,ChangedIDs).
167 before_after_predicate_no_equalities_aux(Expr,Predicate,ChangedIDs) :-
168 add_error_fail(before_after_predicate,'before-after-predicate implementation missing: ',[Expr,Predicate,ChangedIDs]).
169
170 get_select_conditions(b(select_when(Condition,_),_,_),Condition).
171
172 ba_predicate_equal(LHS,RHS,Res) :-
173 % LHS := RHS trace,
174 get_override(LHS,RHS,TPred), !,
175 %nl,translate:print_bexpr(TPred),nl,
176 Res=TPred.
177
178 :- use_module(probsrc(error_manager),[add_internal_error/2]).
179 % get override Term for f(X)(Y)... := RHS
180 get_override(b(function(FUN,ARG),Type,_Info),ExprSoFar,Res) :- !, % FUN(ARG) := RHS
181 %print(fun(FUN)),nl, translate:print_bexpr(ExprSoFar),nl,
182 create_couple(ARG,ExprSoFar,Update), % ARG|-> ExprSoFar
183 safe_create_texpr(set_extension([Update]),Type,UpdateSET), % {ARG|->ExprSoFar}
184 construct_override(FUN,UpdateSET,Override), % FUN <+ {ARG |-> {...}}
185 get_override(FUN,Override,Res). % Pass Override as new RHS in case FUN itself is a function application
186 get_override(FUNID,OverrideExpr,TPred) :-
187 get_texpr_id(FUNID,_ID), %print(base(ID)),nl,
188 prime_variable(FUNID,FUNPrimeId),
189 safe_create_texpr(equal(FUNPrimeId,OverrideExpr),pred,TPred). % FUN' = FUN <+ {ARG |-> RHS}
190 get_override(FUNID,OverrideExpr,TPred) :-
191 add_internal_error('Cannot compute override: ',get_override(FUNID,OverrideExpr,TPred)),fail.
192
193 construct_override(FunID,Update,Override) :-
194 get_texpr_type(Update,Type),
195 Override = b(overwrite(FunID,Update),Type,[]).
196
197 ba_predicate_member(Set,Id,TPred) :-
198 % prime identifiers on the lhs
199 prime_variable(Id,PrimedId),
200 safe_create_texpr(member(PrimedId,Set),pred,TPred).
201
202 ba_predicate_becomes_such(Ids,Pred,Predicate) :-
203 list_renamings_to_primed_vars(Ids,RenamingList),
204 rename_bt(Pred,RenamingList,Predicate).
205
206 list_renamings_to_primed_vars([],[]).
207 list_renamings_to_primed_vars([Var|Vars],[rename(VarId,PrimedId)|T]) :-
208 get_texpr_id(Var,VarId),
209 atom_concat(VarId,'\'',PrimedId),
210 list_renamings_to_primed_vars(Vars,T).
211
212 add_missing_equalities(AllVariables,PredWithoutEqualities,PredWithEqualities) :-
213 find_typed_identifier_uses(PredWithoutEqualities,UsedIdentifiers),
214 exclude(primed_var_is_used(UsedIdentifiers),AllVariables,VariablesNotOccuringPrimed),
215 maplist(ba_predicate_equal,VariablesNotOccuringPrimed,VariablesNotOccuringPrimed,EqualityPredicates),
216 conjunct_predicates([PredWithoutEqualities|EqualityPredicates],PredWithEqualities).
217
218 primed_var_is_used(UsedIdentifiers,Identifier) :-
219 prime_variable(Identifier,PrimedIdentifier),
220 remove_all_infos(PrimedIdentifier,PrimedIdentifierWithoutInfos),
221 member(PrimedIdentifierWithoutInfos,UsedIdentifiers).
222
223 add_else_if_missing([],[DefaultElse]) :-
224 safe_create_texpr(if_elsif(b(truth,pred,[]),b(skip,subst,[])),subst,DefaultElse).
225 add_else_if_missing([If|Ifs],[If|Ifs]) :-
226 get_texpr_expr(If,if_elsif(Test,_)),
227 is_truth(Test), !.
228 add_else_if_missing([If|Ifs],[If|MoreIfs]) :-
229 add_else_if_missing(Ifs,MoreIfs).
230
231 ba_predicate_if(IF,BA,AllChangedIDs) :-
232 add_else_if_missing(IF,IFWithElse),
233 maplist(ba_predicate_if_aux,IFWithElse,BAPreds,ChangedIDs),
234 append(ChangedIDs,AllChangedIDs),
235 ba_predicate_if(IFWithElse,BAPreds,AllChangedIDs,BA).
236
237 ba_predicate_if([IF|IFs],[BAPred|BAPreds],IDs,BA) :-
238 get_texpr_expr(IF,if_elsif(Test,_)),
239 % if-part
240 add_missing_equalities(IDs,BAPred,InnerBAPredIf),
241 (is_truth(Test)
242 -> InnerBAPredIf = BAPredIf
243 ; safe_create_texpr(implication(Test,InnerBAPredIf),pred,BAPredIf)),
244 % if there are further else/elseif parts, create pos
245 (ba_predicate_if(IFs,BAPreds,IDs,ElsePred)
246 -> create_negation(Test,NegTest),
247 safe_create_texpr(implication(NegTest,ElsePred),pred,BAPredElse),
248 conjunct_predicates([BAPredIf,BAPredElse],BA)
249 ; BA = BAPredIf).
250
251 ba_predicate_if_aux(IF,BAPred,ChangedIDs) :-
252 get_texpr_expr(IF,if_elsif(_,Body)),
253 before_after_predicate_no_equalities(Body,BAPred,ChangedIDs).
254
255 ba_predicate_sequence([Last],Predicate,ChangedIDs) :- !,
256 before_after_predicate_no_equalities(Last,Predicate,ChangedIDs).
257 ba_predicate_sequence([First|SomeMore],Predicate,ChangedIDs) :-
258 before_after_predicate_no_equalities(First,FirstPred,ChangesFirst),
259 find_typed_identifier_uses(FirstPred,Identifiers),
260 include(is_primed,Identifiers,PrimedIdentifiers),
261 list_renamings_to_primed_vars(PrimedIdentifiers,RenamingToTwicePrimedIDs),
262 rename_bt(FirstPred,RenamingToTwicePrimedIDs,FirstPredAfterReplacement),
263
264 ba_predicate_sequence(SomeMore,SecondPred,FurtherChanges),
265 list_renamings_remove_prime(PrimedIdentifiers,RenamingToNotPrimed),
266 rename_bt(SecondPred,RenamingToNotPrimed,SecondPredAfterReplacement),
267
268 conjunct_predicates([FirstPredAfterReplacement,SecondPredAfterReplacement],FullPred),
269
270 prime_variables(PrimedIdentifiers,TwicePrimedIdentifiers),
271 create_exists(TwicePrimedIdentifiers,FullPred,Predicate),
272 append(ChangesFirst,FurtherChanges,ChangedIDs).
273
274 is_primed(TExpr) :-
275 get_texpr_id(TExpr,ID),
276 is_primed_id(ID).
277
278 list_renamings_remove_prime([],[]).
279 list_renamings_remove_prime([Var|Vars],[rename(VarId,NonPrimedID)|T]) :-
280 get_texpr_id(Var,VarId),
281 atom_concat(NonPrimedID,'\'',VarId),
282 list_renamings_remove_prime(Vars,T).