public override HeronValue As(HeronType t) { if (type.name == t.name) { return(obj); } if (type is ClassDefn) { ClassInstance inst = obj as ClassInstance; if (inst == null) { throw new Exception("Expected an instance of a class"); } return(inst.As(t)); } else if (type is InterfaceDefn) { InterfaceInstance ii = obj as InterfaceInstance; if (ii == null) { throw new Exception("Expected an instance of an interface"); } return(ii.As(t)); } else if (type is DotNetClass) { if (!(t is DotNetClass)) { throw new Exception("External objects can only be cast to the type 'DotNetClass'"); } if (t.Equals(type)) { return(obj); } } else if (t.name == "Any") { return(this); } else { Type from = type.GetSystemType(); Type to = t.GetSystemType(); if (from != null && to != null && to.IsAssignableFrom(from)) { return(obj); } } return(null); }
public override HeronValue As(HeronType t) { if (type.name == t.name) return obj; if (type is ClassDefn) { ClassInstance inst = obj as ClassInstance; if (inst == null) throw new Exception("Expected an instance of a class"); return inst.As(t); } else if (type is InterfaceDefn) { InterfaceInstance ii = obj as InterfaceInstance; if (ii == null) throw new Exception("Expected an instance of an interface"); return ii.As(t); } else if (type is DotNetClass) { if (!(t is DotNetClass)) throw new Exception("External objects can only be cast to the type 'DotNetClass'"); if (t.Equals(type)) return obj; } else if (t.name == "Any") { return this; } else { Type from = type.GetSystemType(); Type to = t.GetSystemType(); if (from != null && to != null && to.IsAssignableFrom(from)) return obj; } return null; }
/// <summary> /// Given a list of arguments, it looks at the types and tries to find out which function /// in this list is the best match. /// </summary> /// <param name="list"></param> /// <param name="funcs"></param> /// <returns></returns> public FunctionValue FindBestMatch(List <FunctionValue> list, HeronValue[] args) { // Each iteration removes candidates. This list holds all of the matches // Necessary, because removing items from a list while we iterate it is hard. List <FunctionValue> tmp = new List <FunctionValue>(list); for (int pos = 0; pos < args.Length; ++pos) { // On each iteration, update the main list, to only contain the remaining items list = new List <FunctionValue>(tmp); HeronValue arg = args[pos]; HeronType argType; if (arg is AnyValue) { argType = (arg as AnyValue).GetHeldType(); } else { argType = arg.Type; } for (int i = 0; i < list.Count; ++i) { FunctionValue fo = list[i]; HeronType formalType = fo.GetFormalType(pos); if (!formalType.Equals(argType)) { tmp.Remove(fo); } } if (tmp.Count == 0) { throw new Exception("Could not resolve function " + name + " no function matches perfectly"); } // We found a single best match if (tmp.Count == 1) { return(tmp[0]); } } Debug.Assert(tmp.Count > 1); // There are multiple functions // Choose the function which is the most derived type. // This is a pretty awful hack to make up for a bad design. int n = 0; FunctionValue best = null; foreach (FunctionValue fv in list) { int depth = fv.GetDefn().parent.GetHierarchyDepth(); if (depth > n) { n = depth; best = fv; } else if (depth == n) { // Ambiguous match at this depth. best = null; } } if (best == null) { throw new Exception("Ambiguous function match"); } return(best); }