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