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