示例#1
0
/* We have inferred type1 and type2 as the actual types for the same
   expression.
   Check that the types are compatible (it cant be both a string and
   an integer, for example), and return the combined type. If they
   are not compatible, return a null pointer.
 */
TypePtr Type::Inferred(AnalysisResultConstPtr ar,
                       TypePtr type1, TypePtr type2) {
  if (!type1) return type2;
  if (!type2) return type1;
  KindOf k1 = type1->m_kindOf;
  KindOf k2 = type2->m_kindOf;

  if (k1 == k2) {
    return k1 == KindOfObject ?
      Type::InferredObject(ar, type1, type2) : type1;
  }

  // If one set is a subset of the other, return the subset.
  if ((k1 & k2) == k1) return type1;
  if ((k1 & k2) == k2) return type2;

  // If one type must be numeric and the other might be, then assume numeric
  if (type1->mustBe(KindOfNumeric) && type2->couldBe(KindOfNumeric)) {
    return type1;
  }
  if (type2->mustBe(KindOfNumeric) && type1->couldBe(KindOfNumeric)) {
    return type2;
  }

  // Otherwise, take the intersection
  int resultKind = type1->m_kindOf & type2->m_kindOf;
  if (resultKind == KindOfObject) {
    return Type::InferredObject(ar, type1, type2);
  }
  return resultKind ? GetType(resultKind) : TypePtr();
}
示例#2
0
/* We have inferred type1 and type2 as the actual types for the same
   expression.
   Check that the types are compatible (it cant be both a string and
   an integer, for example), and return the combined type. If they
   are not compatible, return a null pointer.
 */
TypePtr Type::Inferred(AnalysisResultConstPtr ar,
                       TypePtr type1, TypePtr type2) {
  if (!type1) return type2;
  if (!type2) return type1;
  KindOf k1 = type1->m_kindOf;
  KindOf k2 = type2->m_kindOf;

  if (k1 == k2) return type1;

  // If one set is a subset of the other, return the subset.
  if ((k1 & k2) == k1) return type1;
  if ((k1 & k2) == k2) return type2;

  // If one type must be numeric and the other might be, then assume numeric
  if (type1->mustBe(KindOfNumeric) && type2->couldBe(KindOfNumeric))
    return type1;
  if (type2->mustBe(KindOfNumeric) && type1->couldBe(KindOfNumeric))
    return type2;

  // Otherwise, take the intersection
  int resultKind = type1->m_kindOf & type2->m_kindOf;
  std::string resultName = "";

  if (resultKind & KindOfObject) {
    // if they're the same, or we don't know one's name, then use
    // the other
    if (type1->m_name == type2->m_name || type1->m_name.empty()) {
      resultName = type2->m_name;
    } else if (type2->m_name.empty()) {
      resultName = type1->m_name;
    } else {
      // take the subclass
      ClassScopePtr cls1 = ar->findClass(type1->m_name);
        ClassScopePtr cls2 = ar->findClass(type2->m_name);
      if (cls1 && !cls1->isRedeclaring()
          && cls1->derivesFrom(ar, type2->m_name, true, false)) {
        resultName = type1->m_name;
      } else if (cls2 && !cls2->isRedeclaring()
                 && cls2->derivesFrom(ar, type1->m_name, true, false)) {
        resultName = type2->m_name;
      } else {
        resultKind &= ~KindOfObject;
      }
    }
  }

  if (resultKind)
    return TypePtr(new Type((KindOf)resultKind, resultName));
  else
    return TypePtr();
}