1 % (c) 2009-2023 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(seq_rewriter, [rewrite_seq_to_set/3]).
6
7 :- use_module(library(lists),[maplist/3,
8 append/2]).
9
10 :- use_module(probsrc(bsyntaxtree),[remove_bt/4,
11 create_texpr/4,
12 safe_create_texpr/3,
13 replace_ids_by_exprs/4,
14 get_texpr_expr/2,
15 get_texpr_type/2, get_set_type/2,
16 conjunct_predicates/2,
17 disjunct_predicates/2,
18 create_forall/3,
19 create_exists/3,
20 create_implication/3,
21 syntaxtransformation/5,
22 unique_typed_id/3,
23 rewrite_if_then_else_expr_to_b/2]).
24 :- use_module(probsrc(error_manager), [add_internal_error/2,
25 add_error_fail/3]).
26 :- use_module(probsrc(typing_tools), [normalize_type/2]).
27
28 :- use_module(smt_common_predicates).
29
30 :- use_module(probsrc(module_information),[module_info/2]).
31 :- module_info(group,smt_solvers).
32 :- module_info(description,'This module implements transformations of sequences to sets as needed by the SMT-LIB translation.').
33
34 :- set_prolog_flag(double_quotes, codes).
35
36 %% rewrite_seq_to_set(+IsWd, +Expr, -Out).
37 rewrite_seq_to_set(IsWd,Expr,Out) :-
38 %translate:translate_bexpression(Expr,PPExpr),
39 %write(before(PPExpr)),nl,
40 %write(before(Expr)),nl,
41 ? rewrite_seq_to_set(IsWd,Expr,CExpr,[],AC,IDs),
42 % translate:translate_bexpression(CExpr,PPCExpr),
43 % write(after(PPCExpr)),nl,
44 combine_pred_and_ac(CExpr,AC,IDs,Out). % Do not call regular ast_cleanup afterwards: It undoes some of the changes done here
45 rewrite_seq_to_set(IsWd,Expr,CExprOut,Path,ACOut,IDsOut) :-
46 rewrites(pre,IsWd,Expr,[],TPExpr,Path,ACPre,IDsPre),
47 remove_bt(TPExpr,PExpr,LExpr,TLExpr),
48 ? syntaxtransformation(PExpr,Subs,_,NewSubs,LExpr),
49 functor(PExpr,F,N),
50 % recursively clean up sub-expressions
51 ? maplist(rewrite_seq_to_set(IsWd),ACPre,ACPreClean),
52 ? rewrite_seq_to_set_l(IsWd,Subs,NewSubs,F/N,1,Path,ACL,IDsL),
53 ? maplist(rewrite_seq_to_set(IsWd),ACL,ACLClean),
54 rewrites(post,IsWd,TLExpr,[],CExpr,Path,ACPost,IDsPost),
55 maplist(rewrite_seq_to_set(IsWd),ACPost,ACPostClean),
56 append([ACPreClean,ACLClean,ACPostClean],AC),
57 append([IDsPre,IDsL,IDsPost],IDs),
58 (get_texpr_type(CExpr,pred)
59 -> combine_pred_and_ac(CExpr,AC,IDs,CExprOut), IDsOut = [], ACOut = []
60 ; CExprOut = CExpr, ACOut = AC, IDsOut = IDs).
61
62 combine_pred_and_ac(Pred,AC,IDs,Out) :-
63 conjunct_predicates(AC,ACPred),
64 conjunct_predicates([Pred,ACPred],OutInnerPred),
65 create_exists(IDs,OutInnerPred,Out).
66
67 rewrite_seq_to_set_l(_IsWd,[],[],_Functor,_Nr,_Path,[],[]).
68 rewrite_seq_to_set_l(IsWd,[Expr|Rest],[CExpr|CRest],Functor,ArgNr,Path,AC,IDs) :-
69 ? rewrite_seq_to_set(IsWd,Expr,CExpr,[arg(Functor,ArgNr)|Path],ACC,IDsC),
70 A1 is ArgNr+1,
71 ? rewrite_seq_to_set_l(IsWd,Rest,CRest,Functor,A1,Path,ACL,IDsL),
72 append(ACC,ACL,AC),
73 append(IDsC,IDsL,IDs).
74
75 rewrites(Phase,IsWd,Expr,AppliedRules,Result,Path,ACS,IDs) :-
76 assure_single_rules(AppliedRules,Rule),
77 ? ( rewrite_phase(Phase,IsWd,Expr,NExpr,Mode/Rule,Path,ACPhase,IDsPhase) -> % try to apply a rule (matching the current phase)
78 ( Mode==single -> AppRules = [Rule|AppliedRules] % if the rule is marked as "single", we add to the list of already applied rules
79 ; Mode==multi -> AppRules = AppliedRules % if "multi", we do not add it to the list, the rule might be applied more than once
80 ; add_error_fail(seq_rewriter,'Unexpected rule mode ',Mode)),
81 rewrites(Phase,IsWd,NExpr,AppRules,Result,Path,ACRec,IDsRec), % continue recursively with the new expression
82 append(ACPhase,ACRec,ACS), append(IDsPhase,IDsRec,IDs)
83 ; % if no rule matches anymore,
84 Result = Expr, % we leave the expression unmodified
85 ACS = [], IDs = [],
86 Rule = none). % and unblock the co-routine (see assure_single_rules/2)
87
88 assure_single_rules([],_Rule) :- !.
89 assure_single_rules(AppliedRules,Rule) :-
90 assure_single_rules2(AppliedRules,Rule).
91 :- block assure_single_rules2(?,-).
92 assure_single_rules2(_AppliedRules,none) :- !.
93 assure_single_rules2(AppliedRules,Rule) :-
94 \+ member(Rule, AppliedRules).
95
96 rewrite_phase(Phase,IsWd,OTExpr,NTExpr,Mode/Rule,Path,AC,IDs) :-
97 create_texpr(OExpr,OType,OInfo,OTExpr),
98 create_texpr(NExpr,NType,NInfo,NTExpr),
99 ? rewrite_phase2(Phase,IsWd,OExpr,OType,OInfo,NExpr,NType,NInfo,Mode/Rule,Path,AC,IDs).
100 rewrite_phase2(pre,IsWd,OExpr,OType,OInfo,NExpr,NType,NInfo,Mode/Rule,_Path,AC,IDs) :-
101 ? rewrite_pre(OExpr,IsWd,OType,OInfo,NExpr,NType,NInfo,Mode_Rule,AC,IDs),
102 (functor(Mode_Rule,'/',2)
103 -> Mode_Rule = Mode/Rule
104 %,format(' rewrite_pre Rule: ~w/~w~n',[Mode,Rule])
105 ; add_internal_error('Illegal cleanup_pre rule, missing mode: ',Mode_Rule),fail).
106 rewrite_phase2(post,_IsWd,OExpr,OType,OInfo,NExpr,NType,NInfo,Mode/Rule,Path,AC,IDs) :-
107 rewrite_post_with_path(OExpr,OType,OInfo,NExpr,NType,NInfo,Mode_Rule,Path,AC,IDs),
108 (functor(Mode_Rule,'/',2)
109 -> Mode_Rule = Mode/Rule
110 %,format(' rewrite_post Rule: ~w/~w~n',[Mode,Rule])
111 ; add_internal_error('Illegal rewrite_post rule, missing mode: ',Mode_Rule),fail).
112
113 rewrite_pre(if_then_else(If,Then,Else),IsWd,Type,I,NExpr,Type,NI,multi/rewrite_if_then_else_expr,[],[]) :-
114 IsWd == 'FALSE',
115 Type \== pred,
116 !, % rewrite if-then-else expression in order to add WD POs afterwards; all other WD POs are handled by add_wd_pos_to_pred/7
117 % this has nothing to do with seq rewriting but is faster since the AST is already traversed here and seq rewriting is the first step of preprocessing for Z3
118 rewrite_if_then_else_expr_to_b(if_then_else(If,Then,Else), NExpr),
119 NI = I.
120 rewrite_pre(let_expression(Ids,Exprs,Body),IsWd,Type,_,Unfolded,Type,NI,multi/unfold_let_expression,[],[]) :-
121 IsWd == 'FALSE',
122 !, % expand LET expression as a special case in order to add WD POs afterwards; all other WD POs are handled by add_wd_pos_to_pred/7
123 % see above
124 replace_ids_by_exprs(Body, Ids, Exprs, b(Unfolded,_,NI)).
125 rewrite_pre(empty_sequence,_,seq(T),I,empty_set,set(couple(integer,T)),I,multi/empty_sequence_to_set,[],[]).
126 rewrite_pre(general_concat(A),_,Type,I,empty_set,set(couple(integer,T)),I,multi/empty_general_concat,[],[]) :-
127 ( A = b(empty_sequence,_,_); A = b(empty_set,_,_)),
128 ( Type = seq(T); Type = set(couple(integer,T))).
129 rewrite_pre(sequence_extension(SeqExtValues),_,SType,I,set_extension(SetExtValues),set(couple(integer,Type)),I,multi/seq_ext_to_set_ext,[],[]) :-
130 ( SType = seq(Type)
131 ; SType = set(couple(integer,Type))
132 ),
133 seq_ext_to_set_ext(SeqExtValues,1,Type,SetExtValues).
134 % change type of values to set instead of seq
135 %rewrite_pre(value(A),_,seq(integer),I,value(A),set(couple(integer,integer)),I,multi/replace_type_identifier,[],[]).
136 %rewrite_pre(value(A),_,seq(string),I,value(A),set(couple(string,string)),I,multi/replace_type_identifier,[],[]).
137
138 % seq(S)
139 % {f | f : NATURAL1 +-> S & #n.(n : NATURAL & dom(f) = 1..n)}
140 % warum nicht:
141 % {f | #n.(n : NATURAL & f : 1..n --> S)}
142 % scheint kein speedup zu liefern....
143 rewrite_pre(seq(S),_,set(seq(Type)),I,comprehension_set([F],Pred),set(set(couple(integer,Type))),I,multi/rewrite_seq,[],[]) :-
144 unique_typed_id("_smt_tmp",integer,N),
145 unique_typed_id("_smt_tmp",set(couple(integer,Type)),F),
146
147 % f : NATURAL1 +-> S
148 safe_create_texpr(partial_function(b(integer_set('NATURAL1'),set(integer),[]),S),set(set(couple(integer,Type))),PartFunc),
149 safe_create_texpr(member(F,PartFunc),pred,FMember),
150
151 safe_create_texpr(member(N,b(integer_set('NATURAL'),set(integer),[])),pred,NMember),
152 safe_create_texpr(interval(b(integer(1),integer,[]),N),set(integer),Interval),
153 safe_create_texpr(domain(F),set(integer),Dom),
154 safe_create_texpr(equal(Dom,Interval),pred,DomIsEqualToInterval),
155
156 conjunct_predicates([NMember,DomIsEqualToInterval],ExistsInner),
157 create_exists([N],ExistsInner,Exists),
158 conjunct_predicates([Exists,FMember],Pred).
159
160 % seq1(S)
161 % {f | f : NATURAL1 +-> S & #n.(n : NATURAL1 & dom(f) = 1..n)}
162 % warum nicht:
163 % {f | #n.(n : NATURAL1 & f : 1..n +-> S)}
164 % scheint kein speedup zu liefern....
165 rewrite_pre(seq1(S),_,set(seq(Type)),I,comprehension_set([F],Pred),set(set(couple(integer,Type))),I,multi/rewrite_seq,[],[]) :-
166 unique_typed_id("_smt_tmp",integer,N),
167 unique_typed_id("_smt_tmp",set(couple(integer,Type)),F),
168
169 % f : NATURAL1 +-> S
170 safe_create_texpr(partial_function(b(integer_set('NATURAL1'),set(integer),[]),S),set(set(couple(integer,Type))),PartFunc),
171 safe_create_texpr(member(F,PartFunc),pred,FMember),
172
173 safe_create_texpr(member(N,b(integer_set('NATURAL1'),set(integer),[])),pred,NMember),
174 safe_create_texpr(interval(b(integer(1),integer,[]),N),set(integer),Interval),
175 safe_create_texpr(domain(F),set(integer),Dom),
176 safe_create_texpr(equal(Dom,Interval),pred,DomIsEqualToInterval),
177
178 conjunct_predicates([NMember,DomIsEqualToInterval],ExistsInner),
179 create_exists([N],ExistsInner,Exists),
180 conjunct_predicates([Exists,FMember],Pred).
181
182 % iseq(S)
183 % {f | f : NATURAL1 +-> S & #n.(n : NATURAL & dom(f) = 1..n)} /\ (NATURAL1 >+> S)
184 % warum nicht:
185 % {f | #n.(n : NATURAL & f : 1..n +-> S )} /\ (NATURAL1 >+> S)
186 % scheint kein speedup zu liefern....
187 rewrite_pre(iseq(S),_,set(seq(Type)),I,intersection(CompSet,PartInj),set(set(couple(integer,Type))),I,multi/rewrite_seq,[],[]) :-
188 unique_typed_id("_smt_tmp",integer,N),
189 unique_typed_id("_smt_tmp",set(couple(integer,Type)),F),
190
191 % f : NATURAL1 +-> S
192 safe_create_texpr(partial_function(b(integer_set('NATURAL1'),set(integer),[]),S),set(set(couple(integer,Type))),PartFunc),
193 safe_create_texpr(member(F,PartFunc),pred,FMember),
194
195 safe_create_texpr(member(N,b(integer_set('NATURAL'),set(integer),[])),pred,NMember),
196 safe_create_texpr(interval(b(integer(1),integer,[]),N),set(integer),Interval),
197 safe_create_texpr(domain(F),set(integer),Dom),
198 safe_create_texpr(equal(Dom,Interval),pred,DomIsEqualToInterval),
199
200 conjunct_predicates([NMember,DomIsEqualToInterval],ExistsInner),
201 create_exists([N],ExistsInner,Exists),
202 conjunct_predicates([Exists,FMember],Pred),
203 safe_create_texpr(comprehension_set([F],Pred),set(set(couple(integer,Type))),CompSet),
204
205 safe_create_texpr(partial_injection(b(integer_set('NATURAL1'),set(integer),[]),S),set(set(couple(integer,Type))),PartInj).
206
207 % perm(S)
208 % {f | f : NATURAL1 +-> S & #n.(n : NATURAL & dom(f) = 1..n)} /\ (NATURAL1 >+> S) /\ (NATURAL1 +->> S)
209 % warum nicht:
210 % {f | #n.(n : NATURAL & f : 1..n +-> S )} /\ (NATURAL1 >+> S) /\ (NATURAL1 +->> S)
211 % scheint kein speedup zu liefern....
212 rewrite_pre(perm(S),_,set(seq(Type)),I,intersection(CompSet,Intersec),set(set(couple(integer,Type))),I,multi/rewrite_seq,[],[]) :-
213 unique_typed_id("_smt_tmp",integer,N),
214 unique_typed_id("_smt_tmp",set(couple(integer,Type)),F),
215
216 % f : NATURAL1 +-> S
217 safe_create_texpr(partial_function(b(integer_set('NATURAL1'),set(integer),[]),S),set(set(couple(integer,Type))),PartFunc),
218 safe_create_texpr(member(F,PartFunc),pred,FMember),
219
220 safe_create_texpr(member(N,b(integer_set('NATURAL'),set(integer),[])),pred,NMember),
221 safe_create_texpr(interval(b(integer(1),integer,[]),N),set(integer),Interval),
222 safe_create_texpr(domain(F),set(integer),Dom),
223 safe_create_texpr(equal(Dom,Interval),pred,DomIsEqualToInterval),
224
225 conjunct_predicates([NMember,DomIsEqualToInterval],ExistsInner),
226 create_exists([N],ExistsInner,Exists),
227 conjunct_predicates([Exists,FMember],Pred),
228 safe_create_texpr(comprehension_set([F],Pred),set(set(couple(integer,Type))),CompSet),
229
230 safe_create_texpr(partial_injection(b(integer_set('NATURAL1'),set(integer),[]),S),set(set(couple(integer,Type))),PartInj),
231 safe_create_texpr(partial_surjection(b(integer_set('NATURAL1'),set(integer),[]),S),set(set(couple(integer,Type))),TotalSurj),
232 safe_create_texpr(intersection(PartInj,TotalSurj),pred,Intersec).
233
234 % replace size by card -> card performance really bad, timeout with around 20 elements
235 %rewrite_pre(size(A),integer,I,card(A),integer,I,multi/replace_size_card,[],[]).
236 % better take maximum of indices
237 %rewrite_pre(size(b(empty_sequence,_,_)),integer,I,b(integer(0),integer,[]),integer,I,multi/rewrite_size,[],[]).
238 rewrite_pre(size(S),_,integer,I,UnwrappedId,integer,I,multi/rewrite_size,[AC1,AC2],[UId]) :-
239 unique_typed_id("_smt_tmp",integer,UId),
240 get_texpr_expr(UId,UnwrappedId),
241 % two axioms:
242 % !(i,v).((i,v) : Set => uid >= x)
243 % uid=0 or #(i,v).((i,v) : Set & uid = x)
244 % Note: #(i,v) FAILS if set is empty
245
246 unique_typed_id("_smt_tmp",integer,Index),
247 get_texpr_type(S,Type),
248 get_set_type(Type,couple(integer,SeqType)),
249
250 unique_typed_id("_smt_tmp",SeqType,Value),
251 safe_create_texpr(couple(Index,Value),couple(integer,SeqType),QuantifiedVar),
252
253 safe_create_texpr(greater_equal(UId,Index),pred,GreaterEqual),
254 safe_create_texpr(equal(UId,Index),pred,Equal),
255 safe_create_texpr(member(QuantifiedVar,S),pred,QuantifiedInSet),
256 safe_create_texpr(integer(0),integer,Zero),
257 safe_create_texpr(equal(UId,Zero),pred,EqualZero),
258
259 conjunct_predicates([QuantifiedInSet,Equal],ExistsInner),
260 create_implication(QuantifiedInSet,GreaterEqual,ForallInner),
261
262 create_exists([Index,Value],ExistsInner,AC0),
263 disjunct_predicates([EqualZero,AC0],AC1),
264 create_forall([Index,Value],ForallInner,AC2).
265 % gets first element of non-empty seq
266 % card performance, solver answers unknown with >=13 elements (card timeout?)
267 %rewrite_pre(first(A),Type,I,UnwrappedId,Type,I,multi/rewrite_first,[AC],[UId]) :-
268 % unique_typed_id("_smt_tmp",integer,UId),
269 % get_texpr_expr(UId,UnwrappedId),
270
271 % safe_create_texpr(couple(b(integer(1),integer,[]),UId),couple(integer,Type),TheCouple),
272 % safe_create_texpr(member(TheCouple,A),pred,AC).
273 rewrite_pre(first(A),_,Type,I,function(A,b(integer(1),integer,[])),Type,I,multi/rewrite_first,[],[]).
274 % this should be handled by the function(...) itself
275 % safe_create_texpr(size(A),integer,Card).
276 % create_texpr(greater_equal(Card,b(integer(1),integer,[])),pred,[],AC).
277 % gets last element of non-empty seq
278 % card performance, solver answers unknown with >=13 elements (card timeout?)
279 rewrite_pre(last(A),_,Type,I,function(A,Card),Type,I,multi/rewrite_last,[],[]) :-
280 safe_create_texpr(size(A),integer,Card).
281 % this should be handled by the function(...) itself
282 % create_texpr(greater_equal(Card,b(integer(1),integer,[])),pred,[],AC).
283 % reverses sequence
284 rewrite_pre(rev(S),_,seq(Type),I,comprehension_set([Index,Value],QuantifiedInSet),set(couple(integer,Type)),I,multi/rewrite_rev,[AC1],[TmpCard]) :-
285 % {(i,v) | (card(S)-i+1,b) : x}
286 safe_create_texpr(size(S),integer,Card),
287 unique_typed_id("_smt_tmp",integer,Index),
288 unique_typed_id("_smt_tmp",Type,Value),
289
290 % size is stored outside of the set comprehension using a temp. identifier
291 % to increase performance
292 unique_typed_id("_smt_tmp",integer,TmpCard),
293 safe_create_texpr(equal(TmpCard,Card),pred,AC1),
294
295 safe_create_texpr(minus(TmpCard,Index),integer,TmpIndex),
296 safe_create_texpr(add(TmpIndex,b(integer(1),integer,[])),integer,NIndex),
297 safe_create_texpr(couple(NIndex,Value),couple(integer,Type),TheCouple),
298
299 safe_create_texpr(member(TheCouple,S),pred,QuantifiedInSet).
300 % concat returns S2 concatenated to S1 as a Sequence
301 rewrite_pre(concat(S1,S2),_,seq(Type),I,comprehension_set([Index,Value],Disjunct),set(couple(integer,Type)),I,multi/rewrite_concat,[AC1],[TmpCard]) :-
302 % {(i,v) | (i,v) : S1 or (i-card(S1),v) : S2}
303 unique_typed_id("_smt_tmp",integer,Index),
304 unique_typed_id("_smt_tmp",Type,Value),
305
306 safe_create_texpr(size(S1),integer,Card1),
307 % size is stored outside of the set comprehension using a temp. identifier
308 % to increase performance
309 unique_typed_id("_smt_tmp",integer,TmpCard),
310 safe_create_texpr(equal(TmpCard,Card1),pred,AC1),
311
312 safe_create_texpr(couple(Index,Value),couple(integer,Type),QuantifiedVar),
313 % (i,v) : S1
314 safe_create_texpr(member(QuantifiedVar,S1),pred,QuantifiedInSet1),
315
316 % (i-card(S1),v) : S2
317 safe_create_texpr(minus(Index,TmpCard),integer,NIndex),
318 safe_create_texpr(couple(NIndex,Value),couple(integer,Type),QuantifiedVar2),
319 safe_create_texpr(member(QuantifiedVar2,S2),pred,QuantifiedInSet2),
320
321 disjunct_predicates([QuantifiedInSet1,QuantifiedInSet2],Disjunct).
322 % restrict_front returns the first N elements of the sequence S as a Sequence
323 rewrite_pre(restrict_front(S,N),_,seq(Type),I,comprehension_set([Index,Value],Conjunct),set(couple(integer,Type)),I,multi/rewrite_restrict_front,[],[]) :-
324 % {(i,v) | (i,v) : S & i <= N}
325 unique_typed_id("_smt_tmp",integer,Index),
326 unique_typed_id("_smt_tmp",Type,Value),
327 safe_create_texpr(couple(Index,Value),couple(integer,Type),QuantifiedVar),
328 % (i,v) : S
329 safe_create_texpr(member(QuantifiedVar,S),pred,QuantifiedInSet),
330 % i <= N
331 safe_create_texpr(less_equal(Index,N),pred,LessEqual),
332
333 conjunct_predicates([QuantifiedInSet,LessEqual],Conjunct).
334 % restrict_tail returns the sequence S without the first N elements
335 % special case to increase performance
336 rewrite_pre(restrict_tail(S,N),_,seq(Type),I,SExpr,set(couple(integer,Type)),I,multi/rewrite_restrict_tail_special,[],[]) :-
337 get_texpr_expr(N,integer(0)), !,
338 get_texpr_expr(S,SExpr).
339 rewrite_pre(restrict_tail(S,N),_,seq(Type),I,comprehension_set([Index,Value],Conjunct),set(couple(integer,Type)),I,multi/rewrite_restrict_tail,[],[]) :-
340 % {(i,v) | (i+N,v) : S & i > 0}
341 unique_typed_id("_smt_tmp",integer,Index),
342 unique_typed_id("_smt_tmp",Type,Value),
343 %create_texpr(couple(Index,Value),couple(integer,Type),[],AC),
344
345 % NIndex = i+N
346 create_texpr(add(N,Index),integer,[],NIndex),
347 safe_create_texpr(couple(NIndex,Value),couple(integer,Type),TheCouple),
348 safe_create_texpr(member(TheCouple,S),pred,QuantifiedInSet),
349
350 % i > 0
351 safe_create_texpr(integer(0),integer,Null),
352 safe_create_texpr(greater(Index,Null),pred,GreaterEqual),
353
354 conjunct_predicates([QuantifiedInSet,GreaterEqual],Conjunct).
355 % prepends element E to Sequence S
356 rewrite_pre(insert_front(E,S),_,seq(Type),I,union(AC,CompSet),set(couple(integer,Type)),I,multi/rewrite_insert_front,[],[]) :-
357 % {(i,v) | (i-1,v) : S or (i = 1 & v = E)}
358 % easier to code: {(i,v) | (i-1,v) : S} \/ {(1,E)}
359 % {(1,E)}
360 safe_create_texpr(set_extension([b(couple(b(integer(1),integer,[]),E),couple(integer,Type),[])]),set(couple(integer,Type)),AC),
361
362 % {(i,v) | (i-1,v) : S}
363 unique_typed_id("_smt_tmp",integer,Index),
364 unique_typed_id("_smt_tmp",Type,Value),
365
366 safe_create_texpr(minus(Index,b(integer(1),integer,[])),integer,NIndex),
367 safe_create_texpr(couple(NIndex,Value),couple(integer,Type),TheCouple),
368 safe_create_texpr(member(TheCouple,S),pred,QuantifiedInSet),
369
370 safe_create_texpr(comprehension_set([Index,Value],QuantifiedInSet),set(couple(integer,Type)),CompSet).
371 % append element S <- E: S \/ {(size(S)+1,E)}
372 rewrite_pre(insert_tail(S,E),_,seq(Type),I,union(S,AC),set(couple(integer,Type)),I,multi/rewrite_insert_tail,[],[]) :-
373 % NIndex = size(S)+1
374 safe_create_texpr(size(S),integer,Card),
375 safe_create_texpr(add(Card,b(integer(1),integer,[])),integer,NIndex),
376 % AC = {(NIndex,E)}
377 safe_create_texpr(set_extension([b(couple(NIndex,E),couple(integer,Type),[])]),set(couple(integer,Type)),AC).
378 % get front: S - {(size(S),function(S,size(S)))}
379 %rewrite_pre(front(A),seq(Type),I,restrict_front(A,N),seq(Type),I,multi/rewrite_front,[],[]) :-
380 % safe_create_texpr(size(A),integer,Card),
381 % safe_create_texpr(minus(Card,b(integer(1),integer,[])),integer,N).
382 rewrite_pre(front(A),_,seq(Type),I,set_subtraction(A,AC),set(couple(integer,Type)),I,multi/rewrite_front,[],[]) :-
383 safe_create_texpr(size(A),integer,Card),
384 safe_create_texpr(function(A,Card),Type,Last),
385 % AC = {(size(A),function(A,size(A)))}
386 safe_create_texpr(set_extension([b(couple(Card,Last),couple(integer,Type),[])]),set(couple(integer,Type)),AC).
387 rewrite_pre(tail(S),_,seq(Type),I,comprehension_set([Index,Value],Conjunct),set(couple(integer,Type)),I,multi/rewrite_tail,[],[]) :-
388 % {(i,v) | (i+1,v) : S & i > 0}
389 unique_typed_id("_smt_tmp",integer,Index),
390 unique_typed_id("_smt_tmp",Type,Value),
391
392 % (i+1,v) : S
393 safe_create_texpr(add(Index,b(integer(1),integer,[])),integer,NIndex),
394 safe_create_texpr(couple(NIndex,Value),couple(integer,Type),TheCouple),
395 safe_create_texpr(member(TheCouple,S),pred,QuantifiedInSet),
396
397 % i > 0
398 safe_create_texpr(greater(Index,b(integer(0),integer,[])),pred,Greater),
399
400 conjunct_predicates([QuantifiedInSet,Greater],Conjunct).
401 % Change seq -> set(couple(...))
402 rewrite_pre(A,_,TypeIn,I,A,TypeOut,I,multi/replace_seq_type_by_set_type,[],[]) :-
403 normalize_type(TypeIn,TypeOut), TypeIn \= TypeOut.
404
405 % iseq and permutation introduce member of intersection. split again to make cleanup easier later on
406 rewrite_post_with_path(member(X,Intersection),pred,I,conjunct(Member1,Member2),pred,I,multi/split_member_of_intersection,_,[],[]) :-
407 get_texpr_expr(Intersection,intersection(SetA,SetB)),
408 safe_create_texpr(member(X,SetA),pred,Member1),
409 safe_create_texpr(member(X,SetB),pred,Member2).
410
411 seq_ext_to_set_ext([],_,_,[]).
412 seq_ext_to_set_ext([H|T],Counter,Type,[b(couple(CounterAsBExpr,H),couple(integer,Type),[])|List]) :-
413 NCounter is Counter + 1,
414 safe_create_texpr(integer(Counter),integer,CounterAsBExpr),
415 seq_ext_to_set_ext(T,NCounter,Type,List).