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