/// 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 { /// /// All CatKinds should be immutable. This avoids a lot of problems and confusion. /// abstract public class CatKind { public static int gnId = 0; public static CatKind Create(AstType node) { if (node is AstSimpleType) { string s = node.ToString(); Trace.Assert(s.Length > 0); if (s.Length > 1 && s[0] == '_') return CatCustomKind.GetCustomKind(s); else return new CatSimpleTypeKind(s); } else if (node is AstTypeVar) { return new CatTypeVar(node.ToString()); } else if (node is AstStackVar) { return new CatStackVar(node.ToString()); } else if (node is AstFxnType) { return new CatFxnType(node as AstFxnType); } else { throw new Exception("unrecognized kind " + node.ToString()); } } public CatKind() { } public override string ToString() { throw new Exception("ToString must be overridden"); } public virtual string ToIdString() { return ToString(); } public abstract bool Equals(CatKind k); public virtual bool IsSubtypeOf(CatKind k) { if (k.ToString().Equals("any")) return true; return this.Equals(k); } public bool IsKindVar() { return (this is CatTypeVar) || (this is CatStackVar); } public static string TypeNameFromObject(Object o) { if (o is HashList) return "hash_list"; if (o is CatList) return "list"; if (o is Boolean) return "bool"; if (o is int) return "int"; if (o is Double) return "double"; if (o is string) return "string"; if (o is Byte) return "byte"; if (o is Primitives.Bit) return "bit"; if (o is Function) return (o as Function).GetFxnTypeString(); if (o is Char) return "char"; return "any"; } public static string TypeToString(Type t) { // TODO: fix this up. I don't like where it is. switch (t.Name) { case ("HashList"): return "hash_list"; case ("Int32"): return "int"; case ("Double"): return "double"; case ("FList"): return "list"; case ("Object"): return "any"; case ("Function"): return "fun"; case ("Boolean"): return "bool"; case ("String"): return "string"; case ("Char"): return "char"; default: return t.Name; } } public static CatKind GetKindFromObject(object o) { if (o is CatObject) return (o as CatObject).GetClass(); if (o is Function) return (o as Function).GetFxnType(); return new CatSimpleTypeKind(TypeNameFromObject(o)); } public virtual bool IsAny() { return false; } public virtual bool IsDynFxn() { return false; } public abstract IEnumerable GetChildKinds(); public abstract IEnumerable GetDescendantKinds(); } /// /// Base class for the different Cat types /// public abstract class CatTypeKind : CatKind { public CatTypeKind() { } } public class CatSimpleTypeKind : CatTypeKind { string msName; public CatSimpleTypeKind(string s) { msName = s; } public override string ToString() { return msName; } public override bool Equals(CatKind k) { return (k is CatSimpleTypeKind) && (msName == k.ToString()); } public override bool IsSubtypeOf(CatKind k) { if (Equals(k)) return true; // meta_int is a subtype of int // and meta_bool is a subtype of bool // and so on. if (msName.IndexOf("meta_") == 0) { string s = k.ToString(); if (s.Length == 0) throw new Exception("missing type name"); if (msName.IndexOf(s) == 5) return true; } return false; } public override bool IsAny() { return msName.Equals("any"); } public override bool IsDynFxn() { return msName.Equals("fun"); } public override IEnumerable GetChildKinds() { yield return this; } public override IEnumerable GetDescendantKinds() { yield return this; } } public class CatTypeVar : CatTypeKind { string msName; public CatTypeVar(string s) { msName = s; } public override string ToString() { return "'" + msName; } public static CatTypeVar CreateUnique() { return new CatTypeVar("t$" + (gnId++).ToString()); } public override bool Equals(CatKind k) { if (!(k is CatTypeVar)) return false; return ToString().CompareTo(k.ToString()) == 0; } public override IEnumerable GetChildKinds() { yield return this; } public override IEnumerable GetDescendantKinds() { yield return this; } } public abstract class CatStackKind : CatKind { } public class CatTypeVector : CatStackKind { List mList; public CatTypeVector(AstStack node) { mList = new List(); foreach (AstType tn in node.mTypes) mList.Add(Create(tn)); } public CatTypeVector() { mList = new List(); } public CatTypeVector(CatTypeVector k) { mList = new List(k.mList); } public CatTypeVector(List list) { mList = new List(list); } /// /// This is a reversed stack, position [0] is the bottom. /// public List GetKinds() { return mList; } public IEnumerable GetRevKinds() { for (int i = mList.Count - 1; i >= 0; --i) yield return mList[i]; } public void Add(CatKind k) { Trace.Assert(k != null); if (k is CatTypeVector) mList.AddRange((k as CatTypeVector).GetKinds()); else mList.Add(k); } public void PushKindBottom(CatKind k) { Trace.Assert(k != null); if (k is CatTypeVector) mList.InsertRange(0, (k as CatTypeVector).GetKinds()); else mList.Insert(0, k); } public bool IsEmpty() { return mList.Count == 0; } public CatKind GetBottom() { if (mList.Count > 0) return mList[0]; else return null; } public CatKind GetTop() { if (mList.Count > 0) return mList[mList.Count - 1]; else return null; } public CatTypeVector GetRest() { return new CatTypeVector(mList.GetRange(0, mList.Count - 1)); } public override string ToString() { string ret = ""; foreach (CatKind k in mList) ret += " " + k.ToString(); if (mList.Count > 0) return ret.Substring(1); else return ""; } public override string ToIdString() { string ret = ""; foreach (CatKind k in mList) ret += " " + k.ToIdString(); if (mList.Count > 0) return ret.Substring(1); else return ""; } public override bool Equals(CatKind k) { if (!(k is CatTypeVector)) return false; CatTypeVector v1 = this; CatTypeVector v2 = k as CatTypeVector; while (!v1.IsEmpty() && !v2.IsEmpty()) { CatKind t1 = v1.GetTop(); CatKind t2 = v2.GetTop(); if (!t1.Equals(t2)) return false; v1 = v1.GetRest(); v2 = v2.GetRest(); } if (!v1.IsEmpty()) return false; if (!v2.IsEmpty()) return false; return true; } public override bool IsSubtypeOf(CatKind k) { if (k.IsAny()) return true; if (k is CatStackVar) return true; if (!(k is CatTypeVector)) return false; CatTypeVector v1 = this; CatTypeVector v2 = k as CatTypeVector; while (!v1.IsEmpty() && !v2.IsEmpty()) { CatKind t1 = v1.GetTop(); CatKind t2 = v2.GetTop(); if (!t1.IsSubtypeOf(t2)) return false; v1 = v1.GetRest(); v2 = v2.GetRest(); } // v1 has to be at least as long to be a subtype if (v1.IsEmpty() && !v2.IsEmpty()) return false; return true; } public CatTypeVector Clone() { CatTypeVector ret = new CatTypeVector(); foreach (CatKind k in GetKinds()) ret.Add(k); return ret; } public void RemoveBottom() { GetKinds().RemoveAt(0); } public override IEnumerable GetChildKinds() { foreach (CatKind k in GetKinds()) yield return k; } public override IEnumerable GetDescendantKinds() { foreach (CatKind k in GetKinds()) foreach (CatKind j in k.GetDescendantKinds()) yield return j; } public bool IsValid() { foreach (CatKind k in GetKinds()) if (k is CatTypeVector) return false; return true; } } public class CatStackVar : CatStackKind { string msName; public CatStackVar(string s) { msName = s; } public override string ToString() { return "'" + msName; } public static CatStackVar CreateUnique() { return new CatStackVar("R$" + (gnId++).ToString()); } public override bool Equals(CatKind k) { if (!(k is CatStackVar)) return false; return k.ToString() == this.ToString(); } public override IEnumerable GetChildKinds() { yield return this; } public override IEnumerable GetDescendantKinds() { yield return this; } } public class CatCustomKind : CatKind { int mnId; static List gpPool = new List(); public CatCustomKind() { mnId = gpPool.Count; gpPool.Add(this); } public int GetId() { return mnId; } public override string ToString() { return "_" + mnId.ToString(); } public static CatCustomKind GetCustomKind(int n) { return gpPool[n]; } public static CatCustomKind GetCustomKind(string s) { Trace.Assert(s.Length > 1); Trace.Assert(s[0] == '_'); int n = Int32.Parse(s.Substring(1)); return GetCustomKind(n); } public override bool Equals(CatKind k) { if (!(k is CatCustomKind)) return false; if ((k as CatCustomKind).GetId() == GetId()) { Trace.Assert(k == this); return true; } else { return false; } } public override IEnumerable GetChildKinds() { yield return this; } public override IEnumerable GetDescendantKinds() { yield return this; } } public class CatMetaValue : CatCustomKind { T mData; CatSimpleTypeKind mpSuperType = new CatSimpleTypeKind(TypeToString(typeof(T))); public CatMetaValue(T x) { mData = x; } public T GetData() { return mData; } public override bool Equals(CatKind k) { if (k == this) return true; if (!(k is CatMetaValue)) return false; CatMetaValue tmp = k as CatMetaValue; return tmp.GetData().Equals(mData); } public CatKind GetSuperType() { return mpSuperType; } public override bool IsSubtypeOf(CatKind k) { if (k is CatSimpleTypeKind) return GetSuperType().IsSubtypeOf(k); return this.Equals(k); } public override IEnumerable GetChildKinds() { yield return this; } public override IEnumerable GetDescendantKinds() { yield return this; } public override string ToString() { //return "meta_" + TypeToString(typeof(T)); return mData.ToString(); } } }