+
+ private MultUpdateNode getmultupdatenode(Conjunction conj, DNFPredicate dpred, int repairtype) {
+ MultUpdateNode mun=null;
+ GraphNode gn=(GraphNode) termination.conjtonodemap.get(conj);
+
+ for(Iterator edgeit=gn.edges();(mun==null)&&edgeit.hasNext();) {
+ GraphNode gn2=((GraphNode.Edge) edgeit.next()).getTarget();
+ TermNode tn2=(TermNode)gn2.getOwner();
+ if (tn2.getType()==TermNode.ABSTRACT) {
+ AbstractRepair ar=tn2.getAbstract();
+ if (((repairtype==-1)||(ar.getType()==repairtype))&&
+ ar.getPredicate()==dpred) {
+ for(Iterator edgeit2=gn2.edges();edgeit.hasNext();) {
+ GraphNode gn3=((GraphNode.Edge) edgeit2.next()).getTarget();
+ if (!removed.contains(gn3)) {
+ TermNode tn3=(TermNode)gn3.getOwner();
+ if (tn3.getType()==TermNode.UPDATE) {
+ mun=tn3.getUpdate();
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ return mun;
+ }
+
+ public void generatecomparisonrepair(Conjunction conj, DNFPredicate dpred, CodeWriter cr){
+ MultUpdateNode munremove=getmultupdatenode(conj,dpred,AbstractRepair.REMOVEFROMRELATION);
+ MultUpdateNode munadd=getmultupdatenode(conj,dpred,AbstractRepair.ADDTORELATION);
+ ExprPredicate ep=(ExprPredicate)dpred.getPredicate();
+ RelationDescriptor rd=(RelationDescriptor)ep.getDescriptor();
+ boolean usageimage=rd.testUsage(RelationDescriptor.IMAGE);
+ boolean usageinvimage=rd.testUsage(RelationDescriptor.INVIMAGE);
+ boolean inverted=ep.inverted();
+ boolean negated=dpred.isNegated();
+ OpExpr expr=(OpExpr)ep.expr;
+ Opcode opcode=expr.getOpcode();
+ VarDescriptor leftside=VarDescriptor.makeNew("leftside");
+ VarDescriptor rightside=VarDescriptor.makeNew("rightside");
+ VarDescriptor newvalue=VarDescriptor.makeNew("newvalue");
+ if (!inverted) {
+ expr.getLeftExpr().generate(cr,leftside);
+ expr.getRightExpr().generate(cr,newvalue);
+ cr.outputline(rd.getRange().getType().getGenerateType().getSafeSymbol()+" "+rightside.getSafeSymbol()+";");
+ cr.outputline(rd.getSafeSymbol()+"_hash->get("+leftside.getSafeSymbol()+","+rightside.getSafeSymbol()+");");
+ } else {
+ expr.getLeftExpr().generate(cr,rightside);
+ expr.getRightExpr().generate(cr,newvalue);
+ cr.outputline(rd.getDomain().getType().getGenerateType().getSafeSymbol()+" "+leftside.getSafeSymbol()+";");
+ cr.outputline(rd.getSafeSymbol()+"_hashinv->get("+leftside.getSafeSymbol()+","+leftside.getSafeSymbol()+");");
+ }
+ if (negated)
+ if (opcode==Opcode.GT) {
+ opcode=Opcode.LE;
+ } else if (opcode==Opcode.GE) {
+ opcode=Opcode.LT;
+ } else if (opcode==Opcode.LT) {
+ opcode=Opcode.GE;
+ } else if (opcode==Opcode.LE) {
+ opcode=Opcode.GT;
+ } else if (opcode==Opcode.EQ) {
+ opcode=Opcode.NE;
+ } else if (opcode==Opcode.NE) {
+ opcode=Opcode.EQ;
+ } else {
+ throw new Error("Unrecognized Opcode");
+ }
+
+ if (opcode==Opcode.GT) {
+ cr.outputline(newvalue.getSafeSymbol()+"++;");
+ } else if (opcode==Opcode.GE) {
+ /* Equal */
+ } else if (opcode==Opcode.LT) {
+ cr.outputline(newvalue.getSafeSymbol()+"--;");
+ } else if (opcode==Opcode.LE) {
+ /* Equal */
+ } else if (opcode==Opcode.EQ) {
+ /* Equal */
+ } else if (opcode==Opcode.NE) {
+ cr.outputline(newvalue.getSafeSymbol()+"++;");
+ } else {
+ throw new Error("Unrecognized Opcode");
+ }
+ /* Do abstract repairs */
+ if (usageimage) {
+ cr.outputline(rd.getSafeSymbol()+"_hash->remove("+leftside.getSafeSymbol()+","+rightside.getSafeSymbol()+");");
+ if (!inverted) {
+ cr.outputline(rd.getSafeSymbol()+"_hash->add("+leftside.getSafeSymbol()+","+newvalue.getSafeSymbol()+");");
+ } else {
+ cr.outputline(rd.getSafeSymbol()+"_hash->add("+newvalue.getSafeSymbol()+","+rightside.getSafeSymbol()+");");
+ }
+ }
+ if (usageinvimage) {
+ cr.outputline(rd.getSafeSymbol()+"_hashinv->remove("+rightside.getSafeSymbol()+","+leftside.getSafeSymbol()+");");
+ if (!inverted) {
+ cr.outputline(rd.getSafeSymbol()+"_hashinv->add("+newvalue.getSafeSymbol()+","+leftside.getSafeSymbol()+");");
+ } else {
+ cr.outputline(rd.getSafeSymbol()+"_hashinv->add("+rightside.getSafeSymbol()+","+newvalue.getSafeSymbol()+");");
+ }
+ }
+ /* Do concrete repairs */
+ /* Start with scheduling removal */
+ for(int i=0;i<state.vRules.size();i++) {
+ Rule r=(Rule)state.vRules.get(i);
+ if (r.getInclusion().getTargetDescriptors().contains(rd)) {
+ for(int j=0;j<munremove.numUpdates();j++) {
+ UpdateNode un=munremove.getUpdate(i);
+ if (un.getRule()==r) {
+ /* Update for rule r */
+ String name=(String)updatenames.get(un);
+ cr.outputline(repairtable.getSafeSymbol()+"->addrelation("+rd.getNum()+","+r.getNum()+","+leftside.getSafeSymbol()+","+rightside.getSafeSymbol()+",(int) &"+name+");");
+ }
+ }
+ }
+ }
+ /* Now do addition */
+ UpdateNode un=munadd.getUpdate(0);
+ String name=(String)updatenames.get(un);
+ if (!inverted) {
+ cr.outputline(name+"(this,"+newmodel.getSafeSymbol()+","+repairtable.getSafeSymbol()+","+leftside.getSafeSymbol()+","+newvalue.getSafeSymbol()+");");
+ } else {
+ cr.outputline(name+"(this,"+newmodel.getSafeSymbol()+","+repairtable.getSafeSymbol()+","+newvalue.getSafeSymbol()+","+rightside.getSafeSymbol()+");");
+ }
+ }
+
+ public void generatesizerepair(Conjunction conj, DNFPredicate dpred, CodeWriter cr) {
+ ExprPredicate ep=(ExprPredicate)dpred.getPredicate();
+ OpExpr expr=(OpExpr)ep.expr;
+ Opcode opcode=expr.getOpcode();
+ {
+ boolean negated=dpred.isNegated();
+ if (negated)
+ if (opcode==Opcode.GT) {
+ opcode=Opcode.LE;
+ } else if (opcode==Opcode.GE) {
+ opcode=Opcode.LT;
+ } else if (opcode==Opcode.LT) {
+ opcode=Opcode.GE;
+ } else if (opcode==Opcode.LE) {
+ opcode=Opcode.GT;
+ } else if (opcode==Opcode.EQ) {
+ opcode=Opcode.NE;
+ } else if (opcode==Opcode.NE) {
+ opcode=Opcode.EQ;
+ } else {
+ throw new Error("Unrecognized Opcode");
+ }
+ }
+ MultUpdateNode munremove;
+
+ MultUpdateNode munadd;
+ if (ep.getDescriptor() instanceof RelationDescriptor) {
+ munremove=getmultupdatenode(conj,dpred,AbstractRepair.REMOVEFROMRELATION);
+ munadd=getmultupdatenode(conj,dpred,AbstractRepair.ADDTORELATION);
+ } else {
+ munremove=getmultupdatenode(conj,dpred,AbstractRepair.REMOVEFROMSET);
+ munadd=getmultupdatenode(conj,dpred,AbstractRepair.ADDTOSET);
+ }
+ int size=ep.leftsize();
+ VarDescriptor sizevar=VarDescriptor.makeNew("size");
+ ((OpExpr)expr).left.generate(cr, sizevar);
+ VarDescriptor change=VarDescriptor.makeNew("change");
+ cr.outputline("int "+change.getSafeSymbol()+";");
+ boolean generateadd=false;
+ boolean generateremove=false;
+ if (opcode==Opcode.GT) {
+ cr.outputline(change.getSafeSymbol()+"="+String.valueOf(size+1)+"-"+sizevar.getSafeSymbol()+";");
+ generateadd=true;
+ generateremove=false;
+ } else if (opcode==Opcode.GE) {
+ cr.outputline(change.getSafeSymbol()+"="+String.valueOf(size)+"-"+sizevar.getSafeSymbol()+";");
+ generateadd=true;
+ generateremove=false;
+ } else if (opcode==Opcode.LT) {
+ cr.outputline(change.getSafeSymbol()+"="+String.valueOf(size-1)+"-"+sizevar.getSafeSymbol()+";");
+ generateadd=false;
+ generateremove=true;
+ } else if (opcode==Opcode.LE) {
+ cr.outputline(change.getSafeSymbol()+"="+String.valueOf(size)+"-"+sizevar.getSafeSymbol()+";");
+ generateadd=false;
+ generateremove=true;
+ } else if (opcode==Opcode.EQ) {
+ cr.outputline(change.getSafeSymbol()+"="+String.valueOf(size)+"-"+sizevar.getSafeSymbol()+";");
+ generateadd=true;
+ generateremove=true;
+ } else if (opcode==Opcode.NE) {
+ cr.outputline(change.getSafeSymbol()+"="+String.valueOf(size+1)+"-"+sizevar.getSafeSymbol()+";");
+ generateadd=true;
+ generateremove=false;
+ } else {
+ throw new Error("Unrecognized Opcode");
+ }
+ Descriptor d=ep.getDescriptor();
+ if (generateremove) {
+ cr.outputline("for(;"+change.getSafeSymbol()+"<0;"+change.getSafeSymbol()+"++)");
+ cr.startblock();
+ /* Find element to remove */
+ VarDescriptor leftvar=VarDescriptor.makeNew("leftvar");
+ VarDescriptor rightvar=VarDescriptor.makeNew("rightvar");
+ if (d instanceof RelationDescriptor) {
+ if (ep.inverted()) {
+ rightvar=((ImageSetExpr)((SizeofExpr)((OpExpr)expr).left).setexpr).getVar();
+ cr.outputline("int "+leftvar.getSafeSymbol()+";");
+ cr.outputline(d.getSafeSymbol()+"_hashinv->get((int)"+rightvar.getSafeSymbol()+","+leftvar.getSafeSymbol()+");");
+ } else {
+ leftvar=((ImageSetExpr)((SizeofExpr)((OpExpr)expr).left).setexpr).getVar();
+ cr.outputline("int "+rightvar.getSafeSymbol()+";");
+ cr.outputline(d.getSafeSymbol()+"_hash->get((int)"+leftvar.getSafeSymbol()+","+rightvar.getSafeSymbol()+");");
+ }
+ } else {
+ cr.outputline("int "+leftvar.getSafeSymbol()+"="+d.getSafeSymbol()+"_hash->firstkey();");
+ }
+ /* Generate abstract remove instruction */
+ if (d instanceof RelationDescriptor) {
+ RelationDescriptor rd=(RelationDescriptor) d;
+ boolean usageimage=rd.testUsage(RelationDescriptor.IMAGE);
+ boolean usageinvimage=rd.testUsage(RelationDescriptor.INVIMAGE);
+ if (usageimage)
+ cr.outputline(rd.getSafeSymbol() + "_hash->remove((int)" + leftvar + ", (int)" + rightvar + ");");
+ if (usageinvimage)
+ cr.outputline(rd.getSafeSymbol() + "_hashinv->remove((int)" + rightvar + ", (int)" + leftvar + ");");
+ } else {
+ cr.outputline(d.getSafeSymbol() + "_hash->remove((int)" + leftvar + ", (int)" + leftvar + ");");
+ }
+ /* Generate concrete remove instruction */
+ for(int i=0;i<state.vRules.size();i++) {
+ Rule r=(Rule)state.vRules.get(i);
+ if (r.getInclusion().getTargetDescriptors().contains(d)) {
+ for(int j=0;j<munremove.numUpdates();j++) {
+ UpdateNode un=munremove.getUpdate(i);
+ if (un.getRule()==r) {
+ /* Update for rule rule r */
+ String name=(String)updatenames.get(un);
+ if (d instanceof RelationDescriptor) {
+ cr.outputline(repairtable.getSafeSymbol()+"->addrelation("+d.getNum()+","+r.getNum()+","+leftvar.getSafeSymbol()+","+rightvar.getSafeSymbol()+",(int) &"+name+");");
+ } else {
+ cr.outputline(repairtable.getSafeSymbol()+"->addset("+d.getNum()+","+r.getNum()+","+leftvar.getSafeSymbol()+",(int) &"+name+");");
+ }
+ }
+ }
+ }
+ }
+ cr.endblock();
+ }
+ if (generateadd) {
+ cr.outputline("for(;"+change.getSafeSymbol()+">0;"+change.getSafeSymbol()+"--)");
+ cr.startblock();
+ cr.endblock();
+ }
+ }
+
+ public void generateinclusionrepair(Conjunction conj, DNFPredicate dpred, CodeWriter cr){
+ InclusionPredicate ip=(InclusionPredicate) dpred.getPredicate();
+ boolean negated=dpred.isNegated();
+ MultUpdateNode mun=getmultupdatenode(conj,dpred,-1);
+ VarDescriptor leftvar=VarDescriptor.makeNew("left");
+ ip.expr.generate(cr, leftvar);
+
+ if (negated) {
+ if (ip.setexpr instanceof ImageSetExpr) {
+ ImageSetExpr ise=(ImageSetExpr) ip.setexpr;
+ VarDescriptor rightvar=ise.getVar();
+ boolean inverse=ise.inverted();
+ RelationDescriptor rd=ise.getRelation();
+ boolean usageimage=rd.testUsage(RelationDescriptor.IMAGE);
+ boolean usageinvimage=rd.testUsage(RelationDescriptor.INVIMAGE);
+ if (inverse) {
+ if (usageimage)
+ cr.outputline(rd.getSafeSymbol() + "_hash->remove((int)" + rightvar + ", (int)" + leftvar + ");");
+ if (usageinvimage)
+ cr.outputline(rd.getSafeSymbol() + "_hashinv->remove((int)" + leftvar + ", (int)" + rightvar + ");");
+ } else {
+ if (usageimage)
+ cr.outputline(rd.getSafeSymbol() + "_hash->remove((int)" + leftvar + ", (int)" + rightvar + ");");
+ if (usageinvimage)
+ cr.outputline(rd.getSafeSymbol() + "_hashinv->remove((int)" + rightvar + ", (int)" + leftvar + ");");
+ }
+ for(int i=0;i<state.vRules.size();i++) {
+ Rule r=(Rule)state.vRules.get(i);
+ if (r.getInclusion().getTargetDescriptors().contains(rd)) {
+ for(int j=0;j<mun.numUpdates();j++) {
+ UpdateNode un=mun.getUpdate(i);
+ if (un.getRule()==r) {
+ /* Update for rule rule r */
+ String name=(String)updatenames.get(un);
+ if (inverse) {
+ cr.outputline(repairtable.getSafeSymbol()+"->addrelation("+rd.getNum()+","+r.getNum()+","+rightvar.getSafeSymbol()+","+leftvar.getSafeSymbol()+",(int) &"+name+");");
+ } else {
+ cr.outputline(repairtable.getSafeSymbol()+"->addrelation("+rd.getNum()+","+r.getNum()+","+leftvar.getSafeSymbol()+","+rightvar.getSafeSymbol()+",(int) &"+name+");");
+ }
+ }
+ }
+ }
+ }
+ } else {
+ SetDescriptor sd=ip.setexpr.sd;
+ cr.outputline(sd.getSafeSymbol() + "_hash->remove((int)" + leftvar + ", (int)" + leftvar + ");");
+
+ for(int i=0;i<state.vRules.size();i++) {
+ Rule r=(Rule)state.vRules.get(i);
+ if (r.getInclusion().getTargetDescriptors().contains(sd)) {
+ for(int j=0;j<mun.numUpdates();j++) {
+ UpdateNode un=mun.getUpdate(i);
+ if (un.getRule()==r) {
+ /* Update for rule rule r */
+ String name=(String)updatenames.get(un);
+ cr.outputline(repairtable.getSafeSymbol()+"->addset("+sd.getNum()+","+r.getNum()+","+leftvar.getSafeSymbol()+",(int) &"+name+");");
+ }
+ }
+ }
+ }
+ }
+ } else {
+ /* Generate update */
+ if (ip.setexpr instanceof ImageSetExpr) {
+ ImageSetExpr ise=(ImageSetExpr) ip.setexpr;
+ VarDescriptor rightvar=ise.getVar();
+ boolean inverse=ise.inverted();
+ RelationDescriptor rd=ise.getRelation();
+ boolean usageimage=rd.testUsage(RelationDescriptor.IMAGE);
+ boolean usageinvimage=rd.testUsage(RelationDescriptor.INVIMAGE);
+ if (inverse) {
+ if (usageimage)
+ cr.outputline(rd.getSafeSymbol() + "_hash->add((int)" + rightvar + ", (int)" + leftvar + ");");
+ if (usageinvimage)
+ cr.outputline(rd.getSafeSymbol() + "_hashinv->add((int)" + leftvar + ", (int)" + rightvar + ");");
+ } else {
+ if (usageimage)
+ cr.outputline(rd.getSafeSymbol() + "_hash->add((int)" + leftvar + ", (int)" + rightvar + ");");
+ if (usageinvimage)
+ cr.outputline(rd.getSafeSymbol() + "_hashinv->add((int)" + rightvar + ", (int)" + leftvar + ");");
+ }
+ UpdateNode un=mun.getUpdate(0);
+ String name=(String)updatenames.get(un);
+ if (inverse) {
+ cr.outputline(name+"(this,"+newmodel.getSafeSymbol()+","+repairtable.getSafeSymbol()+","+rightvar.getSafeSymbol()+","+leftvar.getSafeSymbol()+");");
+ } else {
+ cr.outputline(name+"(this,"+newmodel.getSafeSymbol()+","+repairtable.getSafeSymbol()+","+leftvar.getSafeSymbol()+","+rightvar.getSafeSymbol()+");");
+ }
+ } else {
+ SetDescriptor sd=ip.setexpr.sd;
+ cr.outputline(sd.getSafeSymbol() + "_hash->add((int)" + leftvar + ", (int)" + leftvar + ");");
+
+ UpdateNode un=mun.getUpdate(0);
+ /* Update for rule rule r */
+ String name=(String)updatenames.get(un);
+ cr.outputline(name+"(this,"+newmodel.getSafeSymbol()+","+repairtable.getSafeSymbol()+","+leftvar.getSafeSymbol()+");");
+ }
+ }
+ }