| 1 | % (c) 2009-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(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). |