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