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