Fixed a variety of bugs...
[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 import MCC.Compiler;
7
8 public class RepairGenerator {
9     State state;
10     java.io.PrintWriter outputrepair = null;
11     java.io.PrintWriter outputaux = null;
12     java.io.PrintWriter outputhead = null;
13     String name="foo";
14     String headername;
15     static VarDescriptor oldmodel=null;
16     static VarDescriptor newmodel=null;
17     static VarDescriptor worklist=null;
18     static VarDescriptor repairtable=null;
19     static VarDescriptor goodflag=null;
20     Rule currentrule=null;
21     Hashtable updatenames;
22     HashSet usedupdates;
23     Termination termination;
24     Set removed;
25     HashSet togenerate;
26     static boolean DEBUG=false;
27     Cost cost;
28     ModelRuleDependence mrd;
29
30     public RepairGenerator(State state, Termination t) {
31         this.state = state;
32         updatenames=new Hashtable();
33         usedupdates=new HashSet();
34         termination=t;
35         removed=t.removedset;
36         togenerate=new HashSet();
37         togenerate.addAll(termination.conjunctions);
38         if (Compiler.REPAIR)
39             togenerate.removeAll(removed);
40         GraphNode.computeclosure(togenerate,removed);
41         cost=new Cost();
42         mrd=ModelRuleDependence.doAnalysis(state);
43         Repair.repairgenerator=this;
44     }
45
46     private void generatetypechecks(boolean flag) {
47         if (flag) {
48             DotExpr.DOTYPECHECKS=true;
49             VarExpr.DOTYPECHECKS=true;
50             DotExpr.DONULL=true;
51             VarExpr.DONULL=true;
52         } else {
53             VarExpr.DOTYPECHECKS=false;
54             DotExpr.DOTYPECHECKS=false;
55             VarExpr.DONULL=true;
56             DotExpr.DONULL=true;
57         }
58     }
59
60
61     private void name_updates() {
62         int count=0;
63         for(Iterator it=termination.updatenodes.iterator();it.hasNext();) {
64             GraphNode gn=(GraphNode) it.next();
65             TermNode tn=(TermNode) gn.getOwner();
66             MultUpdateNode mun=tn.getUpdate();
67             if (togenerate.contains(gn))
68             for (int i=0;i<mun.numUpdates();i++) {
69                 UpdateNode un=mun.getUpdate(i);
70                 String name="update"+String.valueOf(count++);
71                 updatenames.put(un,name);
72             }
73         }
74     }
75
76     public void generate(OutputStream outputrepair, OutputStream outputaux,OutputStream outputhead, String st) {
77         this.outputrepair = new java.io.PrintWriter(outputrepair, true);
78         this.outputaux = new java.io.PrintWriter(outputaux, true);
79         this.outputhead = new java.io.PrintWriter(outputhead, true);
80         headername=st;
81         name_updates();
82         generatetypechecks(true);
83         generate_tokentable();
84         generate_hashtables();
85         generate_stateobject();
86         generate_call();
87         generate_start();
88         generate_rules();
89         if (!Compiler.REPAIR||Compiler.GENERATEDEBUGPRINT) {
90             generate_print();
91         }
92         generate_checks();
93         generate_teardown();
94         CodeWriter crhead = new StandardCodeWriter(this.outputhead);
95         CodeWriter craux = new StandardCodeWriter(this.outputaux);
96         crhead.outputline("};");
97         craux.outputline("}");
98
99         if (Compiler.GENERATEDEBUGHOOKS) {
100             crhead.outputline("void debughook();");
101             craux.outputline("void debughook() {}");
102         }
103         generatetypechecks(false);
104         generate_computesizes();
105         generatetypechecks(true);
106         generate_recomputesizes();
107         generatetypechecks(false);
108         generate_updates();
109         StructureGenerator sg=new StructureGenerator(state,this);
110         sg.buildall();
111         crhead.outputline("#endif");
112     }
113
114     String ststate="state";
115     String stmodel="model";
116     String strepairtable="repairtable";
117     String stleft="left";
118     String stright="right";
119     String stnew="newvalue";
120
121     private void generate_updates() {
122         int count=0;
123         CodeWriter crhead = new StandardCodeWriter(outputhead);        
124         CodeWriter craux = new StandardCodeWriter(outputaux);        
125         RelationDescriptor.prefix = "model->";
126         SetDescriptor.prefix = "model->";
127
128         /* Rewrite globals */
129
130         for (Iterator it=this.state.stGlobals.descriptors();it.hasNext();) {
131             VarDescriptor vd=(VarDescriptor)it.next();
132             craux.outputline("#define "+vd.getSafeSymbol()+" "+ststate+"->"+vd.getSafeSymbol());
133         }
134
135         for(Iterator it=termination.updatenodes.iterator();it.hasNext();) {
136             GraphNode gn=(GraphNode) it.next();
137             TermNode tn=(TermNode) gn.getOwner();
138             MultUpdateNode mun=tn.getUpdate();
139             boolean isrelation=(mun.getDescriptor() instanceof RelationDescriptor);
140             if (togenerate.contains(gn))
141             for (int i=0;i<mun.numUpdates();i++) {
142                 UpdateNode un=mun.getUpdate(i);
143                 String methodname=(String)updatenames.get(un);
144                 
145                 switch(mun.op) {
146                 case MultUpdateNode.ADD:
147                     if (isrelation) {
148                         crhead.outputline("void "+methodname+"("+name+"_state * " +ststate+","+name+" * "+stmodel+", RepairHash * "+strepairtable+", int "+stleft+", int "+stright+");");
149                         craux.outputline("void "+methodname+"("+name+"_state * "+ ststate+","+name+" * "+stmodel+", RepairHash * "+strepairtable+", int "+stleft+", int "+stright+")");
150                     } else {
151                         crhead.outputline("void "+methodname+"("+name+"_state * "+ ststate+","+name+" * "+stmodel+", RepairHash * "+strepairtable+", int "+stleft+");");
152                         craux.outputline("void "+methodname+"("+name+"_state * "+ststate+","+name+" * "+stmodel+", RepairHash * "+strepairtable+", int "+stleft+")");
153                     }
154                     craux.startblock();
155                     craux.outputline("int maybe=0;");
156                     final SymbolTable st = un.getRule().getSymbolTable();                
157                     CodeWriter cr = new StandardCodeWriter(outputaux) {
158                         public SymbolTable getSymbolTable() { return st; }
159                     };
160                     un.generate(cr, false, false, stleft,stright, null,this);
161                     craux.outputline("if (maybe) printf(\"REALLY BAD\");");
162                     craux.endblock();
163                     break;
164                 case MultUpdateNode.REMOVE: {
165                     Rule r=un.getRule();
166                     String methodcall="void "+methodname+"("+name+"_state * "+ststate+","+name+" * "+stmodel+", RepairHash * "+strepairtable;
167                     for(int j=0;j<r.numQuantifiers();j++) {
168                         Quantifier q=r.getQuantifier(j);
169                         if (q instanceof SetQuantifier) {
170                             SetQuantifier sq=(SetQuantifier) q;
171                             methodcall+=","+sq.getVar().getType().getGenerateType().getSafeSymbol()+" "+sq.getVar().getSafeSymbol();
172                         } else if (q instanceof RelationQuantifier) {
173                             RelationQuantifier rq=(RelationQuantifier) q;
174                             
175                             methodcall+=","+rq.x.getType().getGenerateType().getSafeSymbol()+" "+rq.x.getSafeSymbol();
176                             methodcall+=","+rq.y.getType().getGenerateType().getSafeSymbol()+" "+rq.y.getSafeSymbol();
177                         } else if (q instanceof ForQuantifier) {
178                             ForQuantifier fq=(ForQuantifier) q;
179                             methodcall+=",int "+fq.getVar().getSafeSymbol();
180                         }
181                     }
182                     methodcall+=")";
183                     crhead.outputline(methodcall+";");
184                     craux.outputline(methodcall);
185                     craux.startblock();
186                     craux.outputline("int maybe=0;");
187                     final SymbolTable st2 = un.getRule().getSymbolTable();
188                     CodeWriter cr2 = new StandardCodeWriter(outputaux) {
189                         public SymbolTable getSymbolTable() { return st2; }
190                     };
191                     un.generate(cr2, true, false, null,null, null,this);
192                     craux.outputline("if (maybe) printf(\"REALLY BAD\");");
193                     craux.endblock();
194                 }
195                     break;
196                 case MultUpdateNode.MODIFY: {
197                     Rule r=un.getRule();
198                     String methodcall="void "+methodname+"("+name+"_state * "+ststate+","+name+" * "+stmodel+", RepairHash * "+strepairtable;
199                     for(int j=0;j<r.numQuantifiers();j++) {
200                         Quantifier q=r.getQuantifier(j);
201                         if (q instanceof SetQuantifier) {
202                             SetQuantifier sq=(SetQuantifier) q;
203                             methodcall+=","+sq.getVar().getType().getGenerateType().getSafeSymbol()+" "+sq.getVar().getSafeSymbol();
204                         } else if (q instanceof RelationQuantifier) {
205                             RelationQuantifier rq=(RelationQuantifier) q;
206                             
207                             methodcall+=", "+rq.x.getType().getGenerateType().getSafeSymbol()+" "+rq.x.getSafeSymbol();
208                             methodcall+=", "+rq.y.getType().getGenerateType().getSafeSymbol()+" "+rq.y.getSafeSymbol();
209                         } else if (q instanceof ForQuantifier) {
210                             ForQuantifier fq=(ForQuantifier) q;
211                             methodcall+=", int "+fq.getVar().getSafeSymbol();
212                         }
213                     }
214                     methodcall+=", int "+stleft+", int "+stright+", int "+stnew;
215                     methodcall+=")";
216                     crhead.outputline(methodcall+";");
217                     craux.outputline(methodcall);
218                     craux.startblock();
219                     craux.outputline("int maybe=0;");
220                     final SymbolTable st2 = un.getRule().getSymbolTable();
221                     CodeWriter cr2 = new StandardCodeWriter(outputaux) {
222                         public SymbolTable getSymbolTable() { return st2; }
223                     };
224                     un.generate(cr2, false, true, stleft, stright, stnew, this);
225                     craux.outputline("if (maybe) printf(\"REALLY BAD\");");
226                     craux.endblock();
227                 }
228                     break;
229
230                 default:
231                     throw new Error("Nonimplement Update");
232                 }
233             }
234         }
235     }
236
237     private void generate_call() {
238         CodeWriter cr = new StandardCodeWriter(outputrepair);        
239         VarDescriptor vdstate=VarDescriptor.makeNew("repairstate");
240         cr.outputline(name+"_state * "+vdstate.getSafeSymbol()+"=new "+name+"_state();");
241         Iterator globals=state.stGlobals.descriptors();
242         while (globals.hasNext()) {
243             VarDescriptor vd=(VarDescriptor) globals.next();
244             cr.outputline(vdstate.getSafeSymbol()+"->"+vd.getSafeSymbol()+"=("+vd.getType().getGenerateType().getSafeSymbol()+")"+vd.getSafeSymbol()+";");
245         }
246         /* Insert repair here */
247         cr.outputline(vdstate.getSafeSymbol()+"->doanalysis();");
248         globals=state.stGlobals.descriptors();
249         while (globals.hasNext()) {
250             VarDescriptor vd=(VarDescriptor) globals.next();
251             cr.outputline("*(("+vd.getType().getGenerateType().getSafeSymbol()+"*) &"+vd.getSafeSymbol()+")="+vdstate.getSafeSymbol()+"->"+vd.getSafeSymbol()+";");
252         }
253         cr.outputline("delete "+vdstate.getSafeSymbol()+";");
254     }
255
256     private void generate_tokentable() {
257         CodeWriter cr = new StandardCodeWriter(outputrepair);        
258         Iterator tokens = TokenLiteralExpr.tokens.keySet().iterator();        
259
260         cr.outputline("");
261         cr.outputline("// Token values");
262         cr.outputline("");
263
264         while (tokens.hasNext()) {
265             Object token = tokens.next();
266             cr.outputline("// " + token.toString() + " = " + TokenLiteralExpr.tokens.get(token).toString());            
267         }
268
269         cr.outputline("");
270         cr.outputline("");
271     }
272
273     private void generate_stateobject() {
274         CodeWriter crhead = new StandardCodeWriter(outputhead);
275         crhead.outputline("class "+name+"_state {");
276         crhead.outputline("public:");
277         Iterator globals=state.stGlobals.descriptors();
278         while (globals.hasNext()) {
279             VarDescriptor vd=(VarDescriptor) globals.next();
280             crhead.outputline(vd.getType().getGenerateType().getSafeSymbol()+" "+vd.getSafeSymbol()+";");
281         }
282         crhead.outputline("void computesizes(int *,int **);");
283         crhead.outputline("void recomputesizes();");
284     }
285
286     private void generate_computesizes() {
287         int max=TypeDescriptor.counter;
288         TypeDescriptor[] tdarray=new TypeDescriptor[max];
289         for(Iterator it=state.stTypes.descriptors();it.hasNext();) {
290             TypeDescriptor ttd=(TypeDescriptor)it.next();
291             tdarray[ttd.getId()]=ttd;
292         }
293         final SymbolTable st = state.stGlobals;
294         CodeWriter cr = new StandardCodeWriter(outputaux) {
295                 public SymbolTable getSymbolTable() { return st; }
296             };
297
298         cr.outputline("void "+name+"_state::computesizes(int *sizearray,int **numele) {");
299         cr.outputline("int maybe=0;");
300         for(int i=0;i<max;i++) {
301             TypeDescriptor td=tdarray[i];
302             Expr size=td.getSizeExpr();
303             VarDescriptor vd=VarDescriptor.makeNew("size");
304             size.generate(cr,vd);
305             cr.outputline("sizearray["+i+"]="+vd.getSafeSymbol()+";");
306         }
307         for(int i=0;i<max;i++) {
308             TypeDescriptor td=tdarray[i];
309             if (td instanceof StructureTypeDescriptor) {
310                 StructureTypeDescriptor std=(StructureTypeDescriptor) td;
311                 for(int j=0;j<std.fieldlist.size();j++) {
312                     FieldDescriptor fd=(FieldDescriptor)std.fieldlist.get(j);
313                     if (fd instanceof ArrayDescriptor) {
314                         ArrayDescriptor ad=(ArrayDescriptor)fd;
315                         Expr index=ad.getIndexBound();
316                         VarDescriptor vd=VarDescriptor.makeNew("index");
317                         index.generate(cr,vd);
318                         cr.outputline("numele["+i+"]["+j+"]="+vd.getSafeSymbol()+";");
319                     }
320                 }
321             }
322         }
323         cr.outputline("if (maybe) printf(\"BAD ERROR\");");
324         cr.outputline("}");
325     }
326
327     private void generate_recomputesizes() {
328         int max=TypeDescriptor.counter;
329         TypeDescriptor[] tdarray=new TypeDescriptor[max];
330         for(Iterator it=state.stTypes.descriptors();it.hasNext();) {
331             TypeDescriptor ttd=(TypeDescriptor)it.next();
332             tdarray[ttd.getId()]=ttd;
333         }
334         final SymbolTable st = state.stGlobals;
335         CodeWriter cr = new StandardCodeWriter(outputaux) {
336                 public SymbolTable getSymbolTable() { return st; }
337             };
338         cr.outputline("void "+name+"_state::recomputesizes() {");
339         cr.outputline("int maybe=0;");
340         for(int i=0;i<max;i++) {
341             TypeDescriptor td=tdarray[i];
342             Expr size=td.getSizeExpr();
343             VarDescriptor vd=VarDescriptor.makeNew("size");
344             size.generate(cr,vd);
345         }
346         for(int i=0;i<max;i++) {
347             TypeDescriptor td=tdarray[i];
348             if (td instanceof StructureTypeDescriptor) {
349                 StructureTypeDescriptor std=(StructureTypeDescriptor) td;
350                 for(int j=0;j<std.fieldlist.size();j++) {
351                     FieldDescriptor fd=(FieldDescriptor)std.fieldlist.get(j);
352                     if (fd instanceof ArrayDescriptor) {
353                         ArrayDescriptor ad=(ArrayDescriptor)fd;
354                         Expr index=ad.getIndexBound();
355                         VarDescriptor vd=VarDescriptor.makeNew("index");
356                         index.generate(cr,vd);
357                     }
358                 }
359             }
360         }
361         cr.outputline("if (maybe) printf(\"BAD ERROR\");");
362         cr.outputline("}");
363     }
364
365
366     private void generate_hashtables() {
367         CodeWriter craux = new StandardCodeWriter(outputaux);
368         CodeWriter crhead = new StandardCodeWriter(outputhead);
369         crhead.outputline("#ifndef "+name+"_h");
370         crhead.outputline("#define "+name+"_h");
371         crhead.outputline("#include \"SimpleHash.h\"");
372         crhead.outputline("extern \"C\" {");
373         crhead.outputline("#include \"instrument.h\"");
374         crhead.outputline("}");
375         crhead.outputline("#include <stdio.h>");
376         crhead.outputline("#include <stdlib.h>");
377         crhead.outputline("class "+name+" {");
378         crhead.outputline("public:");
379         crhead.outputline(name+"();");
380         crhead.outputline("~"+name+"();");
381         craux.outputline("#include \""+headername+"\"");
382         craux.outputline("#include \"size.h\"");
383
384         craux.outputline(name+"::"+name+"() {");
385         craux.outputline("// creating hashtables ");
386         
387         /* build sets */
388         Iterator sets = state.stSets.descriptors();
389         
390         /* first pass create all the hash tables */
391         while (sets.hasNext()) {
392             SetDescriptor set = (SetDescriptor) sets.next();
393             crhead.outputline("SimpleHash* " + set.getSafeSymbol() + "_hash;");
394             craux.outputline(set.getSafeSymbol() + "_hash = new SimpleHash();");
395         }
396         
397         /* second pass build relationships between hashtables */
398         sets = state.stSets.descriptors();
399         
400         while (sets.hasNext()) {
401             SetDescriptor set = (SetDescriptor) sets.next();
402             Iterator subsets = set.subsets();
403             
404             while (subsets.hasNext()) {
405                 SetDescriptor subset = (SetDescriptor) subsets.next();                
406                 craux.outputline(subset.getSafeSymbol() + "_hash->addParent(" + set.getSafeSymbol() + "_hash);");
407             }
408         } 
409
410         /* build relations */
411         Iterator relations = state.stRelations.descriptors();
412         
413         /* first pass create all the hash tables */
414         while (relations.hasNext()) {
415             RelationDescriptor relation = (RelationDescriptor) relations.next();
416             
417             if (relation.testUsage(RelationDescriptor.IMAGE)) {
418                 crhead.outputline("SimpleHash* " + relation.getSafeSymbol() + "_hash;");
419                 craux.outputline(relation.getSafeSymbol() + "_hash = new SimpleHash();");
420             }
421
422             if (relation.testUsage(RelationDescriptor.INVIMAGE)) {
423                 crhead.outputline("SimpleHash* " + relation.getSafeSymbol() + "_hashinv;");
424                 craux.outputline(relation.getSafeSymbol() + "_hashinv = new SimpleHash();");
425             } 
426         }
427
428         craux.outputline("}");
429         crhead.outputline("};");
430         craux.outputline(name+"::~"+name+"() {");
431         craux.outputline("// deleting hashtables");
432
433         /* build destructor */
434         sets = state.stSets.descriptors();
435         
436         /* first pass create all the hash tables */
437         while (sets.hasNext()) {
438             SetDescriptor set = (SetDescriptor) sets.next();
439             craux.outputline("delete "+set.getSafeSymbol() + "_hash;");
440         } 
441         
442         /* destroy relations */
443         relations = state.stRelations.descriptors();
444         
445         /* first pass create all the hash tables */
446         while (relations.hasNext()) {
447             RelationDescriptor relation = (RelationDescriptor) relations.next();
448             
449             if (relation.testUsage(RelationDescriptor.IMAGE)) {
450                 craux.outputline("delete "+relation.getSafeSymbol() + "_hash;");
451             }
452
453             if (relation.testUsage(RelationDescriptor.INVIMAGE)) {
454                 craux.outputline("delete " + relation.getSafeSymbol() + "_hashinv;");
455             } 
456         }
457         craux.outputline("}");
458     }
459
460     private void generate_start() {
461         CodeWriter crhead = new StandardCodeWriter(outputhead);
462         CodeWriter craux = new StandardCodeWriter(outputaux);
463         oldmodel=VarDescriptor.makeNew("oldmodel");
464         newmodel=VarDescriptor.makeNew("newmodel");
465         worklist=VarDescriptor.makeNew("worklist");
466         goodflag=VarDescriptor.makeNew("goodflag");
467         repairtable=VarDescriptor.makeNew("repairtable");
468         crhead.outputline("void doanalysis();");
469         craux.outputline("void "+name +"_state::doanalysis()");
470         craux.startblock();
471         craux.outputline("int highmark;");
472         craux.outputline("initializestack(&highmark);");
473         craux.outputline("typeobject *typeobject1=gettypeobject();");
474         craux.outputline("typeobject1->computesizes(this);");
475         craux.outputline("recomputesizes();");
476         craux.outputline(name+ " * "+oldmodel.getSafeSymbol()+"=0;");
477         craux.outputline("WorkList * "+worklist.getSafeSymbol()+" = new WorkList();");
478         craux.outputline("RepairHash * "+repairtable.getSafeSymbol()+"=0;");
479         craux.outputline("while (1)");
480         craux.startblock();
481         craux.outputline(name+ " * "+newmodel.getSafeSymbol()+"=new "+name+"();");
482     }
483     
484     private void generate_teardown() {
485         CodeWriter cr = new StandardCodeWriter(outputaux);        
486         cr.endblock();
487     }
488
489     private void generate_print() {
490         
491         final SymbolTable st = new SymbolTable();
492
493         CodeWriter cr = new StandardCodeWriter(outputaux) {
494                 public SymbolTable getSymbolTable() { return st; }
495             };
496
497         cr.outputline("// printing sets!");
498         cr.outputline("printf(\"\\n\\nPRINTING SETS AND RELATIONS\\n\");");
499
500         Iterator setiterator = state.stSets.descriptors();
501         while (setiterator.hasNext()) {
502             SetDescriptor sd = (SetDescriptor) setiterator.next();
503             if (sd.getSymbol().equals("int") || sd.getSymbol().equals("token")) {
504                 continue;
505             }
506
507             String setname = sd.getSafeSymbol();
508
509             cr.startblock();
510             cr.outputline("// printing set " + setname);
511             cr.outputline("printf(\"\\nPrinting set " + sd.getSymbol() + " - %d elements \\n\", " + setname + "_hash->count());");
512             cr.outputline("SimpleIterator __setiterator;");
513             cr.outputline("" + setname + "_hash->iterator(__setiterator);");
514             cr.outputline("while (__setiterator.hasNext())");
515             cr.startblock();
516             cr.outputline("int __setval = (int) __setiterator.next();");
517
518             TypeDescriptor td = sd.getType();
519             if (td instanceof StructureTypeDescriptor) {
520                 StructureTypeDescriptor std = (StructureTypeDescriptor) td;
521                 VarDescriptor vd = new VarDescriptor ("__setval", "__setval", td, false);
522                 std.generate_printout(cr, vd);
523             } else { // Missing type descriptor or reserved type, just print int
524                 cr.outputline("printf(\"<%d> \", __setval);");                  
525             }
526
527
528             cr.endblock();
529             cr.endblock();
530         }
531
532         cr.outputline("printf(\"\\n\\n------------------- END PRINTING\\n\");");
533     }
534
535     Set ruleset=null;
536     private void generate_rules() {
537         /* first we must sort the rules */
538         RelationDescriptor.prefix = newmodel.getSafeSymbol()+"->";
539         SetDescriptor.prefix = newmodel.getSafeSymbol()+"->";
540         System.out.println("SCC="+(mrd.numSCC()-1));
541         for(int sccindex=0;sccindex<mrd.numSCC();sccindex++) {
542             ruleset=mrd.getSCC(sccindex);
543             boolean needworklist=mrd.hasCycle(sccindex);
544             
545             if (!needworklist) {
546                 Iterator iterator_rs = ruleset.iterator();
547                 while (iterator_rs.hasNext()) {
548                     Rule rule = (Rule) iterator_rs.next();
549                     {
550                         final SymbolTable st = rule.getSymbolTable();
551                         CodeWriter cr = new StandardCodeWriter(outputaux) {
552                                 public SymbolTable getSymbolTable() { return st; }
553                             };
554                         cr.outputline("// build " +escape(rule.toString()));
555                         cr.startblock();
556                         cr.outputline("int maybe=0;");
557                         ListIterator quantifiers = rule.quantifiers();
558                         while (quantifiers.hasNext()) {
559                             Quantifier quantifier = (Quantifier) quantifiers.next();
560                             quantifier.generate_open(cr);
561                         }
562                         
563                         /* pretty print! */
564                         cr.output("//");
565                         rule.getGuardExpr().prettyPrint(cr);
566                         cr.outputline("");
567                         
568                         /* now we have to generate the guard test */
569                         VarDescriptor guardval = VarDescriptor.makeNew();
570                         rule.getGuardExpr().generate(cr, guardval);
571                         cr.outputline("if (" + guardval.getSafeSymbol() + ")");
572                         cr.startblock();
573                         
574                         /* now we have to generate the inclusion code */
575                         currentrule=rule;
576                         rule.getInclusion().generate(cr);
577                         cr.endblock();
578                         while (quantifiers.hasPrevious()) {
579                             Quantifier quantifier = (Quantifier) quantifiers.previous();
580                             cr.endblock();
581                         }
582                         cr.endblock();
583                         cr.outputline("");
584                         cr.outputline("");
585                     }
586                 }
587             } else {
588                 CodeWriter cr2 = new StandardCodeWriter(outputaux);
589                 
590                 for(Iterator initialworklist=ruleset.iterator();initialworklist.hasNext();) {
591                     /** Construct initial worklist set */
592                     Rule rule=(Rule)initialworklist.next();
593                     cr2.outputline(worklist.getSafeSymbol()+"->add("+rule.getNum()+",-1,0,0);");
594                 }
595
596                 cr2.outputline("while ("+worklist.getSafeSymbol()+"->hasMoreElements())");
597                 cr2.startblock();
598                 VarDescriptor idvar=VarDescriptor.makeNew("id");
599                 cr2.outputline("int "+idvar.getSafeSymbol()+"="+worklist.getSafeSymbol()+"->getid();");
600                 
601                 String elseladder = "if";
602                 
603                 Iterator iterator_rules = ruleset.iterator();
604                 while (iterator_rules.hasNext()) {
605                     
606                     Rule rule = (Rule) iterator_rules.next();
607                     int dispatchid = rule.getNum();
608                     
609                     {
610                         final SymbolTable st = rule.getSymbolTable();
611                         CodeWriter cr = new StandardCodeWriter(outputaux) {
612                                 public SymbolTable getSymbolTable() { return st; }
613                             };
614                         
615                         cr.indent();
616                         cr.outputline(elseladder + " ("+idvar.getSafeSymbol()+" == " + dispatchid + ")");
617                         cr.startblock();
618                         cr.outputline("int maybe=0;");
619                         VarDescriptor typevar=VarDescriptor.makeNew("type");
620                         VarDescriptor leftvar=VarDescriptor.makeNew("left");
621                         VarDescriptor rightvar=VarDescriptor.makeNew("right");
622                         cr.outputline("int "+typevar.getSafeSymbol()+"="+worklist.getSafeSymbol()+"->gettype();");
623                         cr.outputline("int "+leftvar.getSafeSymbol()+"="+worklist.getSafeSymbol()+"->getlvalue();");
624                         cr.outputline("int "+rightvar.getSafeSymbol()+"="+worklist.getSafeSymbol()+"->getrvalue();");
625                         cr.outputline("// build " +escape(rule.toString()));
626                         
627                         
628                         for (int j=0;j<rule.numQuantifiers();j++) {
629                             Quantifier quantifier = rule.getQuantifier(j);
630                             quantifier.generate_open(cr, typevar.getSafeSymbol(),j,leftvar.getSafeSymbol(),rightvar.getSafeSymbol());
631                         }
632                         
633                         /* pretty print! */
634                         cr.output("//");
635                         
636                         rule.getGuardExpr().prettyPrint(cr);
637                         cr.outputline("");
638                         
639                         /* now we have to generate the guard test */
640                         
641                         VarDescriptor guardval = VarDescriptor.makeNew();
642                         rule.getGuardExpr().generate(cr, guardval);
643                         
644                         cr.outputline("if (" + guardval.getSafeSymbol() + ")");
645                         cr.startblock();
646                         
647                         /* now we have to generate the inclusion code */
648                         currentrule=rule;
649                         rule.getInclusion().generate(cr);
650                         cr.endblock();
651                         
652                         for (int j=0;j<rule.numQuantifiers();j++) {
653                             cr.endblock();
654                         }
655                         
656                         // close startblocks generated by DotExpr memory checks
657                         //DotExpr.generate_memory_endblocks(cr);
658                         
659                         cr.endblock(); // end else-if WORKLIST ladder
660                         
661                         elseladder = "else if";
662                     }
663                 }
664                 cr2.outputline("else");
665                 cr2.startblock();
666                 cr2.outputline("printf(\"VERY BAD !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\\n\\n\");");
667                 cr2.outputline("exit(1);");
668                 cr2.endblock();
669                 // end block created for worklist
670                 cr2.outputline(worklist.getSafeSymbol()+"->pop();");
671                 cr2.endblock();
672             }
673         }
674     }
675
676     public static String escape(String s) {
677         String newstring="";
678         for(int i=0;i<s.length();i++) {
679             char c=s.charAt(i);
680             if (c=='"')
681                 newstring+="\"";
682             else
683                 newstring+=c;
684         }
685         return newstring;
686     }
687
688     private void generate_checks() {
689
690         /* do constraint checks */
691         //        Vector constraints = state.vConstraints;
692
693
694         //        for (int i = 0; i < constraints.size(); i++) {
695         //            Constraint constraint = (Constraint) constraints.elementAt(i); 
696         for (Iterator i = termination.constraintdependence.computeOrdering().iterator(); i.hasNext();) {
697             Constraint constraint = (Constraint) ((GraphNode)i.next()).getOwner();
698             
699             {
700                 final SymbolTable st = constraint.getSymbolTable();
701                 CodeWriter cr = new StandardCodeWriter(outputaux);
702                 cr.pushSymbolTable(constraint.getSymbolTable());
703
704                 cr.outputline("// checking " + escape(constraint.toString()));
705                 cr.startblock();
706
707                 ListIterator quantifiers = constraint.quantifiers();
708
709                 while (quantifiers.hasNext()) {
710                     Quantifier quantifier = (Quantifier) quantifiers.next();
711                     quantifier.generate_open(cr);
712                 }
713
714                 cr.outputline("int maybe = 0;");
715                         
716                 /* now we have to generate the guard test */
717         
718                 VarDescriptor constraintboolean = VarDescriptor.makeNew("constraintboolean");
719                 constraint.getLogicStatement().generate(cr, constraintboolean);
720                 
721                 cr.outputline("if (maybe)");
722                 cr.startblock();
723                 cr.outputline("printf(\"maybe fail " +  escape(constraint.toString()) + ". \\n\");");
724                 cr.outputline("exit(1);");
725                 cr.endblock();
726
727                 cr.outputline("else if (!" + constraintboolean.getSafeSymbol() + ")");
728                 cr.startblock();
729                 if (!Compiler.REPAIR||Compiler.GENERATEDEBUGHOOKS)
730                     cr.outputline("printf(\"fail " + escape(constraint.toString()) + ". \\n\");");
731                 
732                 if (Compiler.REPAIR) {
733                 /* Do repairs */
734                 /* Build new repair table */
735                 cr.outputline("if ("+repairtable.getSafeSymbol()+")");
736                 cr.outputline("delete "+repairtable.getSafeSymbol()+";");
737                 cr.outputline(repairtable.getSafeSymbol()+"=new RepairHash();");
738                 
739                 if (Compiler.GENERATEDEBUGHOOKS)
740                     cr.outputline("debughook();");
741                 /* Compute cost of each repair */
742                 VarDescriptor mincost=VarDescriptor.makeNew("mincost");
743                 VarDescriptor mincostindex=VarDescriptor.makeNew("mincostindex");
744                 Vector dnfconst=new Vector();
745                 dnfconst.addAll((Set)termination.conjunctionmap.get(constraint));
746
747                 if (dnfconst.size()<=1) {
748                     cr.outputline("int "+mincostindex.getSafeSymbol()+"=0;");
749                 }
750                 if (dnfconst.size()>1) {
751                     cr.outputline("int "+mincostindex.getSafeSymbol()+";");
752                     boolean first=true;
753                     for(int j=0;j<dnfconst.size();j++) {
754                         GraphNode gn=(GraphNode)dnfconst.get(j);
755                         Conjunction conj=((TermNode)gn.getOwner()).getConjunction();
756                         if (removed.contains(gn))
757                             continue;
758                         
759                         VarDescriptor costvar;
760                         if (first) {
761                             costvar=mincost;
762                         } else
763                             costvar=VarDescriptor.makeNew("cost");
764                         for(int k=0;k<conj.size();k++) {
765                             DNFPredicate dpred=conj.get(k);
766                             Predicate p=dpred.getPredicate();
767                             boolean negate=dpred.isNegated();
768                             VarDescriptor predvalue=VarDescriptor.makeNew("Predicatevalue");
769                             p.generate(cr,predvalue);
770                             if (negate)
771                                 cr.outputline("if (maybe||"+predvalue.getSafeSymbol()+")");
772                             else
773                                 cr.outputline("if (maybe||!"+predvalue.getSafeSymbol()+")");
774                             if (k==0)
775                                 cr.outputline("int "+costvar.getSafeSymbol()+"="+cost.getCost(dpred)+";");
776                             else
777                                 cr.outputline(costvar.getSafeSymbol()+"+="+cost.getCost(dpred)+";");
778                         }
779
780                         if(!first) {
781                             cr.outputline("if ("+costvar.getSafeSymbol()+"<"+mincost.getSafeSymbol()+")");
782                             cr.startblock();
783                             cr.outputline(mincost.getSafeSymbol()+"="+costvar.getSafeSymbol()+";");
784                             cr.outputline(mincostindex.getSafeSymbol()+"="+j+";");
785                             cr.endblock();
786                         } else
787                             cr.outputline(mincostindex.getSafeSymbol()+"="+j+";");
788                         first=false;
789                     }
790                 }
791                 cr.outputline("switch("+mincostindex.getSafeSymbol()+") {");
792                 for(int j=0;j<dnfconst.size();j++) {
793                     GraphNode gn=(GraphNode)dnfconst.get(j);
794                     Conjunction conj=((TermNode)gn.getOwner()).getConjunction();
795
796                     if (removed.contains(gn))
797                         continue;
798                     cr.outputline("case "+j+":");
799                     for(int k=0;k<conj.size();k++) {
800                         DNFPredicate dpred=conj.get(k);
801                         Predicate p=dpred.getPredicate();
802                         boolean negate=dpred.isNegated();
803                         VarDescriptor predvalue=VarDescriptor.makeNew("Predicatevalue");
804                         p.generate(cr,predvalue);
805                         if (negate)
806                             cr.outputline("if (maybe||"+predvalue.getSafeSymbol()+")");
807                         else
808                             cr.outputline("if (maybe||!"+predvalue.getSafeSymbol()+")");
809                         cr.startblock();
810                         if (p instanceof InclusionPredicate)
811                             generateinclusionrepair(conj,dpred, cr);
812                         else if (p instanceof ExprPredicate) {
813                             ExprPredicate ep=(ExprPredicate)p;
814                             if (ep.getType()==ExprPredicate.SIZE)
815                                 generatesizerepair(conj,dpred,cr);
816                             else if (ep.getType()==ExprPredicate.COMPARISON)
817                                 generatecomparisonrepair(conj,dpred,cr);
818                         } else throw new Error("Unrecognized Predicate");
819                         cr.endblock();
820                     }
821                     /* Update model */
822                     cr.outputline("break;");
823                 }
824                 cr.outputline("}");
825
826                 cr.outputline("if ("+oldmodel.getSafeSymbol()+")");
827                 cr.outputline("delete "+oldmodel.getSafeSymbol()+";");
828                 cr.outputline(oldmodel.getSafeSymbol()+"="+newmodel.getSafeSymbol()+";");
829                 cr.outputline("goto rebuild;");  /* Rebuild model and all */
830                 }
831                 cr.endblock();
832                 
833                 while (quantifiers.hasPrevious()) {
834                     Quantifier quantifier = (Quantifier) quantifiers.previous();
835                     cr.endblock();
836                 }
837                 cr.endblock();
838                 cr.outputline("");
839                 cr.outputline("");
840             }
841         }
842         CodeWriter cr = new StandardCodeWriter(outputaux);
843         cr.startblock();
844         cr.outputline("if ("+repairtable.getSafeSymbol()+")");
845         cr.outputline("delete "+repairtable.getSafeSymbol()+";");
846         cr.outputline("if ("+oldmodel.getSafeSymbol()+")");
847         cr.outputline("delete "+oldmodel.getSafeSymbol()+";");
848         cr.outputline("delete "+newmodel.getSafeSymbol()+";");
849         cr.outputline("delete "+worklist.getSafeSymbol()+";");
850         cr.outputline("resettypemap();");
851         cr.outputline("break;");
852         cr.endblock();
853         cr.outputline("rebuild:");
854         cr.outputline(";");     
855         
856     }
857     
858     private MultUpdateNode getmultupdatenode(Conjunction conj, DNFPredicate dpred, int repairtype) {
859         MultUpdateNode mun=null;
860         GraphNode gn=(GraphNode) termination.conjtonodemap.get(conj);
861         for(Iterator edgeit=gn.edges();(mun==null)&&edgeit.hasNext();) {
862             GraphNode gn2=((GraphNode.Edge) edgeit.next()).getTarget();
863             TermNode tn2=(TermNode)gn2.getOwner();
864             if (tn2.getType()==TermNode.ABSTRACT) {
865                 AbstractRepair ar=tn2.getAbstract();
866                 if (((repairtype==-1)||(ar.getType()==repairtype))&&
867                     ar.getPredicate()==dpred) {
868                     for(Iterator edgeit2=gn2.edges();edgeit2.hasNext();) {
869                         GraphNode gn3=((GraphNode.Edge) edgeit2.next()).getTarget();
870                         if (!removed.contains(gn3)) {
871                             TermNode tn3=(TermNode)gn3.getOwner();
872                             if (tn3.getType()==TermNode.UPDATE) {
873                                 mun=tn3.getUpdate();
874                                 break;
875                             }
876                         }
877                     }
878                 }
879             }
880         }
881         return mun;
882     }
883
884     /** Generates abstract (and concrete) repair for a comparison */
885
886     private void generatecomparisonrepair(Conjunction conj, DNFPredicate dpred, CodeWriter cr){
887         MultUpdateNode munmodify=getmultupdatenode(conj,dpred,AbstractRepair.MODIFYRELATION);
888         MultUpdateNode munremove=getmultupdatenode(conj,dpred,AbstractRepair.REMOVEFROMRELATION);
889         MultUpdateNode munadd=getmultupdatenode(conj,dpred,AbstractRepair.ADDTORELATION);
890         ExprPredicate ep=(ExprPredicate)dpred.getPredicate();
891         RelationDescriptor rd=(RelationDescriptor)ep.getDescriptor();
892         boolean usageimage=rd.testUsage(RelationDescriptor.IMAGE);
893         boolean usageinvimage=rd.testUsage(RelationDescriptor.INVIMAGE);
894         boolean inverted=ep.inverted();
895         boolean negated=dpred.isNegated();
896         OpExpr expr=(OpExpr)ep.expr;
897         Opcode opcode=expr.getOpcode();
898         VarDescriptor leftside=VarDescriptor.makeNew("leftside");
899         VarDescriptor rightside=VarDescriptor.makeNew("rightside");
900         VarDescriptor newvalue=VarDescriptor.makeNew("newvalue");
901         if (!inverted) {
902             ((RelationExpr)expr.getLeftExpr()).getExpr().generate(cr,leftside);
903             expr.getRightExpr().generate(cr,newvalue);
904             cr.outputline(rd.getRange().getType().getGenerateType().getSafeSymbol()+" "+rightside.getSafeSymbol()+";");
905             cr.outputline(rd.getSafeSymbol()+"_hash->get("+leftside.getSafeSymbol()+","+rightside.getSafeSymbol()+");");
906         } else {
907             ((RelationExpr)expr.getLeftExpr()).getExpr().generate(cr,rightside);
908             expr.getRightExpr().generate(cr,newvalue);
909             cr.outputline(rd.getDomain().getType().getGenerateType().getSafeSymbol()+" "+leftside.getSafeSymbol()+";");
910             cr.outputline(rd.getSafeSymbol()+"_hashinv->get("+rightside.getSafeSymbol()+","+leftside.getSafeSymbol()+");");
911         }
912         if (negated)
913             if (opcode==Opcode.GT) {
914                 opcode=Opcode.LE;
915             } else if (opcode==Opcode.GE) {
916                 opcode=Opcode.LT;
917             } else if (opcode==Opcode.LT) {
918                 opcode=Opcode.GE;
919             } else if (opcode==Opcode.LE) {
920                 opcode=Opcode.GT;
921             } else if (opcode==Opcode.EQ) {
922                 opcode=Opcode.NE;
923             } else if (opcode==Opcode.NE) {
924                 opcode=Opcode.EQ;
925             } else {
926                 throw new Error("Unrecognized Opcode");
927             }
928
929         if (opcode==Opcode.GT) {
930             cr.outputline(newvalue.getSafeSymbol()+"++;");
931         } else if (opcode==Opcode.GE) {
932             /* Equal */
933         } else if (opcode==Opcode.LT) {
934             cr.outputline(newvalue.getSafeSymbol()+"--;");
935         } else if (opcode==Opcode.LE) {
936             /* Equal */
937         } else if (opcode==Opcode.EQ) {
938             /* Equal */
939         } else if (opcode==Opcode.NE) { /* search for FLAGNE if this is changed*/
940             cr.outputline(newvalue.getSafeSymbol()+"++;");
941         } else {
942             throw new Error("Unrecognized Opcode");
943         }
944         /* Do abstract repairs */
945         if (usageimage) {
946             cr.outputline(rd.getSafeSymbol()+"_hash->remove("+leftside.getSafeSymbol()+","+rightside.getSafeSymbol()+");");
947             if (!inverted) {
948                 cr.outputline(rd.getSafeSymbol()+"_hash->add("+leftside.getSafeSymbol()+","+newvalue.getSafeSymbol()+");");
949             } else {
950                 cr.outputline(rd.getSafeSymbol()+"_hash->add("+newvalue.getSafeSymbol()+","+rightside.getSafeSymbol()+");");
951             }
952         }
953         if (usageinvimage) {
954             cr.outputline(rd.getSafeSymbol()+"_hashinv->remove("+rightside.getSafeSymbol()+","+leftside.getSafeSymbol()+");");
955             if (!inverted) {
956                 cr.outputline(rd.getSafeSymbol()+"_hashinv->add("+newvalue.getSafeSymbol()+","+leftside.getSafeSymbol()+");");
957             } else {
958                 cr.outputline(rd.getSafeSymbol()+"_hashinv->add("+rightside.getSafeSymbol()+","+newvalue.getSafeSymbol()+");");
959             }
960         }
961         /* Do concrete repairs */
962         if (munmodify!=null) {
963             for(int i=0;i<state.vRules.size();i++) {
964                 Rule r=(Rule)state.vRules.get(i);
965                 if (r.getInclusion().getTargetDescriptors().contains(rd)) {
966                     for(int j=0;j<munmodify.numUpdates();j++) {
967                         UpdateNode un=munmodify.getUpdate(j);
968                         if (un.getRule()==r) {
969                             /* Update for rule r */
970                             String name=(String)updatenames.get(un);
971                             cr.outputline(repairtable.getSafeSymbol()+"->addrelation("+rd.getNum()+","+r.getNum()+","+leftside.getSafeSymbol()+","+rightside.getSafeSymbol()+",(int) &"+name+","+newvalue.getSafeSymbol()+");");
972                         }
973                     }
974                 }
975             }
976
977         } else {
978             /* Start with scheduling removal */
979             for(int i=0;i<state.vRules.size();i++) {
980                 Rule r=(Rule)state.vRules.get(i);
981                 if (r.getInclusion().getTargetDescriptors().contains(rd)) {
982                     for(int j=0;j<munremove.numUpdates();j++) {
983                         UpdateNode un=munremove.getUpdate(i);
984                         if (un.getRule()==r) {
985                             /* Update for rule r */
986                             String name=(String)updatenames.get(un);
987                             cr.outputline(repairtable.getSafeSymbol()+"->addrelation("+rd.getNum()+","+r.getNum()+","+leftside.getSafeSymbol()+","+rightside.getSafeSymbol()+",(int) &"+name+");");
988                         }
989                     }
990                 }
991             }
992             /* Now do addition */
993             UpdateNode un=munadd.getUpdate(0);
994             String name=(String)updatenames.get(un);
995             if (!inverted) {
996                 cr.outputline(name+"(this,"+newmodel.getSafeSymbol()+","+repairtable.getSafeSymbol()+","+leftside.getSafeSymbol()+","+newvalue.getSafeSymbol()+");");
997             } else {
998                 cr.outputline(name+"(this,"+newmodel.getSafeSymbol()+","+repairtable.getSafeSymbol()+","+newvalue.getSafeSymbol()+","+rightside.getSafeSymbol()+");");
999             }
1000         }
1001     }
1002
1003     public void generatesizerepair(Conjunction conj, DNFPredicate dpred, CodeWriter cr) {
1004         ExprPredicate ep=(ExprPredicate)dpred.getPredicate();
1005         OpExpr expr=(OpExpr)ep.expr;
1006         Opcode opcode=expr.getOpcode();
1007         opcode=Opcode.translateOpcode(dpred.isNegated(),opcode);
1008
1009         MultUpdateNode munremove;
1010
1011         MultUpdateNode munadd;
1012         if (ep.getDescriptor() instanceof RelationDescriptor) {
1013             munremove=getmultupdatenode(conj,dpred,AbstractRepair.REMOVEFROMRELATION);
1014             munadd=getmultupdatenode(conj,dpred,AbstractRepair.ADDTORELATION);
1015         } else {
1016             munremove=getmultupdatenode(conj,dpred,AbstractRepair.REMOVEFROMSET);
1017             munadd=getmultupdatenode(conj,dpred,AbstractRepair.ADDTOSET);
1018         }
1019         int size=ep.rightSize();
1020         VarDescriptor sizevar=VarDescriptor.makeNew("size");
1021         ((OpExpr)expr).left.generate(cr, sizevar);
1022         VarDescriptor change=VarDescriptor.makeNew("change");
1023         cr.outputline("int "+change.getSafeSymbol()+";");
1024         boolean generateadd=false;
1025         boolean generateremove=false;
1026         if (opcode==Opcode.GT) {
1027             cr.outputline(change.getSafeSymbol()+"="+String.valueOf(size+1)+"-"+sizevar.getSafeSymbol()+";");
1028             generateadd=true;
1029             generateremove=false;
1030         } else if (opcode==Opcode.GE) {
1031             cr.outputline(change.getSafeSymbol()+"="+String.valueOf(size)+"-"+sizevar.getSafeSymbol()+";");
1032             generateadd=true;
1033             generateremove=false;
1034         } else if (opcode==Opcode.LT) {
1035             cr.outputline(change.getSafeSymbol()+"="+String.valueOf(size-1)+"-"+sizevar.getSafeSymbol()+";");
1036             generateadd=false;
1037             generateremove=true;
1038         } else if (opcode==Opcode.LE) {
1039             cr.outputline(change.getSafeSymbol()+"="+String.valueOf(size)+"-"+sizevar.getSafeSymbol()+";");
1040             generateadd=false;
1041             generateremove=true;
1042         } else if (opcode==Opcode.EQ) {
1043             cr.outputline(change.getSafeSymbol()+"="+String.valueOf(size)+"-"+sizevar.getSafeSymbol()+";");
1044             if (size==0)
1045                 generateadd=false;
1046             else 
1047                 generateadd=true;
1048             generateremove=true;
1049         } else if (opcode==Opcode.NE) {
1050             cr.outputline(change.getSafeSymbol()+"="+String.valueOf(size+1)+"-"+sizevar.getSafeSymbol()+";");
1051             generateadd=true;
1052             generateremove=false;
1053         } else {
1054             throw new Error("Unrecognized Opcode");
1055         }
1056
1057 // In some cases the analysis has determined that generating removes
1058 // is unnecessary
1059         if (generateremove&&munremove==null) 
1060             generateremove=false;
1061
1062         Descriptor d=ep.getDescriptor();
1063         if (generateremove) {
1064             cr.outputline("for(;"+change.getSafeSymbol()+"<0;"+change.getSafeSymbol()+"++)");
1065             cr.startblock();
1066             /* Find element to remove */
1067             VarDescriptor leftvar=VarDescriptor.makeNew("leftvar");
1068             VarDescriptor rightvar=VarDescriptor.makeNew("rightvar");
1069             if (d instanceof RelationDescriptor) {
1070                 if (ep.inverted()) {
1071                     rightvar=((ImageSetExpr)((SizeofExpr)((OpExpr)expr).left).setexpr).getVar();
1072                     cr.outputline("int "+leftvar.getSafeSymbol()+";");
1073                     cr.outputline(d.getSafeSymbol()+"_hashinv->get((int)"+rightvar.getSafeSymbol()+","+leftvar.getSafeSymbol()+");");
1074                 } else {
1075                     leftvar=((ImageSetExpr)((SizeofExpr)((OpExpr)expr).left).setexpr).getVar();
1076                     cr.outputline("int "+rightvar.getSafeSymbol()+"=0;");
1077                     cr.outputline(d.getSafeSymbol()+"_hash->get((int)"+leftvar.getSafeSymbol()+","+rightvar.getSafeSymbol()+");");
1078                 }
1079             } else {
1080                 cr.outputline("int "+leftvar.getSafeSymbol()+"="+d.getSafeSymbol()+"_hash->firstkey();");
1081             }
1082             /* Generate abstract remove instruction */
1083             if (d instanceof RelationDescriptor) {
1084                 RelationDescriptor rd=(RelationDescriptor) d;
1085                 boolean usageimage=rd.testUsage(RelationDescriptor.IMAGE);
1086                 boolean usageinvimage=rd.testUsage(RelationDescriptor.INVIMAGE);
1087                 if (usageimage)
1088                     cr.outputline(rd.getSafeSymbol() + "_hash->remove((int)" + leftvar.getSafeSymbol() + ", (int)" + rightvar.getSafeSymbol() + ");");
1089                 if (usageinvimage)
1090                     cr.outputline(rd.getSafeSymbol() + "_hashinv->remove((int)" + rightvar.getSafeSymbol() + ", (int)" + leftvar.getSafeSymbol() + ");");
1091             } else {
1092                 cr.outputline(d.getSafeSymbol() + "_hash->remove((int)" + leftvar.getSafeSymbol() + ", (int)" + leftvar.getSafeSymbol() + ");");
1093             }
1094             /* Generate concrete remove instruction */
1095             for(int i=0;i<state.vRules.size();i++) {
1096                 Rule r=(Rule)state.vRules.get(i);
1097                 if (r.getInclusion().getTargetDescriptors().contains(d)) {
1098                     for(int j=0;j<munremove.numUpdates();j++) {
1099                         UpdateNode un=munremove.getUpdate(j);
1100                         if (un.getRule()==r) {
1101                                 /* Update for rule rule r */
1102                             String name=(String)updatenames.get(un);
1103                             if (d instanceof RelationDescriptor) {
1104                                 cr.outputline(repairtable.getSafeSymbol()+"->addrelation("+d.getNum()+","+r.getNum()+","+leftvar.getSafeSymbol()+","+rightvar.getSafeSymbol()+",(int) &"+name+");");
1105                             } else {
1106                                 cr.outputline(repairtable.getSafeSymbol()+"->addset("+d.getNum()+","+r.getNum()+","+leftvar.getSafeSymbol()+",(int) &"+name+");");
1107                             }
1108                         }
1109                     }
1110                 }
1111             }
1112             cr.endblock();
1113         }
1114         if (generateadd) {
1115
1116             cr.outputline("for(;"+change.getSafeSymbol()+">0;"+change.getSafeSymbol()+"--)");
1117             cr.startblock();
1118             VarDescriptor newobject=VarDescriptor.makeNew("newobject");
1119             if (d instanceof RelationDescriptor) {
1120                 VarDescriptor otherside=((ImageSetExpr)((SizeofExpr)((OpExpr)ep.expr).left).setexpr).vd;
1121                 RelationDescriptor rd=(RelationDescriptor)d;
1122                 if (termination.sources.relsetSource(rd,!ep.inverted())) {
1123                     /* Set Source */
1124                     SetDescriptor sd=termination.sources.relgetSourceSet(rd,!ep.inverted());
1125                     VarDescriptor iterator=VarDescriptor.makeNew("iterator");
1126                     cr.outputline(sd.getType().getGenerateType().getSafeSymbol() +" "+newobject.getSafeSymbol()+";");
1127                     cr.outputline("SimpleIterator "+iterator.getSafeSymbol()+";");
1128                     cr.outputline("for("+sd.getSafeSymbol()+"_hash->iterator("+ iterator.getSafeSymbol() +");"+iterator.getSafeSymbol()+".hasNext();)");
1129                     cr.startblock();
1130                     if (ep.inverted()) {
1131                         cr.outputline("if (!"+rd.getSafeSymbol()+"_hashinv->contains("+iterator.getSafeSymbol()+".key(),"+otherside.getSafeSymbol()+"))");
1132                     } else {
1133                         cr.outputline("if (!"+rd.getSafeSymbol()+"_hash->contains("+otherside.getSafeSymbol()+","+iterator.getSafeSymbol()+".key()))");
1134                     }
1135                     cr.outputline(newobject.getSafeSymbol()+"="+iterator.getSafeSymbol()+".key();");
1136                     cr.outputline(iterator.getSafeSymbol()+".next();");
1137                     cr.endblock();
1138                 } else if (termination.sources.relallocSource(rd,!ep.inverted())) {
1139                     /* Allocation Source*/
1140                     termination.sources.relgenerateSourceAlloc(cr,newobject,rd,!ep.inverted());
1141                 } else throw new Error("No source for adding to Relation");
1142                 if (ep.inverted()) {
1143                     boolean usageimage=rd.testUsage(RelationDescriptor.IMAGE);
1144                     boolean usageinvimage=rd.testUsage(RelationDescriptor.INVIMAGE);
1145                     if (usageimage)
1146                         cr.outputline(rd.getSafeSymbol()+"_hash->add("+newobject.getSafeSymbol()+","+otherside.getSafeSymbol()+");");
1147                     if (usageinvimage)
1148                         cr.outputline(rd.getSafeSymbol()+"_hashinv->add("+otherside.getSafeSymbol()+","+newobject.getSafeSymbol()+");");
1149
1150                     UpdateNode un=munadd.getUpdate(0);
1151                     String name=(String)updatenames.get(un);
1152                     cr.outputline(name+"(this,"+newmodel.getSafeSymbol()+","+repairtable.getSafeSymbol()+","+newobject.getSafeSymbol()+","+otherside.getSafeSymbol()+");");
1153                 } else {
1154                     boolean usageimage=rd.testUsage(RelationDescriptor.IMAGE);
1155                     boolean usageinvimage=rd.testUsage(RelationDescriptor.INVIMAGE);
1156                     if (usageimage)
1157                         cr.outputline(rd.getSafeSymbol()+"_hash->add("+otherside.getSafeSymbol()+","+newobject.getSafeSymbol()+");");
1158                     if (usageinvimage)
1159                         cr.outputline(rd.getSafeSymbol()+"_hashinv->add("+newobject.getSafeSymbol()+","+otherside.getSafeSymbol()+");");
1160                     UpdateNode un=munadd.getUpdate(0);
1161                     String name=(String)updatenames.get(un);
1162                     cr.outputline(name+"(this,"+newmodel.getSafeSymbol()+","+repairtable.getSafeSymbol()+","+otherside.getSafeSymbol()+","+newobject.getSafeSymbol()+");");
1163                 }
1164             } else {
1165                 SetDescriptor sd=(SetDescriptor)d;
1166                 if (termination.sources.setSource(sd)) {
1167                     /* Set Source */
1168                     /* Set Source */
1169                     SetDescriptor sourcesd=termination.sources.getSourceSet(sd);
1170                     VarDescriptor iterator=VarDescriptor.makeNew("iterator");
1171                     cr.outputline(sourcesd.getType().getGenerateType().getSafeSymbol() +" "+newobject.getSafeSymbol()+";");
1172                     cr.outputline("SimpleIterator "+iterator.getSafeSymbol()+";");
1173                     cr.outputline("for("+sourcesd.getSafeSymbol()+"_hash->iterator("+iterator.getSafeSymbol()+");"+iterator.getSafeSymbol()+".hasNext();)");
1174                     cr.startblock();
1175                     cr.outputline("if (!"+sd.getSafeSymbol()+"_hash->contains("+iterator.getSafeSymbol()+".key()))");
1176                     cr.outputline(newobject.getSafeSymbol()+"="+iterator.getSafeSymbol()+".key();");
1177                     cr.outputline(iterator.getSafeSymbol()+".next();");
1178                     cr.endblock();
1179                 } else if (termination.sources.allocSource(sd)) {
1180                     /* Allocation Source*/
1181                     termination.sources.generateSourceAlloc(cr,newobject,sd);
1182                 } else throw new Error("No source for adding to Set");
1183                 cr.outputline(sd.getSafeSymbol()+"_hash->add("+newobject.getSafeSymbol()+","+newobject.getSafeSymbol()+");");
1184                 UpdateNode un=munadd.getUpdate(0);
1185                 String name=(String)updatenames.get(un);
1186                 cr.outputline(name+"(this,"+newmodel.getSafeSymbol()+","+repairtable.getSafeSymbol()+","+newobject.getSafeSymbol()+");");
1187             }
1188             cr.endblock();
1189         }
1190     }
1191
1192     public void generateinclusionrepair(Conjunction conj, DNFPredicate dpred, CodeWriter cr){
1193         InclusionPredicate ip=(InclusionPredicate) dpred.getPredicate();
1194         boolean negated=dpred.isNegated();
1195         MultUpdateNode mun=getmultupdatenode(conj,dpred,-1);
1196         VarDescriptor leftvar=VarDescriptor.makeNew("left");
1197         ip.expr.generate(cr, leftvar);
1198
1199         if (negated) {
1200             if (ip.setexpr instanceof ImageSetExpr) {
1201                 ImageSetExpr ise=(ImageSetExpr) ip.setexpr;
1202                 VarDescriptor rightvar=ise.getVar();
1203                 boolean inverse=ise.inverted();
1204                 RelationDescriptor rd=ise.getRelation();
1205                 boolean usageimage=rd.testUsage(RelationDescriptor.IMAGE);
1206                 boolean usageinvimage=rd.testUsage(RelationDescriptor.INVIMAGE);
1207                 if (inverse) {
1208                     if (usageimage)
1209                         cr.outputline(rd.getSafeSymbol() + "_hash->remove((int)" + rightvar.getSafeSymbol() + ", (int)" + leftvar.getSafeSymbol() + ");");
1210                     if (usageinvimage)
1211                         cr.outputline(rd.getSafeSymbol() + "_hashinv->remove((int)" + leftvar.getSafeSymbol() + ", (int)" + rightvar.getSafeSymbol() + ");");
1212                 } else {
1213                     if (usageimage)
1214                         cr.outputline(rd.getSafeSymbol() + "_hash->remove((int)" + leftvar.getSafeSymbol() + ", (int)" + rightvar.getSafeSymbol() + ");");
1215                     if (usageinvimage)
1216                         cr.outputline(rd.getSafeSymbol() + "_hashinv->remove((int)" + rightvar.getSafeSymbol() + ", (int)" + leftvar.getSafeSymbol() + ");");
1217                 }
1218                 for(int i=0;i<state.vRules.size();i++) {
1219                     Rule r=(Rule)state.vRules.get(i);
1220                     if (r.getInclusion().getTargetDescriptors().contains(rd)) {
1221                         for(int j=0;j<mun.numUpdates();j++) {
1222                             UpdateNode un=mun.getUpdate(j);
1223                             if (un.getRule()==r) {
1224                                 /* Update for rule rule r */
1225                                 String name=(String)updatenames.get(un);
1226                                 if (inverse) {
1227                                     cr.outputline(repairtable.getSafeSymbol()+"->addrelation("+rd.getNum()+","+r.getNum()+","+rightvar.getSafeSymbol()+","+leftvar.getSafeSymbol()+",(int) &"+name+");");
1228                                 } else {
1229                                     cr.outputline(repairtable.getSafeSymbol()+"->addrelation("+rd.getNum()+","+r.getNum()+","+leftvar.getSafeSymbol()+","+rightvar.getSafeSymbol()+",(int) &"+name+");");
1230                                 }
1231                             }
1232                         }
1233                     }
1234                 }
1235             } else {
1236                 SetDescriptor sd=ip.setexpr.sd;
1237                 cr.outputline(sd.getSafeSymbol() + "_hash->remove((int)" + leftvar.getSafeSymbol() + ", (int)" + leftvar.getSafeSymbol() + ");");
1238
1239                 for(int i=0;i<state.vRules.size();i++) {
1240                     Rule r=(Rule)state.vRules.get(i);
1241                     if (r.getInclusion().getTargetDescriptors().contains(sd)) {
1242                         for(int j=0;j<mun.numUpdates();j++) {
1243                             UpdateNode un=mun.getUpdate(j);
1244                             if (un.getRule()==r) {
1245                                 /* Update for rule rule r */
1246                                 String name=(String)updatenames.get(un);
1247                                 cr.outputline(repairtable.getSafeSymbol()+"->addset("+sd.getNum()+","+r.getNum()+","+leftvar.getSafeSymbol()+",(int) &"+name+");");
1248                             }
1249                         }
1250                     }
1251                 }
1252             }
1253         } else {
1254             /* Generate update */
1255             if (ip.setexpr instanceof ImageSetExpr) {
1256                 ImageSetExpr ise=(ImageSetExpr) ip.setexpr;
1257                 VarDescriptor rightvar=ise.getVar();
1258                 boolean inverse=ise.inverted();
1259                 RelationDescriptor rd=ise.getRelation();
1260                 boolean usageimage=rd.testUsage(RelationDescriptor.IMAGE);
1261                 boolean usageinvimage=rd.testUsage(RelationDescriptor.INVIMAGE);
1262                 if (inverse) {
1263                     if (usageimage)
1264                         cr.outputline(rd.getSafeSymbol() + "_hash->add((int)" + rightvar.getSafeSymbol() + ", (int)" + leftvar.getSafeSymbol() + ");");
1265                     if (usageinvimage)
1266                         cr.outputline(rd.getSafeSymbol() + "_hashinv->add((int)" + leftvar.getSafeSymbol() + ", (int)" + rightvar.getSafeSymbol() + ");");
1267                 } else {
1268                     if (usageimage)
1269                         cr.outputline(rd.getSafeSymbol() + "_hash->add((int)" + leftvar.getSafeSymbol() + ", (int)" + rightvar.getSafeSymbol() + ");");
1270                     if (usageinvimage)
1271                         cr.outputline(rd.getSafeSymbol() + "_hashinv->add((int)" + rightvar.getSafeSymbol() + ", (int)" + leftvar.getSafeSymbol() + ");");
1272                 }
1273                 UpdateNode un=mun.getUpdate(0);
1274                 String name=(String)updatenames.get(un);
1275                 if (inverse) {
1276                     cr.outputline(name+"(this,"+newmodel.getSafeSymbol()+","+repairtable.getSafeSymbol()+","+rightvar.getSafeSymbol()+","+leftvar.getSafeSymbol()+");");
1277                 } else {
1278                     cr.outputline(name+"(this,"+newmodel.getSafeSymbol()+","+repairtable.getSafeSymbol()+","+leftvar.getSafeSymbol()+","+rightvar.getSafeSymbol()+");");
1279                 }
1280             } else {
1281                 SetDescriptor sd=ip.setexpr.sd;
1282                 cr.outputline(sd.getSafeSymbol() + "_hash->add((int)" + leftvar.getSafeSymbol() + ", (int)" + leftvar.getSafeSymbol() + ");");
1283
1284                 UpdateNode un=mun.getUpdate(0);
1285                 /* Update for rule rule r */
1286                 String name=(String)updatenames.get(un);
1287                 cr.outputline(name+"(this,"+newmodel.getSafeSymbol()+","+repairtable.getSafeSymbol()+","+leftvar.getSafeSymbol()+");");
1288             }
1289         }
1290     }
1291
1292     public static Vector getrulelist(Descriptor d) {
1293         Vector dispatchrules = new Vector();
1294         Vector rules = State.currentState.vRules;
1295
1296         for (int i = 0; i < rules.size(); i++) {
1297             Rule rule = (Rule) rules.elementAt(i);
1298             Set requiredsymbols = rule.getRequiredDescriptors();
1299             
1300             // #TBD#: in general this is wrong because these descriptors may contain descriptors
1301             // bound in "in?" expressions which need to be dealt with in a topologically sorted
1302             // fashion...
1303
1304             if (rule.getRequiredDescriptors().contains(d)) {
1305                 dispatchrules.addElement(rule);
1306             }
1307         }
1308         return dispatchrules;
1309     }
1310
1311     private boolean need_compensation(Rule r) {
1312         if (!Compiler.REPAIR)
1313             return false;
1314         GraphNode gn=(GraphNode)termination.scopefalsify.get(r);
1315         for(Iterator edgeit=gn.edges();edgeit.hasNext();) {
1316             GraphNode.Edge edge=(GraphNode.Edge)edgeit.next();
1317             GraphNode gn2=edge.getTarget();
1318             if (!removed.contains(gn2)) {
1319                 TermNode tn2=(TermNode)gn2.getOwner();
1320                 if (tn2.getType()==TermNode.CONSEQUENCE)
1321                     return false;
1322             }
1323         }
1324         return true;
1325     }
1326
1327     private UpdateNode find_compensation(Rule r) {
1328         GraphNode gn=(GraphNode)termination.scopefalsify.get(r);
1329         for(Iterator edgeit=gn.edges();edgeit.hasNext();) {
1330             GraphNode.Edge edge=(GraphNode.Edge)edgeit.next();
1331             GraphNode gn2=edge.getTarget();
1332             if (!removed.contains(gn2)) {
1333                 TermNode tn2=(TermNode)gn2.getOwner();
1334                 if (tn2.getType()==TermNode.UPDATE) {
1335                     MultUpdateNode mun=tn2.getUpdate();
1336                     for(int i=0;i<mun.numUpdates();i++) {
1337                         UpdateNode un=mun.getUpdate(i);
1338                         if (un.getRule()==r)
1339                             return un;
1340                     }
1341                 }
1342             }
1343         }
1344         throw new Error("No Compensation Update could be found");
1345     }
1346
1347     public void generate_dispatch(CodeWriter cr, RelationDescriptor rd, String leftvar, String rightvar) {
1348         boolean usageimage=rd.testUsage(RelationDescriptor.IMAGE);
1349         boolean usageinvimage=rd.testUsage(RelationDescriptor.INVIMAGE);
1350
1351         if (!(usageinvimage||usageimage)) /* not used at all*/
1352             return;
1353
1354         cr.outputline("// RELATION DISPATCH ");
1355         if (Compiler.REPAIR) {
1356             cr.outputline("if ("+oldmodel.getSafeSymbol()+"&&");
1357             if (usageimage)
1358                 cr.outputline("!"+oldmodel.getSafeSymbol() +"->"+rd.getJustSafeSymbol()+"_hash->contains("+leftvar+","+rightvar+"))");
1359             else
1360                 cr.outputline("!"+oldmodel.getSafeSymbol() +"->"+rd.getJustSafeSymbol()+"_hashinv->contains("+rightvar+","+leftvar+"))");
1361
1362             cr.startblock(); {
1363                 /* Adding new item */
1364                 /* Perform safety checks */
1365                 cr.outputline("if ("+repairtable.getSafeSymbol()+"&&");
1366                 cr.outputline(repairtable.getSafeSymbol()+"->containsrelation("+rd.getNum()+","+currentrule.getNum()+","+leftvar+","+rightvar+"))");
1367                 cr.startblock(); {
1368                     /* Have update to call into */
1369                     VarDescriptor mdfyptr=VarDescriptor.makeNew("modifyptr");
1370                     cr.outputline("int "+mdfyptr.getSafeSymbol()+"="+repairtable.getSafeSymbol()+"->getrelation2("+rd.getNum()+","+currentrule.getNum()+","+leftvar+","+rightvar+");");
1371                     
1372                     String parttype="";
1373                     for(int i=0;i<currentrule.numQuantifiers();i++) {
1374                         if (currentrule.getQuantifier(i) instanceof RelationQuantifier)
1375                             parttype=parttype+", int, int";
1376                         else
1377                             parttype=parttype+", int";
1378                     }
1379                     VarDescriptor funptr=VarDescriptor.makeNew("updateptr");
1380                     VarDescriptor tmpptr=VarDescriptor.makeNew("tempupdateptr");
1381                     
1382                     String methodcall="("+funptr.getSafeSymbol()+") (this,"+oldmodel.getSafeSymbol()+","+repairtable.getSafeSymbol();
1383                     for(int i=0;i<currentrule.numQuantifiers();i++) {
1384                         Quantifier q=currentrule.getQuantifier(i);
1385                         if (q instanceof SetQuantifier) {
1386                             SetQuantifier sq=(SetQuantifier) q;
1387                             methodcall+=","+sq.getVar().getSafeSymbol();
1388                         } else if (q instanceof RelationQuantifier) {
1389                             RelationQuantifier rq=(RelationQuantifier) q;
1390                             methodcall+=","+rq.x.getSafeSymbol();
1391                             methodcall+=","+rq.y.getSafeSymbol();
1392                         } else if (q instanceof ForQuantifier) {
1393                             ForQuantifier fq=(ForQuantifier) q;
1394                             methodcall+=","+fq.getVar().getSafeSymbol();
1395                         }
1396                     }
1397                     
1398                     
1399                     
1400                     cr.outputline("void *"+tmpptr.getSafeSymbol()+"=");
1401                     cr.outputline("(void *) "+repairtable.getSafeSymbol()+"->getrelation("+rd.getNum()+","+currentrule.getNum()+","+leftvar+","+rightvar+");");
1402                     cr.outputline("if ("+mdfyptr.getSafeSymbol()+")");
1403                     {
1404                         cr.startblock();
1405                         cr.outputline("void (*"+funptr.getSafeSymbol()+") ("+name+"_state *,"+name+"*,RepairHash *"+parttype+",int,int,int)="+"(void (*) ("+name+"_state *,"+name+"*,RepairHash *"+parttype+",int,int,int)) "+tmpptr.getSafeSymbol()+";");
1406                         cr.outputline(methodcall+","+leftvar+", "+rightvar+", "+mdfyptr.getSafeSymbol() +");");
1407                         cr.endblock();
1408                     }
1409                     cr.outputline("else ");
1410                     {
1411                         cr.startblock();
1412                         cr.outputline("void (*"+funptr.getSafeSymbol()+") ("+name+"_state *,"+name+"*,RepairHash *"+parttype+")="+"(void (*) ("+name+"_state *,"+name+"*,RepairHash *"+parttype+")) "+tmpptr.getSafeSymbol()+";");
1413                         cr.outputline(methodcall+");");
1414                         cr.endblock();
1415                     }
1416                     cr.outputline("delete "+newmodel.getSafeSymbol()+";");
1417                     cr.outputline("goto rebuild;");
1418                 }
1419                 cr.endblock();
1420                 
1421                 /* Build standard compensation actions */
1422                 if (need_compensation(currentrule)) {
1423                     UpdateNode un=find_compensation(currentrule);
1424                     String name=(String)updatenames.get(un);
1425                     usedupdates.add(un); /* Mark as used */
1426                     String methodcall=name+"(this,"+oldmodel.getSafeSymbol()+","+repairtable.getSafeSymbol();
1427                     for(int i=0;i<currentrule.numQuantifiers();i++) {
1428                         Quantifier q=currentrule.getQuantifier(i);
1429                         if (q instanceof SetQuantifier) {
1430                             SetQuantifier sq=(SetQuantifier) q;
1431                             methodcall+=","+sq.getVar().getSafeSymbol();
1432                         } else if (q instanceof RelationQuantifier) {
1433                             RelationQuantifier rq=(RelationQuantifier) q;
1434                             methodcall+=","+rq.x.getSafeSymbol();
1435                             methodcall+=","+rq.y.getSafeSymbol();
1436                         } else if (q instanceof ForQuantifier) {
1437                             ForQuantifier fq=(ForQuantifier) q;
1438                             methodcall+=","+fq.getVar().getSafeSymbol();
1439                         }
1440                     }
1441                     methodcall+=");";
1442                     cr.outputline(methodcall);
1443                     cr.outputline("delete "+newmodel.getSafeSymbol()+";");
1444                     cr.outputline("goto rebuild;");
1445                 }
1446             }
1447             cr.endblock();
1448         }
1449
1450         String addeditem = (VarDescriptor.makeNew("addeditem")).getSafeSymbol();
1451         cr.outputline("int " + addeditem + "=0;");
1452
1453         String ifstring="if (!maybe&&";
1454         boolean dogenerate=false;
1455         if (rd.getDomain().getType() instanceof StructureTypeDescriptor)  {
1456             dogenerate=true;
1457             ifstring+=leftvar;
1458         }
1459
1460         if (rd.getRange().getType() instanceof StructureTypeDescriptor)  {
1461             if (dogenerate)
1462                 ifstring+="&&"+rightvar;
1463             else
1464                 ifstring+=rightvar;
1465             dogenerate=true;
1466         }
1467
1468         ifstring+=")";
1469
1470         if (rd.testUsage(RelationDescriptor.IMAGE)) {
1471             cr.outputline(ifstring);
1472             cr.outputline(addeditem + " = " + rd.getSafeSymbol() + "_hash->add((int)" + leftvar + ", (int)" + rightvar+ ");");
1473         }
1474         
1475         if (rd.testUsage(RelationDescriptor.INVIMAGE)) {
1476             cr.outputline(ifstring);
1477             cr.outputline(addeditem + " = " + rd.getSafeSymbol() + "_hashinv->add((int)" + rightvar + ", (int)" + leftvar + ");");
1478         }
1479         
1480
1481         Vector dispatchrules = getrulelist(rd);
1482         
1483         Set toremove=new HashSet();
1484         for(int i=0;i<dispatchrules.size();i++) {
1485             Rule r=(Rule)dispatchrules.get(i);
1486             if (!ruleset.contains(r))
1487                 toremove.add(r);
1488         }
1489         dispatchrules.removeAll(toremove);
1490         if (dispatchrules.size() == 0) {
1491             cr.outputline("// nothing to dispatch");
1492             return;
1493         }
1494
1495         cr.outputline("if (" + addeditem + ")");
1496         cr.startblock();
1497        
1498         for(int i = 0; i < dispatchrules.size(); i++) {
1499             Rule rule = (Rule) dispatchrules.elementAt(i);
1500             if (rule.getGuardExpr().getRequiredDescriptors().contains(rd)) {
1501                 /* Guard depends on this relation, so we recomput everything */
1502                 cr.outputline(worklist.getSafeSymbol()+"->add("+rule.getNum()+",-1,0,0);");
1503             } else {
1504                 for (int j=0;j<rule.numQuantifiers();j++) {
1505                     Quantifier q=rule.getQuantifier(j);
1506                     if (q.getRequiredDescriptors().contains(rd)) {
1507                         /* Generate add */
1508                         cr.outputline(worklist.getSafeSymbol()+"->add("+rule.getNum()+","+j+","+leftvar+","+rightvar+");");
1509                     }
1510                 }
1511             }
1512         }
1513
1514         cr.endblock();
1515     }
1516
1517
1518     public void generate_dispatch(CodeWriter cr, SetDescriptor sd, String setvar) {
1519                
1520         cr.outputline("// SET DISPATCH ");
1521         if (Compiler.REPAIR) {
1522             cr.outputline("if ("+oldmodel.getSafeSymbol()+"&&");
1523             cr.outputline("!"+oldmodel.getSafeSymbol() +"->"+sd.getJustSafeSymbol()+"_hash->contains("+setvar+"))");
1524             cr.startblock(); {
1525                 /* Adding new item */
1526                 /* Perform safety checks */
1527                 cr.outputline("if ("+repairtable.getSafeSymbol()+"&&");
1528                 cr.outputline(repairtable.getSafeSymbol()+"->containsset("+sd.getNum()+","+currentrule.getNum()+","+setvar+"))");
1529                 cr.startblock(); {
1530                     /* Have update to call into */
1531                     VarDescriptor funptr=VarDescriptor.makeNew("updateptr");
1532                     String parttype="";
1533                     for(int i=0;i<currentrule.numQuantifiers();i++) {
1534                         if (currentrule.getQuantifier(i) instanceof RelationQuantifier)
1535                             parttype=parttype+", int, int";
1536                         else
1537                             parttype=parttype+", int";
1538                     }
1539                     cr.outputline("void (*"+funptr.getSafeSymbol()+") ("+name+"_state *,"+name+"*,RepairHash *"+parttype+")=");
1540                     cr.outputline("(void (*) ("+name+"_state *,"+name+"*,RepairHash *"+parttype+")) "+repairtable.getSafeSymbol()+"->getset("+sd.getNum()+","+currentrule.getNum()+","+setvar+");");
1541                     String methodcall="("+funptr.getSafeSymbol()+") (this,"+oldmodel.getSafeSymbol()+","+
1542                         repairtable.getSafeSymbol();
1543                     for(int i=0;i<currentrule.numQuantifiers();i++) {
1544                         Quantifier q=currentrule.getQuantifier(i);
1545                         if (q instanceof SetQuantifier) {
1546                             SetQuantifier sq=(SetQuantifier) q;
1547                             methodcall+=","+sq.getVar().getSafeSymbol();
1548                         } else if (q instanceof RelationQuantifier) {
1549                             RelationQuantifier rq=(RelationQuantifier) q;
1550                             methodcall+=","+rq.x.getSafeSymbol();
1551                             methodcall+=","+rq.y.getSafeSymbol();
1552                         } else if (q instanceof ForQuantifier) {
1553                             ForQuantifier fq=(ForQuantifier) q;
1554                             methodcall+=","+fq.getVar().getSafeSymbol();
1555                         }
1556                     }
1557                     methodcall+=");";
1558                     cr.outputline(methodcall);
1559                     cr.outputline("delete "+newmodel.getSafeSymbol()+";");
1560                     cr.outputline("goto rebuild;");
1561                 }
1562                 cr.endblock();
1563                 /* Build standard compensation actions */
1564                 if (need_compensation(currentrule)) {
1565                     UpdateNode un=find_compensation(currentrule);
1566                     String name=(String)updatenames.get(un);
1567                     usedupdates.add(un); /* Mark as used */
1568                     
1569                     String methodcall=name+"(this,"+oldmodel.getSafeSymbol()+","+
1570                         repairtable.getSafeSymbol();
1571                     for(int i=0;i<currentrule.numQuantifiers();i++) {
1572                         Quantifier q=currentrule.getQuantifier(i);
1573                         if (q instanceof SetQuantifier) {
1574                             SetQuantifier sq=(SetQuantifier) q;
1575                             methodcall+=","+sq.getVar().getSafeSymbol();
1576                         } else if (q instanceof RelationQuantifier) {
1577                             RelationQuantifier rq=(RelationQuantifier) q;
1578                             methodcall+=","+rq.x.getSafeSymbol();
1579                             methodcall+=","+rq.y.getSafeSymbol();
1580                         } else if (q instanceof ForQuantifier) {
1581                             ForQuantifier fq=(ForQuantifier) q;
1582                             methodcall+=","+fq.getVar().getSafeSymbol();
1583                         }
1584                     }
1585                     methodcall+=");";
1586                     cr.outputline(methodcall);
1587                     cr.outputline("delete "+newmodel.getSafeSymbol()+";");
1588                     cr.outputline("goto rebuild;");
1589                 }
1590             }
1591             cr.endblock();
1592         }
1593
1594         String addeditem = (VarDescriptor.makeNew("addeditem")).getSafeSymbol();
1595         cr.outputline("int " + addeditem + " = 0;");
1596         if (sd.getType() instanceof StructureTypeDescriptor)  {
1597             cr.outputline("if (!maybe&&"+setvar+")");
1598         } else
1599             cr.outputline("if (!maybe)");
1600         cr.outputline(addeditem + " = " + sd.getSafeSymbol() + "_hash->add((int)" + setvar +  ", (int)" + setvar + ");");
1601         cr.startblock();
1602         Vector dispatchrules = getrulelist(sd);
1603
1604         Set toremove=new HashSet();
1605         for(int i=0;i<dispatchrules.size();i++) {
1606             Rule r=(Rule)dispatchrules.get(i);
1607             if (!ruleset.contains(r))
1608                 toremove.add(r);
1609         }
1610         dispatchrules.removeAll(toremove);
1611
1612         if (dispatchrules.size() == 0) {
1613             cr.outputline("// nothing to dispatch");
1614             cr.endblock();
1615             return;
1616         }
1617         cr.outputline("if ("+addeditem+")");
1618         cr.startblock();
1619         for(int i = 0; i < dispatchrules.size(); i++) {
1620             Rule rule = (Rule) dispatchrules.elementAt(i);
1621             if (SetDescriptor.expand(rule.getGuardExpr().getRequiredDescriptors()).contains(sd)) {
1622                 /* Guard depends on this relation, so we recompute everything */
1623                 cr.outputline(worklist.getSafeSymbol()+"->add("+rule.getNum()+",-1,0,0);");
1624             } else {
1625                 for (int j=0;j<rule.numQuantifiers();j++) {
1626                     Quantifier q=rule.getQuantifier(j);
1627                     if (SetDescriptor.expand(q.getRequiredDescriptors()).contains(sd)) {
1628                         /* Generate add */
1629                         cr.outputline(worklist.getSafeSymbol()+"->add("+rule.getNum()+","+j+","+setvar+",0);");
1630                     }
1631                 }
1632             }
1633         }
1634         cr.endblock();
1635         cr.endblock();
1636     }
1637 }