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