/// <summary> /// Computes an upper bound in the type hierarchy for the set of argument types. /// This upper bound is a type that all types in the list are assignable to. /// If the types are all classes, then *the* least-upper-bound in the class /// hierarchy is returned. /// If the types contain at least one interface, then *a* deepest upper-bound /// is found from the intersection of the upward closure of each type. /// Note that if one of the types is System.Object, then that is immediately /// returned as the unified type without further examination of the list. /// </summary> /// <param name="ts">A list containing the set of types from which to compute the unified type.</param> /// <returns>The type corresponding to the least-upper-bound.</returns> public virtual TypeNode UnifiedType(TypeNodeList ts, TypeViewer typeViewer){ if (ts == null || ts.Count == 0) return null; TypeNode unifiedType = SystemTypes.Object; // default unified type bool atLeastOneInterface = false; #region If at least one of the types is System.Object, then that is the unified type for (int i = 0, n = ts.Count; i < n; i++){ TypeNode t = this.Unwrap(ts[i]); if (t == SystemTypes.Object){ return SystemTypes.Object; } } #endregion If at least one of the types is System.Object, then that is the unified type // assert forall{TypeNode t in ts; t != SystemTypes.Object}; #region See if any of the types are interfaces for (int i = 0, n = ts.Count; i < n; i++){ TypeNode t = this.Unwrap(ts[i]); if (t.NodeType == NodeType.Interface){ atLeastOneInterface = true; break; } } #endregion See if any of the types are interfaces #region Find the LUB in the class hierarchy (if there are no interfaces) if (!atLeastOneInterface){ TrivialHashtable h = new TrivialHashtable(ts.Count); // Create the list [s, .., t] for each element t of ts where for each item // in the list, t_i, t_i = t_{i+1}.BaseType. (s.BaseType == SystemTypes.Object) // Store the list in a hashtable keyed by t. // Do this only for classes. Handle interfaces in a different way because of // multiple inheritance. for (int i = 0, n = ts.Count; i < n; i++){ TypeNodeList tl = new TypeNodeList(); TypeNode t = this.Unwrap(ts[i]); tl.Add(t); TypeNode t2 = t.BaseType; while (t2 != null && t2 != SystemTypes.Object){ // avoid including System.Object in the list for classes tl.Insert(t2,0); t2 = this.Unwrap(t2.BaseType); } h[ts[i].UniqueKey] = tl; } bool stop = false; int depth = 0; while (!stop){ TypeNode putativeUnifiedType = null; int i = 0; int n = ts.Count; putativeUnifiedType = ((TypeNodeList) h[ts[0].UniqueKey])[depth]; while (i < n){ TypeNode t = ts[i]; TypeNodeList subTypes = (TypeNodeList) h[t.UniqueKey]; if (subTypes.Count <= depth || subTypes[depth] != putativeUnifiedType){ // either reached the top of the hierarchy for t_i or it is on a different branch // than the current one. stop = true; break; } i++; } if (i == n){ // made it all the way through: all types are subtypes of the current one unifiedType = putativeUnifiedType; } depth++; } } #endregion Find the LUB in the class hierarchy (if there are no interfaces) #region Find *a* LUB in the interface hierarchy (if there is at least one interface or current LUB is object) if (unifiedType == SystemTypes.Object || atLeastOneInterface){ TrivialHashtable interfaces = new TrivialHashtable(); for (int i = 0, n = ts.Count; i < n; i++){ InterfaceList il = new InterfaceList(); interfaces[ts[i].UniqueKey] = il; this.SupportedInterfaces(ts[i],il,typeViewer); // side-effect: il gets added to } // interfaces[ts[i]] is the upward closure of all of the interfaces supported by ts[i] // compute the intersection of all of the upward closures // might as well start with the first type in the list ts InterfaceList intersection = new InterfaceList(); InterfaceList firstIfaceList = (InterfaceList)interfaces[ts[0].UniqueKey]; for (int i = 0, n = firstIfaceList.Count; i < n; i++){ Interface iface = firstIfaceList[i]; bool found = false; int j = 1; // start at second type in the list ts while (j < ts.Count){ InterfaceList cur = (InterfaceList)interfaces[ts[j].UniqueKey]; found = false; for (int k = 0, p = cur.Count; k < p; k++){ if (cur[k] == iface){ found = true; break; } } if (!found){ // then the j-th type doesn't support iface, don't bother looking in the rest break; } j++; } if (found){ intersection.Add(iface); } } // TODO: take the "deepest" interface in the intersection. // "deepest" means that if any other type in the intersection is a subtype // of it, then *don't* consider it. if (intersection.Count > 0){ InterfaceList finalIntersection = new InterfaceList(intersection.Count); Interface iface = intersection[0]; for (int i = 0, n = intersection.Count; i < n; i++){ Interface curFace = intersection [i]; int j = 0; int m = intersection.Count; while (j < m){ if (j != i){ Interface jFace = intersection[j]; if (TypeViewer.GetTypeView(typeViewer, jFace).IsAssignableTo(curFace)) break; } j++; } if (j == m){ // made it all the way through, no other iface is a subtype of curFace finalIntersection.Add(curFace); } } if (finalIntersection.Count > 0){ unifiedType = finalIntersection[0]; // heuristic: just take the first one } } } #endregion Find *a* LUB in the interface hierarchy (if there is at least one interface or current LUB is object) return unifiedType; }