5 public class ConcreteInterferes {
6 Termination termination;
8 public ConcreteInterferes(Termination t) {
12 /** Returns true if the data structure updates performed by mun
13 * may increase (or decrease if satisfy=false) the scope of the
14 * model definition rule r. */
16 public boolean interferes(MultUpdateNode mun, Rule r, boolean satisfy) {
18 // A rule that adds something to a set can't be falsified by
19 // an update that is only performed if the set is empty
20 if (!initialinterferes(mun,r,satisfy))
23 for(int i=0;i<mun.numUpdates();i++) {
24 UpdateNode un=mun.getUpdate(i);
25 for (int j=0;j<un.numUpdates();j++) {
26 Updates update=un.getUpdate(j);
27 //Abstract updates don't have concrete interference1
28 if (update.isAbstract())
31 DNFRule drule=satisfy?r.getDNFNegGuardExpr():r.getDNFGuardExpr();
32 Descriptor updated_des=update.getDescriptor();
33 assert updated_des!=null;
35 /* Test to see if the update only effects new
36 objects and we're only testing for falsifying
37 model definition rules. */
39 if ((!satisfy)&&updateonlytonewobject(mun,un,update))
43 // See if the update interferes with the inclusion
44 // condition for the rule
45 if (r.getInclusion().usesDescriptor(updated_des)) {
48 /* If the update is for this rule, and the effect
49 is the intended effect, and the update only
50 effects one binding, then the abstract repair
51 node already models the action of this
54 if ((un.getRule()==r)&&
55 (((mun.op==MultUpdateNode.ADD)&&satisfy)
56 ||((mun.op==MultUpdateNode.REMOVE)&&!satisfy)
57 ||(mun.op==MultUpdateNode.MODIFY))) {
58 Inclusion inclusion=r.getInclusion();
59 if (inclusion instanceof RelationInclusion) {
60 RelationInclusion ri=(RelationInclusion)inclusion;
61 if ((!testdisjoint(update,r,ri.getLeftExpr()))&&
62 (!testdisjoint(update,r,ri.getRightExpr())))
64 } else if (inclusion instanceof SetInclusion) {
65 SetInclusion si=(SetInclusion)inclusion;
66 if (!testdisjoint(update,r,si.getExpr()))
68 } else throw new Error();
71 if ((un.getRule()==r)&&
72 ((mun.op==MultUpdateNode.ADD)&&!satisfy)&&
73 modifiesremoves(mun,un,r)) {
74 Inclusion inclusion=r.getInclusion();
75 if (inclusion instanceof RelationInclusion) {
76 RelationInclusion ri=(RelationInclusion)inclusion;
77 if ((!testdisjoint(update,r,ri.getLeftExpr()))&&
78 (!testdisjoint(update,r,ri.getRightExpr())))
79 ok=true; /* Update is specific to
80 given binding of the rule,
81 and adds are only performed
82 if the removal is desired or
83 the tuple doesn't exist.*/
89 /** Check to see if the update definitely falsifies r, thus
90 * can't accidentally satisfy it r. */
91 if (interferesinclusion(un, update, r)) {
92 if (Compiler.DEBUGGRAPH)
93 System.out.println("CASE 1");
97 if (Compiler.DEBUGGRAPH)
98 System.out.println("CASE 2");
100 return true; /* Interferes with inclusion condition */
105 for(int k=0;k<drule.size();k++) {
106 RuleConjunction rconj=drule.get(k);
107 for(int l=0;l<rconj.size();l++) {
108 DNFExpr dexpr=rconj.get(l);
109 /* See if update interferes w/ dexpr */
110 if ((un.getRule()==r)&&
111 (((mun.op==MultUpdateNode.ADD)&&satisfy)
112 ||((mun.op==MultUpdateNode.REMOVE)&&!satisfy)
113 ||(mun.op==MultUpdateNode.MODIFY))) {
114 if (!testdisjoint(update,r,dexpr.getExpr()))
115 continue; /* Update is specific to
117 rule, and effect is the
118 intended one, so we're
121 if ((un.getRule()==r)&&
122 ((mun.op==MultUpdateNode.ADD)&&!satisfy)&&
123 modifiesremoves(mun,un,r)) {
124 if (!testdisjoint(update,r,dexpr.getExpr()))
125 continue; /* Update is specific to
127 rule, and adds are only
128 performed if the removal
129 is desired or the tuple
133 if (interferes(update,dexpr)) {
134 if (Compiler.DEBUGGRAPH)
135 System.out.println("CASE 3");
147 static private boolean modifiesremoves(MultUpdateNode mun,UpdateNode un, Rule r) {
148 AbstractRepair ar=mun.getRepair();
149 boolean inverted=ar.getPredicate().getPredicate().inverted();
151 if (ar.getType()!=AbstractRepair.MODIFYRELATION)
153 RelationInclusion ri=(RelationInclusion)r.getInclusion();
154 Expr e=inverted?ri.getRightExpr():ri.getLeftExpr();
155 while(e instanceof CastExpr) {
156 e=((CastExpr)e).getExpr();
158 if (!(e instanceof VarExpr))
160 VarExpr ve=(VarExpr)e;
166 static private boolean updateonlytonewobject(MultUpdateNode mun, UpdateNode un, Updates updates) {
167 AbstractRepair ar=mun.getRepair();
168 if ((ar!=null)&&(ar.getType()==AbstractRepair.ADDTOSET||ar.getType()==AbstractRepair.ADDTORELATION))
169 for(int i=0;i<un.numUpdates();i++) {
170 Updates u=un.getUpdate(i);
171 if (u.getType()==Updates.POSITION&&
172 ar.isNewObject(u.getRightPos()==0)) {
173 Expr newleftexpr=u.getLeftExpr();
174 Expr leftexpr=updates.getLeftExpr();
175 boolean foundfield=false;
177 if (leftexpr.equals(null,newleftexpr)) {
182 } else if (leftexpr instanceof DotExpr) {
186 if (((DotExpr)leftexpr).isPtr())
187 break; //if its not a pointer, we're still in the structure
189 leftexpr=((DotExpr)leftexpr).getExpr();
190 } else if (leftexpr instanceof CastExpr) {
191 leftexpr=((CastExpr)leftexpr).getExpr();
201 /** This method tries to show that if the Update update from the
202 * UpdateNode un changes the value of the inclusion constraint
203 * that it falsifies the guard of model definition rule. */
205 static private boolean interferesinclusion(UpdateNode un, Updates update, Rule r) {
206 Descriptor updated_des=update.getDescriptor();
207 Inclusion inclusion=r.getInclusion();
208 if (inclusion instanceof RelationInclusion) {
209 RelationInclusion ri=(RelationInclusion)inclusion;
210 if (ri.getLeftExpr().usesDescriptor(updated_des)
211 &&searchinterfere(un,update,r,ri.getLeftExpr()))
213 if (ri.getRightExpr().usesDescriptor(updated_des)
214 &&searchinterfere(un,update,r,ri.getRightExpr()))
216 } else if (inclusion instanceof SetInclusion) {
217 SetInclusion si=(SetInclusion)inclusion;
218 if (si.getExpr().usesDescriptor(updated_des)
219 &&searchinterfere(un,update,r,si.getExpr()))
221 } else throw new Error();
225 /** This method finds all instances of a field or global that an
226 * update may modify, and builds a variable correspondance */
228 static private boolean searchinterfere(UpdateNode un, Updates update, Rule r, Expr inclusionexpr) {
229 Descriptor updated_des=update.getDescriptor();
230 if (updated_des instanceof FieldDescriptor) {
231 /* Build variable correspondance */
232 HashSet set=new HashSet();
233 inclusionexpr.findmatch(updated_des,set);
235 for(Iterator matchit=set.iterator();matchit.hasNext();) {
236 DotExpr dotexpr=(DotExpr)matchit.next();
237 DotExpr updateexpr=(DotExpr)update.getLeftExpr();
239 if (dotexpr.getField()!=updateexpr.getField())
241 Expr de=dotexpr.getExpr();
242 Expr ue=updateexpr.getExpr();
243 if ((de instanceof DotExpr)&&(ue instanceof DotExpr)) {
245 updateexpr=(DotExpr)ue;
246 } else if ((de instanceof VarExpr)&&(ue instanceof VarExpr)) {
247 VarDescriptor dvd=((VarExpr)de).getVar();
248 VarDescriptor uvd=((VarExpr)ue).getVar();
249 if (interferesinclusion(un,r,dvd,uvd))
257 } else if (updated_des instanceof VarDescriptor) {
258 /* We have a VarDescriptor - no correspondance necessary */
259 VarDescriptor vd=(VarDescriptor)updated_des;
260 if (interferesinclusion(un,r,vd,vd))
262 } else throw new Error();
266 /** This method tries to show that if dvd=uvd, then the update un
267 * must falsify the rule r. */
269 static private boolean interferesinclusion(UpdateNode un, Rule r, VarDescriptor dvd, VarDescriptor uvd) {
270 DNFRule negrule=r.getDNFNegGuardExpr();
271 HashMap remap=new HashMap();
274 for(int i=0;i<negrule.size();i++) {
275 RuleConjunction rconj=negrule.get(i);
277 for(int j=0;j<rconj.size();j++) {
278 DNFExpr dexpr=rconj.get(j);
279 if (dexpr.getExpr() instanceof OpExpr) {
280 OpExpr expr=(OpExpr)dexpr.getExpr();
281 Expr lexpr=expr.getLeftExpr();
282 Expr rexpr=expr.getRightExpr();
285 Set vars=rexpr.freeVars();
287 for(Iterator it=vars.iterator();it.hasNext();) {
288 VarDescriptor vd=(VarDescriptor) it.next();
289 if (!vd.isGlobal()) {
290 /* VarDescriptor isn't a global */
301 Opcode op=expr.getOpcode();
302 op=Opcode.translateOpcode(dexpr.getNegation(),op);
305 for(int k=0;k<un.numUpdates();k++) {
306 Updates update=un.getUpdate(k);
307 if(update.isExpr()) {
308 Set uvars=update.getRightExpr().freeVars();
309 boolean freevarok=true;
311 for(Iterator it=uvars.iterator();it.hasNext();) {
312 VarDescriptor vd=(VarDescriptor) it.next();
313 if (!vd.isGlobal()) {
314 /* VarDescriptor isn't a global */
324 Opcode op2=update.getOpcode();
326 ((op2==Opcode.GT)&&(op==Opcode.GE))||
327 ((op2==Opcode.LT)&&(op==Opcode.LE))||
328 ((op2==Opcode.EQ)&&((op==Opcode.GE)||(op==Opcode.LE)))) {
329 /* Operations match*/
330 if (lexpr.equals(remap,update.getLeftExpr())&&
331 rexpr.equals(remap,update.getRightExpr())) {
343 /* TODO: Check to see if there is an abstract repair */
345 break; /* try next conjunction */
354 /** This method checks whether the update effects only the
355 * intended binding for the model definition rule. */
357 private boolean testdisjoint(Updates u, Rule r, Expr e) {
358 // find all exprs that may be be effected by update
359 Set exprs=e.useDescriptor(u.getDescriptor());
360 for(Iterator eit=exprs.iterator();eit.hasNext();) {
361 Expr e2=(Expr)eit.next();
362 if (testdisjointness(u,r,e2))
368 /** This method tries to show that the modification only effects
369 * one binding of the model definition rule, and thus has no
370 * unintended side effects. */
372 private boolean testdisjointness(Updates u, Rule r, Expr e) {
373 // Note: rule of u must be r
375 Expr update_e=u.getLeftExpr();
376 HashSet quantifierset=new HashSet();
378 if (termination.analyzeQuantifiers(r,quantifierset))
379 return false; /* Can't accidentally interfere with other bindings if there aren't any! */
381 boolean firstfield=true;
385 if (update_e instanceof CastExpr)
386 update_e=((CastExpr)update_e).getExpr();
387 else if (e instanceof CastExpr)
388 e=((CastExpr)e).getExpr();
389 else if ((update_e instanceof DotExpr)&&(e instanceof DotExpr)) {
390 DotExpr de1=(DotExpr)update_e;
391 DotExpr de2=(DotExpr)e;
392 if (de1.isValue(null)&&!firstfield)
393 return true; /* Could have aliasing from this */
394 if (de1.getField()!=de2.getField())
395 return true; /* Different fields: not comparible */
398 Expr index1=de1.getIndex();
399 Expr index2=de2.getIndex();
402 if ((index1 instanceof VarExpr)&&(index2 instanceof VarExpr)) {
403 VarDescriptor vd1=((VarExpr)index1).getVar();
404 VarDescriptor vd2=((VarExpr)index2).getVar();
405 if ((vd1==vd2)&&!vd1.isGlobal()) {
406 quantifierset.add(getQuantifier(r,vd1));
407 if (termination.analyzeQuantifiers(r,quantifierset))
408 return false; /* State is disjoint from any other example */
412 update_e=de1.getExpr();
414 } else if ((update_e instanceof VarExpr)&&(e instanceof VarExpr)) {
415 VarDescriptor vd1=((VarExpr)update_e).getVar();
416 VarDescriptor vd2=((VarExpr)e).getVar();
417 if ((vd1==vd2)&&!vd1.isGlobal()) {
418 quantifierset.add(getQuantifier(r,vd1));
419 if (termination.analyzeQuantifiers(r,quantifierset))
420 return false; /* State is disjoint from any other example */
427 /** This method returns the quantifier that defines the quantifier
429 static private Quantifier getQuantifier(Quantifiers qs, VarDescriptor vd) {
430 for (int i=0;i<qs.numQuantifiers();i++) {
431 Quantifier q=qs.getQuantifier(i);
432 if (q instanceof SetQuantifier) {
433 SetQuantifier sq=(SetQuantifier)q;
436 } else if (q instanceof RelationQuantifier) {
437 RelationQuantifier rq=(RelationQuantifier)q;
438 if ((rq.x==vd)||(rq.y==vd))
440 } else if (q instanceof ForQuantifier) {
441 ForQuantifier fq=(ForQuantifier)q;
449 /** This function checks to see if an update is only performed if
450 * a given set (or image set produced by a relation) is empty, and
451 * the algorithm is computing whether the update may falsify a
452 * rule that adds something to the set */
454 private boolean initialinterferes(MultUpdateNode mun, Rule r, boolean satisfy) {
455 AbstractRepair ar=mun.getRepair();
456 if ((!satisfy)&&(ar!=null)&&(ar.getType()==AbstractRepair.ADDTOSET)) {
457 if (!r.getInclusion().getTargetDescriptors().contains(ar.getDescriptor()))
459 boolean negated=ar.getPredicate().isNegated();
460 Predicate p=ar.getPredicate().getPredicate();
461 if (!(p instanceof ExprPredicate))
463 ExprPredicate ep=(ExprPredicate)p;
464 if (ep.getType()!=ExprPredicate.SIZE)
466 Opcode op=Opcode.translateOpcode(negated,ep.getOp());
468 if (((op==Opcode.EQ)&&(ep.rightSize()==1))|| //(=1)
469 ((op==Opcode.NE)&&(ep.rightSize()==0))|| //(!=0)
470 ((op==Opcode.GT)&&(ep.rightSize()==0))|| //(>0)
471 ((op==Opcode.GE)&&(ep.rightSize()==1))) //(>=1)
473 } else if ((!satisfy)&&(ar!=null)&&(ar.getType()==AbstractRepair.ADDTORELATION)) {
474 /* This test is for image sets of relations. */
475 if (!r.getInclusion().getTargetDescriptors().contains(ar.getDescriptor()))
477 boolean negated=ar.getPredicate().isNegated();
478 Predicate p=ar.getPredicate().getPredicate();
479 if (!(p instanceof ExprPredicate))
481 ExprPredicate ep=(ExprPredicate)p;
482 if (ep.getType()!=ExprPredicate.SIZE)
485 Opcode op=Opcode.translateOpcode(negated,ep.getOp());
486 if (!(((op==Opcode.EQ)&&(ep.rightSize()==1))|| //(=1)
487 ((op==Opcode.NE)&&(ep.rightSize()==0))|| //(!=0)
488 ((op==Opcode.GT)&&(ep.rightSize()==0))|| //(>0)
489 ((op==Opcode.GE)&&(ep.rightSize()==1)))) //(>=1)
492 RelationInclusion ri=(RelationInclusion)r.getInclusion();
493 Expr tmpve=ep.inverted()?ri.getRightExpr():ri.getLeftExpr();
494 if (!(tmpve instanceof VarExpr))
496 for(int i=0;i<mun.numUpdates();i++) {
497 UpdateNode un=mun.getUpdate(i);
498 for (int j=0;j<un.numUpdates();j++) {
499 Updates update=un.getUpdate(j);
500 //Abstract updates don't have concrete interference1
501 if (update.isAbstract())
503 if (testdisjoint(update, r, r.getGuardExpr()))
512 static private boolean interferes(Updates update, DNFExpr dexpr) {
513 Descriptor descriptor=update.getDescriptor();
514 /* If the DNFExpr expr doesn't use the updated descriptor,
515 there is no interference. */
516 if (!dexpr.getExpr().usesDescriptor(descriptor))
519 if (update.isExpr()) {
520 /* We need to pair the variables */
521 Set vars=update.getRightExpr().freeVars();
522 Opcode op1=update.getOpcode();
523 Expr lexpr1=update.getLeftExpr();
524 Expr rexpr1=update.getRightExpr();
527 for(Iterator it=vars.iterator();it.hasNext();) {
528 VarDescriptor vd=(VarDescriptor) it.next();
529 /* VarDescriptor isn't a global */
530 if (!vd.isGlobal()) {
531 if (update.getVar()!=vd) {
537 if (good&&(dexpr.getExpr() instanceof OpExpr)) {
538 OpExpr expr=(OpExpr)dexpr.getExpr();
539 Expr lexpr2=expr.getLeftExpr();
540 Expr rexpr2=expr.getRightExpr();
541 Opcode op2=expr.getOpcode();
542 op2=Opcode.translateOpcode(dexpr.getNegation(),op2);
544 VarDescriptor leftdescriptor=null;
547 while(!(e instanceof VarExpr)) {
548 for(;e instanceof DotExpr;e=((DotExpr)e).getExpr()) ;
549 if (e instanceof VarExpr)
551 if (e instanceof CastExpr)
552 e=((CastExpr)e).getExpr();
553 else throw new Error("Bad Expr Type:"+e.name());
555 leftdescriptor=((VarExpr)e).getVar();
558 vars=rexpr2.freeVars();
560 for(Iterator it=vars.iterator();it.hasNext();) {
561 VarDescriptor vd=(VarDescriptor) it.next();
562 if (!vd.isGlobal()) {
563 /* VarDescriptor isn't a global */
564 if (leftdescriptor!=vd) {
573 HashMap remap=new HashMap();
574 remap.put(update.getVar(),leftdescriptor);
576 lexpr1.equals(remap,lexpr2)&&
577 rexpr1.equals(remap,rexpr2))