4 public class ConcreteInterferes {
5 Termination termination;
7 public ConcreteInterferes(Termination t) {
11 /** Returns true if the data structure updates performed by mun
12 * may increase (or decrease if satisfy=false) the scope of the
13 * model definition rule r. */
15 public boolean interferes(MultUpdateNode mun, Rule r, boolean satisfy) {
17 // A rule that adds something to a set can't be falsified by
18 // an update that is only performed if the set is empty
19 if (!initialinterferes(mun,r,satisfy))
22 for(int i=0;i<mun.numUpdates();i++) {
23 UpdateNode un=mun.getUpdate(i);
24 for (int j=0;j<un.numUpdates();j++) {
25 Updates update=un.getUpdate(j);
26 //Abstract updates don't have concrete interference1
27 if (update.isAbstract())
30 DNFRule drule=satisfy?r.getDNFNegGuardExpr():r.getDNFGuardExpr();
31 Descriptor updated_des=update.getDescriptor();
32 assert updated_des!=null;
34 /* Test to see if the update only effects new
35 objects and we're only testing for falsifying
36 model definition rules. */
38 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();
73 /** Check to see if the update definitely falsifies r, thus
74 * can't accidentally satisfy it r. */
75 if (interferesinclusion(un, update, r))
78 return true; /* Interferes with inclusion condition */
82 for(int k=0;k<drule.size();k++) {
83 RuleConjunction rconj=drule.get(k);
84 for(int l=0;l<rconj.size();l++) {
85 DNFExpr dexpr=rconj.get(l);
86 /* See if update interferes w/ dexpr */
87 if ((un.getRule()==r)&&
88 (((mun.op==MultUpdateNode.ADD)&&satisfy)
89 ||((mun.op==MultUpdateNode.REMOVE)&&!satisfy)
90 ||(mun.op==MultUpdateNode.MODIFY))) {
91 if (!testdisjoint(update,r,dexpr.getExpr()))
92 continue; /* Update is specific to
94 rule, and effect is the
95 intended one, so we're
98 if (interferes(update,dexpr))
107 static private boolean updateonlytonewobject(MultUpdateNode mun, UpdateNode un, Updates updates) {
108 AbstractRepair ar=mun.getRepair();
109 for(int i=0;i<un.numUpdates();i++) {
110 Updates u=un.getUpdate(i);
111 if (u.getType()==Updates.POSITION&&
112 ar.isNewObject(u.getRightPos()==0)) {
113 Expr newleftexpr=u.getLeftExpr();
114 Expr leftexpr=updates.getLeftExpr();
115 boolean foundfield=false;
117 if (leftexpr.equals(null,newleftexpr)) {
122 } else if (leftexpr instanceof DotExpr) {
126 if (((DotExpr)leftexpr).isPtr())
127 break; //if its not a pointer, we're still in the structure
129 leftexpr=((DotExpr)leftexpr).getExpr();
130 } else if (leftexpr instanceof CastExpr) {
131 leftexpr=((CastExpr)leftexpr).getExpr();
141 /** This method tries to show that if the Update update from the
142 * UpdateNode un changes the value of the inclusion constraint
143 * that it falsifies the guard of model definition rule. */
145 static private boolean interferesinclusion(UpdateNode un, Updates update, Rule r) {
146 Descriptor updated_des=update.getDescriptor();
147 Inclusion inclusion=r.getInclusion();
148 if (inclusion instanceof RelationInclusion) {
149 RelationInclusion ri=(RelationInclusion)inclusion;
150 if (ri.getLeftExpr().usesDescriptor(updated_des)
151 &&searchinterfere(un,update,r,ri.getLeftExpr()))
153 if (ri.getRightExpr().usesDescriptor(updated_des)
154 &&searchinterfere(un,update,r,ri.getRightExpr()))
156 } else if (inclusion instanceof SetInclusion) {
157 SetInclusion si=(SetInclusion)inclusion;
158 if (si.getExpr().usesDescriptor(updated_des)
159 &&searchinterfere(un,update,r,si.getExpr()))
161 } else throw new Error();
165 /** This method finds all instances of a field or global that an
166 * update may modify, and builds a variable correspondance */
168 static private boolean searchinterfere(UpdateNode un, Updates update, Rule r, Expr inclusionexpr) {
169 Descriptor updated_des=update.getDescriptor();
170 if (updated_des instanceof FieldDescriptor) {
171 /* Build variable correspondance */
172 HashSet set=new HashSet();
173 inclusionexpr.findmatch(updated_des,set);
175 for(Iterator matchit=set.iterator();matchit.hasNext();) {
176 DotExpr dotexpr=(DotExpr)matchit.next();
177 DotExpr updateexpr=(DotExpr)update.getLeftExpr();
179 if (dotexpr.getField()!=updateexpr.getField())
181 Expr de=dotexpr.getExpr();
182 Expr ue=updateexpr.getExpr();
183 if ((de instanceof DotExpr)&&(ue instanceof DotExpr)) {
185 updateexpr=(DotExpr)ue;
186 } else if ((de instanceof VarExpr)&&(ue instanceof VarExpr)) {
187 VarDescriptor dvd=((VarExpr)de).getVar();
188 VarDescriptor uvd=((VarExpr)ue).getVar();
189 if (interferesinclusion(un,r,dvd,uvd))
197 } else if (updated_des instanceof VarDescriptor) {
198 /* We have a VarDescriptor - no correspondance necessary */
199 VarDescriptor vd=(VarDescriptor)updated_des;
200 if (interferesinclusion(un,r,vd,vd))
202 } else throw new Error();
206 /** This method tries to show that if dvd=uvd, then the update un
207 * must falsify the rule r. */
209 static private boolean interferesinclusion(UpdateNode un, Rule r, VarDescriptor dvd, VarDescriptor uvd) {
210 DNFRule negrule=r.getDNFNegGuardExpr();
211 HashMap remap=new HashMap();
214 for(int i=0;i<negrule.size();i++) {
215 RuleConjunction rconj=negrule.get(i);
217 for(int j=0;j<rconj.size();j++) {
218 DNFExpr dexpr=rconj.get(j);
219 if (dexpr.getExpr() instanceof OpExpr) {
220 OpExpr expr=(OpExpr)dexpr.getExpr();
221 Expr lexpr=expr.getLeftExpr();
222 Expr rexpr=expr.getRightExpr();
225 Set vars=rexpr.freeVars();
227 for(Iterator it=vars.iterator();it.hasNext();) {
228 VarDescriptor vd=(VarDescriptor) it.next();
229 if (!vd.isGlobal()) {
230 /* VarDescriptor isn't a global */
241 Opcode op=expr.getOpcode();
242 op=Opcode.translateOpcode(dexpr.getNegation(),op);
245 for(int k=0;k<un.numUpdates();k++) {
246 Updates update=un.getUpdate(k);
247 if(update.isExpr()) {
248 Set uvars=update.getRightExpr().freeVars();
249 boolean freevarok=true;
251 for(Iterator it=uvars.iterator();it.hasNext();) {
252 VarDescriptor vd=(VarDescriptor) it.next();
253 if (!vd.isGlobal()) {
254 /* VarDescriptor isn't a global */
264 Opcode op2=update.getOpcode();
266 ((op2==Opcode.GT)&&(op==Opcode.GE))||
267 ((op2==Opcode.LT)&&(op==Opcode.LE))||
268 ((op2==Opcode.EQ)&&((op==Opcode.GE)||(op==Opcode.LE)))) {
269 /* Operations match*/
270 if (lexpr.equals(remap,update.getLeftExpr())&&
271 rexpr.equals(remap,update.getRightExpr())) {
283 /* TODO: Check to see if there is an abstract repair */
285 break; /* try next conjunction */
294 /** This method checks whether the update effects only the
295 * intended binding for the model definition rule. */
297 private boolean testdisjoint(Updates u, Rule r, Expr e) {
298 // find all exprs that may be be effected by update
299 Set exprs=e.useDescriptor(u.getDescriptor());
300 for(Iterator eit=exprs.iterator();eit.hasNext();) {
301 Expr e2=(Expr)eit.next();
302 if (testdisjointness(u,r,e2))
308 /** This method tries to show that the modification only effects
309 * one binding of the model definition rule, and thus has no
310 * unintended side effects. */
312 private boolean testdisjointness(Updates u, Rule r, Expr e) {
313 // Note: rule of u must be r
315 Expr update_e=u.getLeftExpr();
316 HashSet quantifierset=new HashSet();
318 if (termination.analyzeQuantifiers(r,quantifierset))
319 return false; /* Can't accidentally interfere with other bindings if there aren't any! */
321 boolean firstfield=true;
325 if (update_e instanceof CastExpr)
326 update_e=((CastExpr)update_e).getExpr();
327 else if (e instanceof CastExpr)
328 e=((CastExpr)e).getExpr();
329 else if ((update_e instanceof DotExpr)&&(e instanceof DotExpr)) {
330 DotExpr de1=(DotExpr)update_e;
331 DotExpr de2=(DotExpr)e;
332 if (de1.isValue(null)&&!firstfield)
333 return true; /* Could have aliasing from this */
334 if (de1.getField()!=de2.getField())
335 return true; /* Different fields: not comparible */
338 Expr index1=de1.getIndex();
339 Expr index2=de2.getIndex();
342 if ((index1 instanceof VarExpr)&&(index2 instanceof VarExpr)) {
343 VarDescriptor vd1=((VarExpr)index1).getVar();
344 VarDescriptor vd2=((VarExpr)index2).getVar();
345 if ((vd1==vd2)&&!vd1.isGlobal()) {
346 quantifierset.add(getQuantifier(r,vd1));
347 if (termination.analyzeQuantifiers(r,quantifierset))
348 return false; /* State is disjoint from any other example */
352 update_e=de1.getExpr();
354 } else if ((update_e instanceof VarExpr)&&(e instanceof VarExpr)) {
355 VarDescriptor vd1=((VarExpr)update_e).getVar();
356 VarDescriptor vd2=((VarExpr)e).getVar();
357 if ((vd1==vd2)&&!vd1.isGlobal()) {
358 quantifierset.add(getQuantifier(r,vd1));
359 if (termination.analyzeQuantifiers(r,quantifierset))
360 return false; /* State is disjoint from any other example */
367 /** This method returns the quantifier that defines the quantifier
369 static private Quantifier getQuantifier(Quantifiers qs, VarDescriptor vd) {
370 for (int i=0;i<qs.numQuantifiers();i++) {
371 Quantifier q=qs.getQuantifier(i);
372 if (q instanceof SetQuantifier) {
373 SetQuantifier sq=(SetQuantifier)q;
376 } else if (q instanceof RelationQuantifier) {
377 RelationQuantifier rq=(RelationQuantifier)q;
378 if ((rq.x==vd)||(rq.y==vd))
380 } else if (q instanceof ForQuantifier) {
381 ForQuantifier fq=(ForQuantifier)q;
389 /** This function checks to see if an update is only performed if
390 * a given set (or image set produced by a relation) is empty, and
391 * the algorithm is computing whether the update may falsify a
392 * rule that adds something to the set */
394 private boolean initialinterferes(MultUpdateNode mun, Rule r, boolean satisfy) {
395 AbstractRepair ar=mun.getRepair();
396 if ((!satisfy)&&(ar!=null)&&(ar.getType()==AbstractRepair.ADDTOSET)) {
397 if (!r.getInclusion().getTargetDescriptors().contains(ar.getDescriptor()))
399 boolean negated=ar.getPredicate().isNegated();
400 Predicate p=ar.getPredicate().getPredicate();
401 if (!(p instanceof ExprPredicate))
403 ExprPredicate ep=(ExprPredicate)p;
404 if (ep.getType()!=ExprPredicate.SIZE)
406 Opcode op=Opcode.translateOpcode(negated,ep.getOp());
408 if (((op==Opcode.EQ)&&(ep.rightSize()==1))|| //(=1)
409 ((op==Opcode.NE)&&(ep.rightSize()==0))|| //(!=0)
410 ((op==Opcode.GT)&&(ep.rightSize()==0))|| //(>0)
411 ((op==Opcode.GE)&&(ep.rightSize()==1))) //(>=1)
413 } else if ((!satisfy)&&(ar!=null)&&(ar.getType()==AbstractRepair.ADDTORELATION)) {
414 /* This test is for image sets of relations. */
415 if (!r.getInclusion().getTargetDescriptors().contains(ar.getDescriptor()))
417 boolean negated=ar.getPredicate().isNegated();
418 Predicate p=ar.getPredicate().getPredicate();
419 if (!(p instanceof ExprPredicate))
421 ExprPredicate ep=(ExprPredicate)p;
422 if (ep.getType()!=ExprPredicate.SIZE)
425 Opcode op=Opcode.translateOpcode(negated,ep.getOp());
426 if (!(((op==Opcode.EQ)&&(ep.rightSize()==1))|| //(=1)
427 ((op==Opcode.NE)&&(ep.rightSize()==0))|| //(!=0)
428 ((op==Opcode.GT)&&(ep.rightSize()==0))|| //(>0)
429 ((op==Opcode.GE)&&(ep.rightSize()==1)))) //(>=1)
432 RelationInclusion ri=(RelationInclusion)r.getInclusion();
433 Expr tmpve=ep.inverted()?ri.getRightExpr():ri.getLeftExpr();
434 if (!(tmpve instanceof VarExpr))
436 for(int i=0;i<mun.numUpdates();i++) {
437 UpdateNode un=mun.getUpdate(i);
438 for (int j=0;j<un.numUpdates();j++) {
439 Updates update=un.getUpdate(j);
440 //Abstract updates don't have concrete interference1
441 if (update.isAbstract())
443 if (testdisjoint(update, r, r.getGuardExpr()))
452 static private boolean interferes(Updates update, DNFExpr dexpr) {
453 Descriptor descriptor=update.getDescriptor();
454 /* If the DNFExpr expr doesn't use the updated descriptor,
455 there is no interference. */
456 if (!dexpr.getExpr().usesDescriptor(descriptor))
459 if (update.isExpr()) {
460 /* We need to pair the variables */
461 Set vars=update.getRightExpr().freeVars();
462 Opcode op1=update.getOpcode();
463 Expr lexpr1=update.getLeftExpr();
464 Expr rexpr1=update.getRightExpr();
467 for(Iterator it=vars.iterator();it.hasNext();) {
468 VarDescriptor vd=(VarDescriptor) it.next();
469 /* VarDescriptor isn't a global */
470 if (!vd.isGlobal()) {
471 if (update.getVar()!=vd) {
477 if (good&&(dexpr.getExpr() instanceof OpExpr)) {
478 OpExpr expr=(OpExpr)dexpr.getExpr();
479 Expr lexpr2=expr.getLeftExpr();
480 Expr rexpr2=expr.getRightExpr();
481 Opcode op2=expr.getOpcode();
482 op2=Opcode.translateOpcode(dexpr.getNegation(),op2);
484 VarDescriptor leftdescriptor=null;
487 while(!(e instanceof VarExpr)) {
488 for(;e instanceof DotExpr;e=((DotExpr)e).getExpr()) ;
489 if (e instanceof VarExpr)
491 if (e instanceof CastExpr)
492 e=((CastExpr)e).getExpr();
493 else throw new Error("Bad Expr Type:"+e.name());
495 leftdescriptor=((VarExpr)e).getVar();
498 vars=rexpr2.freeVars();
500 for(Iterator it=vars.iterator();it.hasNext();) {
501 VarDescriptor vd=(VarDescriptor) it.next();
502 if (!vd.isGlobal()) {
503 /* VarDescriptor isn't a global */
504 if (leftdescriptor!=vd) {
513 HashMap remap=new HashMap();
514 remap.put(update.getVar(),leftdescriptor);
516 lexpr1.equals(remap,lexpr2)&&
517 rexpr1.equals(remap,rexpr2))