CSC448: Clogs Implementation [14/14] Previous pageContents

file:clogs/transform/IntroduceThreeAddressCode.java [source] [doc-public] [doc-private]
00001: package clogs.transform;
00002: 
00003: import clogs.ast.*;
00004: import clogs.util.List;
00005: import clogs.util.Optional;
00006: 
00007: 
00008: public class IntroduceThreeAddressCode extends Phase
00009: {
00010:   public List<ExtDecl> transform (List<ExtDecl> edecls)
00011:   {
00012:     List<ExtDecl> result = List.nil ();
00013: 
00014:     for (ExtDecl edecl : edecls) {
00015:       if (edecl instanceof Decl) {
00016:         Decl decl = (Decl) edecl;
00017:         assert (decl.eo.isEmpty ());
00018:         result = result.snoc (decl);
00019: 
00020:       } else if (edecl instanceof FunDef) {
00021:         FunDef fundef = (FunDef) edecl;
00022:         result = result.snoc (new FunDef (fundef.type, fundef.name, fundef.params, transformBody (fundef.body)));
00023: 
00024:       } else {
00025:         throw new RuntimeException ("Missing ExtDecl case: " + edecl.getClass ().getName ());
00026:       }
00027:     }
00028: 
00029:     return result;
00030:   }
00031: 
00032:   static class DeclsStats
00033:   {
00034:     final List<Decl> decls;
00035:     final List<Stat> stats;
00036: 
00037:     DeclsStats (List<Decl> decls, List<Stat> stats)
00038:     {
00039:       this.decls = decls;
00040:       this.stats = stats;
00041:     }
00042:   }
00043: 
00044: 
00045:   static class DeclsStatsVariable
00046:   {
00047:     final List<Decl> decls;
00048:     final List<Stat> stats;
00049:     final Optional<Exp> oe; // A call to a function with void return type does not produce a result.
00050: 
00051:     DeclsStatsVariable (List<Decl> decls, List<Stat> stats, Optional<Exp> oe)
00052:     {
00053:       assert ((oe.isEmpty ()) || (oe.get () instanceof ExpInt) || (oe.get () instanceof ExpVar));
00054:       this.decls = decls;
00055:       this.stats = stats;
00056:       this.oe = oe;
00057:     }
00058:   }
00059: 
00060: 
00061:   // Write compound statements as
00062:   //   { decls stats }
00063:   //
00064:   // Write instances of DeclsStats as
00065:   //   < decls | stats > 
00066:   //
00067:   // Write instances of DeclsStatsVariable as
00068:   //   < decls | stats | Optional<v> >
00069:   // If the exp must be present, then:
00070:   //   < decls | stats | v >
00071:   //
00072:   // The relevant functions are:
00073:   //   transformBody (({ decls stats })) = { decls' stats' }
00074:   //   transformStat (stat) = < decls | stats >
00075:   //   transformExp (exp) = < decls | stats | Optional<v> >
00076:   //
00077: 
00078:   
00079:   static StatCompound transformBody (StatCompound statC) {
00080:     // transformStat (stat_0) = < decls_0 | stats_0 >
00081:     // ...
00082:     // transformStat (stat_n) = < decls_n | stats_n >
00083:     // -----------------------------------------------------
00084:     // transformBody (({decls stat_0 ... stat_n}))
00085:     //   = { decls decls_0 ... decls_n stats_0 ... stats_m }
00086:     //
00087:     List<Decl> declsNew = List.nil ();
00088:     List<Stat> statsNew = List.nil ();
00089:     for (Stat stat : statC.stats) {
00090:       DeclsStats ds = transformStat (stat);
00091:       declsNew = declsNew.concat (ds.decls);
00092:       statsNew = statsNew.concat (ds.stats);
00093:     }
00094:     return new StatCompound (statC.decls.concat (declsNew), statsNew);
00095:   }
00096: 
00097: 
00098:   static DeclsStats transformStat (Stat stat) {
00099:     List<Decl> declsNew = List.nil ();
00100:     List<Stat> statsNew = List.nil ();
00101: 
00102:     if (stat instanceof StatCompound) {
00103:       // transformBody (statC) = statC'
00104:       // -----------------------------------------------------
00105:       // transformStat (statC) = < nil | statC' >
00106:       //
00107:       StatCompound statC = (StatCompound) stat;
00108:       for (Stat s : statC.stats) {
00109:         DeclsStats ds = transformStat (s);
00110:         declsNew = declsNew.concat (ds.decls);
00111:         statsNew = statsNew.concat (ds.stats);
00112:       }
00113:       statsNew = List.singleton ((Stat)new StatCompound (statC.decls, statsNew));
00114:       statsNew = addLabelsToHead (statsNew, statC.labels);
00115: 
00116:     } else if (stat instanceof StatExp) {
00117:       // transformExp (exp) = < decls | stats | ... >
00118:       // -----------------------------------------------------
00119:       // transformStat ((exp;)) = < decls | stats >
00120:       //
00121:       StatExp statE = (StatExp) stat;
00122:       DeclsStatsVariable sav = transformExp (statE.exp);
00123:       declsNew = declsNew.concat (sav.decls);
00124:       statsNew = statsNew.concat (sav.stats); 
00125:       if (!statE.labels.isNil()) {
00126:         if (statsNew.isNil()) {
00127:           statsNew = statsNew.snoc (new StatSkip());
00128:         }
00129:         statsNew = addLabelsToHead (statsNew, statE.labels);
00130:       }
00131:       
00132:     } else if (stat instanceof StatGoto) {
00133:       // transformStat ((goto exp;)) = < nil | (goto exp;) >
00134:       //
00135:       statsNew = statsNew.snoc (stat);
00136: 
00137:     } else if (stat instanceof StatIf) {
00138:       // transformExp (exp) = < decls | stats | v >
00139:       // -----------------------------------------------------
00140:       // transformStat ((if (exp) goto l1; else goto l2;))
00141:       //   = < decls | stats  (if (v) goto l1; else goto l2;) >
00142:       //
00143:       StatIf statI = (StatIf) stat;
00144:       assert (statI.statT instanceof StatGoto);
00145:       assert (statI.statF instanceof StatGoto);
00146:       DeclsStatsVariable sav = transformExp (statI.exp);
00147:       declsNew = declsNew.concat (sav.decls);
00148:       statsNew = statsNew.concat (sav.stats); 
00149:       statsNew = statsNew.snoc (new StatIf (sav.oe.get (), statI.statT, statI.statF));
00150:       statsNew = addLabelsToHead (statsNew, statI.labels);
00151: 
00152:     } else if (stat instanceof StatReturn) {
00153:       // -----------------------------------------------------
00154:       // transformStat ((return;)) = < nil | (return;) >
00155:       //
00156:       // transformExp (exp) = < decls | stats | v >
00157:       // -----------------------------------------------------------------
00158:       // transformStat ((return exp;)) = < decls | stats (return v;) >
00159:       //
00160:       StatReturn statR = (StatReturn) stat;
00161:       if (statR.oe.isEmpty ()) {
00162:         statsNew = statsNew.snoc (stat);
00163:       } else {
00164:         DeclsStatsVariable sav = transformExp (statR.oe.get ());
00165:         declsNew = declsNew.concat (sav.decls);
00166:         statsNew = statsNew.concat (sav.stats); 
00167:         statsNew = statsNew.snoc (new StatReturn (new Optional<Exp> (sav.oe.get ())));
00168:         statsNew = addLabelsToHead (statsNew, statR.labels);
00169:       }
00170: 
00171:     } else if (stat instanceof StatSkip) {
00172:       // transformStat ((skip;)) = < nil | (skip;) >
00173:       //
00174:       statsNew = statsNew.snoc (stat);
00175: 
00176:     } else if (stat instanceof StatWhile) {
00177:       assert (false);
00178: 
00179:     } else {
00180:       throw new RuntimeException ("Missing Stat case: " + stat.getClass ().getName ());
00181:     }
00182: 
00183:     return new DeclsStats (declsNew, statsNew);
00184:   }
00185: 
00186: 
00187:   static List<Stat> addLabelsToHead (List<Stat> stats, List<String> labels)
00188:   {
00189:     Stat headNew = stats.head ().addLabels (labels);
00190:     return stats.tail ().cons (headNew);
00191:   }
00192: 
00193:   
00194:   static DeclsStatsVariable transformExp (Exp exp) 
00195:   {
00196:     if (exp instanceof ExpArrayAccess) {
00197:       // transformExp (array) = < decls1 | stats1 | v1 >
00198:       // transformExp (index) = < decls2 | stats2 | v2 >
00199:       // ------------------------------------------------------------------------------
00200:       // transformExp ((array[index]) :: resultType)
00201:       //   = < decls1 decls2 (resultType x;) | stats1 stats2 (x = (v1[v2]);) | x >
00202:       //
00203:       ExpArrayAccess expA = (ExpArrayAccess) exp;
00204:       DeclsStatsVariable sav1 = transformExp (expA.array);
00205:       DeclsStatsVariable sav2 = transformExp (expA.index);
00206:       List<Decl> declsNew = sav1.decls.concat (sav2.decls);
00207:       List<Stat> statsNew = sav1.stats.concat (sav2.stats);
00208:       String labelNew = Fresh.getVar () + "_array";
00209:       Exp expNew = new ExpVar (labelNew);
00210:       declsNew = declsNew.snoc (new Decl (expA.to.get (), labelNew, new Optional<Exp> ()));
00211:       statsNew = statsNew.snoc (new StatExp (new ExpAssign (expNew, new ExpArrayAccess (sav1.oe.get (), sav2.oe.get ()))));
00212:       return new DeclsStatsVariable (declsNew, statsNew, new Optional<Exp> (expNew));
00213: 
00214:     } else if (exp instanceof ExpAssign) {
00215:       // transformExp (right) = < decls3 | stats3 | v3 >
00216:       // -----------------------------------------------------
00217:       // transformExp ((x = right))
00218:       //   = < decls3 | stats3 (x = v3;) | v3 >
00219:       //
00220:       // transformExp (array) = < decls1 | stats1 | v1 >
00221:       // transformExp (index) = < decls2 | stats2 | v2 >
00222:       // transformExp (right) = < decls3 | stats3 | v3 >
00223:       // -------------------------------------------------------------------------------
00224:       // transformExp ((array[index] = right))
00225:       //   = < decls1 decls2 decls3 | stats1 stats2 stats3 (v1[v2] = v3;) | v3 >
00226:       //
00227:       ExpAssign expA = (ExpAssign) exp;
00228:       List<Decl> declsNew = List.nil ();
00229:       List<Stat> statsNew = List.nil ();
00230:       Exp left;
00231:       if (expA.left instanceof ExpArrayAccess) {
00232:         ExpArrayAccess expAA = (ExpArrayAccess) expA.left;
00233:         DeclsStatsVariable sav1 = transformExp (expAA.array);
00234:         declsNew = declsNew.concat (sav1.decls);
00235:         statsNew = statsNew.concat (sav1.stats);
00236:         DeclsStatsVariable sav2 = transformExp (expAA.index);
00237:         declsNew = declsNew.concat (sav2.decls);
00238:         statsNew = statsNew.concat (sav2.stats);
00239:         left = new ExpArrayAccess (sav1.oe.get (), sav2.oe.get ());
00240:       } else if (expA.left instanceof ExpVar) {
00241:         left = expA.left;
00242:       } else {
00243:         assert (false); // Impossible to reach this case in a well-typed program.
00244:         left = null;
00245:       } 
00246:       DeclsStatsVariable sav3 = transformExp (expA.right);
00247:       declsNew = declsNew.concat (sav3.decls);
00248:       statsNew = statsNew.concat (sav3.stats);
00249:       statsNew = statsNew.snoc (new StatExp (new ExpAssign (left, sav3.oe.get ())));
00250:       return new DeclsStatsVariable (declsNew, statsNew, sav3.oe);
00251: 
00252:     } else if (exp instanceof ExpBinOp) {
00253:       // transformExp (left)  = < decls1 | stats1 | v1 >
00254:       // transformExp (right) = < decls2 | stats2 | v2 >
00255:       // ----------------------------------------------------------------------------------
00256:       // transformExp ((left op right) :: resultType)
00257:       //   = < decls1 decls2 (resultType x;) | stats1 stats2 (x = (v1 op v2);) | x >
00258:       //
00259:       ExpBinOp expB = (ExpBinOp) exp;
00260:       DeclsStatsVariable sav1 = transformExp (expB.left);
00261:       DeclsStatsVariable sav2 = transformExp (expB.right);
00262:       List<Decl> declsNew = sav1.decls.concat (sav2.decls);
00263:       List<Stat> statsNew = sav1.stats.concat (sav2.stats);
00264:       String labelNew = Fresh.getVar () + "_binop";
00265:       Exp expNew = new ExpVar (labelNew);
00266:       declsNew = declsNew.snoc (new Decl (expB.to.get (), labelNew, new Optional<Exp> ()));
00267:       statsNew = statsNew.snoc (new StatExp (new ExpAssign (expNew, new ExpBinOp (expB.op, sav1.oe.get (), sav2.oe.get ()))));
00268:       return new DeclsStatsVariable (declsNew, statsNew, new Optional<Exp> (expNew));
00269: 
00270:     } else if (exp instanceof ExpComma) {
00271:       // transformExp (left)  = < decls1 | stats1 | Optional<exp1> >
00272:       // transformExp (right) = < decls2 | stats2 | Optional<exp2> >
00273:       // -----------------------------------------------------------
00274:       // transformExp ((left , right))
00275:       //   = < decls1 decls2 | stats1 stats2 | Optional<exp2> >
00276:       //
00277:       ExpComma expC = (ExpComma) exp;
00278:       DeclsStatsVariable sav1 = transformExp (expC.left);
00279:       DeclsStatsVariable sav2 = transformExp (expC.right);
00280:       List<Decl> declsNew = sav1.decls.concat (sav2.decls);
00281:       List<Stat> statsNew = sav1.stats.concat (sav2.stats);
00282:       return new DeclsStatsVariable (declsNew, statsNew, sav2.oe);
00283: 
00284:     } else if (exp instanceof ExpFunCall) {
00285:       // transformExp (arg1) = < decls1 | stats1 | v1 >
00286:       // ...
00287:       // transformExp (argn) = < declsn | statsn | vn >
00288:       // -------------------------------------------------------------------------
00289:       // transformExp ((name(arg1,...,argn)) :: void)
00290:       //   = < decls1 ... declsn | stats1 ... statsn (name(v1,...,vn)) | nil >
00291:       // AND
00292:       // transformExp ((name(arg1,...,argn)) :: resultType)
00293:       //   = < decls1 ... declsn (resultType x;) | stats1 ... statsn (x = (name(v1,...,vn))) | x >
00294:       //
00295:       ExpFunCall expF = (ExpFunCall) exp;
00296:       List<Decl> declsNew = List.nil ();
00297:       List<Stat> statsNew = List.nil ();
00298:       List<Exp> argsNew = List.nil ();
00299:       for (Exp exp2 : expF.args) {
00300:         DeclsStatsVariable sav1 = transformExp (exp2);
00301:         declsNew = declsNew.concat (sav1.decls);
00302:         statsNew = statsNew.concat (sav1.stats);
00303:         argsNew = argsNew.snoc (sav1.oe.get ());
00304:       }
00305:       if (expF.to.get () instanceof TypeVoid) {
00306:         statsNew = statsNew.snoc (new StatExp (new ExpFunCall (expF.name, argsNew)));
00307:         return new DeclsStatsVariable (declsNew, statsNew, new Optional<Exp> ());
00308:       } else {
00309:         String labelNew = Fresh.getVar () + "_funcall";
00310:         Exp expNew = new ExpVar (labelNew);
00311:         declsNew = declsNew.snoc (new Decl (expF.to.get (), labelNew, new Optional<Exp> ()));
00312:         statsNew = statsNew.snoc (new StatExp (new ExpAssign (expNew, new ExpFunCall (expF.name, argsNew))));
00313:         return new DeclsStatsVariable (declsNew, statsNew, new Optional<Exp> (expNew));
00314:       }
00315: 
00316:     } else if (exp instanceof ExpInt) {
00317:       // -----------------------------------------------------
00318:       // transformExp (n) = < nil | nil | n >
00319:       //
00320:       return new DeclsStatsVariable (List.<Decl>nil (), List.<Stat>nil (), new Optional<Exp> (exp));
00321: 
00322:     } else if (exp instanceof ExpNew) {
00323:       // transformExp (size) = < decls | stats | v >
00324:       // -----------------------------------------------------
00325:       // transformExp ((new contentType[size];))
00326:       //   = < decls (contentType[] x;) | stats (x = (new contentType[v]);) | x >
00327:       //
00328:       ExpNew expN = (ExpNew) exp;
00329:       DeclsStatsVariable sav = transformExp (expN.size);
00330:       List<Decl> declsNew = sav.decls;
00331:       List<Stat> statsNew = sav.stats;
00332:       String labelNew = Fresh.getVar () + "_new";
00333:       Exp expNew = new ExpVar (labelNew);
00334:       declsNew = declsNew.snoc (new Decl (new TypeArray (expN.contentType), labelNew, new Optional<Exp> ()));
00335:       statsNew = statsNew.snoc (new StatExp (new ExpAssign (expNew, new ExpNew (expN.contentType, sav.oe.get ()))));
00336:       return new DeclsStatsVariable (declsNew, statsNew, new Optional<Exp> (expNew));
00337: 
00338:     } else if (exp instanceof ExpString) {
00339:       // -----------------------------------------------------
00340:       // transformExp (("value"))
00341:       //   = < (int[] x;) | (x = ("value");) | x >
00342:       //
00343:       ExpString expS = (ExpString) exp;
00344:       String labelNew = Fresh.getVar () + "_string_literal";
00345:       Exp expNew = new ExpVar (labelNew);
00346:       List<Decl> declsNew = List.nil ();
00347:       List<Stat> statsNew = List.nil ();
00348:       declsNew = declsNew.snoc (new Decl (new TypeArray (new TypeInt ()), labelNew, new Optional<Exp> ()));
00349:       statsNew = statsNew.snoc (new StatExp (new ExpAssign (expNew, new ExpString (expS.value))));
00350:       return new DeclsStatsVariable (declsNew, statsNew, new Optional<Exp> (expNew));
00351: 
00352:     } else if (exp instanceof ExpUnOp) {
00353:       // transformExp (exp) = < decls | stats | v >
00354:       // ------------------------------------------------------------
00355:       // transformExp ((unop exp) :: resultType)
00356:       //   = < decls (resultType x;) | stats (x = (unop v);) | x >
00357:       //
00358:       ExpUnOp expU = (ExpUnOp) exp;
00359:       DeclsStatsVariable sav = transformExp (expU.exp);
00360:       List<Decl> declsNew = sav.decls;
00361:       List<Stat> statsNew = sav.stats;
00362:       String labelNew = Fresh.getVar () + "_unop";
00363:       Exp expNew = new ExpVar (labelNew);
00364:       declsNew = declsNew.snoc (new Decl (expU.to.get (), labelNew, new Optional<Exp> ()));
00365:       statsNew = statsNew.snoc (new StatExp (new ExpAssign (expNew, new ExpUnOp (expU.op, sav.oe.get ()))));
00366:       return new DeclsStatsVariable (declsNew, statsNew, new Optional<Exp> (expNew));
00367: 
00368:     } else if (exp instanceof ExpVar) {
00369:       // -----------------------------------------------------
00370:       // transformExp (x) = < nil | nil | x >
00371:       //
00372:       return new DeclsStatsVariable (List.<Decl>nil (), List.<Stat>nil (), new Optional<Exp> (exp));
00373: 
00374:     } else {
00375:       throw new RuntimeException ("Missing Exp case: " + exp.getClass ().getName ());
00376:     }
00377:   }
00378: }
00379: 

Previous pageContents