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: