Bug fixes
[IRC.git] / Robust / src / IR / Flat / BuildFlat.java
1 package IR.Flat;
2 import IR.*;
3 import IR.Tree.*;
4 import java.util.*;
5
6 public class BuildFlat {
7     State state;
8     Hashtable temptovar;
9
10     public BuildFlat(State st) {
11         state=st;
12         temptovar=new Hashtable();
13     }
14
15     public Hashtable getMap() {
16         return temptovar;
17     }
18
19     public void buildFlat() {
20         Iterator it=state.getClassSymbolTable().getDescriptorsIterator();
21         while(it.hasNext()) {
22             ClassDescriptor cn=(ClassDescriptor)it.next();
23             flattenClass(cn);
24         }
25         
26         Iterator task_it=state.getTaskSymbolTable().getDescriptorsIterator();
27         while(task_it.hasNext()) {
28             TaskDescriptor td=(TaskDescriptor)task_it.next();
29             flattenTask(td);
30         }
31     }
32     
33     private void flattenTask(TaskDescriptor td) {
34         BlockNode bn=state.getMethodBody(td);
35         FlatNode fn=flattenBlockNode(bn).getBegin();
36         FlatFlagActionNode ffan=new FlatFlagActionNode(false);
37         ffan.addNext(fn);
38         FlatMethod fm=new FlatMethod(td, ffan);
39
40         for(int i=0;i<td.numParameters();i++) {
41             fm.addParameterTemp(getTempforVar(td.getParameter(i)));
42         }
43
44         /* Flatten Vector of Flag Effects */
45         Vector flags=td.getFlagEffects();
46         updateFlagActionNode(ffan,flags);
47
48         state.addFlatCode(td,fm);
49     }
50
51
52     /* This method transforms a vector of FlagEffects into the FlatFlagActionNode */
53     private void updateFlagActionNode(FlatFlagActionNode ffan, Vector flags) {
54         if (flags==null) // Do nothing if the flag effects vector is empty
55             return;
56
57         for(int i=0;i<flags.size();i++) {
58             FlagEffects fes=(FlagEffects)flags.get(i);
59             TempDescriptor flagtemp=getTempforVar(fes.getVar());
60             for(int j=0;j<fes.numEffects();j++) {
61                 FlagEffect fe=fes.getEffect(j);
62                 ffan.addFlagAction(flagtemp, fe.getFlag(), fe.getStatus());
63             }
64         }
65     }
66
67     private void flattenClass(ClassDescriptor cn) {
68         Iterator methodit=cn.getMethods();
69         while(methodit.hasNext()) {
70             MethodDescriptor md=(MethodDescriptor)methodit.next();
71             BlockNode bn=state.getMethodBody(md);
72             FlatNode fn=flattenBlockNode(bn).getBegin();
73             FlatMethod fm=new FlatMethod(md, fn);
74             if (!md.isStatic())
75                 fm.addParameterTemp(getTempforVar(md.getThis()));
76             for(int i=0;i<md.numParameters();i++) {
77                 fm.addParameterTemp(getTempforVar(md.getParameter(i)));
78             }
79             System.out.println(fm.printMethod());
80             state.addFlatCode(md,fm);
81         }
82     }
83
84     private NodePair flattenBlockNode(BlockNode bn) {
85         FlatNode begin=null;
86         FlatNode end=null;
87         for(int i=0;i<bn.size();i++) {
88             NodePair np=flattenBlockStatementNode(bn.get(i));
89             FlatNode np_begin=np.getBegin();
90             FlatNode np_end=np.getEnd();
91             if (begin==null) {
92                 begin=np_begin;
93             }
94             if (end==null) {
95                 end=np_end;
96             } else {
97                 end.addNext(np_begin);
98                 end=np_end;
99             }
100         }
101         if (begin==null) {
102             end=begin=new FlatNop();
103         }
104         return new NodePair(begin,end);
105     }
106
107     private NodePair flattenBlockExpressionNode(BlockExpressionNode en) {
108         TempDescriptor tmp=TempDescriptor.tempFactory("neverused",en.getExpression().getType());
109         return flattenExpressionNode(en.getExpression(),tmp);
110     }
111
112     private NodePair flattenCastNode(CastNode cn,TempDescriptor out_temp) {
113         TempDescriptor tmp=TempDescriptor.tempFactory("tocast",cn.getExpression().getType());
114         NodePair np=flattenExpressionNode(cn.getExpression(), tmp);
115         FlatCastNode fcn=new FlatCastNode(cn.getType(), tmp, out_temp);
116         np.getEnd().addNext(fcn);
117         return new NodePair(np.getBegin(),fcn);
118     }
119
120     private NodePair flattenLiteralNode(LiteralNode ln,TempDescriptor out_temp) {
121         FlatLiteralNode fln=new FlatLiteralNode(ln.getType(), ln.getValue(), out_temp);
122         return new NodePair(fln,fln);
123     }
124
125     private NodePair flattenCreateObjectNode(CreateObjectNode con,TempDescriptor out_temp) {
126         TypeDescriptor td=con.getType();
127         if (!td.isArray()) {
128             FlatNew fn=new FlatNew(td, out_temp);
129             TempDescriptor[] temps=new TempDescriptor[con.numArgs()];
130             FlatNode last=fn;
131
132             if (con.getFlagEffects()!=null) {
133                 FlatFlagActionNode ffan=new FlatFlagActionNode(false);
134                 FlagEffects fes=con.getFlagEffects();
135                 TempDescriptor flagtemp=out_temp;
136                 for(int j=0;j<fes.numEffects();j++) {
137                     FlagEffect fe=fes.getEffect(j);
138                     ffan.addFlagAction(flagtemp, fe.getFlag(), fe.getStatus());
139                 }
140                 last.addNext(ffan);
141                 last=ffan;
142             }
143             //Build arguments
144             for(int i=0;i<con.numArgs();i++) {
145                 ExpressionNode en=con.getArg(i);
146                 TempDescriptor tmp=TempDescriptor.tempFactory("arg",en.getType());
147                 temps[i]=tmp;
148                 NodePair np=flattenExpressionNode(en, tmp);
149                 last.addNext(np.getBegin());
150                 last=np.getEnd();
151             }
152             MethodDescriptor md=con.getConstructor();
153             //Call to constructor
154             FlatCall fc=new FlatCall(md, null, out_temp, temps);
155             last.addNext(fc);
156             last=fc;
157             return new NodePair(fn,last); 
158         } else {
159             FlatNode first=null;
160             FlatNode last=null;
161             TempDescriptor[] temps=new TempDescriptor[con.numArgs()];
162             for (int i=0;i<con.numArgs();i++) {
163                 ExpressionNode en=con.getArg(i);
164                 TempDescriptor tmp=TempDescriptor.tempFactory("arg",en.getType());
165                 temps[i]=tmp;           
166                 NodePair np=flattenExpressionNode(en, tmp);
167                 if (first==null)
168                     first=np.getBegin();
169                 else
170                     last.addNext(np.getBegin());
171                 last=np.getEnd();
172                 
173                 TempDescriptor tmp2=(i==0)?
174                     out_temp:
175                 TempDescriptor.tempFactory("arg",en.getType());
176             }
177             FlatNew fn=new FlatNew(td, out_temp, temps[0]);
178             last.addNext(fn);
179             if (temps.length>1) {
180                 NodePair np=generateNewArrayLoop(temps, td.dereference(), out_temp, 0);
181                 fn.addNext(np.getBegin());
182                 return new NodePair(first,np.getEnd()); 
183             } else
184                 return new NodePair(first, fn);
185         }
186     }
187
188     private NodePair generateNewArrayLoop(TempDescriptor[] temparray, TypeDescriptor td, TempDescriptor tmp, int i) {
189         TempDescriptor index=TempDescriptor.tempFactory("index",new TypeDescriptor(TypeDescriptor.INT));
190         TempDescriptor tmpone=TempDescriptor.tempFactory("index",new TypeDescriptor(TypeDescriptor.INT));
191         FlatNop fnop=new FlatNop();//last node
192
193         //index=0
194         FlatLiteralNode fln=new FlatLiteralNode(index.getType(),new Integer(0),index);
195         //tmpone=1
196         FlatLiteralNode fln2=new FlatLiteralNode(tmpone.getType(),new Integer(1),tmpone);
197
198         TempDescriptor tmpbool=TempDescriptor.tempFactory("comp",new TypeDescriptor(TypeDescriptor.BOOLEAN));
199
200         FlatOpNode fcomp=new FlatOpNode(tmpbool,index,temparray[i],new Operation(Operation.LT));
201         FlatCondBranch fcb=new FlatCondBranch(tmpbool);
202         //is index<temp[i]
203         TempDescriptor new_tmp=TempDescriptor.tempFactory("tmp",td);
204         FlatNew fn=new FlatNew(td, new_tmp, temparray[i+1]);
205         FlatSetElementNode fsen=new FlatSetElementNode(tmp,index,new_tmp);
206         // index=index+1
207         FlatOpNode fon=new FlatOpNode(index,index,tmpone,new Operation(Operation.ADD));
208         //jump out
209         fln.addNext(fln2);
210         fln2.addNext(fcomp);
211         fcomp.addNext(fcb);
212         fcb.addTrueNext(fn);
213         fcb.addFalseNext(fnop);
214         fn.addNext(fsen);
215         //Recursive call here
216         if ((i+2)<temparray.length) {
217             NodePair np2=generateNewArrayLoop(temparray, td.dereference(), new_tmp, i+1);
218             fsen.addNext(np2.getBegin());
219             np2.getEnd().addNext(fon);
220         } else {
221             fsen.addNext(fon);
222         }
223         fon.addNext(fcomp);
224         return new NodePair(fln, fnop);
225     }
226
227     private NodePair flattenMethodInvokeNode(MethodInvokeNode min,TempDescriptor out_temp) {
228         TempDescriptor[] temps=new TempDescriptor[min.numArgs()];
229         FlatNode first=null;
230         FlatNode last=null;
231         TempDescriptor thisarg=null;
232
233         if (min.getExpression()!=null) {
234             thisarg=TempDescriptor.tempFactory("thisarg",min.getExpression().getType());
235             NodePair np=flattenExpressionNode(min.getExpression(),thisarg);
236             first=np.getBegin();
237             last=np.getEnd();
238         }
239         
240         //Build arguments
241         for(int i=0;i<min.numArgs();i++) {
242             ExpressionNode en=min.getArg(i);
243             TempDescriptor td=TempDescriptor.tempFactory("arg",en.getType());
244             temps[i]=td;
245             NodePair np=flattenExpressionNode(en, td);
246             if (first==null)
247                 first=np.getBegin();
248             else 
249                 last.addNext(np.getBegin());
250             last=np.getEnd();
251         }
252
253         MethodDescriptor md=min.getMethod();
254         
255         //Call to constructor
256         
257         FlatCall fc;
258         if(md.getReturnType()==null||md.getReturnType().isVoid())
259             fc=new FlatCall(md, null, thisarg, temps);
260         else 
261             fc=new FlatCall(md, out_temp, thisarg, temps);
262         if (first==null) {
263             first=fc;
264         } else
265             last.addNext(fc);
266         return new NodePair(first,fc);
267     }
268
269     private NodePair flattenFieldAccessNode(FieldAccessNode fan,TempDescriptor out_temp) {
270         TempDescriptor tmp=TempDescriptor.tempFactory("temp",fan.getExpression().getType());
271         NodePair npe=flattenExpressionNode(fan.getExpression(),tmp);
272         FlatFieldNode fn=new FlatFieldNode(fan.getField(),tmp,out_temp);
273         npe.getEnd().addNext(fn);
274         return new NodePair(npe.getBegin(),fn);
275     }
276
277     private NodePair flattenArrayAccessNode(ArrayAccessNode aan,TempDescriptor out_temp) {
278         TempDescriptor tmp=TempDescriptor.tempFactory("temp",aan.getExpression().getType());
279         TempDescriptor tmpindex=TempDescriptor.tempFactory("temp",aan.getIndex().getType());
280         NodePair npe=flattenExpressionNode(aan.getExpression(),tmp);
281         NodePair npi=flattenExpressionNode(aan.getIndex(),tmpindex);
282         FlatElementNode fn=new FlatElementNode(tmp,tmpindex,out_temp);
283         npe.getEnd().addNext(npi.getBegin());
284         npi.getEnd().addNext(fn);
285         return new NodePair(npe.getBegin(),fn);
286     }
287
288     private NodePair flattenAssignmentNode(AssignmentNode an,TempDescriptor out_temp) {
289         // Three cases:
290         // left side is variable
291         // left side is field
292         // left side is array
293         
294         Operation base=an.getOperation().getBaseOp();
295         boolean pre=base==null||(base.getOp()!=Operation.POSTINC&&base.getOp()!=Operation.POSTDEC);
296         
297         if (!pre) {
298             //rewrite the base operation
299             base=base.getOp()==Operation.POSTINC?new Operation(Operation.ADD):new Operation(Operation.SUB);
300         }
301         FlatNode first=null;
302         FlatNode last=null;
303         TempDescriptor src_tmp=an.getSrc()==null?TempDescriptor.tempFactory("srctmp",an.getDest().getType()):TempDescriptor.tempFactory("srctmp",an.getSrc().getType());
304
305         //Get src value
306         if (an.getSrc()!=null) {
307             NodePair np_src=flattenExpressionNode(an.getSrc(),src_tmp);
308             first=np_src.getBegin();
309             last=np_src.getEnd();
310         } else if (!pre) {
311             FlatLiteralNode fln=new FlatLiteralNode(new TypeDescriptor(TypeDescriptor.INT) ,new Integer(1),src_tmp);
312             first=fln;
313             last=fln;
314         }
315         
316         if (an.getDest().kind()==Kind.FieldAccessNode) {
317             //We are assigning an object field
318
319             FieldAccessNode fan=(FieldAccessNode)an.getDest();
320             ExpressionNode en=fan.getExpression();
321             TempDescriptor dst_tmp=TempDescriptor.tempFactory("dst",en.getType());
322             NodePair np_baseexp=flattenExpressionNode(en, dst_tmp);
323             if (first==null)
324                 first=np_baseexp.getBegin();
325             else
326                 last.addNext(np_baseexp.getBegin());
327             last=np_baseexp.getEnd();
328
329             //See if we need to perform an operation
330             if (base!=null) {
331                 //If it is a preinc we need to store the initial value
332                 TempDescriptor src_tmp2=pre?TempDescriptor.tempFactory("src",an.getDest().getType()):out_temp;
333                 TempDescriptor tmp=TempDescriptor.tempFactory("srctmp3",an.getDest().getType());
334
335                 FlatFieldNode ffn=new FlatFieldNode(fan.getField(), dst_tmp, src_tmp2);
336                 last.addNext(ffn);
337                 last=ffn;
338                 FlatOpNode fon=new FlatOpNode(tmp, src_tmp2, src_tmp, base);
339                 src_tmp=tmp;
340                 last.addNext(fon);
341                 last=fon;
342             }
343
344             FlatSetFieldNode fsfn=new FlatSetFieldNode(dst_tmp, fan.getField(), src_tmp);
345             last.addNext(fsfn);
346             last=fsfn;
347             if (pre) {
348                 FlatOpNode fon2=new FlatOpNode(out_temp, src_tmp, null, new Operation(Operation.ASSIGN));
349                 fsfn.addNext(fon2);
350                 last=fon2;
351             }
352             return new NodePair(first, last);
353         } else if (an.getDest().kind()==Kind.ArrayAccessNode) {
354             //We are assigning an array element
355
356
357             ArrayAccessNode aan=(ArrayAccessNode)an.getDest();
358             ExpressionNode en=aan.getExpression();
359             ExpressionNode enindex=aan.getIndex();
360             TempDescriptor dst_tmp=TempDescriptor.tempFactory("dst",en.getType());
361             TempDescriptor index_tmp=TempDescriptor.tempFactory("index",enindex.getType());
362             NodePair np_baseexp=flattenExpressionNode(en, dst_tmp);
363             NodePair np_indexexp=flattenExpressionNode(enindex, index_tmp);
364             if (first==null)
365                 first=np_baseexp.getBegin();
366             else
367                 last.addNext(np_baseexp.getBegin());
368             np_baseexp.getEnd().addNext(np_indexexp.getBegin());
369             last=np_indexexp.getEnd();
370
371             //See if we need to perform an operation
372             if (base!=null) {
373                 //If it is a preinc we need to store the initial value
374                 TempDescriptor src_tmp2=pre?TempDescriptor.tempFactory("src",an.getDest().getType()):out_temp;
375                 TempDescriptor tmp=TempDescriptor.tempFactory("srctmp3",an.getDest().getType());
376
377                 FlatElementNode fen=new FlatElementNode(dst_tmp, index_tmp, src_tmp2);
378                 last.addNext(fen);
379                 last=fen;
380                 FlatOpNode fon=new FlatOpNode(tmp, src_tmp2, src_tmp, base);
381                 src_tmp=tmp;
382                 last.addNext(fon);
383                 last=fon;
384             }
385
386
387             FlatSetElementNode fsen=new FlatSetElementNode(dst_tmp, index_tmp, src_tmp);
388             last.addNext(fsen);
389             last=fsen;
390             if (pre) {
391                 FlatOpNode fon2=new FlatOpNode(out_temp, src_tmp, null, new Operation(Operation.ASSIGN));
392                 fsen.addNext(fon2);
393                 last=fon2;
394             }
395             return new NodePair(first, last);
396         } else if (an.getDest().kind()==Kind.NameNode) {
397             //We could be assigning a field or variable
398             NameNode nn=(NameNode)an.getDest();
399             if (nn.getExpression()!=null) {
400                 //It is a field
401                 FieldAccessNode fan=(FieldAccessNode)nn.getExpression();
402                 ExpressionNode en=fan.getExpression();
403                 TempDescriptor dst_tmp=TempDescriptor.tempFactory("dst",en.getType());
404                 NodePair np_baseexp=flattenExpressionNode(en, dst_tmp);
405                 if (first==null)
406                     first=np_baseexp.getBegin();
407                 else
408                     last.addNext(np_baseexp.getBegin());
409                 last=np_baseexp.getEnd();
410
411                 //See if we need to perform an operation
412                 if (base!=null) {
413                     //If it is a preinc we need to store the initial value
414                     TempDescriptor src_tmp2=pre?TempDescriptor.tempFactory("src",an.getDest().getType()):out_temp;
415                     TempDescriptor tmp=TempDescriptor.tempFactory("srctmp3",an.getDest().getType());
416                     
417                     FlatFieldNode ffn=new FlatFieldNode(fan.getField(), dst_tmp, src_tmp2);
418                     last.addNext(ffn);
419                     last=ffn;
420                     FlatOpNode fon=new FlatOpNode(tmp, src_tmp2, src_tmp, base);
421                     src_tmp=tmp;
422                     last.addNext(fon);
423                     last=fon;
424                 }
425
426
427                 FlatSetFieldNode fsfn=new FlatSetFieldNode(dst_tmp, fan.getField(), src_tmp);
428                 last.addNext(fsfn);
429                 last=fsfn;
430                 if (pre) {
431                     FlatOpNode fon2=new FlatOpNode(out_temp, src_tmp, null, new Operation(Operation.ASSIGN));
432                     fsfn.addNext(fon2);
433                     last=fon2;
434                 }
435                 return new NodePair(first, last);
436             } else {
437                 if (nn.getField()!=null) {
438                     //It is a field
439                     //Get src value
440
441                     //See if we need to perform an operation
442                     if (base!=null) {
443                         //If it is a preinc we need to store the initial value
444                         TempDescriptor src_tmp2=pre?TempDescriptor.tempFactory("src",an.getDest().getType()):out_temp;
445                         TempDescriptor tmp=TempDescriptor.tempFactory("srctmp3",an.getDest().getType());
446                         
447                         FlatFieldNode ffn=new FlatFieldNode(nn.getField(), getTempforVar(nn.getVar()), src_tmp2);
448                         if (first==null)
449                             first=ffn;
450                         else {
451                             last.addNext(ffn);
452                         }
453                         last=ffn;
454                         FlatOpNode fon=new FlatOpNode(tmp, src_tmp2, src_tmp, base);
455                         src_tmp=tmp;
456                         last.addNext(fon);
457                         last=fon;
458                     }               
459
460                     FlatSetFieldNode fsfn=new FlatSetFieldNode(getTempforVar(nn.getVar()), nn.getField(), src_tmp);
461                     if (first==null) {
462                         first=fsfn;
463                     } else {
464                         last.addNext(fsfn);
465                     }
466                     last=fsfn;
467                     if (pre) {
468                         FlatOpNode fon2=new FlatOpNode(out_temp, src_tmp, null, new Operation(Operation.ASSIGN));
469                         fsfn.addNext(fon2);
470                         last=fon2;
471                     }
472                     return new NodePair(first, last);
473                 } else {
474                     //It is a variable
475                     //See if we need to perform an operation
476
477                     if (base!=null) {
478                         //If it is a preinc we need to store the initial value
479                         TempDescriptor src_tmp2=getTempforVar(nn.getVar());
480                         TempDescriptor tmp=TempDescriptor.tempFactory("srctmp3",an.getDest().getType());
481                         if (!pre) {
482                             FlatOpNode fon=new FlatOpNode(out_temp, src_tmp2, null, new Operation(Operation.ASSIGN));
483                             if (first==null)
484                                 first=fon;
485                             else
486                                 last.addNext(fon);
487                             last=fon;
488                         }
489
490                         FlatOpNode fon=new FlatOpNode(tmp, src_tmp2, src_tmp, base);
491                         if (first==null) 
492                             first=fon;
493                         else 
494                             last.addNext(fon);
495                         src_tmp=tmp;
496                         last=fon;
497                     }
498
499                     FlatOpNode fon=new FlatOpNode(getTempforVar(nn.getVar()), src_tmp, null, new Operation(Operation.ASSIGN));
500                     last.addNext(fon);
501                     last=fon;
502                     if (pre) {
503                         FlatOpNode fon2=new FlatOpNode(out_temp, src_tmp, null, new Operation(Operation.ASSIGN));
504                         fon.addNext(fon2);
505                         last=fon2;
506                     }
507                     return new NodePair(first, last);
508                 }
509             }
510         } 
511         throw new Error();
512     }
513
514     private NodePair flattenNameNode(NameNode nn,TempDescriptor out_temp) {
515         if (nn.getExpression()!=null) {
516             /* Hack - use subtree instead */
517             return flattenExpressionNode(nn.getExpression(),out_temp);
518         } else if (nn.getField()!=null) {
519             TempDescriptor tmp=getTempforVar(nn.getVar());
520             FlatFieldNode ffn=new FlatFieldNode(nn.getField(), tmp, out_temp); 
521             return new NodePair(ffn,ffn);
522         } else {
523             TempDescriptor tmp=getTempforVar(nn.getVar());
524             FlatOpNode fon=new FlatOpNode(out_temp, tmp, null, new Operation(Operation.ASSIGN));
525             return new NodePair(fon,fon);
526         }
527     }
528
529     private NodePair flattenOpNode(OpNode on,TempDescriptor out_temp) {
530         TempDescriptor temp_left=TempDescriptor.tempFactory("leftop",on.getLeft().getType());
531         TempDescriptor temp_right=null;
532
533         Operation op=on.getOp();
534         /* We've moved this to assignment nodes
535
536         if (op.getOp()==Operation.POSTINC||
537             op.getOp()==Operation.POSTDEC||
538             op.getOp()==Operation.PREINC||
539             op.getOp()==Operation.PREDEC) {
540             LiteralNode ln=new LiteralNode("int",new Integer(1));
541             ln.setType(new TypeDescriptor(TypeDescriptor.INT));
542             
543             AssignmentNode an=new AssignmentNode(on.getLeft(),
544                                                  new OpNode(on.getLeft(),ln, 
545                                                             new Operation((op.getOp()==Operation.POSTINC||op.getOp()==Operation.PREINC)?Operation.PLUS:Operation.MINUS))
546                                                  );
547             if (op.getOp()==Operation.POSTINC||
548                 op.getOp()==Operation.POSTDEC) {
549                 //Can't do, this could have side effects
550                 NodePair left=flattenExpressionNode(on.getLeft(),out_temp);
551                 NodePair assign=flattenAssignmentNode(an,temp_left);
552                 left.getEnd().addNext(assign.getBegin());
553                 return new NodePair(left.getBegin(),assign.getEnd());
554             } else {
555                 NodePair assign=flattenAssignmentNode(an,out_temp);
556                 return assign;
557             }
558             } */
559         
560         NodePair left=flattenExpressionNode(on.getLeft(),temp_left);
561         NodePair right;
562         if (on.getRight()!=null) {
563             temp_right=TempDescriptor.tempFactory("rightop",on.getRight().getType());
564             right=flattenExpressionNode(on.getRight(),temp_right);
565         } else {
566             FlatNop nop=new FlatNop();
567             right=new NodePair(nop,nop);
568         }
569
570         if (op.getOp()==Operation.LOGIC_OR) {
571             /* Need to do shortcircuiting */
572             FlatCondBranch fcb=new FlatCondBranch(temp_left);
573             FlatOpNode fon1=new FlatOpNode(out_temp,temp_left,null,new Operation(Operation.ASSIGN));
574             FlatOpNode fon2=new FlatOpNode(out_temp,temp_right,null,new Operation(Operation.ASSIGN));
575             FlatNop fnop=new FlatNop();
576             left.getEnd().addNext(fcb);
577             fcb.addFalseNext(right.getBegin());
578             right.getEnd().addNext(fon2);
579             fon2.addNext(fnop);
580             fcb.addTrueNext(fon1);
581             fon1.addNext(fnop);
582             return new NodePair(left.getBegin(), fnop);
583         } else if (op.getOp()==Operation.LOGIC_AND) {
584             /* Need to do shortcircuiting */
585             FlatCondBranch fcb=new FlatCondBranch(temp_left);
586             FlatOpNode fon1=new FlatOpNode(out_temp,temp_left,null,new Operation(Operation.ASSIGN));
587             FlatOpNode fon2=new FlatOpNode(out_temp,temp_right,null,new Operation(Operation.ASSIGN));
588             FlatNop fnop=new FlatNop();
589             left.getEnd().addNext(fcb);
590             fcb.addTrueNext(right.getBegin());
591             right.getEnd().addNext(fon2);
592             fon2.addNext(fnop);
593             fcb.addFalseNext(fon1);
594             fon1.addNext(fnop);
595             return new NodePair(left.getBegin(), fnop);
596         }
597
598         FlatOpNode fon=new FlatOpNode(out_temp,temp_left,temp_right,op);
599         left.getEnd().addNext(right.getBegin());
600         right.getEnd().addNext(fon);
601         return new NodePair(left.getBegin(),fon);
602     }
603
604     private NodePair flattenExpressionNode(ExpressionNode en, TempDescriptor out_temp) {
605         switch(en.kind()) {
606         case Kind.AssignmentNode:
607             return flattenAssignmentNode((AssignmentNode)en,out_temp);
608         case Kind.CastNode:
609             return flattenCastNode((CastNode)en,out_temp);
610         case Kind.CreateObjectNode:
611             return flattenCreateObjectNode((CreateObjectNode)en,out_temp);
612         case Kind.FieldAccessNode:
613             return flattenFieldAccessNode((FieldAccessNode)en,out_temp);
614         case Kind.ArrayAccessNode:
615             return flattenArrayAccessNode((ArrayAccessNode)en,out_temp);
616         case Kind.LiteralNode:
617             return flattenLiteralNode((LiteralNode)en,out_temp);
618         case Kind.MethodInvokeNode:
619             return flattenMethodInvokeNode((MethodInvokeNode)en,out_temp);
620         case Kind.NameNode:
621             return flattenNameNode((NameNode)en,out_temp);
622         case Kind.OpNode:
623             return flattenOpNode((OpNode)en,out_temp);
624         }
625         throw new Error();
626     }
627
628     private NodePair flattenDeclarationNode(DeclarationNode dn) {
629         VarDescriptor vd=dn.getVarDescriptor();
630         TempDescriptor td=getTempforVar(vd);
631         if (dn.getExpression()!=null)
632             return flattenExpressionNode(dn.getExpression(),td);
633         else {
634             FlatNop fn=new FlatNop();
635             return new NodePair(fn,fn);
636         }
637     }
638         
639     private TempDescriptor getTempforVar(VarDescriptor vd) {
640         if (temptovar.containsKey(vd))
641             return (TempDescriptor)temptovar.get(vd);
642         else {
643             TempDescriptor td=TempDescriptor.tempFactory(vd.getName(),vd.getType());
644             temptovar.put(vd,td);
645             return td;
646         }
647     }
648
649     private NodePair flattenIfStatementNode(IfStatementNode isn) {
650         TempDescriptor cond_temp=TempDescriptor.tempFactory("condition",new TypeDescriptor(TypeDescriptor.BOOLEAN));
651         NodePair cond=flattenExpressionNode(isn.getCondition(),cond_temp);
652         FlatCondBranch fcb=new FlatCondBranch(cond_temp);
653         NodePair true_np=flattenBlockNode(isn.getTrueBlock());
654         NodePair false_np;
655         FlatNop nopend=new FlatNop();
656
657         if (isn.getFalseBlock()!=null)
658             false_np=flattenBlockNode(isn.getFalseBlock());
659         else {
660             FlatNop nop=new FlatNop();
661             false_np=new NodePair(nop,nop);
662         }
663
664         cond.getEnd().addNext(fcb);
665         fcb.addTrueNext(true_np.getBegin());
666         fcb.addFalseNext(false_np.getBegin());
667         true_np.getEnd().addNext(nopend);
668         false_np.getEnd().addNext(nopend);
669         return new NodePair(cond.getBegin(), nopend);
670     }
671             
672     private NodePair flattenLoopNode(LoopNode ln) {
673         if (ln.getType()==LoopNode.FORLOOP) {
674             NodePair initializer=flattenBlockNode(ln.getInitializer());
675             TempDescriptor cond_temp=TempDescriptor.tempFactory("condition", new TypeDescriptor(TypeDescriptor.BOOLEAN));
676             NodePair condition=flattenExpressionNode(ln.getCondition(),cond_temp);
677             NodePair update=flattenBlockNode(ln.getUpdate());
678             NodePair body=flattenBlockNode(ln.getBody());
679             FlatNode begin=initializer.getBegin();
680             FlatCondBranch fcb=new FlatCondBranch(cond_temp);
681             FlatNop nopend=new FlatNop();
682
683             initializer.getEnd().addNext(condition.getBegin());
684             body.getEnd().addNext(update.getBegin());
685             update.getEnd().addNext(condition.getBegin());
686             condition.getEnd().addNext(fcb);
687             fcb.addFalseNext(nopend);
688             fcb.addTrueNext(body.getBegin());
689             return new NodePair(begin,nopend);
690         } else if (ln.getType()==LoopNode.WHILELOOP) {
691             TempDescriptor cond_temp=TempDescriptor.tempFactory("condition", new TypeDescriptor(TypeDescriptor.BOOLEAN));
692             NodePair condition=flattenExpressionNode(ln.getCondition(),cond_temp);
693             NodePair body=flattenBlockNode(ln.getBody());
694             FlatNode begin=condition.getBegin();
695             FlatCondBranch fcb=new FlatCondBranch(cond_temp);
696             FlatNop nopend=new FlatNop();
697
698             body.getEnd().addNext(condition.getBegin());
699             condition.getEnd().addNext(fcb);
700             fcb.addFalseNext(nopend);
701             fcb.addTrueNext(body.getBegin());
702             return new NodePair(begin,nopend);
703         } else if (ln.getType()==LoopNode.DOWHILELOOP) {
704             TempDescriptor cond_temp=TempDescriptor.tempFactory("condition", new TypeDescriptor(TypeDescriptor.BOOLEAN));
705             NodePair condition=flattenExpressionNode(ln.getCondition(),cond_temp);
706             NodePair body=flattenBlockNode(ln.getBody());
707             FlatNode begin=body.getBegin();
708             FlatCondBranch fcb=new FlatCondBranch(cond_temp);
709             FlatNop nopend=new FlatNop();
710
711             body.getEnd().addNext(condition.getBegin());
712             condition.getEnd().addNext(fcb);
713             fcb.addFalseNext(nopend);
714             fcb.addTrueNext(body.getBegin());
715             return new NodePair(begin,nopend);
716         } else throw new Error();
717     }
718             
719     private NodePair flattenReturnNode(ReturnNode rntree) {
720         TempDescriptor retval=null;
721         NodePair cond=null;
722         if (rntree.getReturnExpression()!=null) {
723             retval=TempDescriptor.tempFactory("ret_value", rntree.getReturnExpression().getType());
724             cond=flattenExpressionNode(rntree.getReturnExpression(),retval);
725         }
726
727         FlatReturnNode rnflat=new FlatReturnNode(retval);
728
729         if (cond!=null) {
730             cond.getEnd().addNext(rnflat);
731             return new NodePair(cond.getBegin(),rnflat);
732         } else
733             return new NodePair(rnflat,rnflat);
734     }
735
736     private NodePair flattenTaskExitNode(TaskExitNode ten) {
737         FlatFlagActionNode ffan=new FlatFlagActionNode(true);
738         updateFlagActionNode(ffan, ten.getFlagEffects());
739         return new NodePair(ffan, ffan);
740     }
741
742     private NodePair flattenSubBlockNode(SubBlockNode sbn) {
743         return flattenBlockNode(sbn.getBlockNode());
744     }
745
746     private NodePair flattenBlockStatementNode(BlockStatementNode bsn) {
747         switch(bsn.kind()) {
748         case Kind.BlockExpressionNode:
749             return flattenBlockExpressionNode((BlockExpressionNode)bsn);
750             
751         case Kind.DeclarationNode:
752             return flattenDeclarationNode((DeclarationNode)bsn);
753             
754         case Kind.IfStatementNode:
755             return flattenIfStatementNode((IfStatementNode)bsn);
756             
757         case Kind.LoopNode:
758             return flattenLoopNode((LoopNode)bsn);
759             
760         case Kind.ReturnNode:
761             return flattenReturnNode((IR.Tree.ReturnNode)bsn);
762
763         case Kind.TaskExitNode:
764             return flattenTaskExitNode((IR.Tree.TaskExitNode)bsn);
765             
766         case Kind.SubBlockNode:
767             return flattenSubBlockNode((SubBlockNode)bsn);
768             
769         }
770         throw new Error();
771     }
772 }