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