These checking do the reconstruction of the model and invoke concrete repairs.
[repair.git] / Repair / RepairCompiler / MCC / IR / RepairGenerator.java
1 package MCC.IR;
2
3 import java.io.*;
4 import java.util.*;
5 import MCC.State;
6
7 public class RepairGenerator {
8
9     State state;
10     java.io.PrintWriter outputrepair = null;
11     java.io.PrintWriter outputaux = null;
12     java.io.PrintWriter outputhead = null;
13     String name="foo";
14     String headername;
15     static VarDescriptor oldmodel=null;
16     static VarDescriptor newmodel=null;
17     static VarDescriptor worklist=null;
18     static VarDescriptor repairtable=null;
19     static VarDescriptor goodflag=null;
20     Rule currentrule=null;
21     Hashtable updatenames;
22     HashSet usedupdates;
23     Termination termination;
24     Set removed;
25
26     public RepairGenerator(State state, Termination t) {
27         this.state = state;
28         updatenames=new Hashtable();
29         usedupdates=new HashSet();
30         termination=t;
31         removed=t.removedset;
32         Repair.repairgenerator=this;
33     }
34
35     private void name_updates() {
36         int count=0;
37         for(Iterator it=termination.updatenodes.iterator();it.hasNext();) {
38             GraphNode gn=(GraphNode) it.next();
39             TermNode tn=(TermNode) gn.getOwner();
40             MultUpdateNode mun=tn.getUpdate();
41             for (int i=0;i<mun.numUpdates();i++) {
42                 UpdateNode un=mun.getUpdate(i);
43                 String name="update"+String.valueOf(count++);
44                 updatenames.put(un,name);
45             }
46         }
47     }
48
49     public void generate(OutputStream outputrepair, OutputStream outputaux,OutputStream outputhead, String st) {
50         this.outputrepair = new java.io.PrintWriter(outputrepair, true); 
51         this.outputaux = new java.io.PrintWriter(outputaux, true); 
52         this.outputhead = new java.io.PrintWriter(outputhead, true); 
53         headername=st;
54         name_updates();
55
56         generate_tokentable();
57         generate_hashtables();
58         generate_stateobject();
59         generate_call();
60         generate_worklist();
61         generate_rules();/*
62         generate_checks();
63         generate_teardown();*/
64     }
65
66     
67
68     private void generate_call() {
69         CodeWriter cr = new StandardCodeWriter(outputrepair);        
70         VarDescriptor vdstate=VarDescriptor.makeNew("repairstate");
71         cr.outputline(name+"_state * "+vdstate.getSafeSymbol()+"=new "+name+"_state();");
72         Iterator globals=state.stGlobals.descriptors();
73         while (globals.hasNext()) {
74             VarDescriptor vd=(VarDescriptor) globals.next();
75             cr.outputline(vdstate.getSafeSymbol()+"->"+vd.getSafeSymbol()+"=("+vd.getType().getGenerateType().getSafeSymbol()+")"+vd.getSafeSymbol()+";");
76         }
77         /* Insert repair here */
78         cr.outputline(vdstate.getSafeSymbol()+"->doanalysis();");
79         globals=state.stGlobals.descriptors();
80         while (globals.hasNext()) {
81             VarDescriptor vd=(VarDescriptor) globals.next();
82             cr.outputline("*(("+vd.getType().getGenerateType().getSafeSymbol()+"*) &"+vd.getSafeSymbol()+")="+vdstate.getSafeSymbol()+"->"+vd.getSafeSymbol()+";");
83         }
84         cr.outputline("delete "+vdstate.getSafeSymbol()+";");
85     }
86
87     private void generate_tokentable() {
88         CodeWriter cr = new StandardCodeWriter(outputrepair);        
89         Iterator tokens = TokenLiteralExpr.tokens.keySet().iterator();        
90
91         cr.outputline("");
92         cr.outputline("// Token values");
93         cr.outputline("");
94
95         while (tokens.hasNext()) {
96             Object token = tokens.next();
97             cr.outputline("// " + token.toString() + " = " + TokenLiteralExpr.tokens.get(token).toString());            
98         }
99
100         cr.outputline("");
101         cr.outputline("");
102     }
103
104     private void generate_stateobject() {
105         CodeWriter crhead = new StandardCodeWriter(outputhead);
106         crhead.outputline("class "+name+"_state {");
107         crhead.outputline("public:");
108         Iterator globals=state.stGlobals.descriptors();
109         while (globals.hasNext()) {
110             VarDescriptor vd=(VarDescriptor) globals.next();
111             crhead.outputline(vd.getType().getGenerateType().getSafeSymbol()+" "+vd.getSafeSymbol()+";");
112         }
113     }
114
115     private void generate_hashtables() {
116         CodeWriter craux = new StandardCodeWriter(outputaux);
117         CodeWriter crhead = new StandardCodeWriter(outputhead);
118         crhead.outputline("#include \"SimpleHash.h\"");
119         crhead.outputline("class "+name+" {");
120         crhead.outputline("public:");
121         crhead.outputline(name+"();");
122         crhead.outputline("~"+name+"();");
123         craux.outputline("#include \""+headername+"\"");
124
125         craux.outputline(name+"::"+name+"() {");
126         craux.outputline("// creating hashtables ");
127         
128         /* build sets */
129         Iterator sets = state.stSets.descriptors();
130         
131         /* first pass create all the hash tables */
132         while (sets.hasNext()) {
133             SetDescriptor set = (SetDescriptor) sets.next();
134             crhead.outputline("SimpleHash* " + set.getSafeSymbol() + "_hash;");
135             craux.outputline(set.getSafeSymbol() + "_hash = new SimpleHash();");
136         }
137         
138         /* second pass build relationships between hashtables */
139         sets = state.stSets.descriptors();
140         
141         while (sets.hasNext()) {
142             SetDescriptor set = (SetDescriptor) sets.next();
143             Iterator subsets = set.subsets();
144             
145             while (subsets.hasNext()) {
146                 SetDescriptor subset = (SetDescriptor) subsets.next();                
147                 craux.outputline(subset.getSafeSymbol() + "_hash->addParent(" + set.getSafeSymbol() + "_hash);");
148             }
149         } 
150
151         /* build relations */
152         Iterator relations = state.stRelations.descriptors();
153         
154         /* first pass create all the hash tables */
155         while (relations.hasNext()) {
156             RelationDescriptor relation = (RelationDescriptor) relations.next();
157             
158             if (relation.testUsage(RelationDescriptor.IMAGE)) {
159                 crhead.outputline("SimpleHash* " + relation.getSafeSymbol() + "_hash;");
160                 craux.outputline(relation.getSafeSymbol() + "_hash = new SimpleHash();");
161             }
162
163             if (relation.testUsage(RelationDescriptor.INVIMAGE)) {
164                 crhead.outputline("SimpleHash* " + relation.getSafeSymbol() + "_hashinv;");
165                 craux.outputline(relation.getSafeSymbol() + "_hashinv = new SimpleHash();");
166             } 
167         }
168
169         craux.outputline("}");
170         crhead.outputline("};");
171         craux.outputline(name+"::~"+name+"() {");
172         craux.outputline("// deleting hashtables");
173
174         /* build destructor */
175         sets = state.stSets.descriptors();
176         
177         /* first pass create all the hash tables */
178         while (sets.hasNext()) {
179             SetDescriptor set = (SetDescriptor) sets.next();
180             craux.outputline("delete "+set.getSafeSymbol() + "_hash;");
181         } 
182         
183         /* destroy relations */
184         relations = state.stRelations.descriptors();
185         
186         /* first pass create all the hash tables */
187         while (relations.hasNext()) {
188             RelationDescriptor relation = (RelationDescriptor) relations.next();
189             
190             if (relation.testUsage(RelationDescriptor.IMAGE)) {
191                 craux.outputline("delete "+relation.getSafeSymbol() + "_hash;");
192             }
193
194             if (relation.testUsage(RelationDescriptor.INVIMAGE)) {
195                 craux.outputline("delete " + relation.getSafeSymbol() + ";");
196             } 
197         }
198         craux.outputline("}");
199     }
200
201     private void generate_worklist() {
202         CodeWriter crhead = new StandardCodeWriter(outputhead);
203         CodeWriter craux = new StandardCodeWriter(outputaux);
204         oldmodel=VarDescriptor.makeNew("oldmodel");
205         newmodel=VarDescriptor.makeNew("newmodel");
206         worklist=VarDescriptor.makeNew("worklist");
207         goodflag=VarDescriptor.makeNew("goodflag");
208         repairtable=VarDescriptor.makeNew("repairtable");
209         crhead.outputline("void doanalysis();");
210         craux.outputline("void "+name +"_state::doanalysis() {");
211         craux.outputline(name+ " * "+oldmodel.getSafeSymbol()+"=0;");
212         craux.outputline("WorkList * "+worklist.getSafeSymbol()+" = new WorkList();");
213         craux.outputline("RepairHash * "+repairtable.getSafeSymbol()+"=0;");
214         craux.outputline("while (1) {");
215         craux.outputline("int "+goodflag.getSafeSymbol()+"=1;");
216         craux.outputline(name+ " * "+newmodel.getSafeSymbol()+"=new "+name+"();");
217     }
218     
219     private void generate_teardown() {
220         CodeWriter cr = new StandardCodeWriter(outputaux);        
221         cr.outputline("delete "+worklist.getSafeSymbol()+";");
222     }
223
224     private void generate_rules() {
225         /* first we must sort the rules */
226         Iterator allrules = state.vRules.iterator();
227         Vector emptyrules = new Vector(); // rules with no quantifiers
228         Vector worklistrules = new Vector(); // the rest of the rules
229         RelationDescriptor.prefix = newmodel.getSafeSymbol()+"->";
230         SetDescriptor.prefix = newmodel.getSafeSymbol()+"->";
231
232         while (allrules.hasNext()) {
233             Rule rule = (Rule) allrules.next();
234             ListIterator quantifiers = rule.quantifiers();
235             boolean noquantifiers = true;
236             while (quantifiers.hasNext()) {
237                 Quantifier quantifier = (Quantifier) quantifiers.next();
238                 if (quantifier instanceof ForQuantifier) {
239                     // ok, because integers exist already!
240                 } else {
241                     // real quantifier
242                     noquantifiers = false;
243                     break;
244                 }
245             }
246             if (noquantifiers) {
247                 emptyrules.add(rule);
248             } else {
249                 worklistrules.add(rule);
250             }
251         }
252        
253         Iterator iterator_er = emptyrules.iterator();
254         while (iterator_er.hasNext()) {
255             Rule rule = (Rule) iterator_er.next();
256             {
257                 final SymbolTable st = rule.getSymbolTable();                
258                 CodeWriter cr = new StandardCodeWriter(outputaux) {
259                         public SymbolTable getSymbolTable() { return st; }
260                     };
261                 cr.outputline("// build " + rule.getLabel());
262                 cr.startblock();
263                 ListIterator quantifiers = rule.quantifiers();
264                 while (quantifiers.hasNext()) {
265                     Quantifier quantifier = (Quantifier) quantifiers.next();
266                     quantifier.generate_open(cr);
267                 }
268                         
269                 /* pretty print! */
270                 cr.output("//");
271                 rule.getGuardExpr().prettyPrint(cr);
272                 cr.outputline("");
273
274                 /* now we have to generate the guard test */
275                 VarDescriptor guardval = VarDescriptor.makeNew();
276                 rule.getGuardExpr().generate(cr, guardval);
277                 cr.outputline("if (" + guardval.getSafeSymbol() + ")");
278                 cr.startblock();
279
280                 /* now we have to generate the inclusion code */
281                 currentrule=rule;
282                 rule.getInclusion().generate(cr);
283                 cr.endblock();
284                 while (quantifiers.hasPrevious()) {
285                     Quantifier quantifier = (Quantifier) quantifiers.previous();
286                     cr.endblock();
287                 }
288                 cr.endblock();
289                 cr.outputline("");
290                 cr.outputline("");
291             }
292         }
293
294         CodeWriter cr2 = new StandardCodeWriter(outputaux);        
295
296         cr2.outputline("while ("+goodflag.getSafeSymbol()+"&&"+worklist.getSafeSymbol()+"->hasMoreElements())");
297         cr2.startblock();
298         VarDescriptor idvar=VarDescriptor.makeNew("id");
299         cr2.outputline("int "+idvar.getSafeSymbol()+"="+worklist.getSafeSymbol()+"->getid();");
300         
301         String elseladder = "if";
302
303         Iterator iterator_rules = worklistrules.iterator();
304         while (iterator_rules.hasNext()) {
305
306             Rule rule = (Rule) iterator_rules.next();
307             int dispatchid = rule.getNum();
308
309             {
310                 final SymbolTable st = rule.getSymbolTable();
311                 CodeWriter cr = new StandardCodeWriter(outputaux) {
312                         public SymbolTable getSymbolTable() { return st; }
313                     };
314
315                 cr.indent();
316                 cr.outputline(elseladder + " ("+idvar.getSafeSymbol()+" == " + dispatchid + ")");
317                 cr.startblock();
318                 VarDescriptor typevar=VarDescriptor.makeNew("type");
319                 VarDescriptor leftvar=VarDescriptor.makeNew("left");
320                 VarDescriptor rightvar=VarDescriptor.makeNew("right");
321                 cr.outputline("int "+typevar.getSafeSymbol()+"="+worklist.getSafeSymbol()+"->gettype();");
322                 cr.outputline("int "+leftvar.getSafeSymbol()+"="+worklist.getSafeSymbol()+"->getlvalue();");
323                 cr.outputline("int "+rightvar.getSafeSymbol()+"="+worklist.getSafeSymbol()+"->getrvalue();");
324                 cr.outputline("// build " + rule.getLabel());
325
326
327                 for (int j=0;j<rule.numQuantifiers();j++) {
328                     Quantifier quantifier = rule.getQuantifier(j);
329                     quantifier.generate_open(cr, typevar.getSafeSymbol(),j,leftvar.getSafeSymbol(),rightvar.getSafeSymbol());
330                 }
331
332                 /* pretty print! */
333                 cr.output("//");
334
335                 rule.getGuardExpr().prettyPrint(cr);
336                 cr.outputline("");
337
338                 /* now we have to generate the guard test */
339         
340                 VarDescriptor guardval = VarDescriptor.makeNew();
341                 rule.getGuardExpr().generate(cr, guardval);
342                 
343                 cr.outputline("if (" + guardval.getSafeSymbol() + ")");
344                 cr.startblock();
345
346                 /* now we have to generate the inclusion code */
347                 currentrule=rule;
348                 rule.getInclusion().generate(cr);
349                 cr.endblock();
350
351                 for (int j=0;j<rule.numQuantifiers();j++) {
352                     cr.endblock();
353                 }
354
355                 // close startblocks generated by DotExpr memory checks
356                 //DotExpr.generate_memory_endblocks(cr);
357
358                 cr.endblock(); // end else-if WORKLIST ladder
359
360                 elseladder = "else if";
361             }
362         }
363
364         cr2.outputline("else");
365         cr2.startblock();
366         cr2.outputline("printf(\"VERY BAD !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\\n\\n\");");
367         cr2.outputline("exit(1);");
368         cr2.endblock();
369         // end block created for worklist
370         cr2.endblock();
371     }
372
373     private void generate_checks() {
374
375         /* do constraint checks */
376         Vector constraints = state.vConstraints;
377
378         for (int i = 0; i < constraints.size(); i++) {
379
380             Constraint constraint = (Constraint) constraints.elementAt(i); 
381
382             {
383
384                 final SymbolTable st = constraint.getSymbolTable();
385                 
386                 CodeWriter cr = new StandardCodeWriter(outputaux) {
387                         public SymbolTable getSymbolTable() { return st; }
388                     };
389                 
390                 cr.outputline("// checking " + constraint.getLabel());
391                 cr.startblock();
392
393                 ListIterator quantifiers = constraint.quantifiers();
394
395                 while (quantifiers.hasNext()) {
396                     Quantifier quantifier = (Quantifier) quantifiers.next();                   
397                     quantifier.generate_open(cr);
398                 }            
399
400                 cr.outputline("int maybe = 0;");
401                         
402                 /* now we have to generate the guard test */
403         
404                 VarDescriptor constraintboolean = VarDescriptor.makeNew("constraintboolean");
405                 constraint.getLogicStatement().generate(cr, constraintboolean);
406                 
407                 cr.outputline("if (maybe)");
408                 cr.startblock();
409                 cr.outputline("__Success = 0;");
410                 cr.outputline("printf(\"maybe fail " + (i+1) + ". \");");
411                 cr.outputline("exit(1);");
412                 cr.endblock();
413
414                 cr.outputline("else if (!" + constraintboolean.getSafeSymbol() + ")");
415                 cr.startblock();
416
417                 cr.outputline("__Success = 0;");
418                 cr.outputline("printf(\"fail " + (i+1) + ". \");");
419                 cr.outputline("exit(1);");
420                 cr.endblock();
421
422                 while (quantifiers.hasPrevious()) {
423                     Quantifier quantifier = (Quantifier) quantifiers.previous();
424                     cr.endblock();
425                 }
426
427                 cr.endblock();
428                 cr.outputline("");
429                 cr.outputline("");
430             }          
431         }
432         outputaux.println("// if (__Success) { printf(\"all tests passed\"); }");
433     }    
434
435
436
437     public static Vector getrulelist(Descriptor d) {
438         Vector dispatchrules = new Vector();
439         Vector rules = State.currentState.vRules;
440
441         for (int i = 0; i < rules.size(); i++) {
442             Rule rule = (Rule) rules.elementAt(i);
443             Set requiredsymbols = rule.getRequiredDescriptors();
444             
445             // #TBD#: in general this is wrong because these descriptors may contain descriptors
446             // bound in "in?" expressions which need to be dealt with in a topologically sorted
447             // fashion...
448
449             if (rule.getRequiredDescriptors().contains(d)) {
450                 dispatchrules.addElement(rule);
451             }
452         }
453         return dispatchrules;
454     }
455
456     private boolean need_compensation(Rule r) {
457         GraphNode gn=(GraphNode)termination.scopefalsify.get(r);
458         for(Iterator edgeit=gn.edges();edgeit.hasNext();) {
459             GraphNode.Edge edge=(GraphNode.Edge)edgeit.next();
460             GraphNode gn2=edge.getTarget();
461             if (!removed.contains(gn2)) {
462                 TermNode tn2=(TermNode)gn2.getOwner();
463                 if (tn2.getType()==TermNode.CONSEQUENCE)
464                     return false;
465             }
466         }
467         return true;
468     }
469
470     private UpdateNode find_compensation(Rule r) {
471         GraphNode gn=(GraphNode)termination.scopefalsify.get(r);
472         for(Iterator edgeit=gn.edges();edgeit.hasNext();) {
473             GraphNode.Edge edge=(GraphNode.Edge)edgeit.next();
474             GraphNode gn2=edge.getTarget();
475             if (!removed.contains(gn2)) {
476                 TermNode tn2=(TermNode)gn2.getOwner();
477                 if (tn2.getType()==TermNode.UPDATE) {
478                     MultUpdateNode mun=tn2.getUpdate();
479                     for(int i=0;i<mun.numUpdates();i++) {
480                         UpdateNode un=mun.getUpdate(i);
481                         if (un.getRule()==r)
482                             return un;
483                     }
484                 }
485             }
486         }
487         throw new Error("No Compensation Update could be found");
488     }
489
490     public void generate_dispatch(CodeWriter cr, RelationDescriptor rd, String leftvar, String rightvar) {
491         boolean usageimage=rd.testUsage(RelationDescriptor.IMAGE);
492         boolean usageinvimage=rd.testUsage(RelationDescriptor.INVIMAGE);
493
494         if (!(usageinvimage||usageimage)) /* not used at all*/
495             return;
496
497         cr.outputline("// RELATION DISPATCH ");
498         cr.outputline("if ("+oldmodel.getSafeSymbol()+"&&");
499         if (usageimage)
500             cr.outputline("!"+oldmodel.getSafeSymbol() +"->"+rd.getJustSafeSymbol()+"_hash->contains("+leftvar+","+rightvar+"))");
501         else
502             cr.outputline("!"+oldmodel.getSafeSymbol() +"->"+rd.getJustSafeSymbol()+"_hashinv->contains("+rightvar+","+leftvar+"))");
503         cr.startblock(); {
504             /* Adding new item */
505             /* Perform safety checks */
506             cr.outputline("if ("+repairtable.getSafeSymbol()+"&&");
507             cr.outputline(repairtable.getSafeSymbol()+"->containsrelation("+rd.getNum()+","+currentrule.getNum()+","+leftvar+","+rightvar+"))");
508             cr.startblock(); {
509                 /* Have update to call into */
510                 VarDescriptor funptr=VarDescriptor.makeNew("updateptr");
511                 String parttype="";
512                 for(int i=0;i<currentrule.numQuantifiers();i++) {
513                     if (currentrule.getQuantifier(i) instanceof RelationQuantifier)
514                         parttype=parttype+", int, int";
515                     else
516                         parttype=parttype+", int";
517                 }
518                 cr.outputline("void (*"+funptr.getSafeSymbol()+") ("+name+"_state *,"+name+"*,RepairHash *"+parttype+")=");
519                 cr.outputline("(void (*) ("+name+"_state *,"+name+"*,RepairHash *"+parttype+")) "+repairtable.getSafeSymbol()+"->getrelation("+rd.getNum()+","+currentrule.getNum()+","+leftvar+","+rightvar+");");
520                 String methodcall="("+funptr.getSafeSymbol()+") (this,"+oldmodel.getSafeSymbol()+","+repairtable.getSafeSymbol();
521                 for(int i=0;i<currentrule.numQuantifiers();i++) {
522                     Quantifier q=currentrule.getQuantifier(i);
523                     if (q instanceof SetQuantifier) {
524                         SetQuantifier sq=(SetQuantifier) q;
525                         methodcall+=","+sq.getVar().getSafeSymbol();
526                     } else if (q instanceof RelationQuantifier) {
527                         RelationQuantifier rq=(RelationQuantifier) q;
528                         methodcall+=","+rq.x.getSafeSymbol();
529                         methodcall+=","+rq.y.getSafeSymbol();
530                     } else if (q instanceof ForQuantifier) {
531                         ForQuantifier fq=(ForQuantifier) q;
532                         methodcall+=","+fq.getVar().getSafeSymbol();
533                     }
534                 }
535                 methodcall+=");";
536                 cr.outputline(methodcall);
537                 cr.outputline(goodflag.getSafeSymbol()+"=0;");
538                 cr.outputline("continue;");
539             }
540             cr.endblock();
541             /* Build standard compensation actions */
542             if (need_compensation(currentrule)) {
543                 UpdateNode un=find_compensation(currentrule);
544                 String name=(String)updatenames.get(un);
545                 usedupdates.add(un); /* Mark as used */
546                 String methodcall=name+"(this,"+oldmodel.getSafeSymbol()+","+repairtable.getSafeSymbol();
547                 for(int i=0;i<currentrule.numQuantifiers();i++) {
548                     Quantifier q=currentrule.getQuantifier(i);
549                     if (q instanceof SetQuantifier) {
550                         SetQuantifier sq=(SetQuantifier) q;
551                         methodcall+=","+sq.getVar().getSafeSymbol();
552                     } else if (q instanceof RelationQuantifier) {
553                         RelationQuantifier rq=(RelationQuantifier) q;
554                         methodcall+=","+rq.x.getSafeSymbol();
555                         methodcall+=","+rq.y.getSafeSymbol();
556                     } else if (q instanceof ForQuantifier) {
557                         ForQuantifier fq=(ForQuantifier) q;
558                         methodcall+=","+fq.getVar().getSafeSymbol();
559                     }
560                 }
561                 methodcall+=");";
562                 cr.outputline(methodcall);
563                 cr.outputline(goodflag.getSafeSymbol()+"=0;");
564                 cr.outputline("continue;");
565             }
566         }
567         cr.endblock();
568
569         String addeditem = (VarDescriptor.makeNew("addeditem")).getSafeSymbol();
570         cr.outputline("int " + addeditem + ";");
571         if (rd.testUsage(RelationDescriptor.IMAGE)) {
572             cr.outputline(addeditem + " = " + rd.getSafeSymbol() + "_hash->add((int)" + leftvar + ", (int)" + rightvar + ");");
573         }
574         
575         if (rd.testUsage(RelationDescriptor.INVIMAGE)) {
576             cr.outputline(addeditem + " = " + rd.getSafeSymbol() + "_hashinv->add((int)" + rightvar + ", (int)" + leftvar + ");");
577         }
578         
579         cr.outputline("if (" + addeditem + ")");
580         cr.startblock();
581
582         Vector dispatchrules = getrulelist(rd);
583         
584         if (dispatchrules.size() == 0) {
585             cr.outputline("// nothing to dispatch");
586             cr.endblock();
587             return;
588         }
589        
590         for(int i = 0; i < dispatchrules.size(); i++) {
591             Rule rule = (Rule) dispatchrules.elementAt(i);
592             if (rule.getGuardExpr().getRequiredDescriptors().contains(rd)) {
593                 /* Guard depends on this relation, so we recomput everything */
594                 cr.outputline(worklist.getSafeSymbol()+"->add("+rule.getNum()+",-1,0,0);");
595             } else {
596                 for (int j=0;j<rule.numQuantifiers();j++) {
597                     Quantifier q=rule.getQuantifier(j);
598                     if (q.getRequiredDescriptors().contains(rd)) {
599                         /* Generate add */
600                         cr.outputline(worklist.getSafeSymbol()+"->add("+rule.getNum()+","+j+","+leftvar+","+rightvar+");");
601                     }
602                 }
603             }
604         }
605         cr.endblock();
606     }
607
608
609     public void generate_dispatch(CodeWriter cr, SetDescriptor sd, String setvar) {
610                
611         cr.outputline("// SET DISPATCH ");
612
613         cr.outputline("if ("+oldmodel.getSafeSymbol()+"&&");
614         cr.outputline("!"+oldmodel.getSafeSymbol() +"->"+sd.getJustSafeSymbol()+"_hash->contains("+setvar+"))");
615         cr.startblock(); {
616             /* Adding new item */
617             /* Perform safety checks */
618             cr.outputline("if ("+repairtable.getSafeSymbol()+"&&");
619             cr.outputline(repairtable.getSafeSymbol()+"->containsset("+sd.getNum()+","+currentrule.getNum()+","+setvar+"))");
620             cr.startblock(); {
621                 /* Have update to call into */
622                 VarDescriptor funptr=VarDescriptor.makeNew("updateptr");
623                 String parttype="";
624                 for(int i=0;i<currentrule.numQuantifiers();i++) {
625                     if (currentrule.getQuantifier(i) instanceof RelationQuantifier)
626                         parttype=parttype+", int, int";
627                     else
628                         parttype=parttype+", int";
629                 }
630                 cr.outputline("void (*"+funptr.getSafeSymbol()+") ("+name+"_state *,"+name+"*,RepairHash *"+parttype+")=");
631                 cr.outputline("(void (*) ("+name+"_state *,"+name+"*,RepairHash *"+parttype+")) "+repairtable.getSafeSymbol()+"->getset("+sd.getNum()+","+currentrule.getNum()+","+setvar+");");
632                 String methodcall="("+funptr.getSafeSymbol()+") (this,"+oldmodel.getSafeSymbol()+","+
633                               repairtable.getSafeSymbol();
634                 for(int i=0;i<currentrule.numQuantifiers();i++) {
635                     Quantifier q=currentrule.getQuantifier(i);
636                     if (q instanceof SetQuantifier) {
637                         SetQuantifier sq=(SetQuantifier) q;
638                         methodcall+=","+sq.getVar().getSafeSymbol();
639                     } else if (q instanceof RelationQuantifier) {
640                         RelationQuantifier rq=(RelationQuantifier) q;
641                         methodcall+=","+rq.x.getSafeSymbol();
642                         methodcall+=","+rq.y.getSafeSymbol();
643                     } else if (q instanceof ForQuantifier) {
644                         ForQuantifier fq=(ForQuantifier) q;
645                         methodcall+=","+fq.getVar().getSafeSymbol();
646                     }
647                 }
648                 methodcall+=");";
649                 cr.outputline(methodcall);
650                 cr.outputline(goodflag.getSafeSymbol()+"=0;");
651                 cr.outputline("continue;");
652             }
653             cr.endblock();
654             /* Build standard compensation actions */
655             if (need_compensation(currentrule)) {
656                 UpdateNode un=find_compensation(currentrule);
657                 String name=(String)updatenames.get(un);
658                 usedupdates.add(un); /* Mark as used */
659
660                 String methodcall=name+"(this,"+oldmodel.getSafeSymbol()+","+
661                               repairtable.getSafeSymbol();
662                 for(int i=0;i<currentrule.numQuantifiers();i++) {
663                     Quantifier q=currentrule.getQuantifier(i);
664                     if (q instanceof SetQuantifier) {
665                         SetQuantifier sq=(SetQuantifier) q;
666                         methodcall+=","+sq.getVar().getSafeSymbol();
667                     } else if (q instanceof RelationQuantifier) {
668                         RelationQuantifier rq=(RelationQuantifier) q;
669                         methodcall+=","+rq.x.getSafeSymbol();
670                         methodcall+=","+rq.y.getSafeSymbol();
671                     } else if (q instanceof ForQuantifier) {
672                         ForQuantifier fq=(ForQuantifier) q;
673                         methodcall+=","+fq.getVar().getSafeSymbol();
674                     }
675                 }
676                 methodcall+=");";
677                 cr.outputline(methodcall);
678                 cr.outputline(goodflag.getSafeSymbol()+"=0;");
679                 cr.outputline("continue;");
680             }
681         }
682         cr.endblock();
683
684         String addeditem = (VarDescriptor.makeNew("addeditem")).getSafeSymbol();
685         cr.outputline("int " + addeditem + " = 1;");
686         cr.outputline(addeditem + " = " + sd.getSafeSymbol() + "_hash->add((int)" + setvar +  ", (int)" + setvar + ");");
687         cr.startblock();
688         Vector dispatchrules = getrulelist(sd);
689
690         if (dispatchrules.size() == 0) {
691             cr.outputline("// nothing to dispatch");
692             cr.endblock();
693             return;
694         }
695
696         for(int i = 0; i < dispatchrules.size(); i++) {
697             Rule rule = (Rule) dispatchrules.elementAt(i);
698             if (SetDescriptor.expand(rule.getGuardExpr().getRequiredDescriptors()).contains(sd)) {
699                 /* Guard depends on this relation, so we recompute everything */
700                 cr.outputline(worklist.getSafeSymbol()+"->add("+rule.getNum()+",-1,0,0);");
701             } else {
702                 for (int j=0;j<rule.numQuantifiers();j++) {
703                     Quantifier q=rule.getQuantifier(j);
704                     if (SetDescriptor.expand(q.getRequiredDescriptors()).contains(sd)) {
705                         /* Generate add */
706                         cr.outputline(worklist.getSafeSymbol()+"->add("+rule.getNum()+","+j+","+setvar+",0);");
707                     }
708                 }
709             }
710         }
711         cr.endblock();
712     }
713
714 }
715
716
717