Fixed Dan's confusion regarding alignment of fields. Modified the
[repair.git] / Repair / RepairCompiler / MCC / IR / RepairGenerator.java
1 package MCC.IR;
2
3 import java.io.*;
4 import java.util.*;
5 import MCC.State;
6
7 public class RepairGenerator {
8     State state;
9     java.io.PrintWriter outputrepair = null;
10     java.io.PrintWriter outputaux = null;
11     java.io.PrintWriter outputhead = null;
12     String name="foo";
13     String headername;
14     static VarDescriptor oldmodel=null;
15     static VarDescriptor newmodel=null;
16     static VarDescriptor worklist=null;
17     static VarDescriptor repairtable=null;
18     static VarDescriptor goodflag=null;
19     Rule currentrule=null;
20     Hashtable updatenames;
21     HashSet usedupdates;
22     Termination termination;
23     Set removed;
24     HashSet togenerate;
25     static boolean DEBUG=false;
26     Cost cost;
27     Sources sources;
28
29     public RepairGenerator(State state, Termination t) {
30         this.state = state;
31         updatenames=new Hashtable();
32         usedupdates=new HashSet();
33         termination=t;
34         removed=t.removedset;
35         togenerate=new HashSet();
36         togenerate.addAll(termination.conjunctions);
37         togenerate.removeAll(removed);
38         GraphNode.computeclosure(togenerate,removed);
39
40         cost=new Cost();
41         sources=new Sources(state);
42         Repair.repairgenerator=this;
43     }
44
45     private void name_updates() {
46         int count=0;
47         for(Iterator it=termination.updatenodes.iterator();it.hasNext();) {
48             GraphNode gn=(GraphNode) it.next();
49             TermNode tn=(TermNode) gn.getOwner();
50             MultUpdateNode mun=tn.getUpdate();
51             if (togenerate.contains(gn))
52             for (int i=0;i<mun.numUpdates();i++) {
53                 UpdateNode un=mun.getUpdate(i);
54                 String name="update"+String.valueOf(count++);
55                 updatenames.put(un,name);
56             }
57         }
58     }
59
60     public void generate(OutputStream outputrepair, OutputStream outputaux,OutputStream outputhead, String st) {
61         this.outputrepair = new java.io.PrintWriter(outputrepair, true);
62         this.outputaux = new java.io.PrintWriter(outputaux, true);
63         this.outputhead = new java.io.PrintWriter(outputhead, true);
64         headername=st;
65         name_updates();
66
67         generate_tokentable();
68         generate_hashtables();
69         generate_stateobject();
70         generate_call();
71         generate_worklist();
72         generate_rules();
73         generate_checks();
74         generate_teardown();
75         CodeWriter crhead = new StandardCodeWriter(this.outputhead);
76         CodeWriter craux = new StandardCodeWriter(this.outputaux);
77         crhead.outputline("};");
78         craux.outputline("};");
79         generate_updates();
80     }
81
82     private void generate_updates() {
83         int count=0;
84         CodeWriter crhead = new StandardCodeWriter(outputhead);        
85         CodeWriter craux = new StandardCodeWriter(outputaux);        
86         String state="state";
87         String model="model";
88         String repairtable="repairtable";
89         String left="left";
90         String right="right";
91         /* Rewrite globals */
92
93         for (Iterator it=this.state.stGlobals.descriptors();it.hasNext();) {
94             VarDescriptor vd=(VarDescriptor)it.next();
95             craux.outputline("#define "+vd.getSafeSymbol()+" "+state+"->"+vd.getSafeSymbol());
96         }
97
98         for(Iterator it=termination.updatenodes.iterator();it.hasNext();) {
99             GraphNode gn=(GraphNode) it.next();
100             TermNode tn=(TermNode) gn.getOwner();
101             MultUpdateNode mun=tn.getUpdate();
102             boolean isrelation=(mun.getDescriptor() instanceof RelationDescriptor);
103             if (togenerate.contains(gn))
104             for (int i=0;i<mun.numUpdates();i++) {
105                 UpdateNode un=mun.getUpdate(i);
106                 String methodname=(String)updatenames.get(un);
107                 
108                 switch(mun.op) {
109                 case MultUpdateNode.ADD:
110                     if (isrelation) {
111                         crhead.outputline("void "+methodname+"("+name+"_state * " +state+","+name+" * "+model+", RepairHash * "+repairtable+", int "+left+", int "+right+");");
112                         craux.outputline("void "+methodname+"("+name+"_state * "+ state+","+name+" * "+model+", RepairHash * "+repairtable+", int "+left+", int "+right+")");
113                     } else {
114                         crhead.outputline("void "+methodname+"("+name+"_state * "+ state+","+name+" * "+model+", RepairHash * "+repairtable+", int "+left+");");
115                         craux.outputline("void "+methodname+"("+name+"_state * "+state+","+name+" * "+model+", RepairHash * "+repairtable+", int "+left+")");
116                     }
117                     craux.startblock();
118                     final SymbolTable st = un.getRule().getSymbolTable();                
119                     CodeWriter cr = new StandardCodeWriter(outputaux) {
120                         public SymbolTable getSymbolTable() { return st; }
121                     };
122                     un.generate(cr, false, left,right);
123                     craux.endblock();
124                     break;
125                 case MultUpdateNode.REMOVE:
126                     Rule r=un.getRule();
127                     String methodcall="void "+methodname+"("+name+"_state * "+state+","+name+" * "+model+", RepairHash * "+repairtable;
128                     for(int j=0;j<r.numQuantifiers();j++) {
129                         Quantifier q=r.getQuantifier(j);
130                         if (q instanceof SetQuantifier) {
131                             SetQuantifier sq=(SetQuantifier) q;
132                             methodcall+=","+sq.getVar().getType().getGenerateType().getSafeSymbol()+" "+sq.getVar().getSafeSymbol();
133                         } else if (q instanceof RelationQuantifier) {
134                             RelationQuantifier rq=(RelationQuantifier) q;
135                             
136                             methodcall+=","+rq.x.getType().getGenerateType().getSafeSymbol()+" "+rq.x.getSafeSymbol();
137                             methodcall+=","+rq.y.getType().getGenerateType().getSafeSymbol()+" "+rq.y.getSafeSymbol();
138                         } else if (q instanceof ForQuantifier) {
139                             ForQuantifier fq=(ForQuantifier) q;
140                             methodcall+=",int "+fq.getVar().getSafeSymbol();
141                         }
142                     }
143                     methodcall+=")";
144                     crhead.outputline(methodcall+";");
145                     craux.outputline(methodcall);
146                     craux.startblock();
147                     final SymbolTable st2 = un.getRule().getSymbolTable();                
148                     CodeWriter cr2 = new StandardCodeWriter(outputaux) {
149                         public SymbolTable getSymbolTable() { return st2; }
150                     };
151                     un.generate(cr2, true, null,null);
152                     craux.endblock();
153                     break;
154                 case MultUpdateNode.MODIFY:
155                 default:
156                     throw new Error("Nonimplement Update");
157                 }
158             }
159         }
160     }
161
162     private void generate_call() {
163         CodeWriter cr = new StandardCodeWriter(outputrepair);        
164         VarDescriptor vdstate=VarDescriptor.makeNew("repairstate");
165         cr.outputline(name+"_state * "+vdstate.getSafeSymbol()+"=new "+name+"_state();");
166         Iterator globals=state.stGlobals.descriptors();
167         while (globals.hasNext()) {
168             VarDescriptor vd=(VarDescriptor) globals.next();
169             cr.outputline(vdstate.getSafeSymbol()+"->"+vd.getSafeSymbol()+"=("+vd.getType().getGenerateType().getSafeSymbol()+")"+vd.getSafeSymbol()+";");
170         }
171         /* Insert repair here */
172         cr.outputline(vdstate.getSafeSymbol()+"->doanalysis();");
173         globals=state.stGlobals.descriptors();
174         while (globals.hasNext()) {
175             VarDescriptor vd=(VarDescriptor) globals.next();
176             cr.outputline("*(("+vd.getType().getGenerateType().getSafeSymbol()+"*) &"+vd.getSafeSymbol()+")="+vdstate.getSafeSymbol()+"->"+vd.getSafeSymbol()+";");
177         }
178         cr.outputline("delete "+vdstate.getSafeSymbol()+";");
179     }
180
181     private void generate_tokentable() {
182         CodeWriter cr = new StandardCodeWriter(outputrepair);        
183         Iterator tokens = TokenLiteralExpr.tokens.keySet().iterator();        
184
185         cr.outputline("");
186         cr.outputline("// Token values");
187         cr.outputline("");
188
189         while (tokens.hasNext()) {
190             Object token = tokens.next();
191             cr.outputline("// " + token.toString() + " = " + TokenLiteralExpr.tokens.get(token).toString());            
192         }
193
194         cr.outputline("");
195         cr.outputline("");
196     }
197
198     private void generate_stateobject() {
199         CodeWriter crhead = new StandardCodeWriter(outputhead);
200         crhead.outputline("class "+name+"_state {");
201         crhead.outputline("public:");
202         Iterator globals=state.stGlobals.descriptors();
203         while (globals.hasNext()) {
204             VarDescriptor vd=(VarDescriptor) globals.next();
205             crhead.outputline(vd.getType().getGenerateType().getSafeSymbol()+" "+vd.getSafeSymbol()+";");
206         }
207     }
208
209     private void generate_hashtables() {
210         CodeWriter craux = new StandardCodeWriter(outputaux);
211         CodeWriter crhead = new StandardCodeWriter(outputhead);
212         crhead.outputline("#include \"SimpleHash.h\"");
213         crhead.outputline("#include <stdio.h>");
214         crhead.outputline("#include <stdlib.h>");
215         crhead.outputline("class "+name+" {");
216         crhead.outputline("public:");
217         crhead.outputline(name+"();");
218         crhead.outputline("~"+name+"();");
219         craux.outputline("#include \""+headername+"\"");
220
221         craux.outputline(name+"::"+name+"() {");
222         craux.outputline("// creating hashtables ");
223         
224         /* build sets */
225         Iterator sets = state.stSets.descriptors();
226         
227         /* first pass create all the hash tables */
228         while (sets.hasNext()) {
229             SetDescriptor set = (SetDescriptor) sets.next();
230             crhead.outputline("SimpleHash* " + set.getSafeSymbol() + "_hash;");
231             craux.outputline(set.getSafeSymbol() + "_hash = new SimpleHash();");
232         }
233         
234         /* second pass build relationships between hashtables */
235         sets = state.stSets.descriptors();
236         
237         while (sets.hasNext()) {
238             SetDescriptor set = (SetDescriptor) sets.next();
239             Iterator subsets = set.subsets();
240             
241             while (subsets.hasNext()) {
242                 SetDescriptor subset = (SetDescriptor) subsets.next();                
243                 craux.outputline(subset.getSafeSymbol() + "_hash->addParent(" + set.getSafeSymbol() + "_hash);");
244             }
245         } 
246
247         /* build relations */
248         Iterator relations = state.stRelations.descriptors();
249         
250         /* first pass create all the hash tables */
251         while (relations.hasNext()) {
252             RelationDescriptor relation = (RelationDescriptor) relations.next();
253             
254             if (relation.testUsage(RelationDescriptor.IMAGE)) {
255                 crhead.outputline("SimpleHash* " + relation.getSafeSymbol() + "_hash;");
256                 craux.outputline(relation.getSafeSymbol() + "_hash = new SimpleHash();");
257             }
258
259             if (relation.testUsage(RelationDescriptor.INVIMAGE)) {
260                 crhead.outputline("SimpleHash* " + relation.getSafeSymbol() + "_hashinv;");
261                 craux.outputline(relation.getSafeSymbol() + "_hashinv = new SimpleHash();");
262             } 
263         }
264
265         craux.outputline("}");
266         crhead.outputline("};");
267         craux.outputline(name+"::~"+name+"() {");
268         craux.outputline("// deleting hashtables");
269
270         /* build destructor */
271         sets = state.stSets.descriptors();
272         
273         /* first pass create all the hash tables */
274         while (sets.hasNext()) {
275             SetDescriptor set = (SetDescriptor) sets.next();
276             craux.outputline("delete "+set.getSafeSymbol() + "_hash;");
277         } 
278         
279         /* destroy relations */
280         relations = state.stRelations.descriptors();
281         
282         /* first pass create all the hash tables */
283         while (relations.hasNext()) {
284             RelationDescriptor relation = (RelationDescriptor) relations.next();
285             
286             if (relation.testUsage(RelationDescriptor.IMAGE)) {
287                 craux.outputline("delete "+relation.getSafeSymbol() + "_hash;");
288             }
289
290             if (relation.testUsage(RelationDescriptor.INVIMAGE)) {
291                 craux.outputline("delete " + relation.getSafeSymbol() + ";");
292             } 
293         }
294         craux.outputline("}");
295     }
296
297     private void generate_worklist() {
298         CodeWriter crhead = new StandardCodeWriter(outputhead);
299         CodeWriter craux = new StandardCodeWriter(outputaux);
300         oldmodel=VarDescriptor.makeNew("oldmodel");
301         newmodel=VarDescriptor.makeNew("newmodel");
302         worklist=VarDescriptor.makeNew("worklist");
303         goodflag=VarDescriptor.makeNew("goodflag");
304         repairtable=VarDescriptor.makeNew("repairtable");
305         crhead.outputline("void doanalysis();");
306         craux.outputline("void "+name +"_state::doanalysis()");
307         craux.startblock();
308         craux.outputline(name+ " * "+oldmodel.getSafeSymbol()+"=0;");
309         craux.outputline("WorkList * "+worklist.getSafeSymbol()+" = new WorkList();");
310         craux.outputline("RepairHash * "+repairtable.getSafeSymbol()+"=0;");
311         craux.outputline("while (1)");
312         craux.startblock();
313         craux.outputline("int "+goodflag.getSafeSymbol()+"=1;");
314         craux.outputline(name+ " * "+newmodel.getSafeSymbol()+"=new "+name+"();");
315     }
316     
317     private void generate_teardown() {
318         CodeWriter cr = new StandardCodeWriter(outputaux);        
319         cr.outputline("if ("+repairtable.getSafeSymbol()+")");
320         cr.outputline("delete "+repairtable.getSafeSymbol()+";");
321         cr.outputline("if ("+oldmodel.getSafeSymbol()+")");
322         cr.outputline("delete "+oldmodel.getSafeSymbol()+";");
323         cr.outputline("delete "+newmodel.getSafeSymbol()+";");
324         cr.outputline("delete "+worklist.getSafeSymbol()+";");
325         cr.endblock();
326     }
327
328     private void generate_rules() {
329         /* first we must sort the rules */
330         Iterator allrules = state.vRules.iterator();
331         Vector emptyrules = new Vector(); // rules with no quantifiers
332         Vector worklistrules = new Vector(); // the rest of the rules
333         RelationDescriptor.prefix = newmodel.getSafeSymbol()+"->";
334         SetDescriptor.prefix = newmodel.getSafeSymbol()+"->";
335
336         while (allrules.hasNext()) {
337             Rule rule = (Rule) allrules.next();
338             ListIterator quantifiers = rule.quantifiers();
339             boolean noquantifiers = true;
340             while (quantifiers.hasNext()) {
341                 Quantifier quantifier = (Quantifier) quantifiers.next();
342                 if (quantifier instanceof ForQuantifier) {
343                     // ok, because integers exist already!
344                 } else {
345                     // real quantifier
346                     noquantifiers = false;
347                     break;
348                 }
349             }
350             if (noquantifiers) {
351                 emptyrules.add(rule);
352             } else {
353                 worklistrules.add(rule);
354             }
355         }
356        
357         Iterator iterator_er = emptyrules.iterator();
358         while (iterator_er.hasNext()) {
359             Rule rule = (Rule) iterator_er.next();
360             {
361                 final SymbolTable st = rule.getSymbolTable();                
362                 CodeWriter cr = new StandardCodeWriter(outputaux) {
363                         public SymbolTable getSymbolTable() { return st; }
364                     };
365                 cr.outputline("// build " +escape(rule.toString()));
366                 cr.startblock();
367                 ListIterator quantifiers = rule.quantifiers();
368                 while (quantifiers.hasNext()) {
369                     Quantifier quantifier = (Quantifier) quantifiers.next();
370                     quantifier.generate_open(cr);
371                 }
372                         
373                 /* pretty print! */
374                 cr.output("//");
375                 rule.getGuardExpr().prettyPrint(cr);
376                 cr.outputline("");
377
378                 /* now we have to generate the guard test */
379                 VarDescriptor guardval = VarDescriptor.makeNew();
380                 rule.getGuardExpr().generate(cr, guardval);
381                 cr.outputline("if (" + guardval.getSafeSymbol() + ")");
382                 cr.startblock();
383
384                 /* now we have to generate the inclusion code */
385                 currentrule=rule;
386                 rule.getInclusion().generate(cr);
387                 cr.endblock();
388                 while (quantifiers.hasPrevious()) {
389                     Quantifier quantifier = (Quantifier) quantifiers.previous();
390                     cr.endblock();
391                 }
392                 cr.endblock();
393                 cr.outputline("");
394                 cr.outputline("");
395             }
396         }
397
398         CodeWriter cr2 = new StandardCodeWriter(outputaux);        
399
400         cr2.outputline("while ("+goodflag.getSafeSymbol()+"&&"+worklist.getSafeSymbol()+"->hasMoreElements())");
401         cr2.startblock();
402         VarDescriptor idvar=VarDescriptor.makeNew("id");
403         cr2.outputline("int "+idvar.getSafeSymbol()+"="+worklist.getSafeSymbol()+"->getid();");
404         
405         String elseladder = "if";
406
407         Iterator iterator_rules = worklistrules.iterator();
408         while (iterator_rules.hasNext()) {
409
410             Rule rule = (Rule) iterator_rules.next();
411             int dispatchid = rule.getNum();
412
413             {
414                 final SymbolTable st = rule.getSymbolTable();
415                 CodeWriter cr = new StandardCodeWriter(outputaux) {
416                         public SymbolTable getSymbolTable() { return st; }
417                     };
418
419                 cr.indent();
420                 cr.outputline(elseladder + " ("+idvar.getSafeSymbol()+" == " + dispatchid + ")");
421                 cr.startblock();
422                 VarDescriptor typevar=VarDescriptor.makeNew("type");
423                 VarDescriptor leftvar=VarDescriptor.makeNew("left");
424                 VarDescriptor rightvar=VarDescriptor.makeNew("right");
425                 cr.outputline("int "+typevar.getSafeSymbol()+"="+worklist.getSafeSymbol()+"->gettype();");
426                 cr.outputline("int "+leftvar.getSafeSymbol()+"="+worklist.getSafeSymbol()+"->getlvalue();");
427                 cr.outputline("int "+rightvar.getSafeSymbol()+"="+worklist.getSafeSymbol()+"->getrvalue();");
428                 cr.outputline("// build " +escape(rule.toString()));
429
430
431                 for (int j=0;j<rule.numQuantifiers();j++) {
432                     Quantifier quantifier = rule.getQuantifier(j);
433                     quantifier.generate_open(cr, typevar.getSafeSymbol(),j,leftvar.getSafeSymbol(),rightvar.getSafeSymbol());
434                 }
435
436                 /* pretty print! */
437                 cr.output("//");
438
439                 rule.getGuardExpr().prettyPrint(cr);
440                 cr.outputline("");
441
442                 /* now we have to generate the guard test */
443         
444                 VarDescriptor guardval = VarDescriptor.makeNew();
445                 rule.getGuardExpr().generate(cr, guardval);
446                 
447                 cr.outputline("if (" + guardval.getSafeSymbol() + ")");
448                 cr.startblock();
449
450                 /* now we have to generate the inclusion code */
451                 currentrule=rule;
452                 rule.getInclusion().generate(cr);
453                 cr.endblock();
454
455                 for (int j=0;j<rule.numQuantifiers();j++) {
456                     cr.endblock();
457                 }
458
459                 // close startblocks generated by DotExpr memory checks
460                 //DotExpr.generate_memory_endblocks(cr);
461
462                 cr.endblock(); // end else-if WORKLIST ladder
463
464                 elseladder = "else if";
465             }
466         }
467
468         cr2.outputline("else");
469         cr2.startblock();
470         cr2.outputline("printf(\"VERY BAD !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\\n\\n\");");
471         cr2.outputline("exit(1);");
472         cr2.endblock();
473         // end block created for worklist
474         cr2.endblock();
475     }
476
477     public static String escape(String s) {
478         String newstring="";
479         for(int i=0;i<s.length();i++) {
480             char c=s.charAt(i);
481             if (c=='"')
482                 newstring+="\"";
483             else
484                 newstring+=c;
485         }
486         return newstring;
487     }
488
489     private void generate_checks() {
490
491         /* do constraint checks */
492         Vector constraints = state.vConstraints;
493
494         for (int i = 0; i < constraints.size(); i++) {
495
496             Constraint constraint = (Constraint) constraints.elementAt(i); 
497
498             {
499
500                 final SymbolTable st = constraint.getSymbolTable();
501                 
502                 CodeWriter cr = new StandardCodeWriter(outputaux) {
503                         public SymbolTable getSymbolTable() { return st; }
504                     };
505
506                 cr.outputline("// checking " + escape(constraint.toString()));
507                 cr.startblock();
508
509                 ListIterator quantifiers = constraint.quantifiers();
510
511                 while (quantifiers.hasNext()) {
512                     Quantifier quantifier = (Quantifier) quantifiers.next();                   
513                     quantifier.generate_open(cr);
514                 }            
515
516                 cr.outputline("int maybe = 0;");
517                         
518                 /* now we have to generate the guard test */
519         
520                 VarDescriptor constraintboolean = VarDescriptor.makeNew("constraintboolean");
521                 constraint.getLogicStatement().generate(cr, constraintboolean);
522                 
523                 cr.outputline("if (maybe)");
524                 cr.startblock();
525                 cr.outputline("printf(\"maybe fail " +  escape(constraint.toString()) + ". \");");
526                 cr.outputline("exit(1);");
527                 cr.endblock();
528
529                 cr.outputline("else if (!" + constraintboolean.getSafeSymbol() + ")");
530                 cr.startblock();
531                 if (DEBUG)
532                     cr.outputline("printf(\"fail " + escape(constraint.toString()) + ". \");");
533
534                 /* Do repairs */
535                 /* Build new repair table */
536                 cr.outputline("if ("+repairtable.getSafeSymbol()+")");
537                 cr.outputline("delete "+repairtable.getSafeSymbol()+";");
538                 cr.outputline(repairtable.getSafeSymbol()+"=new RepairHash();");
539
540                 
541                 /* Compute cost of each repair */
542                 VarDescriptor mincost=VarDescriptor.makeNew("mincost");
543                 VarDescriptor mincostindex=VarDescriptor.makeNew("mincostindex");
544                 DNFConstraint dnfconst=constraint.dnfconstraint;
545                 cr.outputline("int "+mincostindex.getSafeSymbol()+";");
546                 if (dnfconst.size()>1) {
547                     boolean first=true;
548                     for(int j=0;j<dnfconst.size();j++) {
549                         Conjunction conj=dnfconst.get(j);
550                         GraphNode gn=(GraphNode)termination.conjtonodemap.get(conj);
551                         if (removed.contains(gn))
552                             continue;
553                         
554                         VarDescriptor costvar;
555                         if (first) {
556                             costvar=mincost;
557                         } else
558                             costvar=VarDescriptor.makeNew("cost");
559                         for(int k=0;k<conj.size();k++) {
560                             DNFPredicate dpred=conj.get(k);
561                             Predicate p=dpred.getPredicate();
562                             boolean negate=dpred.isNegated();
563                             VarDescriptor predvalue=VarDescriptor.makeNew("Predicatevalue");
564                             p.generate(cr,predvalue);
565                             if (negate)
566                                 cr.outputline("if (maybe||"+predvalue.getSafeSymbol()+")");
567                             else
568                                 cr.outputline("if (maybe||!"+predvalue.getSafeSymbol()+")");
569                             if (k==0)
570                                 cr.outputline("int "+costvar.getSafeSymbol()+"="+cost.getCost(dpred)+";");
571                             else
572                                 cr.outputline(costvar.getSafeSymbol()+"+="+cost.getCost(dpred)+";");
573                         }
574
575                         if(!first) {
576                             cr.outputline("if ("+costvar.getSafeSymbol()+"<"+mincost.getSafeSymbol()+")");
577                             cr.startblock();
578                             cr.outputline(mincost.getSafeSymbol()+"="+costvar.getSafeSymbol()+";");
579                             cr.outputline(mincostindex.getSafeSymbol()+"="+j+";");
580                             cr.endblock();
581                         } else
582                             cr.outputline(mincostindex.getSafeSymbol()+"="+j+";");
583                         first=false;
584                     }
585                 }
586                 cr.outputline("switch("+mincostindex.getSafeSymbol()+") {");
587                 for(int j=0;j<dnfconst.size();j++) {
588                     Conjunction conj=dnfconst.get(j);
589                     GraphNode gn=(GraphNode)termination.conjtonodemap.get(conj);                    if (removed.contains(gn))
590                         continue;
591                     cr.outputline("case "+j+":");
592                     for(int k=0;k<conj.size();k++) {
593                         DNFPredicate dpred=conj.get(k);
594                         Predicate p=dpred.getPredicate();
595                         boolean negate=dpred.isNegated();
596                         VarDescriptor predvalue=VarDescriptor.makeNew("Predicatevalue");
597                         p.generate(cr,predvalue);
598                         if (negate)
599                             cr.outputline("if (maybe||"+predvalue.getSafeSymbol()+")");
600                         else
601                             cr.outputline("if (maybe||!"+predvalue.getSafeSymbol()+")");
602                         cr.startblock();
603                         if (p instanceof InclusionPredicate)
604                             generateinclusionrepair(conj,dpred, cr);
605                         else if (p instanceof ExprPredicate) {
606                             ExprPredicate ep=(ExprPredicate)p;
607                             if (ep.getType()==ExprPredicate.SIZE)
608                                 generatesizerepair(conj,dpred,cr);
609                             else if (ep.getType()==ExprPredicate.COMPARISON)
610                                 generatecomparisonrepair(conj,dpred,cr);
611                         } else throw new Error("Unrecognized Predicate");
612                         cr.endblock();
613                     }
614                     /* Update model */
615                     
616                     cr.outputline("break;");
617                 }
618                 cr.outputline("}");
619
620                 cr.outputline(goodflag.getSafeSymbol()+"=0;");
621                 cr.outputline("if ("+oldmodel.getSafeSymbol()+")");
622                 cr.outputline("delete "+oldmodel.getSafeSymbol()+";");
623                 cr.outputline(oldmodel.getSafeSymbol()+"="+newmodel.getSafeSymbol()+";");
624                 cr.outputline("break;");  /* Rebuild model and all */
625
626                 cr.endblock();
627
628                 while (quantifiers.hasPrevious()) {
629                     Quantifier quantifier = (Quantifier) quantifiers.previous();
630                     cr.endblock();
631                 }
632                 cr.outputline("if ("+goodflag.getSafeSymbol()+")");
633                 cr.outputline("break;");
634                 cr.endblock();
635                 cr.outputline("");
636                 cr.outputline("");
637             }
638         }
639     }    
640     
641     private MultUpdateNode getmultupdatenode(Conjunction conj, DNFPredicate dpred, int repairtype) {
642         MultUpdateNode mun=null;
643         GraphNode gn=(GraphNode) termination.conjtonodemap.get(conj);
644         for(Iterator edgeit=gn.edges();(mun==null)&&edgeit.hasNext();) {
645             GraphNode gn2=((GraphNode.Edge) edgeit.next()).getTarget();
646             TermNode tn2=(TermNode)gn2.getOwner();
647             if (tn2.getType()==TermNode.ABSTRACT) {
648                 AbstractRepair ar=tn2.getAbstract();
649                 if (((repairtype==-1)||(ar.getType()==repairtype))&&
650                     ar.getPredicate()==dpred) {
651                     for(Iterator edgeit2=gn2.edges();edgeit2.hasNext();) {
652                         GraphNode gn3=((GraphNode.Edge) edgeit2.next()).getTarget();
653                         if (!removed.contains(gn3)) {
654                             TermNode tn3=(TermNode)gn3.getOwner();
655                             if (tn3.getType()==TermNode.UPDATE) {
656                                 mun=tn3.getUpdate();
657                                 break;
658                             }
659                         }
660                     }
661                 }
662             }
663         }
664         return mun;
665     }
666
667     public void generatecomparisonrepair(Conjunction conj, DNFPredicate dpred, CodeWriter cr){
668         MultUpdateNode munremove=getmultupdatenode(conj,dpred,AbstractRepair.REMOVEFROMRELATION);
669         MultUpdateNode munadd=getmultupdatenode(conj,dpred,AbstractRepair.ADDTORELATION);
670         ExprPredicate ep=(ExprPredicate)dpred.getPredicate();
671         RelationDescriptor rd=(RelationDescriptor)ep.getDescriptor();
672         boolean usageimage=rd.testUsage(RelationDescriptor.IMAGE);
673         boolean usageinvimage=rd.testUsage(RelationDescriptor.INVIMAGE);
674         boolean inverted=ep.inverted();
675         boolean negated=dpred.isNegated();
676         OpExpr expr=(OpExpr)ep.expr;
677         Opcode opcode=expr.getOpcode();
678         VarDescriptor leftside=VarDescriptor.makeNew("leftside");
679         VarDescriptor rightside=VarDescriptor.makeNew("rightside");
680         VarDescriptor newvalue=VarDescriptor.makeNew("newvalue");
681         if (!inverted) {
682             expr.getLeftExpr().generate(cr,leftside);
683             expr.getRightExpr().generate(cr,newvalue);
684             cr.outputline(rd.getRange().getType().getGenerateType().getSafeSymbol()+" "+rightside.getSafeSymbol()+";");
685             cr.outputline(rd.getSafeSymbol()+"_hash->get("+leftside.getSafeSymbol()+","+rightside.getSafeSymbol()+");");
686         } else {
687             expr.getLeftExpr().generate(cr,rightside);
688             expr.getRightExpr().generate(cr,newvalue);
689             cr.outputline(rd.getDomain().getType().getGenerateType().getSafeSymbol()+" "+leftside.getSafeSymbol()+";");
690             cr.outputline(rd.getSafeSymbol()+"_hashinv->get("+leftside.getSafeSymbol()+","+leftside.getSafeSymbol()+");");
691         }
692         if (negated)
693             if (opcode==Opcode.GT) {
694                 opcode=Opcode.LE;
695             } else if (opcode==Opcode.GE) {
696                 opcode=Opcode.LT;
697             } else if (opcode==Opcode.LT) {
698                 opcode=Opcode.GE;
699             } else if (opcode==Opcode.LE) {
700                 opcode=Opcode.GT;
701             } else if (opcode==Opcode.EQ) {
702                 opcode=Opcode.NE;
703             } else if (opcode==Opcode.NE) {
704                 opcode=Opcode.EQ;
705             } else {
706                 throw new Error("Unrecognized Opcode");
707             }
708
709         if (opcode==Opcode.GT) {
710             cr.outputline(newvalue.getSafeSymbol()+"++;");
711         } else if (opcode==Opcode.GE) {
712             /* Equal */
713         } else if (opcode==Opcode.LT) {
714             cr.outputline(newvalue.getSafeSymbol()+"--;");
715         } else if (opcode==Opcode.LE) {
716             /* Equal */
717         } else if (opcode==Opcode.EQ) {
718             /* Equal */
719         } else if (opcode==Opcode.NE) {
720             cr.outputline(newvalue.getSafeSymbol()+"++;");
721         } else {
722             throw new Error("Unrecognized Opcode");
723         }
724         /* Do abstract repairs */
725         if (usageimage) {
726             cr.outputline(rd.getSafeSymbol()+"_hash->remove("+leftside.getSafeSymbol()+","+rightside.getSafeSymbol()+");");
727             if (!inverted) {
728                 cr.outputline(rd.getSafeSymbol()+"_hash->add("+leftside.getSafeSymbol()+","+newvalue.getSafeSymbol()+");");
729             } else {
730                 cr.outputline(rd.getSafeSymbol()+"_hash->add("+newvalue.getSafeSymbol()+","+rightside.getSafeSymbol()+");");
731             }
732         }
733         if (usageinvimage) {
734             cr.outputline(rd.getSafeSymbol()+"_hashinv->remove("+rightside.getSafeSymbol()+","+leftside.getSafeSymbol()+");");
735             if (!inverted) {
736                 cr.outputline(rd.getSafeSymbol()+"_hashinv->add("+newvalue.getSafeSymbol()+","+leftside.getSafeSymbol()+");");
737             } else {
738                 cr.outputline(rd.getSafeSymbol()+"_hashinv->add("+rightside.getSafeSymbol()+","+newvalue.getSafeSymbol()+");");
739             }
740         }
741         /* Do concrete repairs */
742         /* Start with scheduling removal */
743         for(int i=0;i<state.vRules.size();i++) {
744             Rule r=(Rule)state.vRules.get(i);
745             if (r.getInclusion().getTargetDescriptors().contains(rd)) {
746                 for(int j=0;j<munremove.numUpdates();j++) {
747                     UpdateNode un=munremove.getUpdate(i);
748                     if (un.getRule()==r) {
749                         /* Update for rule r */
750                         String name=(String)updatenames.get(un);
751                         cr.outputline(repairtable.getSafeSymbol()+"->addrelation("+rd.getNum()+","+r.getNum()+","+leftside.getSafeSymbol()+","+rightside.getSafeSymbol()+",(int) &"+name+");");
752                     }
753                 }
754             }
755         }
756         /* Now do addition */
757         UpdateNode un=munadd.getUpdate(0);
758         String name=(String)updatenames.get(un);
759         if (!inverted) {
760             cr.outputline(name+"(this,"+newmodel.getSafeSymbol()+","+repairtable.getSafeSymbol()+","+leftside.getSafeSymbol()+","+newvalue.getSafeSymbol()+");");
761         } else {
762             cr.outputline(name+"(this,"+newmodel.getSafeSymbol()+","+repairtable.getSafeSymbol()+","+newvalue.getSafeSymbol()+","+rightside.getSafeSymbol()+");");
763         }
764     }
765
766     public void generatesizerepair(Conjunction conj, DNFPredicate dpred, CodeWriter cr) {
767         ExprPredicate ep=(ExprPredicate)dpred.getPredicate();
768         OpExpr expr=(OpExpr)ep.expr;
769         Opcode opcode=expr.getOpcode();
770         {
771             boolean negated=dpred.isNegated();
772             if (negated)
773                 if (opcode==Opcode.GT) {
774                     opcode=Opcode.LE;
775                 } else if (opcode==Opcode.GE) {
776                     opcode=Opcode.LT;
777                 } else if (opcode==Opcode.LT) {
778                     opcode=Opcode.GE;
779                 } else if (opcode==Opcode.LE) {
780                     opcode=Opcode.GT;
781                 } else if (opcode==Opcode.EQ) {
782                     opcode=Opcode.NE;
783                 } else if (opcode==Opcode.NE) {
784                     opcode=Opcode.EQ;
785                 } else {
786                     throw new Error("Unrecognized Opcode");
787                 }       
788         }
789         MultUpdateNode munremove;
790
791         MultUpdateNode munadd;
792         if (ep.getDescriptor() instanceof RelationDescriptor) {
793             munremove=getmultupdatenode(conj,dpred,AbstractRepair.REMOVEFROMRELATION);
794             munadd=getmultupdatenode(conj,dpred,AbstractRepair.ADDTORELATION);
795         } else {
796             munremove=getmultupdatenode(conj,dpred,AbstractRepair.REMOVEFROMSET);
797             munadd=getmultupdatenode(conj,dpred,AbstractRepair.ADDTOSET);
798         }
799         int size=ep.leftsize();
800         VarDescriptor sizevar=VarDescriptor.makeNew("size");
801         ((OpExpr)expr).left.generate(cr, sizevar);
802         VarDescriptor change=VarDescriptor.makeNew("change");
803         cr.outputline("int "+change.getSafeSymbol()+";");
804         boolean generateadd=false;
805         boolean generateremove=false;
806         if (opcode==Opcode.GT) {
807             cr.outputline(change.getSafeSymbol()+"="+String.valueOf(size+1)+"-"+sizevar.getSafeSymbol()+";");
808             generateadd=true;
809             generateremove=false;
810         } else if (opcode==Opcode.GE) {
811             cr.outputline(change.getSafeSymbol()+"="+String.valueOf(size)+"-"+sizevar.getSafeSymbol()+";");
812             generateadd=true;
813             generateremove=false;
814         } else if (opcode==Opcode.LT) {
815             cr.outputline(change.getSafeSymbol()+"="+String.valueOf(size-1)+"-"+sizevar.getSafeSymbol()+";");
816             generateadd=false;
817             generateremove=true;
818         } else if (opcode==Opcode.LE) {
819             cr.outputline(change.getSafeSymbol()+"="+String.valueOf(size)+"-"+sizevar.getSafeSymbol()+";");
820             generateadd=false;
821             generateremove=true;
822         } else if (opcode==Opcode.EQ) {
823             cr.outputline(change.getSafeSymbol()+"="+String.valueOf(size)+"-"+sizevar.getSafeSymbol()+";");
824             generateadd=true;
825             generateremove=true;
826         } else if (opcode==Opcode.NE) {
827             cr.outputline(change.getSafeSymbol()+"="+String.valueOf(size+1)+"-"+sizevar.getSafeSymbol()+";");
828             generateadd=true;
829             generateremove=false;
830         } else {
831             throw new Error("Unrecognized Opcode");
832         }
833         Descriptor d=ep.getDescriptor();
834         if (generateremove) {
835             cr.outputline("for(;"+change.getSafeSymbol()+"<0;"+change.getSafeSymbol()+"++)");
836             cr.startblock();
837             /* Find element to remove */
838             VarDescriptor leftvar=VarDescriptor.makeNew("leftvar");
839             VarDescriptor rightvar=VarDescriptor.makeNew("rightvar");
840             if (d instanceof RelationDescriptor) {
841                 if (ep.inverted()) {
842                     rightvar=((ImageSetExpr)((SizeofExpr)((OpExpr)expr).left).setexpr).getVar();
843                     cr.outputline("int "+leftvar.getSafeSymbol()+";");
844                     cr.outputline(d.getSafeSymbol()+"_hashinv->get((int)"+rightvar.getSafeSymbol()+","+leftvar.getSafeSymbol()+");");
845                 } else {
846                     leftvar=((ImageSetExpr)((SizeofExpr)((OpExpr)expr).left).setexpr).getVar();
847                     cr.outputline("int "+rightvar.getSafeSymbol()+";");
848                     cr.outputline(d.getSafeSymbol()+"_hash->get((int)"+leftvar.getSafeSymbol()+","+rightvar.getSafeSymbol()+");");
849                 }
850             } else {
851                 cr.outputline("int "+leftvar.getSafeSymbol()+"="+d.getSafeSymbol()+"_hash->firstkey();");
852             }
853             /* Generate abstract remove instruction */
854             if (d instanceof RelationDescriptor) {
855                 RelationDescriptor rd=(RelationDescriptor) d;
856                 boolean usageimage=rd.testUsage(RelationDescriptor.IMAGE);
857                 boolean usageinvimage=rd.testUsage(RelationDescriptor.INVIMAGE);
858                 if (usageimage)
859                     cr.outputline(rd.getSafeSymbol() + "_hash->remove((int)" + leftvar + ", (int)" + rightvar + ");");
860                 if (usageinvimage)
861                     cr.outputline(rd.getSafeSymbol() + "_hashinv->remove((int)" + rightvar + ", (int)" + leftvar + ");");
862             } else {
863                 cr.outputline(d.getSafeSymbol() + "_hash->remove((int)" + leftvar + ", (int)" + leftvar + ");");
864             }
865             /* Generate concrete remove instruction */
866             for(int i=0;i<state.vRules.size();i++) {
867                 Rule r=(Rule)state.vRules.get(i);
868                 if (r.getInclusion().getTargetDescriptors().contains(d)) {
869                     for(int j=0;j<munremove.numUpdates();j++) {
870                         UpdateNode un=munremove.getUpdate(i);
871                         if (un.getRule()==r) {
872                                 /* Update for rule rule r */
873                             String name=(String)updatenames.get(un);
874                             if (d instanceof RelationDescriptor) {
875                                 cr.outputline(repairtable.getSafeSymbol()+"->addrelation("+d.getNum()+","+r.getNum()+","+leftvar.getSafeSymbol()+","+rightvar.getSafeSymbol()+",(int) &"+name+");");
876                             } else {
877                                 cr.outputline(repairtable.getSafeSymbol()+"->addset("+d.getNum()+","+r.getNum()+","+leftvar.getSafeSymbol()+",(int) &"+name+");");
878                             }
879                         }
880                     }
881                 }
882             }
883             cr.endblock();
884         }
885         if (generateadd) {
886
887             cr.outputline("for(;"+change.getSafeSymbol()+">0;"+change.getSafeSymbol()+"--)");
888             cr.startblock();
889             VarDescriptor newobject=VarDescriptor.makeNew("newobject");
890             if (d instanceof RelationDescriptor) {
891                 VarDescriptor otherside=((ImageSetExpr)((SizeofExpr)ep.expr).setexpr).vd;
892                 RelationDescriptor rd=(RelationDescriptor)d;
893                 if (sources.relsetSource(rd,!ep.inverted())) {
894                     /* Set Source */
895                     SetDescriptor sd=sources.relgetSourceSet(rd,!ep.inverted());
896                     VarDescriptor iterator=VarDescriptor.makeNew("iterator");
897                     cr.outputline(sd.getType().getGenerateType().getSafeSymbol() +" "+newobject.getSafeSymbol()+";");
898                     cr.outputline("for("+iterator.getSafeSymbol()+"="+sd.getSafeSymbol()+"_hash->iterator();"+iterator.getSafeSymbol()+".hasNext();)");
899                     cr.startblock();
900                     if (ep.inverted()) {
901                         cr.outputline("if !"+rd.getSafeSymbol()+"_hashinv->contains("+iterator.getSafeSymbol()+"->key(),"+otherside.getSafeSymbol()+")");
902                     } else {
903                         cr.outputline("if !"+rd.getSafeSymbol()+"_hash->contains("+otherside.getSafeSymbol()+","+iterator.getSafeSymbol()+"->key())");
904                     }
905                     cr.outputline(newobject.getSafeSymbol()+"="+iterator.getSafeSymbol()+".key();");
906                     cr.outputline(iterator.getSafeSymbol()+"->next();");
907                     cr.endblock();
908                 } else if (sources.relallocSource(rd,!ep.inverted())) {
909                     /* Allocation Source*/
910                     sources.relgenerateSourceAlloc(cr,newobject,rd,!ep.inverted());
911                 } else throw new Error("No source for adding to Relation");
912                 if (ep.inverted()) {
913                     boolean usageimage=rd.testUsage(RelationDescriptor.IMAGE);
914                     boolean usageinvimage=rd.testUsage(RelationDescriptor.INVIMAGE);
915                     if (usageimage)
916                         cr.outputline(rd.getSafeSymbol()+"_hash->add("+newobject.getSafeSymbol()+","+otherside.getSafeSymbol()+");");
917                     if (usageinvimage)
918                         cr.outputline(rd.getSafeSymbol()+"_hashinv->add("+otherside.getSafeSymbol()+","+newobject.getSafeSymbol()+");");
919
920                     UpdateNode un=munadd.getUpdate(0);
921                     String name=(String)updatenames.get(un);
922                     cr.outputline(name+"(this,"+newmodel.getSafeSymbol()+","+repairtable.getSafeSymbol()+","+newobject.getSafeSymbol()+","+otherside.getSafeSymbol()+");");
923                 } else {
924                     boolean usageimage=rd.testUsage(RelationDescriptor.IMAGE);
925                     boolean usageinvimage=rd.testUsage(RelationDescriptor.INVIMAGE);
926                     if (usageimage)
927                         cr.outputline(rd.getSafeSymbol()+"_hash->add("+otherside.getSafeSymbol()+","+newobject.getSafeSymbol()+");");
928                     if (usageinvimage)
929                         cr.outputline(rd.getSafeSymbol()+"_hashinv->add("+newobject.getSafeSymbol()+","+otherside.getSafeSymbol()+");");
930                     UpdateNode un=munadd.getUpdate(0);
931                     String name=(String)updatenames.get(un);
932                     cr.outputline(name+"(this,"+newmodel.getSafeSymbol()+","+repairtable.getSafeSymbol()+","+otherside.getSafeSymbol()+","+newobject.getSafeSymbol()+");");
933                 }
934             } else {
935                 SetDescriptor sd=(SetDescriptor)d;
936                 if (sources.setSource(sd)) {
937                     /* Set Source */
938                     /* Set Source */
939                     SetDescriptor sourcesd=sources.getSourceSet(sd);
940                     VarDescriptor iterator=VarDescriptor.makeNew("iterator");
941                     cr.outputline(sourcesd.getType().getGenerateType().getSafeSymbol() +" "+newobject.getSafeSymbol()+";");
942                     cr.outputline("for("+iterator.getSafeSymbol()+"="+sourcesd.getSafeSymbol()+"_hash->iterator();"+iterator.getSafeSymbol()+".hasNext();)");
943                     cr.startblock();
944                     cr.outputline("if !"+sd.getSafeSymbol()+"_hash->contains("+iterator.getSafeSymbol()+"->key())");
945                     cr.outputline(newobject.getSafeSymbol()+"="+iterator.getSafeSymbol()+".key();");
946                     cr.outputline(iterator.getSafeSymbol()+"->next();");
947                     cr.endblock();
948                 } else if (sources.allocSource(sd)) {
949                     /* Allocation Source*/
950                     sources.generateSourceAlloc(cr,newobject,sd);
951                 } else throw new Error("No source for adding to Set");
952                 cr.outputline(sd.getSafeSymbol()+"_hash->add("+newobject.getSafeSymbol()+","+newobject.getSafeSymbol()+");");
953                 UpdateNode un=munadd.getUpdate(0);
954                 String name=(String)updatenames.get(un);
955                 cr.outputline(name+"(this,"+newmodel.getSafeSymbol()+","+repairtable.getSafeSymbol()+","+newobject.getSafeSymbol()+");");
956             }
957             cr.endblock();
958         }
959     }
960
961     public void generateinclusionrepair(Conjunction conj, DNFPredicate dpred, CodeWriter cr){
962         InclusionPredicate ip=(InclusionPredicate) dpred.getPredicate();
963         boolean negated=dpred.isNegated();
964         MultUpdateNode mun=getmultupdatenode(conj,dpred,-1);
965         VarDescriptor leftvar=VarDescriptor.makeNew("left");
966         ip.expr.generate(cr, leftvar);
967
968         if (negated) {
969             if (ip.setexpr instanceof ImageSetExpr) {
970                 ImageSetExpr ise=(ImageSetExpr) ip.setexpr;
971                 VarDescriptor rightvar=ise.getVar();
972                 boolean inverse=ise.inverted();
973                 RelationDescriptor rd=ise.getRelation();
974                 boolean usageimage=rd.testUsage(RelationDescriptor.IMAGE);
975                 boolean usageinvimage=rd.testUsage(RelationDescriptor.INVIMAGE);
976                 if (inverse) {
977                     if (usageimage)
978                         cr.outputline(rd.getSafeSymbol() + "_hash->remove((int)" + rightvar + ", (int)" + leftvar + ");");
979                     if (usageinvimage)
980                         cr.outputline(rd.getSafeSymbol() + "_hashinv->remove((int)" + leftvar + ", (int)" + rightvar + ");");
981                 } else {
982                     if (usageimage)
983                         cr.outputline(rd.getSafeSymbol() + "_hash->remove((int)" + leftvar + ", (int)" + rightvar + ");");
984                     if (usageinvimage)
985                         cr.outputline(rd.getSafeSymbol() + "_hashinv->remove((int)" + rightvar + ", (int)" + leftvar + ");");
986                 }
987                 for(int i=0;i<state.vRules.size();i++) {
988                     Rule r=(Rule)state.vRules.get(i);
989                     if (r.getInclusion().getTargetDescriptors().contains(rd)) {
990                         for(int j=0;j<mun.numUpdates();j++) {
991                             UpdateNode un=mun.getUpdate(i);
992                             if (un.getRule()==r) {
993                                 /* Update for rule rule r */
994                                 String name=(String)updatenames.get(un);
995                                 if (inverse) {
996                                     cr.outputline(repairtable.getSafeSymbol()+"->addrelation("+rd.getNum()+","+r.getNum()+","+rightvar.getSafeSymbol()+","+leftvar.getSafeSymbol()+",(int) &"+name+");");
997                                 } else {
998                                     cr.outputline(repairtable.getSafeSymbol()+"->addrelation("+rd.getNum()+","+r.getNum()+","+leftvar.getSafeSymbol()+","+rightvar.getSafeSymbol()+",(int) &"+name+");");
999                                 }
1000                             }
1001                         }
1002                     }
1003                 }
1004             } else {
1005                 SetDescriptor sd=ip.setexpr.sd;
1006                 cr.outputline(sd.getSafeSymbol() + "_hash->remove((int)" + leftvar + ", (int)" + leftvar + ");");
1007
1008                 for(int i=0;i<state.vRules.size();i++) {
1009                     Rule r=(Rule)state.vRules.get(i);
1010                     if (r.getInclusion().getTargetDescriptors().contains(sd)) {
1011                         for(int j=0;j<mun.numUpdates();j++) {
1012                             UpdateNode un=mun.getUpdate(i);
1013                             if (un.getRule()==r) {
1014                                 /* Update for rule rule r */
1015                                 String name=(String)updatenames.get(un);
1016                                 cr.outputline(repairtable.getSafeSymbol()+"->addset("+sd.getNum()+","+r.getNum()+","+leftvar.getSafeSymbol()+",(int) &"+name+");");
1017                             }
1018                         }
1019                     }
1020                 }
1021             }
1022         } else {
1023             /* Generate update */
1024             if (ip.setexpr instanceof ImageSetExpr) {
1025                 ImageSetExpr ise=(ImageSetExpr) ip.setexpr;
1026                 VarDescriptor rightvar=ise.getVar();
1027                 boolean inverse=ise.inverted();
1028                 RelationDescriptor rd=ise.getRelation();
1029                 boolean usageimage=rd.testUsage(RelationDescriptor.IMAGE);
1030                 boolean usageinvimage=rd.testUsage(RelationDescriptor.INVIMAGE);
1031                 if (inverse) {
1032                     if (usageimage)
1033                         cr.outputline(rd.getSafeSymbol() + "_hash->add((int)" + rightvar + ", (int)" + leftvar + ");");
1034                     if (usageinvimage)
1035                         cr.outputline(rd.getSafeSymbol() + "_hashinv->add((int)" + leftvar + ", (int)" + rightvar + ");");
1036                 } else {
1037                     if (usageimage)
1038                         cr.outputline(rd.getSafeSymbol() + "_hash->add((int)" + leftvar + ", (int)" + rightvar + ");");
1039                     if (usageinvimage)
1040                         cr.outputline(rd.getSafeSymbol() + "_hashinv->add((int)" + rightvar + ", (int)" + leftvar + ");");
1041                 }
1042                 UpdateNode un=mun.getUpdate(0);
1043                 String name=(String)updatenames.get(un);
1044                 if (inverse) {
1045                     cr.outputline(name+"(this,"+newmodel.getSafeSymbol()+","+repairtable.getSafeSymbol()+","+rightvar.getSafeSymbol()+","+leftvar.getSafeSymbol()+");");
1046                 } else {
1047                     cr.outputline(name+"(this,"+newmodel.getSafeSymbol()+","+repairtable.getSafeSymbol()+","+leftvar.getSafeSymbol()+","+rightvar.getSafeSymbol()+");");
1048                 }
1049             } else {
1050                 SetDescriptor sd=ip.setexpr.sd;
1051                 cr.outputline(sd.getSafeSymbol() + "_hash->add((int)" + leftvar + ", (int)" + leftvar + ");");
1052
1053                 UpdateNode un=mun.getUpdate(0);
1054                 /* Update for rule rule r */
1055                 String name=(String)updatenames.get(un);
1056                 cr.outputline(name+"(this,"+newmodel.getSafeSymbol()+","+repairtable.getSafeSymbol()+","+leftvar.getSafeSymbol()+");");
1057             }
1058         }
1059     }
1060
1061
1062
1063     public static Vector getrulelist(Descriptor d) {
1064         Vector dispatchrules = new Vector();
1065         Vector rules = State.currentState.vRules;
1066
1067         for (int i = 0; i < rules.size(); i++) {
1068             Rule rule = (Rule) rules.elementAt(i);
1069             Set requiredsymbols = rule.getRequiredDescriptors();
1070             
1071             // #TBD#: in general this is wrong because these descriptors may contain descriptors
1072             // bound in "in?" expressions which need to be dealt with in a topologically sorted
1073             // fashion...
1074
1075             if (rule.getRequiredDescriptors().contains(d)) {
1076                 dispatchrules.addElement(rule);
1077             }
1078         }
1079         return dispatchrules;
1080     }
1081
1082     private boolean need_compensation(Rule r) {
1083         GraphNode gn=(GraphNode)termination.scopefalsify.get(r);
1084         for(Iterator edgeit=gn.edges();edgeit.hasNext();) {
1085             GraphNode.Edge edge=(GraphNode.Edge)edgeit.next();
1086             GraphNode gn2=edge.getTarget();
1087             if (!removed.contains(gn2)) {
1088                 TermNode tn2=(TermNode)gn2.getOwner();
1089                 if (tn2.getType()==TermNode.CONSEQUENCE)
1090                     return false;
1091             }
1092         }
1093         return true;
1094     }
1095
1096     private UpdateNode find_compensation(Rule r) {
1097         GraphNode gn=(GraphNode)termination.scopefalsify.get(r);
1098         for(Iterator edgeit=gn.edges();edgeit.hasNext();) {
1099             GraphNode.Edge edge=(GraphNode.Edge)edgeit.next();
1100             GraphNode gn2=edge.getTarget();
1101             if (!removed.contains(gn2)) {
1102                 TermNode tn2=(TermNode)gn2.getOwner();
1103                 if (tn2.getType()==TermNode.UPDATE) {
1104                     MultUpdateNode mun=tn2.getUpdate();
1105                     for(int i=0;i<mun.numUpdates();i++) {
1106                         UpdateNode un=mun.getUpdate(i);
1107                         if (un.getRule()==r)
1108                             return un;
1109                     }
1110                 }
1111             }
1112         }
1113         throw new Error("No Compensation Update could be found");
1114     }
1115
1116     public void generate_dispatch(CodeWriter cr, RelationDescriptor rd, String leftvar, String rightvar) {
1117         boolean usageimage=rd.testUsage(RelationDescriptor.IMAGE);
1118         boolean usageinvimage=rd.testUsage(RelationDescriptor.INVIMAGE);
1119
1120         if (!(usageinvimage||usageimage)) /* not used at all*/
1121             return;
1122
1123         cr.outputline("// RELATION DISPATCH ");
1124         cr.outputline("if ("+oldmodel.getSafeSymbol()+"&&");
1125         if (usageimage)
1126             cr.outputline("!"+oldmodel.getSafeSymbol() +"->"+rd.getJustSafeSymbol()+"_hash->contains("+leftvar+","+rightvar+"))");
1127         else
1128             cr.outputline("!"+oldmodel.getSafeSymbol() +"->"+rd.getJustSafeSymbol()+"_hashinv->contains("+rightvar+","+leftvar+"))");
1129         cr.startblock(); {
1130             /* Adding new item */
1131             /* Perform safety checks */
1132             cr.outputline("if ("+repairtable.getSafeSymbol()+"&&");
1133             cr.outputline(repairtable.getSafeSymbol()+"->containsrelation("+rd.getNum()+","+currentrule.getNum()+","+leftvar+","+rightvar+"))");
1134             cr.startblock(); {
1135                 /* Have update to call into */
1136                 VarDescriptor funptr=VarDescriptor.makeNew("updateptr");
1137                 String parttype="";
1138                 for(int i=0;i<currentrule.numQuantifiers();i++) {
1139                     if (currentrule.getQuantifier(i) instanceof RelationQuantifier)
1140                         parttype=parttype+", int, int";
1141                     else
1142                         parttype=parttype+", int";
1143                 }
1144                 cr.outputline("void (*"+funptr.getSafeSymbol()+") ("+name+"_state *,"+name+"*,RepairHash *"+parttype+")=");
1145                 cr.outputline("(void (*) ("+name+"_state *,"+name+"*,RepairHash *"+parttype+")) "+repairtable.getSafeSymbol()+"->getrelation("+rd.getNum()+","+currentrule.getNum()+","+leftvar+","+rightvar+");");
1146                 String methodcall="("+funptr.getSafeSymbol()+") (this,"+oldmodel.getSafeSymbol()+","+repairtable.getSafeSymbol();
1147                 for(int i=0;i<currentrule.numQuantifiers();i++) {
1148                     Quantifier q=currentrule.getQuantifier(i);
1149                     if (q instanceof SetQuantifier) {
1150                         SetQuantifier sq=(SetQuantifier) q;
1151                         methodcall+=","+sq.getVar().getSafeSymbol();
1152                     } else if (q instanceof RelationQuantifier) {
1153                         RelationQuantifier rq=(RelationQuantifier) q;
1154                         methodcall+=","+rq.x.getSafeSymbol();
1155                         methodcall+=","+rq.y.getSafeSymbol();
1156                     } else if (q instanceof ForQuantifier) {
1157                         ForQuantifier fq=(ForQuantifier) q;
1158                         methodcall+=","+fq.getVar().getSafeSymbol();
1159                     }
1160                 }
1161                 methodcall+=");";
1162                 cr.outputline(methodcall);
1163                 cr.outputline(goodflag.getSafeSymbol()+"=0;");
1164                 cr.outputline("continue;");
1165             }
1166             cr.endblock();
1167             /* Build standard compensation actions */
1168             if (need_compensation(currentrule)) {
1169                 UpdateNode un=find_compensation(currentrule);
1170                 String name=(String)updatenames.get(un);
1171                 usedupdates.add(un); /* Mark as used */
1172                 String methodcall=name+"(this,"+oldmodel.getSafeSymbol()+","+repairtable.getSafeSymbol();
1173                 for(int i=0;i<currentrule.numQuantifiers();i++) {
1174                     Quantifier q=currentrule.getQuantifier(i);
1175                     if (q instanceof SetQuantifier) {
1176                         SetQuantifier sq=(SetQuantifier) q;
1177                         methodcall+=","+sq.getVar().getSafeSymbol();
1178                     } else if (q instanceof RelationQuantifier) {
1179                         RelationQuantifier rq=(RelationQuantifier) q;
1180                         methodcall+=","+rq.x.getSafeSymbol();
1181                         methodcall+=","+rq.y.getSafeSymbol();
1182                     } else if (q instanceof ForQuantifier) {
1183                         ForQuantifier fq=(ForQuantifier) q;
1184                         methodcall+=","+fq.getVar().getSafeSymbol();
1185                     }
1186                 }
1187                 methodcall+=");";
1188                 cr.outputline(methodcall);
1189                 cr.outputline(goodflag.getSafeSymbol()+"=0;");
1190                 cr.outputline("continue;");
1191             }
1192         }
1193         cr.endblock();
1194
1195         String addeditem = (VarDescriptor.makeNew("addeditem")).getSafeSymbol();
1196         cr.outputline("int " + addeditem + ";");
1197         if (rd.testUsage(RelationDescriptor.IMAGE)) {
1198             cr.outputline(addeditem + " = " + rd.getSafeSymbol() + "_hash->add((int)" + leftvar + ", (int)" + rightvar + ");");
1199         }
1200         
1201         if (rd.testUsage(RelationDescriptor.INVIMAGE)) {
1202             cr.outputline(addeditem + " = " + rd.getSafeSymbol() + "_hashinv->add((int)" + rightvar + ", (int)" + leftvar + ");");
1203         }
1204         
1205         cr.outputline("if (" + addeditem + ")");
1206         cr.startblock();
1207
1208         Vector dispatchrules = getrulelist(rd);
1209         
1210         if (dispatchrules.size() == 0) {
1211             cr.outputline("// nothing to dispatch");
1212             cr.endblock();
1213             return;
1214         }
1215        
1216         for(int i = 0; i < dispatchrules.size(); i++) {
1217             Rule rule = (Rule) dispatchrules.elementAt(i);
1218             if (rule.getGuardExpr().getRequiredDescriptors().contains(rd)) {
1219                 /* Guard depends on this relation, so we recomput everything */
1220                 cr.outputline(worklist.getSafeSymbol()+"->add("+rule.getNum()+",-1,0,0);");
1221             } else {
1222                 for (int j=0;j<rule.numQuantifiers();j++) {
1223                     Quantifier q=rule.getQuantifier(j);
1224                     if (q.getRequiredDescriptors().contains(rd)) {
1225                         /* Generate add */
1226                         cr.outputline(worklist.getSafeSymbol()+"->add("+rule.getNum()+","+j+","+leftvar+","+rightvar+");");
1227                     }
1228                 }
1229             }
1230         }
1231         cr.endblock();
1232     }
1233
1234
1235     public void generate_dispatch(CodeWriter cr, SetDescriptor sd, String setvar) {
1236                
1237         cr.outputline("// SET DISPATCH ");
1238
1239         cr.outputline("if ("+oldmodel.getSafeSymbol()+"&&");
1240         cr.outputline("!"+oldmodel.getSafeSymbol() +"->"+sd.getJustSafeSymbol()+"_hash->contains("+setvar+"))");
1241         cr.startblock(); {
1242             /* Adding new item */
1243             /* Perform safety checks */
1244             cr.outputline("if ("+repairtable.getSafeSymbol()+"&&");
1245             cr.outputline(repairtable.getSafeSymbol()+"->containsset("+sd.getNum()+","+currentrule.getNum()+","+setvar+"))");
1246             cr.startblock(); {
1247                 /* Have update to call into */
1248                 VarDescriptor funptr=VarDescriptor.makeNew("updateptr");
1249                 String parttype="";
1250                 for(int i=0;i<currentrule.numQuantifiers();i++) {
1251                     if (currentrule.getQuantifier(i) instanceof RelationQuantifier)
1252                         parttype=parttype+", int, int";
1253                     else
1254                         parttype=parttype+", int";
1255                 }
1256                 cr.outputline("void (*"+funptr.getSafeSymbol()+") ("+name+"_state *,"+name+"*,RepairHash *"+parttype+")=");
1257                 cr.outputline("(void (*) ("+name+"_state *,"+name+"*,RepairHash *"+parttype+")) "+repairtable.getSafeSymbol()+"->getset("+sd.getNum()+","+currentrule.getNum()+","+setvar+");");
1258                 String methodcall="("+funptr.getSafeSymbol()+") (this,"+oldmodel.getSafeSymbol()+","+
1259                               repairtable.getSafeSymbol();
1260                 for(int i=0;i<currentrule.numQuantifiers();i++) {
1261                     Quantifier q=currentrule.getQuantifier(i);
1262                     if (q instanceof SetQuantifier) {
1263                         SetQuantifier sq=(SetQuantifier) q;
1264                         methodcall+=","+sq.getVar().getSafeSymbol();
1265                     } else if (q instanceof RelationQuantifier) {
1266                         RelationQuantifier rq=(RelationQuantifier) q;
1267                         methodcall+=","+rq.x.getSafeSymbol();
1268                         methodcall+=","+rq.y.getSafeSymbol();
1269                     } else if (q instanceof ForQuantifier) {
1270                         ForQuantifier fq=(ForQuantifier) q;
1271                         methodcall+=","+fq.getVar().getSafeSymbol();
1272                     }
1273                 }
1274                 methodcall+=");";
1275                 cr.outputline(methodcall);
1276                 cr.outputline(goodflag.getSafeSymbol()+"=0;");
1277                 cr.outputline("continue;");
1278             }
1279             cr.endblock();
1280             /* Build standard compensation actions */
1281             if (need_compensation(currentrule)) {
1282                 UpdateNode un=find_compensation(currentrule);
1283                 String name=(String)updatenames.get(un);
1284                 usedupdates.add(un); /* Mark as used */
1285
1286                 String methodcall=name+"(this,"+oldmodel.getSafeSymbol()+","+
1287                               repairtable.getSafeSymbol();
1288                 for(int i=0;i<currentrule.numQuantifiers();i++) {
1289                     Quantifier q=currentrule.getQuantifier(i);
1290                     if (q instanceof SetQuantifier) {
1291                         SetQuantifier sq=(SetQuantifier) q;
1292                         methodcall+=","+sq.getVar().getSafeSymbol();
1293                     } else if (q instanceof RelationQuantifier) {
1294                         RelationQuantifier rq=(RelationQuantifier) q;
1295                         methodcall+=","+rq.x.getSafeSymbol();
1296                         methodcall+=","+rq.y.getSafeSymbol();
1297                     } else if (q instanceof ForQuantifier) {
1298                         ForQuantifier fq=(ForQuantifier) q;
1299                         methodcall+=","+fq.getVar().getSafeSymbol();
1300                     }
1301                 }
1302                 methodcall+=");";
1303                 cr.outputline(methodcall);
1304                 cr.outputline(goodflag.getSafeSymbol()+"=0;");
1305                 cr.outputline("continue;");
1306             }
1307         }
1308         cr.endblock();
1309
1310         String addeditem = (VarDescriptor.makeNew("addeditem")).getSafeSymbol();
1311         cr.outputline("int " + addeditem + " = 1;");
1312         cr.outputline(addeditem + " = " + sd.getSafeSymbol() + "_hash->add((int)" + setvar +  ", (int)" + setvar + ");");
1313         cr.startblock();
1314         Vector dispatchrules = getrulelist(sd);
1315
1316         if (dispatchrules.size() == 0) {
1317             cr.outputline("// nothing to dispatch");
1318             cr.endblock();
1319             return;
1320         }
1321
1322         for(int i = 0; i < dispatchrules.size(); i++) {
1323             Rule rule = (Rule) dispatchrules.elementAt(i);
1324             if (SetDescriptor.expand(rule.getGuardExpr().getRequiredDescriptors()).contains(sd)) {
1325                 /* Guard depends on this relation, so we recompute everything */
1326                 cr.outputline(worklist.getSafeSymbol()+"->add("+rule.getNum()+",-1,0,0);");
1327             } else {
1328                 for (int j=0;j<rule.numQuantifiers();j++) {
1329                     Quantifier q=rule.getQuantifier(j);
1330                     if (SetDescriptor.expand(q.getRequiredDescriptors()).contains(sd)) {
1331                         /* Generate add */
1332                         cr.outputline(worklist.getSafeSymbol()+"->add("+rule.getNum()+","+j+","+setvar+",0);");
1333                     }
1334                 }
1335             }
1336         }
1337         cr.endblock();
1338     }
1339 }
1340
1341
1342