00001: package clogs.transform;
00002: 
00003: import clogs.ast.*;
00004: import clogs.staticanalysis.GatherLabelsInStat;
00005: import clogs.util.List;
00006: import clogs.util.Map;
00007: import clogs.util.Optional;
00008: 
00009: 
00010: public class RenameLabelsUniquely extends Phase
00011: {
00012:   public List<ExtDecl> transform (List<ExtDecl> edecls)
00013:   {
00014:     List<ExtDecl> result = List.nil ();
00015: 
00016:     for (ExtDecl edecl : edecls) {
00017:       if (edecl instanceof Decl) {
00018:         result = result.snoc (edecl);
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: 
00033:   StatCompound transformBody (StatCompound statC) {
00034:     GatherLabelsInStat glisc = new GatherLabelsInStat ();
00035:     glisc.gather (statC);
00036:     Map<String, String> labelRenaming = Map.empty ();
00037:     for (String oldLabel : glisc.labelsDefined) {
00038:       String newLabel = Fresh.getLabel (oldLabel);
00039:       labelRenaming = labelRenaming.add (oldLabel, newLabel);
00040:     }
00041: 
00042:     List<Stat> statsNew = List.nil ();
00043:     for (Stat stat : statC.stats) {
00044:       statsNew = statsNew.snoc (transformStat (labelRenaming, stat));
00045:     }
00046: 
00047:     return new StatCompound (statC.decls, statsNew);
00048:   }
00049: 
00050: 
00051:   Stat transformStat (Map<String, String> labelRenaming, Stat stat) 
00052:   {
00053:     List<String> newLabels = List.nil ();
00054:     for (String oldLabel : stat.labels) {
00055:       newLabels = newLabels.snoc (labelRenaming.get (oldLabel));
00056:     }
00057: 
00058:     if (stat instanceof StatCompound) {
00059:       StatCompound statC = (StatCompound) stat;
00060:       List<Stat> statsNew = List.nil ();
00061:       for (Stat s : statC.stats) {
00062:         statsNew = statsNew.snoc (transformStat (labelRenaming, s));
00063:       }
00064:       return new StatCompound (statC.decls, statsNew).removeLabels ().addLabels (newLabels); 
00065: 
00066:     } else if (stat instanceof StatExp) {
00067:       return stat.removeLabels ().addLabels (newLabels);
00068: 
00069:     } else if (stat instanceof StatGoto) {
00070:       StatGoto statG = (StatGoto) stat;
00071:       return new StatGoto (labelRenaming.get (statG.target)).removeLabels ().addLabels (newLabels);
00072: 
00073:     } else if (stat instanceof StatIf) {
00074:       StatIf statI = (StatIf) stat;
00075:       return new StatIf (statI.exp, transformStat (labelRenaming, statI.statT), transformStat (labelRenaming, statI.statF)).removeLabels ().addLabels (newLabels);
00076: 
00077:     } else if (stat instanceof StatReturn) {
00078:       return stat.removeLabels ().addLabels (newLabels);
00079: 
00080:     } else if (stat instanceof StatSkip) {
00081:       return stat.removeLabels ().addLabels (newLabels);
00082: 
00083:     } else if (stat instanceof StatWhile) {
00084:       StatWhile statW = (StatWhile) stat;
00085:       return new StatWhile (statW.exp, transformStat (labelRenaming, statW.stat)).removeLabels ().addLabels (newLabels);
00086: 
00087:     } else {
00088:       throw new RuntimeException ("Missing Stat case: " + stat.getClass ().getName ());
00089:     }
00090:   }
00091: }
00092: 
00093: