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