示例#1
0
    /// <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;
    }