a5cfe5fa7bd9a5f450cf11cbd4926085007b74c9
[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         TempDescriptor src_tmp=TempDescriptor.tempFactory("src",an.getSrc().getType());
293         NodePair np_src=flattenExpressionNode(an.getSrc(),src_tmp);
294         FlatNode last=np_src.getEnd();
295         if (base!=null) {
296             TempDescriptor src_tmp2=TempDescriptor.tempFactory("tmp", an.getDest().getType());
297             NodePair np_dst_init=flattenExpressionNode(an.getDest(),src_tmp2);
298             last.addNext(np_dst_init.getBegin());
299             TempDescriptor dst_tmp=TempDescriptor.tempFactory("dst_tmp",an.getDest().getType());
300             FlatOpNode fon=new FlatOpNode(dst_tmp, src_tmp,src_tmp2, base);
301             np_dst_init.getEnd().addNext(fon);
302             last=fon;
303             src_tmp=dst_tmp;
304         }
305         
306         if (an.getDest().kind()==Kind.FieldAccessNode) {
307             //We are assigning an object field
308             FieldAccessNode fan=(FieldAccessNode)an.getDest();
309             ExpressionNode en=fan.getExpression();
310             TempDescriptor dst_tmp=TempDescriptor.tempFactory("dst",en.getType());
311             NodePair np_baseexp=flattenExpressionNode(en, dst_tmp);
312             last.addNext(np_baseexp.getBegin());
313             FlatSetFieldNode fsfn=new FlatSetFieldNode(dst_tmp, fan.getField(), src_tmp);
314             np_baseexp.getEnd().addNext(fsfn);
315             FlatOpNode fon2=new FlatOpNode(out_temp, src_tmp, null, new Operation(Operation.ASSIGN));
316             fsfn.addNext(fon2);
317             return new NodePair(np_src.getBegin(), fon2);
318         } else if (an.getDest().kind()==Kind.ArrayAccessNode) {
319             //We are assigning an array element
320             ArrayAccessNode aan=(ArrayAccessNode)an.getDest();
321             ExpressionNode en=aan.getExpression();
322             ExpressionNode enindex=aan.getIndex();
323             TempDescriptor dst_tmp=TempDescriptor.tempFactory("dst",en.getType());
324             TempDescriptor index_tmp=TempDescriptor.tempFactory("index",enindex.getType());
325             NodePair np_baseexp=flattenExpressionNode(en, dst_tmp);
326             NodePair np_indexexp=flattenExpressionNode(enindex, index_tmp);
327             last.addNext(np_baseexp.getBegin());
328             np_baseexp.getEnd().addNext(np_indexexp.getBegin());
329             FlatSetElementNode fsen=new FlatSetElementNode(dst_tmp, index_tmp, src_tmp);
330             np_indexexp.getEnd().addNext(fsen);
331             FlatOpNode fon2=new FlatOpNode(out_temp, src_tmp, null, new Operation(Operation.ASSIGN));
332             fsen.addNext(fon2);
333             return new NodePair(np_src.getBegin(), fon2);
334         } else if (an.getDest().kind()==Kind.NameNode) {
335             //We could be assigning a field or variable
336             NameNode nn=(NameNode)an.getDest();
337             if (nn.getExpression()!=null) {
338                 //It is a field
339                 FieldAccessNode fan=(FieldAccessNode)nn.getExpression();
340                 ExpressionNode en=fan.getExpression();
341                 TempDescriptor dst_tmp=TempDescriptor.tempFactory("dst",en.getType());
342                 NodePair np_baseexp=flattenExpressionNode(en, dst_tmp);
343                 last.addNext(np_baseexp.getBegin());
344                 FlatSetFieldNode fsfn=new FlatSetFieldNode(dst_tmp, fan.getField(), src_tmp);
345                 np_baseexp.getEnd().addNext(fsfn);
346                 FlatOpNode fon2=new FlatOpNode(out_temp, src_tmp, null, new Operation(Operation.ASSIGN));
347                 fsfn.addNext(fon2);
348                 return new NodePair(np_src.getBegin(), fon2);
349             } else {
350                 if (nn.getField()!=null) {
351                     //It is a field
352                     FlatSetFieldNode fsfn=new FlatSetFieldNode(getTempforVar(nn.getVar()), nn.getField(), src_tmp);
353                     last.addNext(fsfn);
354                     FlatOpNode fon2=new FlatOpNode(out_temp, src_tmp, null, new Operation(Operation.ASSIGN));
355                     fsfn.addNext(fon2);
356                     return new NodePair(np_src.getBegin(), fon2);
357                 } else {
358                     //It is a variable
359                     FlatOpNode fon=new FlatOpNode(getTempforVar(nn.getVar()), src_tmp, null, new Operation(Operation.ASSIGN));
360                     last.addNext(fon);
361                     FlatOpNode fon2=new FlatOpNode(out_temp, src_tmp, null, new Operation(Operation.ASSIGN));
362                     fon.addNext(fon2);
363                     return new NodePair(np_src.getBegin(),fon2);
364                 }
365             }
366         } 
367         throw new Error();
368     }
369
370     private NodePair flattenNameNode(NameNode nn,TempDescriptor out_temp) {
371         if (nn.getExpression()!=null) {
372             /* Hack - use subtree instead */
373             return flattenExpressionNode(nn.getExpression(),out_temp);
374         } else if (nn.getField()!=null) {
375             TempDescriptor tmp=getTempforVar(nn.getVar());
376             FlatFieldNode ffn=new FlatFieldNode(nn.getField(), tmp, out_temp); 
377             return new NodePair(ffn,ffn);
378         } else {
379             TempDescriptor tmp=getTempforVar(nn.getVar());
380             FlatOpNode fon=new FlatOpNode(out_temp, tmp, null, new Operation(Operation.ASSIGN));
381             return new NodePair(fon,fon);
382         }
383     }
384
385     private NodePair flattenOpNode(OpNode on,TempDescriptor out_temp) {
386         TempDescriptor temp_left=TempDescriptor.tempFactory("leftop",on.getLeft().getType());
387         TempDescriptor temp_right=null;
388
389         Operation op=on.getOp();
390         if (op.getOp()==Operation.POSTINC||
391             op.getOp()==Operation.POSTDEC||
392             op.getOp()==Operation.PREINC||
393             op.getOp()==Operation.PREDEC) {
394             LiteralNode ln=new LiteralNode("int",new Integer(1));
395             ln.setType(new TypeDescriptor(TypeDescriptor.INT));
396             
397             AssignmentNode an=new AssignmentNode(on.getLeft(),
398                                                  new OpNode(on.getLeft(),ln, 
399                                                             new Operation((op.getOp()==Operation.POSTINC||op.getOp()==Operation.PREINC)?Operation.PLUS:Operation.MINUS))
400                                                  );
401             if (op.getOp()==Operation.POSTINC||
402                 op.getOp()==Operation.POSTDEC) {
403                 //Can't do, this could have side effects
404                 NodePair left=flattenExpressionNode(on.getLeft(),out_temp);
405                 NodePair assign=flattenAssignmentNode(an,temp_left);
406                 left.getEnd().addNext(assign.getBegin());
407                 return new NodePair(left.getBegin(),assign.getEnd());
408             } else {
409                 NodePair assign=flattenAssignmentNode(an,out_temp);
410                 return assign;
411             }
412         } 
413         
414         NodePair left=flattenExpressionNode(on.getLeft(),temp_left);
415         NodePair right;
416         if (on.getRight()!=null) {
417             temp_right=TempDescriptor.tempFactory("rightop",on.getRight().getType());
418             right=flattenExpressionNode(on.getRight(),temp_right);
419         } else {
420             FlatNop nop=new FlatNop();
421             right=new NodePair(nop,nop);
422         }
423
424         if (op.getOp()==Operation.LOGIC_OR) {
425             /* Need to do shortcircuiting */
426             FlatCondBranch fcb=new FlatCondBranch(temp_left);
427             FlatOpNode fon1=new FlatOpNode(out_temp,temp_left,null,new Operation(Operation.ASSIGN));
428             FlatOpNode fon2=new FlatOpNode(out_temp,temp_right,null,new Operation(Operation.ASSIGN));
429             FlatNop fnop=new FlatNop();
430             left.getEnd().addNext(fcb);
431             fcb.addFalseNext(right.getBegin());
432             right.getEnd().addNext(fon2);
433             fon2.addNext(fnop);
434             fcb.addTrueNext(fon1);
435             fon1.addNext(fnop);
436             return new NodePair(left.getBegin(), fnop);
437         } else if (op.getOp()==Operation.LOGIC_AND) {
438             /* Need to do shortcircuiting */
439             FlatCondBranch fcb=new FlatCondBranch(temp_left);
440             FlatOpNode fon1=new FlatOpNode(out_temp,temp_left,null,new Operation(Operation.ASSIGN));
441             FlatOpNode fon2=new FlatOpNode(out_temp,temp_right,null,new Operation(Operation.ASSIGN));
442             FlatNop fnop=new FlatNop();
443             left.getEnd().addNext(fcb);
444             fcb.addTrueNext(right.getBegin());
445             right.getEnd().addNext(fon2);
446             fon2.addNext(fnop);
447             fcb.addFalseNext(fon1);
448             fon1.addNext(fnop);
449             return new NodePair(left.getBegin(), fnop);
450         }
451
452         FlatOpNode fon=new FlatOpNode(out_temp,temp_left,temp_right,op);
453         left.getEnd().addNext(right.getBegin());
454         right.getEnd().addNext(fon);
455         return new NodePair(left.getBegin(),fon);
456     }
457
458     private NodePair flattenExpressionNode(ExpressionNode en, TempDescriptor out_temp) {
459         switch(en.kind()) {
460         case Kind.AssignmentNode:
461             return flattenAssignmentNode((AssignmentNode)en,out_temp);
462         case Kind.CastNode:
463             return flattenCastNode((CastNode)en,out_temp);
464         case Kind.CreateObjectNode:
465             return flattenCreateObjectNode((CreateObjectNode)en,out_temp);
466         case Kind.FieldAccessNode:
467             return flattenFieldAccessNode((FieldAccessNode)en,out_temp);
468         case Kind.ArrayAccessNode:
469             return flattenArrayAccessNode((ArrayAccessNode)en,out_temp);
470         case Kind.LiteralNode:
471             return flattenLiteralNode((LiteralNode)en,out_temp);
472         case Kind.MethodInvokeNode:
473             return flattenMethodInvokeNode((MethodInvokeNode)en,out_temp);
474         case Kind.NameNode:
475             return flattenNameNode((NameNode)en,out_temp);
476         case Kind.OpNode:
477             return flattenOpNode((OpNode)en,out_temp);
478         }
479         throw new Error();
480     }
481
482     private NodePair flattenDeclarationNode(DeclarationNode dn) {
483         VarDescriptor vd=dn.getVarDescriptor();
484         TempDescriptor td=getTempforVar(vd);
485         if (dn.getExpression()!=null)
486             return flattenExpressionNode(dn.getExpression(),td);
487         else {
488             FlatNop fn=new FlatNop();
489             return new NodePair(fn,fn);
490         }
491     }
492         
493     private TempDescriptor getTempforVar(VarDescriptor vd) {
494         if (temptovar.containsKey(vd))
495             return (TempDescriptor)temptovar.get(vd);
496         else {
497             TempDescriptor td=TempDescriptor.tempFactory(vd.getName(),vd.getType());
498             temptovar.put(vd,td);
499             return td;
500         }
501     }
502
503     private NodePair flattenIfStatementNode(IfStatementNode isn) {
504         TempDescriptor cond_temp=TempDescriptor.tempFactory("condition",new TypeDescriptor(TypeDescriptor.BOOLEAN));
505         NodePair cond=flattenExpressionNode(isn.getCondition(),cond_temp);
506         FlatCondBranch fcb=new FlatCondBranch(cond_temp);
507         NodePair true_np=flattenBlockNode(isn.getTrueBlock());
508         NodePair false_np;
509         FlatNop nopend=new FlatNop();
510
511         if (isn.getFalseBlock()!=null)
512             false_np=flattenBlockNode(isn.getFalseBlock());
513         else {
514             FlatNop nop=new FlatNop();
515             false_np=new NodePair(nop,nop);
516         }
517
518         cond.getEnd().addNext(fcb);
519         fcb.addTrueNext(true_np.getBegin());
520         fcb.addFalseNext(false_np.getBegin());
521         true_np.getEnd().addNext(nopend);
522         false_np.getEnd().addNext(nopend);
523         return new NodePair(cond.getBegin(), nopend);
524     }
525             
526     private NodePair flattenLoopNode(LoopNode ln) {
527         if (ln.getType()==LoopNode.FORLOOP) {
528             NodePair initializer=flattenBlockNode(ln.getInitializer());
529             TempDescriptor cond_temp=TempDescriptor.tempFactory("condition", new TypeDescriptor(TypeDescriptor.BOOLEAN));
530             NodePair condition=flattenExpressionNode(ln.getCondition(),cond_temp);
531             NodePair update=flattenBlockNode(ln.getUpdate());
532             NodePair body=flattenBlockNode(ln.getBody());
533             FlatNode begin=initializer.getBegin();
534             FlatCondBranch fcb=new FlatCondBranch(cond_temp);
535             FlatNop nopend=new FlatNop();
536
537             initializer.getEnd().addNext(condition.getBegin());
538             body.getEnd().addNext(update.getBegin());
539             update.getEnd().addNext(condition.getBegin());
540             condition.getEnd().addNext(fcb);
541             fcb.addFalseNext(nopend);
542             fcb.addTrueNext(body.getBegin());
543             return new NodePair(begin,nopend);
544         } else if (ln.getType()==LoopNode.WHILELOOP) {
545             TempDescriptor cond_temp=TempDescriptor.tempFactory("condition", new TypeDescriptor(TypeDescriptor.BOOLEAN));
546             NodePair condition=flattenExpressionNode(ln.getCondition(),cond_temp);
547             NodePair body=flattenBlockNode(ln.getBody());
548             FlatNode begin=condition.getBegin();
549             FlatCondBranch fcb=new FlatCondBranch(cond_temp);
550             FlatNop nopend=new FlatNop();
551
552             body.getEnd().addNext(condition.getBegin());
553             condition.getEnd().addNext(fcb);
554             fcb.addFalseNext(nopend);
555             fcb.addTrueNext(body.getBegin());
556             return new NodePair(begin,nopend);
557         } else if (ln.getType()==LoopNode.DOWHILELOOP) {
558             TempDescriptor cond_temp=TempDescriptor.tempFactory("condition", new TypeDescriptor(TypeDescriptor.BOOLEAN));
559             NodePair condition=flattenExpressionNode(ln.getCondition(),cond_temp);
560             NodePair body=flattenBlockNode(ln.getBody());
561             FlatNode begin=body.getBegin();
562             FlatCondBranch fcb=new FlatCondBranch(cond_temp);
563             FlatNop nopend=new FlatNop();
564
565             body.getEnd().addNext(condition.getBegin());
566             condition.getEnd().addNext(fcb);
567             fcb.addFalseNext(nopend);
568             fcb.addTrueNext(body.getBegin());
569             return new NodePair(begin,nopend);
570         } else throw new Error();
571     }
572             
573     private NodePair flattenReturnNode(ReturnNode rntree) {
574         TempDescriptor retval=null;
575         NodePair cond=null;
576         if (rntree.getReturnExpression()!=null) {
577             retval=TempDescriptor.tempFactory("ret_value", rntree.getReturnExpression().getType());
578             cond=flattenExpressionNode(rntree.getReturnExpression(),retval);
579         }
580
581         FlatReturnNode rnflat=new FlatReturnNode(retval);
582
583         if (cond!=null) {
584             cond.getEnd().addNext(rnflat);
585             return new NodePair(cond.getBegin(),rnflat);
586         } else
587             return new NodePair(rnflat,rnflat);
588     }
589
590     private NodePair flattenTaskExitNode(TaskExitNode ten) {
591         FlatFlagActionNode ffan=new FlatFlagActionNode(true);
592         updateFlagActionNode(ffan, ten.getFlagEffects());
593         return new NodePair(ffan, ffan);
594     }
595
596     private NodePair flattenSubBlockNode(SubBlockNode sbn) {
597         return flattenBlockNode(sbn.getBlockNode());
598     }
599
600     private NodePair flattenBlockStatementNode(BlockStatementNode bsn) {
601         switch(bsn.kind()) {
602         case Kind.BlockExpressionNode:
603             return flattenBlockExpressionNode((BlockExpressionNode)bsn);
604             
605         case Kind.DeclarationNode:
606             return flattenDeclarationNode((DeclarationNode)bsn);
607             
608         case Kind.IfStatementNode:
609             return flattenIfStatementNode((IfStatementNode)bsn);
610             
611         case Kind.LoopNode:
612             return flattenLoopNode((LoopNode)bsn);
613             
614         case Kind.ReturnNode:
615             return flattenReturnNode((IR.Tree.ReturnNode)bsn);
616
617         case Kind.TaskExitNode:
618             return flattenTaskExitNode((IR.Tree.TaskExitNode)bsn);
619             
620         case Kind.SubBlockNode:
621             return flattenSubBlockNode((SubBlockNode)bsn);
622             
623         }
624         throw new Error();
625     }
626 }