Bug in the freeciv spec.
[repair.git] / Repair / RepairCompiler / MCC / IR / ConcreteInterferes.java
index 4f6c333b01ea850589294aa9f5a6a55ea1d1a0d6..2e657ef323d83019da8fc960abb86f43d7790e51 100755 (executable)
@@ -26,11 +26,19 @@ public class ConcreteInterferes {
                //Abstract updates don't have concrete interference1
                if (update.isAbstract()) 
                    continue;
-               
+
                DNFRule drule=satisfy?r.getDNFNegGuardExpr():r.getDNFGuardExpr();
                Descriptor updated_des=update.getDescriptor();
                assert updated_des!=null;
 
+               /* Test to see if the update only effects new
+                  objects and we're only testing for falsifying
+                  model definition rules. */
+               
+               if ((!satisfy)&&updateonlytonewobject(mun,un,update))
+                   continue;
+
+
                // See if the update interferes with the inclusion
                // condition for the rule
                if (r.getInclusion().usesDescriptor(updated_des)) {
@@ -59,6 +67,21 @@ public class ConcreteInterferes {
                        } else throw new Error();
                    }
 
+                   if ((un.getRule()==r)&&
+                       ((mun.op==MultUpdateNode.ADD)&&!satisfy)&&
+                       modifiesremoves(mun,un,r)) {
+                       Inclusion inclusion=r.getInclusion();
+                       if (inclusion instanceof RelationInclusion) {
+                           RelationInclusion ri=(RelationInclusion)inclusion;
+                           if ((!testdisjoint(update,r,ri.getLeftExpr()))&&
+                               (!testdisjoint(update,r,ri.getRightExpr())))
+                               ok=true;         /* Update is specific to
+                                                   given binding of the rule,
+                                                   and adds are only performed
+                                                   if the removal is desired or
+                                                   the tuple doesn't exist.*/
+                       }
+                   }
 
                    if (!ok) {
                        if (satisfy) {
@@ -87,6 +110,18 @@ public class ConcreteInterferes {
                                              intended one, so we're
                                              okay */
                        }
+                       if ((un.getRule()==r)&&
+                           ((mun.op==MultUpdateNode.ADD)&&!satisfy)&&
+                           modifiesremoves(mun,un,r)) {
+                           if (!testdisjoint(update,r,dexpr.getExpr()))
+                               continue; /* Update is specific to
+                                             given binding of the
+                                             rule, and adds are only
+                                             performed if the removal
+                                             is desired or the tuple
+                                             doesn't exist.*/
+                       }
+
                        if (interferes(update,dexpr))
                            return true;
                    }
@@ -96,6 +131,61 @@ public class ConcreteInterferes {
        return false;
     }
 
+
+    static private boolean modifiesremoves(MultUpdateNode mun,UpdateNode un, Rule r) {
+       AbstractRepair ar=mun.getRepair();
+       boolean inverted=ar.getPredicate().getPredicate().inverted();
+
+       if (ar.getType()!=AbstractRepair.MODIFYRELATION)
+           return false;
+       RelationInclusion ri=(RelationInclusion)r.getInclusion();
+       Expr e=inverted?ri.getRightExpr():ri.getLeftExpr();
+       while(e instanceof CastExpr) {
+           e=((CastExpr)e).getExpr();
+       }
+       if (!(e instanceof VarExpr))
+           return false;
+       VarExpr ve=(VarExpr)e;
+       if (ve.isValue())
+           return false;
+       return true;
+    }
+    
+    static private boolean updateonlytonewobject(MultUpdateNode mun, UpdateNode un, Updates updates) {
+       AbstractRepair ar=mun.getRepair();
+       if ((ar!=null)&&(ar.getType()==AbstractRepair.ADDTOSET||ar.getType()==AbstractRepair.ADDTORELATION))
+           for(int i=0;i<un.numUpdates();i++) {
+               Updates u=un.getUpdate(i);
+               if (u.getType()==Updates.POSITION&&
+                   ar.isNewObject(u.getRightPos()==0)) {
+                   Expr newleftexpr=u.getLeftExpr();
+                   Expr leftexpr=updates.getLeftExpr();
+                   boolean foundfield=false;
+                   while(true) {
+                       if (leftexpr.equals(null,newleftexpr)) {
+                           if (foundfield)
+                               return true;
+                           else
+                               break;
+                       } else if (leftexpr instanceof DotExpr) {
+                           if (!foundfield) {
+                               foundfield=true;
+                           } else {
+                               if (((DotExpr)leftexpr).isPtr())
+                                   break; //if its not a pointer, we're still in the structure
+                           }
+                           leftexpr=((DotExpr)leftexpr).getExpr();
+                       } else if (leftexpr instanceof CastExpr) {
+                           leftexpr=((CastExpr)leftexpr).getExpr();
+                       } else
+                           break;
+                   }
+               }
+           }
+       
+       return false;
+    }
+
     /** This method tries to show that if the Update update from the
      *  UpdateNode un changes the value of the inclusion constraint
      * that it falsifies the guard of model definition rule. */
@@ -344,12 +434,12 @@ public class ConcreteInterferes {
        return null;
     }
     
-    
     /** This function checks to see if an update is only performed if
-     * a given set is empty, and the algorithm is computing whether
-     * the update may falsify a rule that adds something to the set */
+     * a given set (or image set produced by a relation) is empty, and
+     * the algorithm is computing whether the update may falsify a
+     * rule that adds something to the set */
 
-    static private boolean initialinterferes(MultUpdateNode mun, Rule r, boolean satisfy) {
+    private boolean initialinterferes(MultUpdateNode mun, Rule r, boolean satisfy) {
        AbstractRepair ar=mun.getRepair();
        if ((!satisfy)&&(ar!=null)&&(ar.getType()==AbstractRepair.ADDTOSET)) {
            if (!r.getInclusion().getTargetDescriptors().contains(ar.getDescriptor()))
@@ -368,7 +458,42 @@ public class ConcreteInterferes {
                ((op==Opcode.GT)&&(ep.rightSize()==0))|| //(>0)
                ((op==Opcode.GE)&&(ep.rightSize()==1))) //(>=1)
                return false;
-       }
+       } else if ((!satisfy)&&(ar!=null)&&(ar.getType()==AbstractRepair.ADDTORELATION)) {
+           /* This test is for image sets of relations. */
+           if (!r.getInclusion().getTargetDescriptors().contains(ar.getDescriptor()))
+               return true;
+           boolean negated=ar.getPredicate().isNegated();
+           Predicate p=ar.getPredicate().getPredicate();
+           if (!(p instanceof ExprPredicate))
+               return true;
+           ExprPredicate ep=(ExprPredicate)p;
+           if (ep.getType()!=ExprPredicate.SIZE)
+               return true;
+
+           Opcode op=Opcode.translateOpcode(negated,ep.getOp());
+           if (!(((op==Opcode.EQ)&&(ep.rightSize()==1))|| //(=1)
+               ((op==Opcode.NE)&&(ep.rightSize()==0))|| //(!=0)
+               ((op==Opcode.GT)&&(ep.rightSize()==0))|| //(>0)
+               ((op==Opcode.GE)&&(ep.rightSize()==1)))) //(>=1)
+               return true;
+
+           RelationInclusion ri=(RelationInclusion)r.getInclusion();
+           Expr tmpve=ep.inverted()?ri.getRightExpr():ri.getLeftExpr();
+           if (!(tmpve instanceof VarExpr))
+               return true;
+           for(int i=0;i<mun.numUpdates();i++) {
+               UpdateNode un=mun.getUpdate(i);
+               for (int j=0;j<un.numUpdates();j++) {
+                   Updates update=un.getUpdate(j);
+                   //Abstract updates don't have concrete interference1
+                   if (update.isAbstract()) 
+                       continue;
+                   if (testdisjoint(update, r, r.getGuardExpr()))
+                       return true;
+               }
+           }
+           return false;
+       }
        return true;
     }