more changes
[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         FlatMethod fm=new FlatMethod(td, fn);
37
38         for(int i=0;i<td.numParameters();i++) {
39             fm.addParameterTemp(getTempforVar(td.getParameter(i)));
40         }
41         state.addFlatCode(td,fm);
42     }
43
44     private void flattenClass(ClassDescriptor cn) {
45         Iterator methodit=cn.getMethods();
46         while(methodit.hasNext()) {
47             MethodDescriptor md=(MethodDescriptor)methodit.next();
48             BlockNode bn=state.getMethodBody(md);
49             FlatNode fn=flattenBlockNode(bn).getBegin();
50             FlatMethod fm=new FlatMethod(md, fn);
51             if (!md.isStatic())
52                 fm.addParameterTemp(getTempforVar(md.getThis()));
53             for(int i=0;i<md.numParameters();i++) {
54                 fm.addParameterTemp(getTempforVar(md.getParameter(i)));
55             }
56             System.out.println(fm.printMethod());
57             state.addFlatCode(md,fm);
58         }
59     }
60
61     private NodePair flattenBlockNode(BlockNode bn) {
62         FlatNode begin=null;
63         FlatNode end=null;
64         for(int i=0;i<bn.size();i++) {
65             NodePair np=flattenBlockStatementNode(bn.get(i));
66             FlatNode np_begin=np.getBegin();
67             FlatNode np_end=np.getEnd();
68             if (begin==null) {
69                 begin=np_begin;
70             }
71             if (end==null) {
72                 end=np_end;
73             } else {
74                 end.addNext(np_begin);
75                 end=np_end;
76             }
77         }
78         if (begin==null) {
79             end=begin=new FlatNop();
80         }
81         return new NodePair(begin,end);
82     }
83
84     private NodePair flattenBlockExpressionNode(BlockExpressionNode en) {
85         TempDescriptor tmp=TempDescriptor.tempFactory("neverused",en.getExpression().getType());
86         return flattenExpressionNode(en.getExpression(),tmp);
87     }
88
89     private NodePair flattenCastNode(CastNode cn,TempDescriptor out_temp) {
90         TempDescriptor tmp=TempDescriptor.tempFactory("tocast",cn.getExpression().getType());
91         NodePair np=flattenExpressionNode(cn.getExpression(), tmp);
92         FlatCastNode fcn=new FlatCastNode(cn.getType(), tmp, out_temp);
93         np.getEnd().addNext(fcn);
94         return new NodePair(np.getBegin(),fcn);
95     }
96
97     private NodePair flattenLiteralNode(LiteralNode ln,TempDescriptor out_temp) {
98         FlatLiteralNode fln=new FlatLiteralNode(ln.getType(), ln.getValue(), out_temp);
99         return new NodePair(fln,fln);
100     }
101
102     private NodePair flattenCreateObjectNode(CreateObjectNode con,TempDescriptor out_temp) {
103         TypeDescriptor td=con.getType();
104         if (!td.isArray()) {
105             FlatNew fn=new FlatNew(td, out_temp);
106             TempDescriptor[] temps=new TempDescriptor[con.numArgs()];
107             FlatNode last=fn;
108             //Build arguments
109             for(int i=0;i<con.numArgs();i++) {
110                 ExpressionNode en=con.getArg(i);
111                 TempDescriptor tmp=TempDescriptor.tempFactory("arg",en.getType());
112                 temps[i]=tmp;
113                 NodePair np=flattenExpressionNode(en, tmp);
114                 last.addNext(np.getBegin());
115                 last=np.getEnd();
116             }
117             MethodDescriptor md=con.getConstructor();
118             //Call to constructor
119             FlatCall fc=new FlatCall(md, null, out_temp, temps);
120             last.addNext(fc);
121             return new NodePair(fn,fc); 
122         } else {
123             FlatNode first=null;
124             FlatNode last=null;
125             TempDescriptor[] temps=new TempDescriptor[con.numArgs()];
126             for (int i=0;i<con.numArgs();i++) {
127                 ExpressionNode en=con.getArg(i);
128                 TempDescriptor tmp=TempDescriptor.tempFactory("arg",en.getType());
129                 temps[i]=tmp;           
130                 NodePair np=flattenExpressionNode(en, tmp);
131                 if (first==null)
132                     first=np.getBegin();
133                 else
134                     last.addNext(np.getBegin());
135                 last=np.getEnd();
136                 
137                 TempDescriptor tmp2=(i==0)?
138                     out_temp:
139                 TempDescriptor.tempFactory("arg",en.getType());
140             }
141             FlatNew fn=new FlatNew(td, out_temp, temps[0]);
142             last.addNext(fn);
143             if (temps.length>1) {
144                 NodePair np=generateNewArrayLoop(temps, td.dereference(), out_temp, 0);
145                 fn.addNext(np.getBegin());
146                 return new NodePair(first,np.getEnd()); 
147             } else
148                 return new NodePair(first, fn);
149         }
150     }
151
152     private NodePair generateNewArrayLoop(TempDescriptor[] temparray, TypeDescriptor td, TempDescriptor tmp, int i) {
153         TempDescriptor index=TempDescriptor.tempFactory("index",new TypeDescriptor(TypeDescriptor.INT));
154         TempDescriptor tmpone=TempDescriptor.tempFactory("index",new TypeDescriptor(TypeDescriptor.INT));
155         FlatNop fnop=new FlatNop();//last node
156
157         //index=0
158         FlatLiteralNode fln=new FlatLiteralNode(index.getType(),new Integer(0),index);
159         //tmpone=1
160         FlatLiteralNode fln2=new FlatLiteralNode(tmpone.getType(),new Integer(1),tmpone);
161
162         TempDescriptor tmpbool=TempDescriptor.tempFactory("comp",new TypeDescriptor(TypeDescriptor.BOOLEAN));
163
164         FlatOpNode fcomp=new FlatOpNode(tmpbool,index,temparray[i],new Operation(Operation.LT));
165         FlatCondBranch fcb=new FlatCondBranch(tmpbool);
166         //is index<temp[i]
167         TempDescriptor new_tmp=TempDescriptor.tempFactory("tmp",td);
168         FlatNew fn=new FlatNew(td, new_tmp, temparray[i+1]);
169         FlatSetElementNode fsen=new FlatSetElementNode(tmp,index,new_tmp);
170         // index=index+1
171         FlatOpNode fon=new FlatOpNode(index,index,tmpone,new Operation(Operation.ADD));
172         //jump out
173         fln.addNext(fln2);
174         fln2.addNext(fcomp);
175         fcomp.addNext(fcb);
176         fcb.addTrueNext(fn);
177         fcb.addFalseNext(fnop);
178         fn.addNext(fsen);
179         //Recursive call here
180         if ((i+2)<temparray.length) {
181             NodePair np2=generateNewArrayLoop(temparray, td.dereference(), new_tmp, i+1);
182             fsen.addNext(np2.getBegin());
183             np2.getEnd().addNext(fon);
184         } else {
185             fsen.addNext(fon);
186         }
187         fon.addNext(fcomp);
188         return new NodePair(fln, fnop);
189     }
190
191     private NodePair flattenMethodInvokeNode(MethodInvokeNode min,TempDescriptor out_temp) {
192         TempDescriptor[] temps=new TempDescriptor[min.numArgs()];
193         FlatNode first=null;
194         FlatNode last=null;
195         TempDescriptor thisarg=null;
196
197         if (min.getExpression()!=null) {
198             thisarg=TempDescriptor.tempFactory("thisarg",min.getExpression().getType());
199             NodePair np=flattenExpressionNode(min.getExpression(),thisarg);
200             first=np.getBegin();
201             last=np.getEnd();
202         }
203         
204         //Build arguments
205         for(int i=0;i<min.numArgs();i++) {
206             ExpressionNode en=min.getArg(i);
207             TempDescriptor td=TempDescriptor.tempFactory("arg",en.getType());
208             temps[i]=td;
209             NodePair np=flattenExpressionNode(en, td);
210             if (first==null)
211                 first=np.getBegin();
212             else 
213                 last.addNext(np.getBegin());
214             last=np.getEnd();
215         }
216
217         MethodDescriptor md=min.getMethod();
218         
219         //Call to constructor
220         
221         FlatCall fc;
222         if(md.getReturnType()==null||md.getReturnType().isVoid())
223             fc=new FlatCall(md, null, thisarg, temps);
224         else 
225             fc=new FlatCall(md, out_temp, thisarg, temps);
226         if (first==null) {
227             first=fc;
228         } else
229             last.addNext(fc);
230         return new NodePair(first,fc);
231     }
232
233     private NodePair flattenFieldAccessNode(FieldAccessNode fan,TempDescriptor out_temp) {
234         TempDescriptor tmp=TempDescriptor.tempFactory("temp",fan.getExpression().getType());
235         NodePair npe=flattenExpressionNode(fan.getExpression(),tmp);
236         FlatFieldNode fn=new FlatFieldNode(fan.getField(),tmp,out_temp);
237         npe.getEnd().addNext(fn);
238         return new NodePair(npe.getBegin(),fn);
239     }
240
241     private NodePair flattenArrayAccessNode(ArrayAccessNode aan,TempDescriptor out_temp) {
242         TempDescriptor tmp=TempDescriptor.tempFactory("temp",aan.getExpression().getType());
243         TempDescriptor tmpindex=TempDescriptor.tempFactory("temp",aan.getIndex().getType());
244         NodePair npe=flattenExpressionNode(aan.getExpression(),tmp);
245         NodePair npi=flattenExpressionNode(aan.getIndex(),tmpindex);
246         FlatElementNode fn=new FlatElementNode(tmp,tmpindex,out_temp);
247         npe.getEnd().addNext(npi.getBegin());
248         npi.getEnd().addNext(fn);
249         return new NodePair(npe.getBegin(),fn);
250     }
251
252     private NodePair flattenAssignmentNode(AssignmentNode an,TempDescriptor out_temp) {
253         // Two cases:
254         // left side is variable
255         // left side is field
256         
257         Operation base=an.getOperation().getBaseOp();
258         TempDescriptor src_tmp=TempDescriptor.tempFactory("src",an.getSrc().getType());
259         NodePair np_src=flattenExpressionNode(an.getSrc(),src_tmp);
260         FlatNode last=np_src.getEnd();
261         if (base!=null) {
262             TempDescriptor src_tmp2=TempDescriptor.tempFactory("tmp", an.getDest().getType());
263             NodePair np_dst_init=flattenExpressionNode(an.getDest(),src_tmp2);
264             last.addNext(np_dst_init.getBegin());
265             TempDescriptor dst_tmp=TempDescriptor.tempFactory("dst_tmp",an.getDest().getType());
266             FlatOpNode fon=new FlatOpNode(dst_tmp, src_tmp,src_tmp2, base);
267             np_dst_init.getEnd().addNext(fon);
268             last=fon;
269             src_tmp=dst_tmp;
270         }
271         
272         if (an.getDest().kind()==Kind.FieldAccessNode) {
273             FieldAccessNode fan=(FieldAccessNode)an.getDest();
274             ExpressionNode en=fan.getExpression();
275             TempDescriptor dst_tmp=TempDescriptor.tempFactory("dst",en.getType());
276             NodePair np_baseexp=flattenExpressionNode(en, dst_tmp);
277             last.addNext(np_baseexp.getBegin());
278             FlatSetFieldNode fsfn=new FlatSetFieldNode(dst_tmp, fan.getField(), src_tmp);
279             np_baseexp.getEnd().addNext(fsfn);
280             return new NodePair(np_src.getBegin(), fsfn);
281         } else if (an.getDest().kind()==Kind.ArrayAccessNode) {
282             ArrayAccessNode aan=(ArrayAccessNode)an.getDest();
283             ExpressionNode en=aan.getExpression();
284             ExpressionNode enindex=aan.getIndex();
285             TempDescriptor dst_tmp=TempDescriptor.tempFactory("dst",en.getType());
286             TempDescriptor index_tmp=TempDescriptor.tempFactory("index",enindex.getType());
287             NodePair np_baseexp=flattenExpressionNode(en, dst_tmp);
288             NodePair np_indexexp=flattenExpressionNode(enindex, index_tmp);
289             last.addNext(np_baseexp.getBegin());
290             np_baseexp.getEnd().addNext(np_indexexp.getBegin());
291             FlatSetElementNode fsen=new FlatSetElementNode(dst_tmp, index_tmp, src_tmp);
292             np_indexexp.getEnd().addNext(fsen);
293             return new NodePair(np_src.getBegin(), fsen);
294         } else if (an.getDest().kind()==Kind.NameNode) {
295             NameNode nn=(NameNode)an.getDest();
296             if (nn.getExpression()!=null) {
297                 FieldAccessNode fan=(FieldAccessNode)nn.getExpression();
298                 ExpressionNode en=fan.getExpression();
299                 TempDescriptor dst_tmp=TempDescriptor.tempFactory("dst",en.getType());
300                 NodePair np_baseexp=flattenExpressionNode(en, dst_tmp);
301                 last.addNext(np_baseexp.getBegin());
302                 FlatSetFieldNode fsfn=new FlatSetFieldNode(dst_tmp, fan.getField(), src_tmp);
303                 np_baseexp.getEnd().addNext(fsfn);
304                 return new NodePair(np_src.getBegin(), fsfn);
305             } else {
306                 if (nn.getField()!=null) {
307                     FlatSetFieldNode fsfn=new FlatSetFieldNode(getTempforVar(nn.getVar()), nn.getField(), src_tmp);
308                     last.addNext(fsfn);
309                     return new NodePair(np_src.getBegin(), fsfn);
310                 } else {
311                     FlatOpNode fon=new FlatOpNode(getTempforVar(nn.getVar()), src_tmp, null, new Operation(Operation.ASSIGN));
312                     last.addNext(fon);
313                     return new NodePair(np_src.getBegin(),fon);
314                 }
315             }
316         } 
317         throw new Error();
318     }
319
320     private NodePair flattenNameNode(NameNode nn,TempDescriptor out_temp) {
321         if (nn.getExpression()!=null) {
322             /* Hack - use subtree instead */
323             return flattenExpressionNode(nn.getExpression(),out_temp);
324         } else if (nn.getField()!=null) {
325             TempDescriptor tmp=getTempforVar(nn.getVar());
326             FlatFieldNode ffn=new FlatFieldNode(nn.getField(), tmp, out_temp); 
327             return new NodePair(ffn,ffn);
328         } else {
329             TempDescriptor tmp=getTempforVar(nn.getVar());
330             FlatOpNode fon=new FlatOpNode(out_temp, tmp, null, new Operation(Operation.ASSIGN));
331             return new NodePair(fon,fon);
332         }
333     }
334
335     private NodePair flattenOpNode(OpNode on,TempDescriptor out_temp) {
336         TempDescriptor temp_left=TempDescriptor.tempFactory("leftop",on.getLeft().getType());
337         TempDescriptor temp_right=null;
338
339         Operation op=on.getOp();
340         if (op.getOp()==Operation.POSTINC||
341             op.getOp()==Operation.POSTDEC||
342             op.getOp()==Operation.PREINC||
343             op.getOp()==Operation.PREDEC) {
344             LiteralNode ln=new LiteralNode("int",new Integer(1));
345             ln.setType(new TypeDescriptor(TypeDescriptor.INT));
346             AssignmentNode an=new AssignmentNode(on.getLeft(),ln,
347                                new AssignOperation((op.getOp()==Operation.POSTINC||op.getOp()==Operation.PREINC)?AssignOperation.PLUSEQ:AssignOperation.MINUSEQ));
348             if (op.getOp()==Operation.POSTINC||
349                 op.getOp()==Operation.POSTDEC) {
350                 NodePair left=flattenExpressionNode(on.getLeft(),out_temp);
351                 NodePair assign=flattenAssignmentNode(an,temp_left);
352                 left.getEnd().addNext(assign.getBegin());
353                 return new NodePair(left.getBegin(),assign.getEnd());
354             } else {
355                 NodePair assign=flattenAssignmentNode(an,out_temp);
356                 return assign;
357             }
358         } 
359         
360         NodePair left=flattenExpressionNode(on.getLeft(),temp_left);
361         NodePair right;
362         if (on.getRight()!=null) {
363             temp_right=TempDescriptor.tempFactory("rightop",on.getRight().getType());
364             right=flattenExpressionNode(on.getRight(),temp_right);
365         } else {
366             FlatNop nop=new FlatNop();
367             right=new NodePair(nop,nop);
368         }
369
370         if (op.getOp()==Operation.LOGIC_OR) {
371             /* Need to do shortcircuiting */
372             FlatCondBranch fcb=new FlatCondBranch(temp_left);
373             FlatOpNode fon1=new FlatOpNode(out_temp,temp_left,null,new Operation(Operation.ASSIGN));
374             FlatOpNode fon2=new FlatOpNode(out_temp,temp_right,null,new Operation(Operation.ASSIGN));
375             FlatNop fnop=new FlatNop();
376             left.getEnd().addNext(fcb);
377             fcb.addFalseNext(right.getBegin());
378             right.getEnd().addNext(fon2);
379             fon2.addNext(fnop);
380             fcb.addTrueNext(fon1);
381             fon1.addNext(fnop);
382             return new NodePair(left.getBegin(), fnop);
383         } else if (op.getOp()==Operation.LOGIC_AND) {
384             /* Need to do shortcircuiting */
385             FlatCondBranch fcb=new FlatCondBranch(temp_left);
386             FlatOpNode fon1=new FlatOpNode(out_temp,temp_left,null,new Operation(Operation.ASSIGN));
387             FlatOpNode fon2=new FlatOpNode(out_temp,temp_right,null,new Operation(Operation.ASSIGN));
388             FlatNop fnop=new FlatNop();
389             left.getEnd().addNext(fcb);
390             fcb.addTrueNext(right.getBegin());
391             right.getEnd().addNext(fon2);
392             fon2.addNext(fnop);
393             fcb.addFalseNext(fon1);
394             fon1.addNext(fnop);
395             return new NodePair(left.getBegin(), fnop);
396         }
397
398         FlatOpNode fon=new FlatOpNode(out_temp,temp_left,temp_right,op);
399         left.getEnd().addNext(right.getBegin());
400         right.getEnd().addNext(fon);
401         return new NodePair(left.getBegin(),fon);
402     }
403
404     private NodePair flattenExpressionNode(ExpressionNode en, TempDescriptor out_temp) {
405         switch(en.kind()) {
406         case Kind.AssignmentNode:
407             return flattenAssignmentNode((AssignmentNode)en,out_temp);
408         case Kind.CastNode:
409             return flattenCastNode((CastNode)en,out_temp);
410         case Kind.CreateObjectNode:
411             return flattenCreateObjectNode((CreateObjectNode)en,out_temp);
412         case Kind.FieldAccessNode:
413             return flattenFieldAccessNode((FieldAccessNode)en,out_temp);
414         case Kind.ArrayAccessNode:
415             return flattenArrayAccessNode((ArrayAccessNode)en,out_temp);
416         case Kind.LiteralNode:
417             return flattenLiteralNode((LiteralNode)en,out_temp);
418         case Kind.MethodInvokeNode:
419             return flattenMethodInvokeNode((MethodInvokeNode)en,out_temp);
420         case Kind.NameNode:
421             return flattenNameNode((NameNode)en,out_temp);
422         case Kind.OpNode:
423             return flattenOpNode((OpNode)en,out_temp);
424         }
425         throw new Error();
426     }
427
428     private NodePair flattenDeclarationNode(DeclarationNode dn) {
429         VarDescriptor vd=dn.getVarDescriptor();
430         TempDescriptor td=getTempforVar(vd);
431         if (dn.getExpression()!=null)
432             return flattenExpressionNode(dn.getExpression(),td);
433         else {
434             FlatNop fn=new FlatNop();
435             return new NodePair(fn,fn);
436         }
437     }
438         
439     private TempDescriptor getTempforVar(VarDescriptor vd) {
440         if (temptovar.containsKey(vd))
441             return (TempDescriptor)temptovar.get(vd);
442         else {
443             TempDescriptor td=TempDescriptor.tempFactory(vd.getName(),vd.getType());
444             temptovar.put(vd,td);
445             return td;
446         }
447     }
448
449     private NodePair flattenIfStatementNode(IfStatementNode isn) {
450         TempDescriptor cond_temp=TempDescriptor.tempFactory("condition",new TypeDescriptor(TypeDescriptor.BOOLEAN));
451         NodePair cond=flattenExpressionNode(isn.getCondition(),cond_temp);
452         FlatCondBranch fcb=new FlatCondBranch(cond_temp);
453         NodePair true_np=flattenBlockNode(isn.getTrueBlock());
454         NodePair false_np;
455         FlatNop nopend=new FlatNop();
456
457         if (isn.getFalseBlock()!=null)
458             false_np=flattenBlockNode(isn.getFalseBlock());
459         else {
460             FlatNop nop=new FlatNop();
461             false_np=new NodePair(nop,nop);
462         }
463
464         cond.getEnd().addNext(fcb);
465         fcb.addTrueNext(true_np.getBegin());
466         fcb.addFalseNext(false_np.getBegin());
467         true_np.getEnd().addNext(nopend);
468         false_np.getEnd().addNext(nopend);
469         return new NodePair(cond.getBegin(), nopend);
470     }
471             
472     private NodePair flattenLoopNode(LoopNode ln) {
473         if (ln.getType()==LoopNode.FORLOOP) {
474             NodePair initializer=flattenBlockNode(ln.getInitializer());
475             TempDescriptor cond_temp=TempDescriptor.tempFactory("condition", new TypeDescriptor(TypeDescriptor.BOOLEAN));
476             NodePair condition=flattenExpressionNode(ln.getCondition(),cond_temp);
477             NodePair update=flattenBlockNode(ln.getUpdate());
478             NodePair body=flattenBlockNode(ln.getBody());
479             FlatNode begin=initializer.getBegin();
480             FlatCondBranch fcb=new FlatCondBranch(cond_temp);
481             FlatNop nopend=new FlatNop();
482
483             initializer.getEnd().addNext(condition.getBegin());
484             body.getEnd().addNext(update.getBegin());
485             update.getEnd().addNext(condition.getBegin());
486             condition.getEnd().addNext(fcb);
487             fcb.addFalseNext(nopend);
488             fcb.addTrueNext(body.getBegin());
489             return new NodePair(begin,nopend);
490         } else if (ln.getType()==LoopNode.WHILELOOP) {
491             TempDescriptor cond_temp=TempDescriptor.tempFactory("condition", new TypeDescriptor(TypeDescriptor.BOOLEAN));
492             NodePair condition=flattenExpressionNode(ln.getCondition(),cond_temp);
493             NodePair body=flattenBlockNode(ln.getBody());
494             FlatNode begin=condition.getBegin();
495             FlatCondBranch fcb=new FlatCondBranch(cond_temp);
496             FlatNop nopend=new FlatNop();
497
498             body.getEnd().addNext(condition.getBegin());
499             condition.getEnd().addNext(fcb);
500             fcb.addFalseNext(nopend);
501             fcb.addTrueNext(body.getBegin());
502             return new NodePair(begin,nopend);
503         } else if (ln.getType()==LoopNode.DOWHILELOOP) {
504             TempDescriptor cond_temp=TempDescriptor.tempFactory("condition", new TypeDescriptor(TypeDescriptor.BOOLEAN));
505             NodePair condition=flattenExpressionNode(ln.getCondition(),cond_temp);
506             NodePair body=flattenBlockNode(ln.getBody());
507             FlatNode begin=body.getBegin();
508             FlatCondBranch fcb=new FlatCondBranch(cond_temp);
509             FlatNop nopend=new FlatNop();
510
511             body.getEnd().addNext(condition.getBegin());
512             condition.getEnd().addNext(fcb);
513             fcb.addFalseNext(nopend);
514             fcb.addTrueNext(body.getBegin());
515             return new NodePair(begin,nopend);
516         } else throw new Error();
517     }
518             
519     private NodePair flattenReturnNode(ReturnNode rntree) {
520         TempDescriptor retval=null;
521         NodePair cond=null;
522         if (rntree.getReturnExpression()!=null) {
523             retval=TempDescriptor.tempFactory("ret_value", rntree.getReturnExpression().getType());
524             cond=flattenExpressionNode(rntree.getReturnExpression(),retval);
525         }
526
527         FlatReturnNode rnflat=new FlatReturnNode(retval);
528
529         if (cond!=null) {
530             cond.getEnd().addNext(rnflat);
531             return new NodePair(cond.getBegin(),rnflat);
532         } else
533             return new NodePair(rnflat,rnflat);
534     }
535
536     private NodePair flattenTaskExitNode(TaskExitNode ten) {
537         FlatTaskExitNode tenflat=new FlatTaskExitNode();
538         return new NodePair(tenflat,tenflat);
539     }
540             
541     private NodePair flattenSubBlockNode(SubBlockNode sbn) {
542         return flattenBlockNode(sbn.getBlockNode());
543     }
544
545     private NodePair flattenBlockStatementNode(BlockStatementNode bsn) {
546         switch(bsn.kind()) {
547         case Kind.BlockExpressionNode:
548             return flattenBlockExpressionNode((BlockExpressionNode)bsn);
549             
550         case Kind.DeclarationNode:
551             return flattenDeclarationNode((DeclarationNode)bsn);
552             
553         case Kind.IfStatementNode:
554             return flattenIfStatementNode((IfStatementNode)bsn);
555             
556         case Kind.LoopNode:
557             return flattenLoopNode((LoopNode)bsn);
558             
559         case Kind.ReturnNode:
560             return flattenReturnNode((IR.Tree.ReturnNode)bsn);
561
562         case Kind.TaskExitNode:
563             return flattenTaskExitNode((IR.Tree.TaskExitNode)bsn);
564             
565         case Kind.SubBlockNode:
566             return flattenSubBlockNode((SubBlockNode)bsn);
567             
568         }
569         throw new Error();
570     }
571 }