Changes:
[repair.git] / Repair / RepairCompiler / MCC / IR / ConstraintDependence.java
diff --git a/Repair/RepairCompiler/MCC/IR/ConstraintDependence.java b/Repair/RepairCompiler/MCC/IR/ConstraintDependence.java
new file mode 100755 (executable)
index 0000000..49d4cb9
--- /dev/null
@@ -0,0 +1,216 @@
+package MCC.IR;
+import MCC.State;
+import java.util.*;
+
+public class ConstraintDependence {
+    State state;
+    HashSet constnodes;
+    HashSet nodes;
+    Hashtable constonode;
+    Hashtable nodetonode;
+    Termination termination;
+
+    ConstraintDependence(State state, Termination t) {
+       this.state=state;
+       this.termination=t;
+       constnodes=new HashSet();
+       nodes=new HashSet();
+       constonode=new Hashtable();
+       nodetonode=new Hashtable();
+       constructnodes();
+       constructconjunctionnodes();
+       constructconjunctionedges();
+    }
+    
+    public void addNode(GraphNode gn) {
+       GraphNode gn2=new GraphNode(gn.getLabel(),gn.getTextLabel(),gn);
+       nodes.add(gn2);
+       nodetonode.put(gn,gn2);
+    }
+
+    public void associateWithConstraint(GraphNode gn, Constraint c) {
+       GraphNode ggn=(GraphNode)nodetonode.get(gn);
+       GraphNode gc=(GraphNode)constonode.get(c);
+       GraphNode.Edge e=new GraphNode.Edge("associated",ggn);
+       gc.addEdge(e);
+    }
+
+    public void requiresConstraint(GraphNode gn, Constraint c) {
+       GraphNode ggn=(GraphNode)nodetonode.get(gn);
+       GraphNode gc=(GraphNode)constonode.get(c);
+       GraphNode.Edge e=new GraphNode.Edge("requires",gc);
+       ggn.addEdge(e);
+    }
+
+    /** Constructs a node for each Constraint */
+    private void constructnodes() {
+       for(int i=0;i<state.vConstraints.size();i++) {
+           Constraint c=(Constraint)state.vConstraints.get(i);
+           GraphNode gn=new GraphNode(c.toString(),c);
+           constonode.put(c,gn);
+           constnodes.add(gn);
+       }
+    }
+    
+    private void constructconjunctionnodes() {
+       for(Iterator it=termination.conjunctions.iterator();it.hasNext();) {
+           GraphNode conjnode=(GraphNode)it.next();
+           TermNode tn=(TermNode)conjnode.getOwner();
+           Conjunction conj=tn.getConjunction();
+           addNode(conjnode);
+       }
+       for(int i=0;i<state.vConstraints.size();i++) {
+           Constraint c=(Constraint)state.vConstraints.get(i);
+           Set conjset=(Set)termination.conjunctionmap.get(c);
+           for(Iterator it=conjset.iterator();it.hasNext();) {
+               GraphNode gn=(GraphNode)it.next();
+               associateWithConstraint(gn,c);
+           }
+       }
+    }
+
+    private void constructconjunctionedges() {
+       for(Iterator it=termination.conjunctions.iterator();it.hasNext();) {
+           GraphNode conjnode=(GraphNode)it.next();
+           TermNode tn=(TermNode)conjnode.getOwner();
+           Conjunction conj=tn.getConjunction();
+           for(int i=0;i<conj.size();i++) {
+               DNFPredicate dpred=conj.get(i);
+               Predicate pred=dpred.getPredicate();
+               Expr expr=null;
+               if (pred instanceof InclusionPredicate) {
+                   InclusionPredicate ip=(InclusionPredicate)pred;
+                   expr=ip.expr;
+               } else if (pred instanceof ExprPredicate) {
+                   ExprPredicate ep=(ExprPredicate)pred;
+                   expr=ep.expr;
+               } else throw new Error("Unrecognized Predicate");
+               Set functions=expr.getfunctions();
+               if (functions==null)
+                   continue;
+               for(Iterator fit=functions.iterator();fit.hasNext();) {
+                   Function f=(Function)fit.next();
+                   if (rulesensurefunction(f))
+                       continue; //no constraint needed to ensure
+
+                   Set s=providesfunction(f);
+                   if (s.size()==0) {
+                       System.out.println("Error: No constraint ensures that [forall v in "+f.getSet()+"], size(v."+(f.isInverse()?"~":"")+f.getRelation()+")=1");
+                       System.exit(-1);
+                   }
+                   Constraint c=(Constraint)s.iterator().next(); //Take the first one
+                   requiresConstraint(conjnode,c);
+               }
+           }
+       }
+    }
+
+    private boolean rulesensurefunction(Function f) {
+       boolean foundrule=false;
+       for(int i=0;i<state.vRules.size();i++) {
+           Rule r=(Rule)state.vRules.get(i);
+           if (r.getInclusion().getTargetDescriptors().contains(f.getRelation())) {
+               RelationInclusion ri=(RelationInclusion)r.getInclusion();
+               Expr e=f.isInverse()?ri.getRightExpr():ri.getLeftExpr();
+               SetDescriptor sd=e.getSet();
+               if (!(sd.isSubset(f.getSet())||f.getSet().isSubset(sd)))
+                   continue; /* This rule doesn't effect the function */
+               if (foundrule) /* two different rules are a problem */
+                   return false;
+               if (!((e instanceof VarExpr)&&(r.numQuantifiers()==1)))
+                   return false;
+               VarExpr ve=(VarExpr)e;
+               Quantifier q=r.getQuantifier(0);
+               if (!(q instanceof SetQuantifier))
+                   return false;
+               SetQuantifier sq=(SetQuantifier)q;
+               if (ve.getVar()!=sq.getVar())
+                   return false;
+               if (!sq.getSet().isSubset(f.getSet()))
+                   return false;
+               if (!((r.getGuardExpr() instanceof BooleanLiteralExpr)&&
+                     ((BooleanLiteralExpr)r.getGuardExpr()).getValue()==true))
+                   return false;
+               Expr e2=f.isInverse()?ri.getLeftExpr():ri.getRightExpr();
+               if (e2.isSafe())
+                   foundrule=true;
+               else
+                   return false;
+           }
+       }
+       return foundrule;
+    }
+    private Set providesfunction(Function f) {
+       HashSet set=new HashSet();
+       for(int i=0;i<state.vConstraints.size();i++) {
+           Constraint c=(Constraint)state.vConstraints.get(i);
+           boolean goodconstraint=true;
+           DNFConstraint dnfconst=c.dnfconstraint;
+           for(int j=0;j<dnfconst.size();j++) {
+               Conjunction conj=dnfconst.get(j);
+               boolean conjprovides=false;
+               for(int k=0;k<conj.size();k++) {
+                   DNFPredicate dpred=conj.get(k);
+                   if (!dpred.isNegated()&&
+                       (dpred.getPredicate() instanceof ExprPredicate)&&
+                       ((ExprPredicate)dpred.getPredicate()).getType()==ExprPredicate.SIZE) {
+                       ExprPredicate ep=(ExprPredicate)dpred.getPredicate();
+                       if (ep.isRightInt()&&
+                           ep.rightSize()==1&&
+                           ep.getOp()==Opcode.EQ&&
+                           ep.inverted()==f.isInverse()&&
+                           ep.getDescriptor()==f.getRelation()) {
+                           ImageSetExpr se=(ImageSetExpr) ((SizeofExpr) ((OpExpr)ep.expr).left).getSetExpr();
+                           VarDescriptor vd=se.getVar();
+                           if (c.numQuantifiers()==1) {
+                               for(int l=0;l<c.numQuantifiers();l++) {
+                                   Quantifier q=c.getQuantifier(l);
+                                   if (q instanceof SetQuantifier&&
+                                       ((SetQuantifier)q).getVar()==vd) {
+                                       SetDescriptor sd=((SetQuantifier)q).getSet();
+                                       if (sd.isSubset(f.getSet()))
+                                           conjprovides=true;
+                                   }
+                               }
+                           } else
+                               break;
+                       }
+                   }
+               }
+               if (!conjprovides) {
+                   goodconstraint=false;
+                   break;
+               }
+           }
+           if (goodconstraint)
+               set.add(c);
+       }
+       return set;
+    }
+
+    public static class Function {
+       private RelationDescriptor rd;
+       private SetDescriptor sd;
+       private boolean inverse;
+
+       public Function(RelationDescriptor r, SetDescriptor sd, boolean inverse) {
+           this.inverse=inverse;
+           this.sd=sd;
+           this.rd=r;
+       }
+
+       public SetDescriptor getSet() {
+           return sd;
+       }
+
+       public RelationDescriptor getRelation() {
+           return rd;
+       }
+
+       public boolean isInverse() {
+           return inverse;
+       }
+    }
+
+}