let command line define flags optionally
[repair.git] / Repair / RepairCompiler / MCC / IR / UpdateNode.java
1 package MCC.IR;
2 import java.util.*;
3 import MCC.State;
4 import MCC.Compiler;
5
6 class UpdateNode {
7     Vector updates;
8     Vector bindings;
9     Vector invariants;
10     Hashtable binding;
11     Rule rule;
12
13     public UpdateNode(Rule r) {
14         updates=new Vector();
15         bindings=new Vector();
16         invariants=new Vector();
17         binding=new Hashtable();
18         rule=r;
19     }
20
21     public Rule getRule() {
22         return rule;
23     }
24
25     public String toString() {
26         String st="";
27         st+="Bindings:\n";
28         for(int i=0;i<bindings.size();i++)
29             st+=bindings.get(i).toString()+"\n";
30         st+="---------------------\n";
31         st+="Updates:\n";
32         for(int i=0;i<updates.size();i++)
33             st+=updates.get(i).toString()+"\n";
34         st+="---------------------\n";
35         st+="Invariants:\n";
36         for(int i=0;i<invariants.size();i++)
37             st+=((Expr)invariants.get(i)).name()+"\n";
38         st+="---------------------\n";
39         return st;
40     }
41
42     public void addBindings(Vector v) {
43         for (int i=0;i<v.size();i++) {
44             addBinding((Binding)v.get(i));
45         }
46     }
47
48     public boolean checkupdates(State state) {
49         if (!checkconflicts()) /* Do we have conflicting concrete updates */
50             return false;
51         if (!checknoupdates(state))
52             return false;
53         if (computeordering()) /* Ordering exists */
54             return true;
55         
56         return false;
57     }
58
59     private boolean checknoupdates(State state) {
60         Set noupdate=state.noupdate;
61         for(int i=0;i<updates.size();i++) {
62             Updates u=(Updates)updates.get(i);
63             if (u.isAbstract())
64                 continue; /* Abstract updates don't change fields */
65             Descriptor d=u.getDescriptor();
66             if (noupdate.contains(d))
67                 return false;
68         }
69         return true;
70     }
71
72     private boolean computeordering() {
73         /* Build dependency graph between updates */
74         HashSet graph=new HashSet();
75         Hashtable mapping=new Hashtable();
76         for(int i=0;i<updates.size();i++) {
77             Updates u=(Updates)updates.get(i);
78             GraphNode gn=new GraphNode(String.valueOf(i),u);
79             mapping.put(u, gn);
80             graph.add(gn);
81         }
82         for(int i=0;i<updates.size();i++) {
83             Updates u1=(Updates)updates.get(i);
84             if (u1.isAbstract())
85                 continue;
86             for(int j=0;j<updates.size();j++) {
87                 Updates u2=(Updates)updates.get(j);
88                 if (!u2.isExpr())
89                     continue;
90                 Descriptor d=u1.getDescriptor();
91                 Expr subexpr=null;
92                 Expr intindex=null;
93
94                 if (u2.isField()) {
95                     subexpr=((DotExpr)u2.getLeftExpr()).getExpr();
96                     intindex=((DotExpr)u2.getLeftExpr()).getIndex();
97                 }
98                 if (u2.getRightExpr().usesDescriptor(d)||
99                     (subexpr!=null&&subexpr.usesDescriptor(d))||
100                     (intindex!=null&&intindex.usesDescriptor(d))) {
101                     /* Add edge for dependency */
102                     GraphNode gn1=(GraphNode) mapping.get(u1);
103                     GraphNode gn2=(GraphNode) mapping.get(u2);
104                     GraphNode.Edge e=new GraphNode.Edge("dependency",gn2);
105                     gn1.addEdge(e);
106                 }
107             }
108         }
109
110         if (!GraphNode.DFS.depthFirstSearch(graph))  /* DFS & check for acyclicity */
111             return false;
112
113         TreeSet topologicalsort = new TreeSet(new Comparator() {
114                 public boolean equals(Object obj) { return false; }
115                 public int compare(Object o1, Object o2) {
116                     GraphNode g1 = (GraphNode) o1;
117                     GraphNode g2 = (GraphNode) o2;
118                     return g2.getFinishingTime() - g1.getFinishingTime();
119                 }
120             });
121         topologicalsort.addAll(graph);
122         Vector sortedvector=new Vector();
123         for(Iterator sort=topologicalsort.iterator();sort.hasNext();) {
124             GraphNode gn=(GraphNode)sort.next();
125             sortedvector.add(gn.getOwner());
126         }
127         updates=sortedvector; //replace updates with the sorted array
128         return true;
129     }
130
131     private boolean checkconflicts() {
132         Set toremove=new HashSet();
133         for(int i=0;i<updates.size();i++) {
134             Updates u1=(Updates)updates.get(i);
135             if (!u1.isAbstract()) {
136                 Descriptor d=u1.getDescriptor();
137                 for(int j=0;j<invariants.size();j++) {
138                     Expr invariant=(Expr)invariants.get(j);
139                     if (invariant.usesDescriptor(d))
140                         return false;
141                 }
142             }
143             for(int j=0;j<updates.size();j++) {
144                 Updates u2=(Updates)updates.get(j);
145                 if (i==j)
146                     continue;
147                 if (u1.isAbstract()||u2.isAbstract())
148                     continue;  /* Abstract updates are already accounted for by graph */
149                 if (u1.getDescriptor()!=u2.getDescriptor())
150                     continue; /* No interference - different descriptors */
151
152                 if ((u1.getOpcode()==Opcode.GT||u1.getOpcode()==Opcode.GE)&&
153                     (u2.getOpcode()==Opcode.GT||u2.getOpcode()==Opcode.GE))
154                     continue; /* Can be satisfied simultaneously */
155
156                 if ((u1.getOpcode()==Opcode.LT||u1.getOpcode()==Opcode.LE)&&
157                     (u2.getOpcode()==Opcode.LT||u2.getOpcode()==Opcode.LE))
158                     continue;
159                 if ((u1.getOpcode()==u2.getOpcode())&&
160                     u1.isExpr()&&u2.isExpr()&&
161                     u1.getRightExpr().equals(null, u2.getRightExpr())) {
162                     /*We'll remove the second occurence*/
163                     if (i>j)
164                         toremove.add(u1);
165                     else
166                         toremove.add(u2);
167                     continue;
168                 }
169
170                 /* Handle = or != NULL */
171                 if ((((u1.getOpcode()==Opcode.EQ)&&(u2.getOpcode()==Opcode.NE))||
172                      ((u1.getOpcode()==Opcode.NE)&&(u2.getOpcode()==Opcode.EQ)))&&
173                     (((u1.isExpr()&&u1.getRightExpr().isNull())&&(!u2.isExpr()||u2.getRightExpr().isNonNull()))
174                      ||((!u1.isExpr()||u1.getRightExpr().isNonNull())&&(u2.isExpr()&&u2.getRightExpr().isNull())))) {
175                     if (u1.getOpcode()==Opcode.NE)
176                         toremove.add(u1);
177                     else
178                         toremove.add(u2);
179                     continue;
180                 }
181
182                 /* Handle = and != to different constants */
183                 if ((((u1.getOpcode()==Opcode.EQ)&&(u2.getOpcode()==Opcode.NE))||
184                     ((u1.getOpcode()==Opcode.NE)&&(u2.getOpcode()==Opcode.EQ)))&&
185                     (u1.isExpr()&&u1.getRightExpr() instanceof LiteralExpr)&&
186                     (u2.isExpr()&&u2.getRightExpr() instanceof LiteralExpr)&&
187                     !u1.getRightExpr().equals(u2.getRightExpr())) {
188                     if (u1.getOpcode()==Opcode.NE)
189                         toremove.add(u1);
190                     else
191                         toremove.add(u2);
192                     continue;
193                 }
194
195                 /* Compatible operations < & <= */
196                 if (((u1.getOpcode()==Opcode.LT)||(u1.getOpcode()==Opcode.LE))&&
197                     ((u2.getOpcode()==Opcode.LT)||(u2.getOpcode()==Opcode.LE)))
198                     continue;
199
200                 /* Compatible operations > & >= */
201                 if (((u1.getOpcode()==Opcode.GT)||(u1.getOpcode()==Opcode.GE))&&
202                     ((u2.getOpcode()==Opcode.GT)||(u2.getOpcode()==Opcode.GE)))
203                     continue;
204                 /* Ranges */
205
206                 //XXXXXX: TODO
207                 /* Equality & Comparisons */
208                 //XXXXXX: TODO
209
210                 return false; /* They interfere */
211             }
212         }
213         updates.removeAll(toremove);
214         return true;
215     }
216
217     public void addBinding(Binding b) {
218         bindings.add(b);
219         binding.put(b.getVar(),b);
220     }
221
222     public int numBindings() {
223         return bindings.size();
224     }
225
226     public Binding getBinding(int i) {
227         return (Binding)bindings.get(i);
228     }
229
230     public Binding getBinding(VarDescriptor vd) {
231         if (binding.containsKey(vd))
232             return (Binding)binding.get(vd);
233         else
234             return null;
235     }
236
237     public void addInvariant(Expr e) {
238         invariants.add(e);
239     }
240
241     public int numInvariants() {
242         return invariants.size();
243     }
244
245     public Expr getInvariant(int i) {
246         return (Expr)invariants.get(i);
247     }
248
249     public void addUpdate(Updates u) {
250         updates.add(u);
251     }
252
253     public int numUpdates() {
254         return updates.size();
255     }
256     public Updates getUpdate(int i) {
257         return (Updates)updates.get(i);
258     }
259
260     private MultUpdateNode getMultUpdateNode(boolean negate, Descriptor d, RepairGenerator rg) {
261         Termination termination=rg.termination;
262         MultUpdateNode mun=null;
263         GraphNode gn;
264         if (negate)
265             gn=(GraphNode)termination.abstractremove.get(d);
266         else
267             gn=(GraphNode)termination.abstractadd.get(d);
268         TermNode tn=(TermNode)gn.getOwner();
269         for(Iterator edgeit=gn.edges();edgeit.hasNext();) {
270             GraphNode gn2=((GraphNode.Edge) edgeit.next()).getTarget();
271             if (!rg.removed.contains(gn2)) {
272                 TermNode tn2=(TermNode)gn2.getOwner();
273                 if (tn2.getType()==TermNode.UPDATE) {
274                     mun=tn2.getUpdate();
275                     break;
276                 }
277             }
278         }
279         if (mun==null)
280             throw new Error("Can't find update node!");
281         return mun;
282     }
283
284     public void generate_abstract(CodeWriter cr, Updates u, RepairGenerator rg) {
285         State state=rg.state;
286         Expr abstractexpr=u.getLeftExpr();
287         boolean negated=u.negate;
288         Descriptor d=null;
289         Expr left=null;
290         Expr right=null;
291         boolean istuple=false;
292         if (abstractexpr instanceof TupleOfExpr) {
293             TupleOfExpr toe=(TupleOfExpr) abstractexpr;
294             d=toe.relation;
295             left=toe.left;
296             right=toe.right;
297             istuple=true;
298         } else if (abstractexpr instanceof ElementOfExpr) {
299             ElementOfExpr eoe=(ElementOfExpr) abstractexpr;
300             d=eoe.set;
301             left=eoe.element;
302             istuple=false;
303         } else {
304             throw new Error("Unsupported Expr");
305         }
306         MultUpdateNode mun=getMultUpdateNode(negated,d,rg);
307         VarDescriptor leftvar=VarDescriptor.makeNew("leftvar");
308         VarDescriptor rightvar=VarDescriptor.makeNew("rightvar");
309         left.generate(cr, leftvar);
310         if (istuple)
311             right.generate(cr,rightvar);
312
313         if (negated) {
314             if (istuple) {
315                 RelationDescriptor rd=(RelationDescriptor)d;
316                 boolean usageimage=rd.testUsage(RelationDescriptor.IMAGE);
317                 boolean usageinvimage=rd.testUsage(RelationDescriptor.INVIMAGE);
318                 if (usageimage)
319                     cr.outputline("SimpleHashremove("+rg.stmodel+"->"+rd.getJustSafeSymbol()+"_hash, (int)" + leftvar.getSafeSymbol() + ", (int)" + rightvar.getSafeSymbol() + ");");
320                 if (usageinvimage)
321                     cr.outputline("SimpleHashremove("+rg.stmodel+"->"+rd.getJustSafeSymbol()+"_hashinv, (int)" + rightvar.getSafeSymbol() + ", (int)" + leftvar.getSafeSymbol() + ");");
322
323                 for(int i=0;i<state.vRules.size();i++) {
324                     Rule r=(Rule)state.vRules.get(i);
325                     if (r.getInclusion().getTargetDescriptors().contains(rd)) {
326                         for(int j=0;j<mun.numUpdates();j++) {
327                             UpdateNode un=mun.getUpdate(i);
328                             if (un.getRule()==r) {
329                                 /* Update for rule rule r */
330                                 String name=(String)rg.updatenames.get(un);
331                                 cr.outputline("RepairHashaddrelation("+rg.strepairtable+","+rd.getNum()+","+r.getNum()+","+leftvar.getSafeSymbol()+","+rightvar.getSafeSymbol()+",(int) &"+name+");");
332                             }
333                         }
334                     }
335                 }
336             } else {
337                 SetDescriptor sd=(SetDescriptor) d;
338                 cr.outputline("SimpleHashremove("+rg.stmodel+"->"+sd.getJustSafeSymbol()+"_hash, (int)" + leftvar.getSafeSymbol() + ", (int)" + leftvar.getSafeSymbol() + ");");
339
340                 for(int i=0;i<state.vRules.size();i++) {
341                     Rule r=(Rule)state.vRules.get(i);
342                     if (r.getInclusion().getTargetDescriptors().contains(sd)) {
343                         for(int j=0;j<mun.numUpdates();j++) {
344                             UpdateNode un=mun.getUpdate(j);
345                             if (un.getRule()==r) {
346                                 /* Update for rule rule r */
347                                 String name=(String)rg.updatenames.get(un);
348                                 cr.outputline("RepairHashaddset("+rg.strepairtable+","+sd.getNum()+","+r.getNum()+","+leftvar.getSafeSymbol()+",(int) &"+name+");");
349                             }
350                         }
351                     }
352                 }
353             }
354         } else {
355             /* Generate update */
356             if (istuple) {
357                 RelationDescriptor rd=(RelationDescriptor) d;
358                 boolean usageimage=rd.testUsage(RelationDescriptor.IMAGE);
359                 boolean usageinvimage=rd.testUsage(RelationDescriptor.INVIMAGE);
360                 if (usageimage)
361                     cr.outputline("SimpleHashadd("+rg.stmodel+"->"+rd.getJustSafeSymbol()+"_hash, (int)" + leftvar.getSafeSymbol() + ", (int)" + rightvar.getSafeSymbol() + ");");
362                 if (usageinvimage)
363                     cr.outputline("SimpleHashadd("+rg.stmodel+"->"+rd.getJustSafeSymbol()+"_hashinv, (int)" + rightvar.getSafeSymbol() + ", (int)" + leftvar.getSafeSymbol() + ");");
364
365                 UpdateNode un=mun.getUpdate(0);
366                 String name=(String)rg.updatenames.get(un);
367                 cr.outputline(name+"(this,"+rg.stmodel+","+rg.strepairtable+","+leftvar.getSafeSymbol()+","+rightvar.getSafeSymbol()+");");
368             } else {
369                 SetDescriptor sd=(SetDescriptor)d;
370                 cr.outputline("SimpleHashadd("+rg.stmodel+"->"+sd.getJustSafeSymbol()+"_hash, (int)" + leftvar.getSafeSymbol() + ", (int)" + leftvar.getSafeSymbol() + ");");
371
372                 UpdateNode un=mun.getUpdate(0);
373                 /* Update for rule rule r */
374                 String name=(String)rg.updatenames.get(un);
375                 cr.outputline(name+"(this,"+rg.stmodel+","+rg.strepairtable+","+leftvar.getSafeSymbol()+");");
376             }
377         }
378     }
379
380     public void generate(CodeWriter cr, boolean removal, boolean modify, String slot0, String slot1, String slot2, RepairGenerator rg) {
381         if (!removal&&!modify)
382             generate_bindings(cr, slot0,slot1);
383         for(int i=0;i<updates.size();i++) {
384             Updates u=(Updates)updates.get(i);
385             VarDescriptor right=VarDescriptor.makeNew("right");
386             if (u.getType()==Updates.ABSTRACT) {
387                 generate_abstract(cr, u, rg);
388                 return;
389             }
390
391             switch(u.getType()) {
392             case Updates.EXPR:
393                 u.getRightExpr().generate(cr,right);
394                 break;
395             case Updates.POSITION:
396             case Updates.ACCESSPATH:
397                 if (u.getRightPos()==0) {
398                     cr.addDeclaration("int", right.getSafeSymbol());
399                     cr.outputline(right.getSafeSymbol()+"="+slot0+";");
400                 } else if (u.getRightPos()==1) {
401                     cr.addDeclaration("int", right.getSafeSymbol());
402                     cr.outputline(right.getSafeSymbol()+"="+slot1+";");
403                 } else if (u.getRightPos()==2) {
404                     cr.addDeclaration("int", right.getSafeSymbol());
405                     cr.outputline(right.getSafeSymbol()+"="+slot2+";");
406                 } else throw new Error("Error w/ Position");
407                 break;
408             default:
409                 throw new Error();
410             }
411
412             if (u.getType()==Updates.ACCESSPATH) {
413                 VarDescriptor newright=VarDescriptor.makeNew("right");
414                 generate_accesspath(cr, right,newright,u);
415                 right=newright;
416             }
417             VarDescriptor left=VarDescriptor.makeNew("left");
418             u.getLeftExpr().generate(cr,left);
419             Opcode op=u.getOpcode();
420             cr.outputline("if (!("+left.getSafeSymbol()+op+right.getSafeSymbol()+"))");
421             cr.startblock();
422
423             if (op==Opcode.GT)
424                 cr.outputline(right.getSafeSymbol()+"++;");
425             else if (op==Opcode.GE)
426                 ;
427             else if (op==Opcode.EQ)
428                 ;
429             else if (op==Opcode.NE)
430                 cr.outputline(right.getSafeSymbol()+"++;");
431             else if (op==Opcode.LT)
432                 cr.outputline(right.getSafeSymbol()+"--;");
433             else if (op==Opcode.LE)
434                 ;
435             else throw new Error();
436
437             if (u.isGlobal()) {
438                 VarDescriptor vd=((VarExpr)u.getLeftExpr()).getVar();
439                 cr.outputline(vd.getSafeSymbol()+"="+right.getSafeSymbol()+";");
440                 if (Compiler.PRINTREPAIRS) {
441                     cr.outputline("printf(\""+u.getLeftExpr().toString()+"=%d\\n\","+right.getSafeSymbol()+");");
442                 }
443             } else if (u.isField()) {
444                 /* NEED TO FIX */
445                 Expr subexpr=((DotExpr)u.getLeftExpr()).getExpr();
446                 Expr intindex=((DotExpr)u.getLeftExpr()).getIndex();
447                 VarDescriptor subvd=VarDescriptor.makeNew("subexpr");
448                 VarDescriptor indexvd=VarDescriptor.makeNew("index");
449                 subexpr.generate(cr,subvd);
450
451                 if (intindex!=null)
452                     intindex.generate(cr,indexvd);
453                 FieldDescriptor fd=(FieldDescriptor)u.getDescriptor();
454                 if (Compiler.PRINTREPAIRS) {
455                     if (intindex==null) {
456                         cr.outputline("printf(\"0x%x."+fd.toString()+
457                                       "=%d\\n\","+subvd.getSafeSymbol()+","+right.getSafeSymbol()+");");
458                     } else {
459                         cr.outputline("printf(\"0x%x."+fd.toString()+
460                                       "[%d]=%d\\n\","+subvd.getSafeSymbol()+
461                                       ","+indexvd.getSafeSymbol()+","+right.getSafeSymbol()+");");
462                     }
463                 }
464
465
466                 StructureTypeDescriptor std=(StructureTypeDescriptor)subexpr.getType();
467                 Expr offsetbits = std.getOffsetExpr(fd);
468                 if (fd instanceof ArrayDescriptor) {
469                     fd = ((ArrayDescriptor) fd).getField();
470                 }
471
472                 if (intindex != null) {
473                     Expr basesize = fd.getBaseSizeExpr();
474                     offsetbits = new OpExpr(Opcode.ADD, offsetbits, new OpExpr(Opcode.MULT, basesize, intindex));
475                 }
476                 Expr offsetbytes = new OpExpr(Opcode.SHR, offsetbits,new IntegerLiteralExpr(3));
477                 Expr byteaddress=new OpExpr(Opcode.ADD, offsetbytes, subexpr);
478                 VarDescriptor addr=VarDescriptor.makeNew("byteaddress");
479                 byteaddress.generate(cr,addr);
480
481                 if (fd.getType() instanceof ReservedTypeDescriptor && !fd.getPtr()) {
482                     ReservedTypeDescriptor rtd=(ReservedTypeDescriptor)fd.getType();
483                     if (rtd==ReservedTypeDescriptor.INT) {
484                         cr.outputline("*((int *) "+addr.getSafeSymbol()+")="+right.getSafeSymbol()+";");
485                     } else if (rtd==ReservedTypeDescriptor.SHORT) {
486                         cr.outputline("*((short *) "+addr.getSafeSymbol()+")="+right.getSafeSymbol()+";");
487                     } else if (rtd==ReservedTypeDescriptor.BYTE) {
488                         cr.outputline("*((char *) "+addr.getSafeSymbol()+")="+right.getSafeSymbol()+";");
489                     } else if (rtd==ReservedTypeDescriptor.BIT) {
490                         Expr tmp = new OpExpr(Opcode.SHL, offsetbytes, new IntegerLiteralExpr(3));
491                         Expr offset=new OpExpr(Opcode.SUB, offsetbits, tmp);
492                         Expr mask=new OpExpr(Opcode.SHL, new IntegerLiteralExpr(1), offset);
493                         VarDescriptor maskvar=VarDescriptor.makeNew("mask");
494                         mask.generate(cr,maskvar);
495                         cr.outputline("*((char *) "+addr.getSafeSymbol()+")|="+maskvar.getSafeSymbol()+";");
496                         cr.outputline("if (!"+right.getSafeSymbol()+")");
497                         cr.outputline("*((char *) "+addr.getSafeSymbol()+")^="+maskvar.getSafeSymbol()+";");
498                     } else throw new Error();
499                 } else {
500                     /* Pointer */
501                     cr.outputline("*((int *) "+addr.getSafeSymbol()+")="+right.getSafeSymbol()+";");
502                 }
503             }
504             cr.endblock();
505         }
506     }
507
508
509     private void generate_accesspath(CodeWriter cr, VarDescriptor right, VarDescriptor newright, Updates u) {
510         Vector dotvector=new Vector();
511         Expr ptr=u.getRightExpr();
512         VarExpr rightve=new VarExpr(right);
513         right.td=ReservedTypeDescriptor.INT;
514
515         while(true) {
516             /* Does something other than a dereference? */
517             dotvector.add(ptr);
518             if (ptr instanceof DotExpr)
519                 ptr=((DotExpr)ptr).left;
520             else if (ptr instanceof CastExpr)
521                 ptr=((CastExpr)ptr).getExpr();
522             if (ptr instanceof VarExpr) {
523                 /* Finished constructing vector */
524                 break;
525             }
526         }
527         ArrayAnalysis.AccessPath ap=u.getAccessPath();
528         VarDescriptor init=VarDescriptor.makeNew("init");
529         if (ap.isSet()) {
530             cr.addDeclaration("int", init.getSafeSymbol());
531             cr.outputline(init.getSafeSymbol()+"= SimpleHashfirstkey("+ap.getSet().getSafeSymbol()+"_hash);");
532             init.td=ap.getSet().getType();
533         } else {
534             init=ap.getVar();
535         }
536         Expr newexpr=new VarExpr(init);
537         int apindex=0;
538         for(int i=dotvector.size()-1;i>=0;i--) {
539             Expr e=(Expr)dotvector.get(i);
540             if (e instanceof CastExpr) {
541                 newexpr.td=e.td;
542                 newexpr=new CastExpr(((CastExpr)e).getType(),newexpr);
543             } else if (e instanceof DotExpr) {
544                 DotExpr de=(DotExpr)e;
545                 if (de.getField() instanceof ArrayDescriptor) {
546                     DotExpr de2=new DotExpr(newexpr,de.field,new IntegerLiteralExpr(0));
547                     de2.fd=de.fd;
548                     de2.fieldtype=de.fieldtype;
549                     de2.td=de.td;
550                     OpExpr offset=new OpExpr(Opcode.SUB,rightve,de2);
551                     OpExpr index=new OpExpr(Opcode.DIV,offset,de.fieldtype.getSizeExpr());
552                     if (u.getRightPos()==apindex) {
553                         index.generate(cr,newright);
554                         return;
555                     } else {
556                         DotExpr de3=new DotExpr(newexpr,de.field,index);
557                         de3.fd=de.fd;
558                         de3.td=de.td;
559                         de3.fieldtype=de.fieldtype;
560                         newexpr=de3;
561                     }
562                 } else {
563                     DotExpr de2=new DotExpr(newexpr,de.field,null);
564                     de2.fd=de.fd;
565                     de2.fieldtype=de.fieldtype;
566                     de2.td=de.td;
567                     newexpr=de2;
568                 }
569                 apindex++;
570             } else throw new Error();
571         }
572         throw new Error();
573     }
574
575     private void generate_bindings(CodeWriter cr, String slot0, String slot1) {
576         for(int i=0;i<bindings.size();i++) {
577             Binding b=(Binding)bindings.get(i);
578
579             if (b.getType()==Binding.SEARCH) {
580                 VarDescriptor vd=b.getVar();
581                 cr.addDeclaration(vd.getType().getGenerateType().getSafeSymbol(), vd.getSafeSymbol());
582                 cr.outputline(vd.getSafeSymbol()+"=SimpleHashfirstkey("+b.getSet().getSafeSymbol()+"_hash);");
583             } else if (b.getType()==Binding.CREATE) {
584                 throw new Error("Creation not supported");
585                 //              source.generateSourceAlloc(cr,vd,b.getSet());
586             } else {
587                 VarDescriptor vd=b.getVar();
588                 switch(b.getPosition()) {
589                 case 0:
590                     cr.addDeclaration(vd.getType().getGenerateType().getSafeSymbol(), vd.getSafeSymbol());
591                     cr.outputline(vd.getSafeSymbol()+"="+slot0+";");
592                     break;
593                 case 1:
594                     cr.addDeclaration(vd.getType().getGenerateType().getSafeSymbol(), vd.getSafeSymbol());
595                     cr.outputline(vd.getSafeSymbol()+"="+slot1+";");
596                     break;
597                 default:
598                     throw new Error("Slot >1 doesn't exist.");
599                 }
600             }
601         }
602     }
603 }