/// Dedicated to the public domain by Christopher Diggins /// http://creativecommons.org/licenses/publicdomain/ using System; using System.Collections.Generic; using System.Text; using System.Diagnostics; namespace Cat { /// /// The renamer assigns new names to a set of variables either from a supplied /// dictionary or by generating unique names. /// public class CatVarRenamer { int mnId = 0; CatTypeVarList mNames; #region constructors public CatVarRenamer() { mNames = new CatTypeVarList(); } #endregion #region static functions public static bool IsStackVarName(string s) { Trace.Assert(s.Length > 0); Trace.Assert(s[0] == '\''); char c = s[1]; if (char.IsLower(c)) return false; else return true; } public CatKind GenerateNewVar(string s) { if (IsStackVarName(s)) return new CatStackVar("S" + (mnId++).ToString()); else return new CatTypeVar("t" + (mnId++).ToString()); } #endregion /// /// This forgets previously generated names, but assures that new names generated will be unique. /// public void ResetNames() { mNames.Clear(); } public static CatFxnType RenameVars(CatFxnType ft) { return (new CatVarRenamer()).Rename(ft); } public CatKind Rename(CatKind k) { if (k is CatFxnType) return Rename(k as CatFxnType); else if (k is CatTypeKind) return Rename(k as CatTypeKind); else if (k is CatStackVar) return Rename(k as CatStackVar); else if (k is CatTypeVector) return Rename(k as CatTypeVector); else if (k is CatCustomKind) return k; else if (k is CatRecursiveType) return k; else throw new Exception(k.ToString() + " is an unrecognized kind"); } public CatFxnType Rename(CatFxnType f) { if (f == null) throw new Exception("Invalid null parameter to rename function"); return new CatFxnType(Rename(f.GetCons()), Rename(f.GetProd()), f.HasSideEffects()); } public CatTypeVector Rename(CatTypeVector s) { CatTypeVector ret = new CatTypeVector(); foreach (CatKind k in s.GetKinds()) ret.Add(Rename(k)); return ret; } public CatStackKind Rename(CatStackVar s) { string sName = s.ToString(); if (mNames.ContainsKey(sName)) { CatKind tmp = mNames[sName]; if (!(tmp is CatStackKind)) throw new Exception(sName + " is not a stack kind"); return tmp as CatStackKind; } CatStackVar var = GenerateNewVar(sName) as CatStackVar; mNames.Add(sName, var); return var; } public CatTypeKind Rename(CatTypeKind t) { if (t == null) throw new Exception("Invalid null parameter to rename function"); if (t is CatFxnType) { return Rename(t as CatFxnType); } else if (t is CatTypeVar) { string sName = t.ToString(); if (mNames.ContainsKey(sName)) { CatTypeKind ret = mNames[sName] as CatTypeKind; if (ret == null) throw new Exception(sName + " is not a type kind"); return ret; } CatTypeVar var = GenerateNewVar(sName) as CatTypeVar; mNames.Add(sName, var); return var; } else { return t; } } public static bool DoesVarOccurIn(CatKind k, CatTypeVector vec, CatFxnType except) { foreach (CatKind tmp in vec.GetKinds()) { if (tmp.IsKindVar() && tmp.Equals(k)) return true; if (tmp is CatFxnType) if (DoesVarOccurIn(k, tmp as CatFxnType, except)) return true; } return false; } public static bool DoesVarOccurIn(CatKind k, CatFxnType ft, CatFxnType except) { if (!k.IsKindVar()) return false; if (k == except) return false; return DoesVarOccurIn(k, ft.GetCons(), except) || DoesVarOccurIn(k, ft.GetProd(), except); } public static bool IsFreeVar(CatKind k, CatFxnType left, CatFxnType right, CatFxnType except) { return !DoesVarOccurIn(k, left, except) && !DoesVarOccurIn(k, right, except); } public static CatFxnType RenameFreeVars(CatFxnType left, CatFxnType right, CatFxnType ft) { CatTypeVarList vars = ft.GetAllVars(); foreach (string s in vars.Keys) { CatKind k = vars[s]; if (IsFreeVar(k, left, right, ft)) { if (k is CatTypeVar) vars[s] = CatTypeVar.CreateUnique(); else vars[s] = CatStackVar.CreateUnique(); } } return RenameVars(ft, vars); } static CatTypeVector RenameVars(CatTypeVector vec, CatTypeVarList vars) { CatTypeVector ret = new CatTypeVector(); foreach (CatKind k in vec.GetKinds()) { if (k.IsKindVar() && vars.ContainsKey(k.ToString())) ret.Add(vars[k.ToString()]); else if (k is CatFxnType) ret.Add(RenameVars(ret, vars)); else if (k is CatTypeVector) throw new Exception("unexpected type vector in function during renaming"); else ret.Add(k); } return ret; } static CatFxnType RenameVars(CatFxnType ft, CatTypeVarList vars) { return new CatFxnType(RenameVars(ft.GetCons(), vars), RenameVars(ft.GetProd(), vars), ft.HasSideEffects()); } } }