| 1 | % (c) 2014-2025 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_for_operation_no_equalities/5, | |
| 8 | before_after_predicate_with_equalities/3, | |
| 9 | before_after_predicate_list_conjunct_with_equalities/3, | |
| 10 | before_after_predicate_list_disjunct_with_equalities/3, | |
| 11 | before_after_predicate_no_equalities/3, | |
| 12 | add_missing_equalities/3, | |
| 13 | prime_bexpr_for_ids/4, prime_dollar0_bexpr_for_ids/3, | |
| 14 | list_renamings_to_primed_vars/2]). | |
| 15 | ||
| 16 | :- use_module(probsrc(module_information),[module_info/2]). | |
| 17 | :- module_info(group,cbc). | |
| 18 | :- module_info(description,'This module computes before-after-predicates of B and Event-B actions.'). | |
| 19 | % NOTE: for the moment it assumes no clashes between operation parameters and variables, constants, ... | |
| 20 | ||
| 21 | :- use_module(library(lists)). | |
| 22 | ||
| 23 | :- use_module(probsrc(bsyntaxtree), [get_texpr_expr/2, | |
| 24 | get_texpr_id/2, | |
| 25 | is_truth/1, | |
| 26 | safe_create_texpr/3, | |
| 27 | get_texpr_type/2, | |
| 28 | conjunct_predicates/2, | |
| 29 | conjunction_to_list/2, | |
| 30 | create_implication/3, | |
| 31 | create_couple/3, | |
| 32 | disjunct_predicates/2, | |
| 33 | find_typed_identifier_uses/2, | |
| 34 | rename_bt/3, | |
| 35 | create_exists/3, create_or_merge_exists/3, | |
| 36 | create_negation/2]). | |
| 37 | :- use_module(probsrc(error_manager), [add_error_fail/3]). | |
| 38 | :- use_module(probsrc(bmachine),[b_get_machine_operation/4, | |
| 39 | b_get_machine_variables/1, | |
| 40 | b_get_machine_constants/1]). | |
| 41 | %:- use_module(probsrc(specfile,[animation_minor_mode/1]). | |
| 42 | :- use_module(probsrc(tools),[split_list/4]). | |
| 43 | :- use_module(probsrc(translate),[translate_bexpression/2]). | |
| 44 | :- use_module(symbolic_model_checker(predicate_handling), | |
| 45 | [prime_id_atom/2, remove_prime_id_atom/2, is_primed_id_atom/1, | |
| 46 | prime_typed_identifier/2,remove_prime_typed_identifier/2, | |
| 47 | is_primed_typed_identifier/1]). | |
| 48 | ||
| 49 | ||
| 50 | tcltk_before_after_predicate_for_operation(OpName,list(Res)) :- | |
| 51 | before_after_predicate_for_operation(OpName,BAPredicate), | |
| 52 | %translate:print_bexpr(BAPredicate),nl, | |
| 53 | conjunction_to_list(BAPredicate,LP), | |
| 54 | maplist(translate_bexpression,LP,Res). | |
| 55 | ||
| 56 | before_after_predicate_for_operation(OpName,BAPredicate) :- | |
| 57 | ? | b_get_machine_operation(OpName,_Results,_Parameters,OpBody), |
| 58 | %print(op(OpName)),nl, | |
| 59 | b_get_machine_variables(Variables), | |
| 60 | %b_get_machine_constants(Constants), append(Variables,Constants,VarsAndConsts), | |
| 61 | before_after_predicate_with_equalities(OpBody,Variables,BAPredicate). | |
| 62 | ||
| 63 | % ---------------- | |
| 64 | ||
| 65 | :- use_module(probsrc(translate), [generate_typing_predicates/2]). | |
| 66 | ||
| 67 | % without equalities for UNCHANGED vars | |
| 68 | before_after_predicate_for_operation_no_equalities(OpName,Parameters,Results,BAPredicate,ChangedIds) :- | |
| 69 | b_get_machine_operation(OpName,Results,Parameters,OpBody), | |
| 70 | % TO DO: rename parameters if clashing | |
| 71 | generate_typing_predicates(Parameters,Typings1), | |
| 72 | generate_typing_predicates(Results,Typings2), | |
| 73 | before_after_predicate_no_equalities_tl4(top_level,OpBody,BAPred,ChangedIds), | |
| 74 | append([Typings1,Typings2,[BAPred]],LP), | |
| 75 | conjunct_predicates(LP,BAPredicate). | |
| 76 | % predicate contains new open identifiers: Results and Parameters | |
| 77 | ||
| 78 | % :- before_after_predicates:before_after_predicate_for_operation_no_equalities(Op,_,_,P,C), format('Op ~w (writing ~w):~n',[Op,C]), translate:print_bexpr(P),nl,nl,fail. | |
| 79 | ||
| 80 | ||
| 81 | ||
| 82 | :- use_module(probsrc(bsyntaxtree),[transform_bexpr_with_scoping/3]). | |
| 83 | % prime those variables inside a formula which are in the ChangedIds list | |
| 84 | prime_bexpr_for_ids(TExpr,ChangedIds,PrimedTExpr,ChangesPerformed) :- | |
| 85 | prime_bexpr_for_ids(TExpr,prime_with_quote,ChangedIds,PrimedTExpr,ChangesPerformed). | |
| 86 | prime_dollar0_bexpr_for_ids(TExpr,ChangedIds,PrimedTExpr) :- | |
| 87 | prime_bexpr_for_ids(TExpr,prime_with_dollar0,ChangedIds,PrimedTExpr,_ChangesPerformed). | |
| 88 | ||
| 89 | prime_bexpr_for_ids(TExpr,Kind,ChangedIds,PrimedTExpr,ChangesPerformed) :- | |
| 90 | sort(ChangedIds,SortedCIds), | |
| 91 | transform_bexpr_with_scoping(before_after_predicates:prime_changed_id(Kind,SortedCIds,Changed),TExpr,PrimedTExpr), | |
| 92 | (var(Changed) -> ChangesPerformed=false ; ChangesPerformed=true). | |
| 93 | ||
| 94 | :- use_module(library(ordsets),[ord_member/2,ord_nonmember/2]). | |
| 95 | prime_changed_id(Kind,ChangedIds,Changed,b(identifier(ID),Type,Info),Result,LocalIds) :- | |
| 96 | ord_member(ID,ChangedIds), | |
| 97 | ord_nonmember(ID,LocalIds), % The ID is not overriden by a locally quantified variable | |
| 98 | my_prime_id(Kind,ID,PrimedID), | |
| 99 | Changed=true, % change was performed | |
| 100 | Result = b(identifier(PrimedID),Type,Info). | |
| 101 | ||
| 102 | ||
| 103 | :- use_module(probsrc(btypechecker),[prime_id/2, prime_atom0/2]). | |
| 104 | my_prime_id(prime_with_dollar0,ID,PrimedID0) :- !, prime_atom0(ID,PrimedID0). % x -> x$0 | |
| 105 | my_prime_id(_,ID,PrimedID) :- !, prime_id(ID,PrimedID). % prime_with_quote: x -> x' | |
| 106 | ||
| 107 | ||
| 108 | % ---------------- | |
| 109 | ||
| 110 | %! before_after_predicate_with_equalities(+Action,+AllIdentifiers,-Predicate) | |
| 111 | % these add missing y' = y equalities for unchanged variables | |
| 112 | before_after_predicate_with_equalities(Action,AllIdentifiers,Predicate) :- | |
| 113 | before_after_predicate_list_conjunct_with_equalities([Action],AllIdentifiers,Predicate). | |
| 114 | before_after_predicate_list_conjunct_with_equalities(Actions,AllIdentifiers,BAPredicateWithEq) :- | |
| 115 | maplist(before_after_predicate_no_equalities_tl3(top_level),Actions,AllPredicates), | |
| 116 | conjunct_predicates(AllPredicates,BAPredicate), | |
| 117 | add_missing_equalities(AllIdentifiers,BAPredicate,BAPredicateWithEq). | |
| 118 | before_after_predicate_list_disjunct_with_equalities(Actions,AllIdentifiers,BAPredicate) :- | |
| 119 | maplist(before_after_predicate_no_equalities_tl3(top_level),Actions,AllPredicates), | |
| 120 | maplist(add_missing_equalities(AllIdentifiers),AllPredicates,BAPredicates), | |
| 121 | disjunct_predicates(BAPredicates,BAPredicate). | |
| 122 | ||
| 123 | % ---------------- | |
| 124 | ||
| 125 | % does not add missing y' = y equalities for unchanged variables | |
| 126 | % top-level version: has a special rule for PRE | |
| 127 | before_after_predicate_no_equalities_tl3(TopLevel,Action,Predicate) :- | |
| 128 | before_after_predicate_no_equalities_tl4(TopLevel,Action,Predicate,_). | |
| 129 | before_after_predicate_no_equalities_tl4(TopLevel,Action,Predicate,ChangedIDs) :- | |
| 130 | get_texpr_expr(Action,Expr), | |
| 131 | before_after_predicate_no_equalities_top_level_aux(Expr,Predicate,ChangedIDs,TopLevel). | |
| 132 | ||
| 133 | :- use_module(probsrc(preferences),[get_preference/2]). | |
| 134 | before_after_predicate_no_equalities_top_level_aux(precondition(Pre,Body),Predicate,ChangedIDs,top_level) :- | |
| 135 | get_preference(treat_outermost_pre_as_select,true), | |
| 136 | !, | |
| 137 | before_after_predicate_no_equalities(Body,BABody,ChangedIDs), | |
| 138 | conjunct_predicates([Pre,BABody],Predicate). % May sometimes have to be an implication (depending on how BA-predicate is used) ! | |
| 139 | before_after_predicate_no_equalities_top_level_aux(Expr,Pred,ChangedIDs,_) :- | |
| 140 | before_after_predicate_no_equalities_aux(Expr,Pred,ChangedIDs). | |
| 141 | ||
| 142 | % ---------------- | |
| 143 | ||
| 144 | % does not add missing y' = y equalities for unchanged variables | |
| 145 | before_after_predicate_no_equalities(Action,Predicate,ChangedIDs) :- | |
| 146 | get_texpr_expr(Action,Expr), | |
| 147 | before_after_predicate_no_equalities_aux(Expr,Predicate,ChangedIDs). | |
| 148 | ||
| 149 | get_changed_id(b(function(FUN,_),_,_),ID) :- !, get_changed_id(FUN,ID). | |
| 150 | get_changed_id(ID,ID). | |
| 151 | ||
| 152 | % TO DO: return list of Predicates rather than single predicate; avoid conjunct_predicates and create flat conj at end | |
| 153 | before_after_predicate_no_equalities_aux(assign_single_id(Id,Pred),Predicate,ChangedIDs) :- !, | |
| 154 | before_after_predicate_no_equalities_aux(assign([Id],[Pred]),Predicate,ChangedIDs). | |
| 155 | before_after_predicate_no_equalities_aux(assign(Ids,Preds),Predicate,ChangedIds) :- !, | |
| 156 | maplist(get_changed_id,Ids,ChangedIds), | |
| 157 | maplist(ba_predicate_equal,Ids,Preds,Predicates), | |
| 158 | conjunct_predicates(Predicates,Predicate). | |
| 159 | before_after_predicate_no_equalities_aux(becomes_element_of(Ids,Set),Predicate,Ids) :- !, | |
| 160 | maplist(ba_predicate_member(Set),Ids,Predicates), | |
| 161 | % THIS IS WRONG: it asserts that each Id is an element of Set, but the tuple Ids is an element! | |
| 162 | conjunct_predicates(Predicates,Predicate). % should we generate Set /= {} => Predicate | |
| 163 | before_after_predicate_no_equalities_aux(becomes_such(Ids,Pred),Predicate,Ids) :- !, | |
| 164 | ba_predicate_becomes_such(Ids,Pred,Predicate). | |
| 165 | before_after_predicate_no_equalities_aux(choice(Choices),Predicate,ChangedIDs) :- !, | |
| 166 | maplist(before_after_predicate_no_equalities,Choices,BAChoices,Changes), | |
| 167 | append(Changes,ChangedIDs), | |
| 168 | maplist(add_missing_equalities(ChangedIDs),BAChoices,BAChoicesWithEqualities), | |
| 169 | disjunct_predicates(BAChoicesWithEqualities,Predicate). | |
| 170 | before_after_predicate_no_equalities_aux(precondition(Pre,Body),Predicate,ChangedIDs) :- !, | |
| 171 | before_after_predicate_no_equalities(Body,BABody,ChangedIDs), | |
| 172 | create_implication(Pre,BABody,Predicate). | |
| 173 | before_after_predicate_no_equalities_aux(witness_then(Pre,Body),Predicate,ChangedIDs) :- !, | |
| 174 | before_after_predicate_no_equalities_aux(assertion(Pre,Body),Predicate,ChangedIDs). % TODO: check if ok, or if we should use SELECT | |
| 175 | before_after_predicate_no_equalities_aux(assertion(Pre,Body),Predicate,ChangedIDs) :- | |
| 176 | !, | |
| 177 | before_after_predicate_no_equalities(Body,BABody,ChangedIDs), | |
| 178 | create_implication(Pre,BABody,Predicate1), | |
| 179 | create_negation(Pre,NotPre), | |
| 180 | add_missing_equalities(ChangedIDs,b(truth,pred,[]),NotPrePredicate), | |
| 181 | create_implication(NotPre,NotPrePredicate,Predicate2), | |
| 182 | conjunct_predicates([Predicate1,Predicate2],Predicate). | |
| 183 | before_after_predicate_no_equalities_aux(select_when(Pre,Body),Predicate,ChangedIDs) :- !, | |
| 184 | before_after_predicate_no_equalities(Body,BABody,ChangedIDs), | |
| 185 | conjunct_predicates([Pre,BABody],Predicate). | |
| 186 | before_after_predicate_no_equalities_aux(select(Whens),Predicate,ChangedIDs) :- !, | |
| 187 | maplist(before_after_predicate_no_equalities,Whens,WhensPredicates,Changes), | |
| 188 | append(Changes,ChangedIDs), | |
| 189 | maplist(add_missing_equalities(ChangedIDs),WhensPredicates,WhensPredicatesWithEqualities), | |
| 190 | disjunct_predicates(WhensPredicatesWithEqualities,Predicate). | |
| 191 | before_after_predicate_no_equalities_aux(select(Whens,Else),Predicate,ChangedIDs) :- !, | |
| 192 | maplist(before_after_predicate_no_equalities,Whens,WhensPredicates,Changes), | |
| 193 | maplist(add_missing_equalities(ChangedIDs),WhensPredicates,WhensPredicatesWithEqualities), | |
| 194 | maplist(get_select_conditions,Whens,SelectConditions), | |
| 195 | disjunct_predicates(SelectConditions,ElseTemp), | |
| 196 | create_negation(ElseTemp,ElseLHS), | |
| 197 | before_after_predicate_no_equalities(Else,ElseRHS,ElseChangedIDs), | |
| 198 | append([ElseChangedIDs|Changes],ChangedIDs), | |
| 199 | conjunct_predicates([ElseLHS,ElseRHS],ElsePred), | |
| 200 | add_missing_equalities(ChangedIDs,ElsePred,ElsePredWithEqualities), | |
| 201 | disjunct_predicates([ElsePredWithEqualities|WhensPredicatesWithEqualities],Predicate). | |
| 202 | % TODO: case, handle while | |
| 203 | before_after_predicate_no_equalities_aux(sequence(ListOfSteps),Predicate,ChangedIDs) :- !, | |
| 204 | ba_predicate_sequence(ListOfSteps,Predicate,ChangedIDs). | |
| 205 | before_after_predicate_no_equalities_aux(if(IfList),Predicate,ChangedIDs) :- !, | |
| 206 | ba_predicate_if(IfList,Predicate,ChangedIDs). | |
| 207 | before_after_predicate_no_equalities_aux(let(P,D,B),Predicate,ChangedIDs) :- !, | |
| 208 | before_after_predicate_no_equalities_aux(any(P,D,B),Predicate,ChangedIDs). % TO DO: create let_predicate | |
| 209 | before_after_predicate_no_equalities_aux(any(Parameters,PreCond,Body),Predicate,ChangedIDs) :- !, | |
| 210 | before_after_predicate_no_equalities(Body,BABody,ChangedIDs), | |
| 211 | conjunct_predicates([PreCond,BABody],Inner), | |
| 212 | create_or_merge_exists(Parameters,Inner,Predicate). | |
| 213 | before_after_predicate_no_equalities_aux(parallel(P),Predicate,ChangedIDs) :- !, | |
| 214 | maplist(before_after_predicate_no_equalities,P,Preds,Changes), | |
| 215 | append(Changes,ChangedIDs), | |
| 216 | conjunct_predicates(Preds,Predicate). | |
| 217 | before_after_predicate_no_equalities_aux(skip,Predicate,[]) :- !, | |
| 218 | Predicate = b(truth,pred,[]). | |
| 219 | before_after_predicate_no_equalities_aux(var(Parameters,Body),Predicate,ChangedIDs) :- !, | |
| 220 | before_after_predicate_no_equalities(Body,BABody,ChangedIDs), | |
| 221 | create_or_merge_exists(Parameters,BABody,Predicate). | |
| 222 | before_after_predicate_no_equalities_aux(rlevent(_Name,_Section,_Stat,_Parameters,Guards,_Thm,Actions,_VWit,_PWit,_Unmod,_AbsEvents),Predicate,ChangedIDs) :- !, | |
| 223 | maplist(before_after_predicate_no_equalities,Actions,BAActions,Changes), | |
| 224 | append(Changes,ChangedIDs), | |
| 225 | conjunct_predicates([Guards|BAActions],Predicate). % should probably be an implication? see precondition. | |
| 226 | before_after_predicate_no_equalities_aux(operation_call(OpId,[],[]),Predicate,ChangedIDs) :- !, | |
| 227 | get_texpr_id(OpId,op(OpName)), | |
| 228 | b_get_machine_operation(OpName,[],[],OpBody), | |
| 229 | before_after_predicate_no_equalities(OpBody,Predicate,ChangedIDs). | |
| 230 | before_after_predicate_no_equalities_aux(Expr,Predicate,ChangedIDs) :- | |
| 231 | add_error_fail(before_after_predicate,'before-after-predicate implementation missing: ',[Expr,Predicate,ChangedIDs]). | |
| 232 | ||
| 233 | get_select_conditions(b(select_when(Condition,_),_,_),Condition). | |
| 234 | ||
| 235 | ba_predicate_equal(LHS,RHS,Res) :- | |
| 236 | % LHS := RHS | |
| 237 | ? | get_override(LHS,RHS,TPred), !, |
| 238 | %nl,translate:print_bexpr(TPred),nl, | |
| 239 | Res=TPred. | |
| 240 | ||
| 241 | :- use_module(probsrc(error_manager),[add_internal_error/2]). | |
| 242 | % get override Term for f(X)(Y)... := RHS | |
| 243 | get_override(b(function(FUN,ARG),_Type,_Info),ExprSoFar,Res) :- !, % FUN(ARG) := RHS | |
| 244 | %print(fun(FUN)),nl, translate:print_bexpr(ExprSoFar),nl, | |
| 245 | get_texpr_type(FUN,FType), | |
| 246 | create_couple(ARG,ExprSoFar,Update), % ARG|-> ExprSoFar | |
| 247 | safe_create_texpr(set_extension([Update]),FType,UpdateSET), % {ARG|->ExprSoFar} | |
| 248 | construct_override(FUN,UpdateSET,Override), % FUN <+ {ARG |-> {...}} | |
| 249 | get_override(FUN,Override,Res). % Pass Override as new RHS in case FUN itself is a function application | |
| 250 | get_override(FUNID,OverrideExpr,TPred) :- | |
| 251 | get_texpr_id(FUNID,_ID), %print(base(ID)),nl, | |
| 252 | prime_typed_identifier(FUNID,FUNPrimeId), | |
| 253 | safe_create_texpr(equal(FUNPrimeId,OverrideExpr),pred,TPred). % FUN' = FUN <+ {ARG |-> RHS} | |
| 254 | get_override(FUNID,OverrideExpr,TPred) :- | |
| 255 | add_internal_error('Cannot compute override: ',get_override(FUNID,OverrideExpr,TPred)),fail. | |
| 256 | ||
| 257 | construct_override(FunID,Update,Override) :- | |
| 258 | get_texpr_type(Update,Type), | |
| 259 | Override = b(overwrite(FunID,Update),Type,[]). | |
| 260 | ||
| 261 | ba_predicate_member(Set,Id,TPred) :- | |
| 262 | % prime identifiers on the lhs | |
| 263 | prime_typed_identifier(Id,PrimedId), | |
| 264 | safe_create_texpr(member(PrimedId,Set),pred,TPred). | |
| 265 | ||
| 266 | ba_predicate_becomes_such(Ids,Pred,Predicate) :- | |
| 267 | list_renamings_to_primed_vars(Ids,RenamingList), | |
| 268 | rename_bt(Pred,RenamingList,Predicate). | |
| 269 | ||
| 270 | list_renamings_to_primed_vars([],[]). | |
| 271 | list_renamings_to_primed_vars([Var|Vars],[rename(VarId,PrimedId)|T]) :- | |
| 272 | get_texpr_id(Var,VarId), | |
| 273 | prime_id_atom(VarId,PrimedId), | |
| 274 | list_renamings_to_primed_vars(Vars,T). | |
| 275 | ||
| 276 | % add missing UNCHANGED equalities (x'=x for all variables that are unchanged) | |
| 277 | add_missing_equalities([],PredWithoutEqualities,Res) :- !, Res=PredWithoutEqualities. | |
| 278 | add_missing_equalities(AllVariables,PredWithoutEqualities,PredWithEqualities) :- | |
| 279 | find_typed_identifier_uses(PredWithoutEqualities,UsedIdentifiers), | |
| 280 | exclude(primed_var_is_used(UsedIdentifiers),AllVariables,VariablesNotOccuringPrimed), | |
| 281 | maplist(ba_predicate_equal,VariablesNotOccuringPrimed,VariablesNotOccuringPrimed,EqualityPredicates), | |
| 282 | conjunct_predicates([PredWithoutEqualities|EqualityPredicates],PredWithEqualities). | |
| 283 | ||
| 284 | :- use_module(probsrc(typing_tools),[normalize_type/2]). | |
| 285 | primed_var_is_used(UsedIdentifiers,Identifier) :- | |
| 286 | prime_typed_identifier(Identifier,PrimedIdentifier), | |
| 287 | remove_infos_and_norm(PrimedIdentifier,PrimedIdentifierWithoutInfos), | |
| 288 | ? | member(PrimedIdentifierWithoutInfos,UsedIdentifiers). |
| 289 | ||
| 290 | remove_infos_and_norm(b(E,Type,_),b(E,NType,_)) :- normalize_type(Type,NType). | |
| 291 | ||
| 292 | add_else_if_missing([],[DefaultElse]) :- | |
| 293 | safe_create_texpr(if_elsif(b(truth,pred,[]),b(skip,subst,[])),subst,DefaultElse). | |
| 294 | add_else_if_missing([If|Ifs],[If|Ifs]) :- | |
| 295 | get_texpr_expr(If,if_elsif(Test,_)), | |
| 296 | is_truth(Test), !. | |
| 297 | add_else_if_missing([If|Ifs],[If|MoreIfs]) :- | |
| 298 | add_else_if_missing(Ifs,MoreIfs). | |
| 299 | ||
| 300 | ba_predicate_if(IF,BA,AllChangedIDs) :- | |
| 301 | add_else_if_missing(IF,IFWithElse), | |
| 302 | maplist(ba_predicate_if_aux,IFWithElse,BAPreds,ChangedIDs), | |
| 303 | append(ChangedIDs,AllChangedIDs), | |
| 304 | ba_predicate_if(IFWithElse,BAPreds,AllChangedIDs,BA). | |
| 305 | ||
| 306 | ba_predicate_if([IF|IFs],[BAPred|BAPreds],IDs,BA) :- | |
| 307 | get_texpr_expr(IF,if_elsif(Test,_)), | |
| 308 | % if-part | |
| 309 | add_missing_equalities(IDs,BAPred,InnerBAPredIf), | |
| 310 | (is_truth(Test) | |
| 311 | -> InnerBAPredIf = BAPredIf | |
| 312 | ; safe_create_texpr(implication(Test,InnerBAPredIf),pred,BAPredIf)), | |
| 313 | % if there are further else/elseif parts, create pos | |
| 314 | (ba_predicate_if(IFs,BAPreds,IDs,ElsePred) | |
| 315 | -> create_negation(Test,NegTest), | |
| 316 | safe_create_texpr(implication(NegTest,ElsePred),pred,BAPredElse), | |
| 317 | conjunct_predicates([BAPredIf,BAPredElse],BA) | |
| 318 | ; BA = BAPredIf). | |
| 319 | ||
| 320 | ba_predicate_if_aux(IF,BAPred,ChangedIDs) :- | |
| 321 | get_texpr_expr(IF,if_elsif(_,Body)), | |
| 322 | before_after_predicate_no_equalities(Body,BAPred,ChangedIDs). | |
| 323 | ||
| 324 | ba_predicate_sequence([Last],Predicate,ChangedIDs) :- !, | |
| 325 | before_after_predicate_no_equalities(Last,Predicate,ChangedIDs). | |
| 326 | ba_predicate_sequence([First|SomeMore],Predicate,ChangedIDs) :- | |
| 327 | before_after_predicate_no_equalities(First,FirstPred,ChangesFirst), | |
| 328 | find_typed_identifier_uses(FirstPred,TypedIdsOfFirst), | |
| 329 | % get primed typed identifiers | |
| 330 | include(is_primed_typed_identifier,TypedIdsOfFirst,PrimedTypedIdsOfFirst), | |
| 331 | % rename them if they are already used in SomeMore | |
| 332 | ba_predicate_sequence(SomeMore,SecondPred,FurtherChanges), | |
| 333 | maplist(find_free_id_by_priming(SecondPred),PrimedTypedIdsOfFirst,UnusedPrimedTypedIds), | |
| 334 | maplist(create_id_renaming,PrimedTypedIdsOfFirst,UnusedPrimedTypedIds,RenamingOfFirst), | |
| 335 | rename_bt(FirstPred,RenamingOfFirst,FirstPredAfterReplacement), | |
| 336 | % rename unprimed ids in SecondPred, which are written by FirstPred | |
| 337 | maplist(remove_prime_typed_identifier,PrimedTypedIdsOfFirst,UnprimedTypedIds), | |
| 338 | maplist(create_id_renaming,UnprimedTypedIds,UnusedPrimedTypedIds,RenamingOfSecond), | |
| 339 | rename_bt(SecondPred,RenamingOfSecond,SecondPredAfterReplacement), | |
| 340 | ||
| 341 | conjunct_predicates([FirstPredAfterReplacement,SecondPredAfterReplacement],FullPred), | |
| 342 | % create exists for typed identifiers, which are primed more than once | |
| 343 | include(is_primed_more_than_once,UnusedPrimedTypedIds,TwoOrMorePrimedTypedIds), | |
| 344 | conjunction_to_list(FullPred,FullPredList), | |
| 345 | split_list(contains_some_typed_id(TwoOrMorePrimedTypedIds),FullPredList,ExistsPredList,RemainingPredList), | |
| 346 | conjunct_predicates(ExistsPredList,ExistsPred), | |
| 347 | create_exists(TwoOrMorePrimedTypedIds,ExistsPred,Exists), | |
| 348 | conjunct_predicates([Exists|RemainingPredList],Predicate), | |
| 349 | append(ChangesFirst,FurtherChanges,ChangedIDs). | |
| 350 | ||
| 351 | ||
| 352 | find_free_id_by_priming(Pred,TypedId,FreePrimedTypedId) :- | |
| 353 | find_typed_identifier_uses(Pred,TypedIds), | |
| 354 | (member(TypedId,TypedIds) -> | |
| 355 | prime_typed_identifier(TypedId,PrimedTypedId), | |
| 356 | find_free_id_by_priming(Pred,PrimedTypedId,FreePrimedTypedId) | |
| 357 | ; FreePrimedTypedId = TypedId). | |
| 358 | ||
| 359 | contains_some_typed_id(TypedIds,Pred) :- | |
| 360 | some(contains_typed_id(Pred),TypedIds). | |
| 361 | ||
| 362 | contains_typed_id(Pred,TypedId) :- | |
| 363 | find_typed_identifier_uses(Pred,TypedIds), | |
| 364 | member(TypedId,TypedIds). | |
| 365 | ||
| 366 | %prime_identifiers(TExprs,Primed) :- | |
| 367 | % maplist(prime_typed_identifier,TExprs,Primed). | |
| 368 | ||
| 369 | is_primed_more_than_once(TExpr) :- | |
| 370 | get_texpr_id(TExpr,ID), | |
| 371 | remove_prime_id_atom(ID,ID2), | |
| 372 | is_primed_id_atom(ID2). | |
| 373 | ||
| 374 | create_id_renaming(Var,RenamedVar,rename(Id,RenamedId)) :- | |
| 375 | get_texpr_id(Var,Id), | |
| 376 | get_texpr_id(RenamedVar,RenamedId). | |
| 377 | ||
| 378 |