Пример #1
0
Type Type::operator|(Type b) const {
  auto a = *this;

  // Representing types like {Int<12>|Arr} could get messy and isn't useful in
  // practice, so unless we're unioning a constant type with itself or Bottom,
  // drop the constant value(s).
  if (a == b || b == Bottom) return a;
  if (a == Bottom) return b;

  a = a.dropConstVal();
  b = b.dropConstVal();

  return combine<Union>(a.m_bits | b.m_bits, a, b);
}
Пример #2
0
Type Type::operator|(Type rhs) const {
  auto lhs = *this;

  if (lhs == rhs || rhs == TBottom) return lhs;
  if (lhs == TBottom) return rhs;

  // Representing types like {Int<12>|Arr} could get messy and isn't useful in
  // practice, so unless we hit one of the trivial cases above, drop the
  // constant value(s).
  lhs = lhs.dropConstVal();
  rhs = rhs.dropConstVal();

  auto const bits = lhs.m_bits | rhs.m_bits;
  auto const ptr = lhs.ptrKind() | rhs.ptrKind();
  auto const spec = lhs.spec() | rhs.spec();

  return Type{bits, ptr}.specialize(spec);
}
Пример #3
0
TEST(Type, Const) {
  auto five = Type::cns(5);
  EXPECT_LT(five, Type::Int);
  EXPECT_NE(five, Type::Int);
  EXPECT_TRUE(five.isConst());
  EXPECT_EQ(5, five.intVal());
  EXPECT_TRUE(five.isConst(Type::Int));
  EXPECT_TRUE(five.isConst(5));
  EXPECT_FALSE(five.isConst(5.0));
  EXPECT_TRUE(Type::Gen.maybe(five));
  EXPECT_EQ(Type::Int, five | Type::Int);
  EXPECT_EQ(Type::Int, five | Type::cns(10));
  EXPECT_EQ(five, five | Type::cns(5));
  EXPECT_EQ(five, Type::cns(5) & five);
  EXPECT_EQ(five, five & Type::Int);
  EXPECT_EQ(five, Type::Gen & five);
  EXPECT_EQ("Int<5>", five.toString());
  EXPECT_EQ(five, five - Type::Arr);
  EXPECT_EQ(five, five - Type::cns(1));
  EXPECT_EQ(Type::Bottom, five - Type::Int);
  EXPECT_EQ(Type::Bottom, five - five);
  EXPECT_EQ(Type::Int, five.dropConstVal());
  EXPECT_TRUE(five.not(Type::cns(2)));

  auto True = Type::cns(true);
  EXPECT_EQ("Bool<true>", True.toString());
  EXPECT_LT(True, Type::Bool);
  EXPECT_NE(True, Type::Bool);
  EXPECT_TRUE(True.isConst());
  EXPECT_EQ(true, True.boolVal());
  EXPECT_TRUE(Type::Uncounted.maybe(True));
  EXPECT_FALSE(five <= True);
  EXPECT_FALSE(five > True);

  EXPECT_TRUE(five.not(True));
  EXPECT_EQ(Type::Int | Type::Bool, five | True);
  EXPECT_EQ(Type::Bottom, five & True);

  EXPECT_TRUE(Type::Uninit.isConst());
  EXPECT_TRUE(Type::InitNull.isConst());
  EXPECT_FALSE(Type::Null.isConst());
  EXPECT_FALSE((Type::Uninit | Type::Bool).isConst());
  EXPECT_FALSE(Type::Int.isConst());
}
Пример #4
0
TEST(Type, Const) {
  auto five = Type::cns(5);
  EXPECT_LT(five, Type::Int);
  EXPECT_NE(five, Type::Int);
  EXPECT_TRUE(five.isConst());
  EXPECT_EQ(5, five.intVal());
  EXPECT_TRUE(five.isConst(Type::Int));
  EXPECT_TRUE(five.isConst(5));
  EXPECT_FALSE(five.isConst(5.0));
  EXPECT_TRUE(Type::Gen.maybe(five));
  EXPECT_EQ(Type::Int, five | Type::Int);
  EXPECT_EQ(Type::Int, five | Type::cns(10));
  EXPECT_EQ(five, five | Type::cns(5));
  EXPECT_EQ(five, Type::cns(5) & five);
  EXPECT_EQ(five, five & Type::Int);
  EXPECT_EQ(five, Type::Gen & five);
  EXPECT_EQ("Int<5>", five.toString());
  EXPECT_EQ(five, five - Type::Arr);
  EXPECT_EQ(five, five - Type::cns(1));
  EXPECT_EQ(Type::Int, Type::Int - five); // conservative
  EXPECT_EQ(Type::Bottom, five - Type::Int);
  EXPECT_EQ(Type::Bottom, five - five);
  EXPECT_EQ(Type::PtrToGen,
            (Type::PtrToGen|Type::Nullptr) - Type::Nullptr);
  EXPECT_EQ(Type::Int, five.dropConstVal());
  EXPECT_TRUE(five.not(Type::cns(2)));

  auto True = Type::cns(true);
  EXPECT_EQ("Bool<true>", True.toString());
  EXPECT_LT(True, Type::Bool);
  EXPECT_NE(True, Type::Bool);
  EXPECT_TRUE(True.isConst());
  EXPECT_EQ(true, True.boolVal());
  EXPECT_TRUE(Type::Uncounted.maybe(True));
  EXPECT_FALSE(five <= True);
  EXPECT_FALSE(five > True);

  EXPECT_TRUE(five.not(True));
  EXPECT_EQ(Type::Int | Type::Bool, five | True);
  EXPECT_EQ(Type::Bottom, five & True);

  EXPECT_TRUE(Type::Uninit.isConst());
  EXPECT_TRUE(Type::InitNull.isConst());
  EXPECT_FALSE(Type::Null.isConst());
  EXPECT_FALSE((Type::Uninit | Type::Bool).isConst());
  EXPECT_FALSE(Type::Int.isConst());

  auto array = make_packed_array(1, 2, 3, 4);
  auto arrData = ArrayData::GetScalarArray(array.get());
  auto constArray = Type::cns(arrData);
  auto packedArray = Type::Arr.specialize(ArrayData::kPackedKind);
  auto mixedArray = Type::Arr.specialize(ArrayData::kMixedKind);

  EXPECT_TRUE(constArray <= packedArray);
  EXPECT_TRUE(constArray < packedArray);
  EXPECT_FALSE(packedArray <= constArray);
  EXPECT_TRUE(constArray <= constArray);
  EXPECT_FALSE(packedArray <= mixedArray);
  EXPECT_FALSE(mixedArray <= packedArray);
  EXPECT_FALSE(constArray <= mixedArray);
  EXPECT_EQ(constArray, constArray & packedArray);

  ArrayTypeTable::Builder ratBuilder;
  auto rat1 = ratBuilder.packedn(RepoAuthType::Array::Empty::No,
                                 RepoAuthType(RepoAuthType::Tag::Str));
  auto ratArray1 = Type::Arr.specialize(rat1);
  auto rat2 = ratBuilder.packedn(RepoAuthType::Array::Empty::No,
                                 RepoAuthType(RepoAuthType::Tag::Int));
  auto ratArray2 = Type::Arr.specialize(rat2);
  EXPECT_EQ(Type::Arr, ratArray1 & ratArray2);
  EXPECT_TRUE(ratArray1 < Type::Arr);
  EXPECT_TRUE(ratArray1 <= ratArray1);
  EXPECT_TRUE(ratArray1 < (Type::Arr|Type::Obj));
  EXPECT_FALSE(ratArray1 < ratArray2);
  EXPECT_NE(ratArray1, ratArray2);

  auto packedRat = packedArray & ratArray1;
  EXPECT_EQ("Arr=PackedKind:N([Str])", packedRat.toString());
  EXPECT_TRUE(packedRat <= packedArray);
  EXPECT_TRUE(packedRat < packedArray);
  EXPECT_TRUE(packedRat <= ratArray1);
  EXPECT_TRUE(packedRat < ratArray1);
  EXPECT_EQ(packedRat, packedRat & packedArray);
  EXPECT_EQ(packedRat, packedRat & ratArray1);
}