| Index: test/cctest/test-types.cc
|
| diff --git a/test/cctest/test-types.cc b/test/cctest/test-types.cc
|
| index 6cdd46c8665d042881a00feb014885826a2803ea..15af42567f88e2738c2ff8a40ee9b60f918e4dae 100644
|
| --- a/test/cctest/test-types.cc
|
| +++ b/test/cctest/test-types.cc
|
| @@ -50,24 +50,29 @@ class Types {
|
| array_map = isolate->factory()->NewMap(JS_ARRAY_TYPE, 4 * kPointerSize);
|
| ObjectClass = Type::Class(object_map, region);
|
| ArrayClass = Type::Class(array_map, region);
|
| - types.push_back(ObjectClass);
|
| - types.push_back(ArrayClass);
|
| +
|
| + maps.push_back(object_map);
|
| + maps.push_back(array_map);
|
| + for (MapVector::iterator it = maps.begin(); it != maps.end(); ++it) {
|
| + types.push_back(Type::Class(*it, region));
|
| + }
|
|
|
| smi = handle(Smi::FromInt(666), isolate);
|
| signed32 = isolate->factory()->NewHeapNumber(0x40000000);
|
| object1 = isolate->factory()->NewJSObjectFromMap(object_map);
|
| object2 = isolate->factory()->NewJSObjectFromMap(object_map);
|
| array = isolate->factory()->NewJSArray(20);
|
| - values.push_back(smi);
|
| - values.push_back(signed32);
|
| - values.push_back(object1);
|
| - values.push_back(object2);
|
| - values.push_back(array);
|
| SmiConstant = Type::Constant(smi, region);
|
| Signed32Constant = Type::Constant(signed32, region);
|
| ObjectConstant1 = Type::Constant(object1, region);
|
| ObjectConstant2 = Type::Constant(object2, region);
|
| ArrayConstant = Type::Constant(array, region);
|
| +
|
| + values.push_back(smi);
|
| + values.push_back(signed32);
|
| + values.push_back(object1);
|
| + values.push_back(object2);
|
| + values.push_back(array);
|
| for (ValueVector::iterator it = values.begin(); it != values.end(); ++it) {
|
| types.push_back(Type::Constant(*it, region));
|
| }
|
| @@ -104,21 +109,26 @@ class Types {
|
| Handle<i::JSArray> array;
|
|
|
| typedef std::vector<TypeHandle> TypeVector;
|
| - TypeVector types;
|
| -
|
| + typedef std::vector<Handle<i::Map> > MapVector;
|
| typedef std::vector<Handle<i::Object> > ValueVector;
|
| + TypeVector types;
|
| + MapVector maps;
|
| ValueVector values;
|
|
|
| - TypeHandle Of(Handle<i::Object> obj) {
|
| - return Type::Of(obj, region_);
|
| + TypeHandle Of(Handle<i::Object> value) {
|
| + return Type::Of(value, region_);
|
| + }
|
| +
|
| + TypeHandle NowOf(Handle<i::Object> value) {
|
| + return Type::NowOf(value, region_);
|
| }
|
|
|
| - TypeHandle NowOf(Handle<i::Object> obj) {
|
| - return Type::NowOf(obj, region_);
|
| + TypeHandle Constant(Handle<i::Object> value) {
|
| + return Type::Constant(value, region_);
|
| }
|
|
|
| - TypeHandle Constant(Handle<i::Object> obj) {
|
| - return Type::Constant(obj, region_);
|
| + TypeHandle Class(Handle<i::Map> map) {
|
| + return Type::Class(map, region_);
|
| }
|
|
|
| TypeHandle Union(TypeHandle t1, TypeHandle t2) {
|
| @@ -201,6 +211,7 @@ template<class Type, class TypeHandle, class Region, class Rep>
|
| struct Tests : Rep {
|
| typedef Types<Type, TypeHandle, Region> TypesInstance;
|
| typedef typename TypesInstance::TypeVector::iterator TypeIterator;
|
| + typedef typename TypesInstance::MapVector::iterator MapIterator;
|
| typedef typename TypesInstance::ValueVector::iterator ValueIterator;
|
|
|
| Isolate* isolate;
|
| @@ -273,64 +284,159 @@ struct Tests : Rep {
|
| }
|
|
|
| void Bitset() {
|
| + // None and Any are bitsets.
|
| CHECK(this->IsBitset(T.None));
|
| CHECK(this->IsBitset(T.Any));
|
| - CHECK(this->IsBitset(T.String));
|
| - CHECK(this->IsBitset(T.Object));
|
| -
|
| - CHECK(this->IsBitset(T.Union(T.String, T.Number)));
|
| - CHECK(this->IsBitset(T.Union(T.String, T.Receiver)));
|
|
|
| CHECK_EQ(0, this->AsBitset(T.None));
|
| - CHECK_EQ(
|
| - this->AsBitset(T.Number) | this->AsBitset(T.String),
|
| - this->AsBitset(T.Union(T.String, T.Number)));
|
| - CHECK_EQ(
|
| - this->AsBitset(T.Receiver),
|
| - this->AsBitset(T.Union(T.Receiver, T.Object)));
|
| + CHECK_EQ(-1, this->AsBitset(T.Any));
|
| +
|
| + // Union(T1, T2) is a bitset for all bitsets T1,T2
|
| + for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
|
| + for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
|
| + TypeHandle type1 = *it1;
|
| + TypeHandle type2 = *it2;
|
| + CHECK(!(this->IsBitset(type1) && this->IsBitset(type2)) ||
|
| + this->IsBitset(T.Union(type1, type2)));
|
| + }
|
| + }
|
| +
|
| + // Union(T1, T2) is a bitset if T2 is a bitset and T1->Is(T2)
|
| + // (and vice versa).
|
| + for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
|
| + for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
|
| + TypeHandle type1 = *it1;
|
| + TypeHandle type2 = *it2;
|
| + CHECK(!(this->IsBitset(type2) && type1->Is(type2)) ||
|
| + this->IsBitset(T.Union(type1, type2)));
|
| + CHECK(!(this->IsBitset(type1) && type2->Is(type1)) ||
|
| + this->IsBitset(T.Union(type1, type2)));
|
| + }
|
| + }
|
| +
|
| + // Union(T1, T2) is bitwise disjunction for all bitsets T1,T2
|
| + for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
|
| + for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
|
| + TypeHandle type1 = *it1;
|
| + TypeHandle type2 = *it2;
|
| + if (this->IsBitset(type1) && this->IsBitset(type2)) {
|
| + CHECK_EQ(
|
| + this->AsBitset(type1) | this->AsBitset(type2),
|
| + this->AsBitset(T.Union(type1, type2)));
|
| + }
|
| + }
|
| + }
|
| +
|
| + // Intersect(T1, T2) is bitwise conjunction for all bitsets T1,T2
|
| + for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
|
| + for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
|
| + TypeHandle type1 = *it1;
|
| + TypeHandle type2 = *it2;
|
| + if (this->IsBitset(type1) && this->IsBitset(type2)) {
|
| + CHECK_EQ(
|
| + this->AsBitset(type1) & this->AsBitset(type2),
|
| + this->AsBitset(T.Intersect(type1, type2)));
|
| + }
|
| + }
|
| + }
|
| }
|
|
|
| void Class() {
|
| - CHECK(this->IsClass(T.ObjectClass));
|
| - CHECK(this->IsClass(T.ArrayClass));
|
| + // Constructor
|
| + for (MapIterator mt = T.maps.begin(); mt != T.maps.end(); ++mt) {
|
| + Handle<i::Map> map = *mt;
|
| + CHECK(this->IsClass(T.Class(map)));
|
| + }
|
|
|
| - CHECK(*T.object_map == this->AsClass(T.ObjectClass));
|
| - CHECK(*T.array_map == this->AsClass(T.ArrayClass));
|
| + // Map attribute
|
| + for (MapIterator mt = T.maps.begin(); mt != T.maps.end(); ++mt) {
|
| + Handle<i::Map> map = *mt;
|
| + CHECK(*map == *T.Class(map)->AsClass());
|
| + }
|
| +
|
| + // Functionality & Injectivity
|
| + for (MapIterator mt1 = T.maps.begin(); mt1 != T.maps.end(); ++mt1) {
|
| + for (MapIterator mt2 = T.maps.begin(); mt2 != T.maps.end(); ++mt2) {
|
| + Handle<i::Map> map1 = *mt1;
|
| + Handle<i::Map> map2 = *mt2;
|
| + CHECK(T.Class(map1)->Is(T.Class(map2)) == (*map1 == *map2));
|
| + }
|
| + }
|
| }
|
|
|
| void Constant() {
|
| - CHECK(this->IsConstant(T.SmiConstant));
|
| - CHECK(this->IsConstant(T.ObjectConstant1));
|
| - CHECK(this->IsConstant(T.ObjectConstant2));
|
| - CHECK(this->IsConstant(T.ArrayConstant));
|
| -
|
| - CHECK(*T.smi == this->AsConstant(T.SmiConstant));
|
| - CHECK(*T.object1 == this->AsConstant(T.ObjectConstant1));
|
| - CHECK(*T.object2 == this->AsConstant(T.ObjectConstant2));
|
| - CHECK(*T.object1 != this->AsConstant(T.ObjectConstant2));
|
| - CHECK(*T.array == this->AsConstant(T.ArrayConstant));
|
| + // Constructor
|
| + for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
|
| + Handle<i::Object> value = *vt;
|
| + CHECK(this->IsConstant(T.Constant(value)));
|
| + }
|
| +
|
| + // Value attribute
|
| + for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
|
| + Handle<i::Object> value = *vt;
|
| + CHECK(*value == *T.Constant(value)->AsConstant());
|
| + }
|
| +
|
| + // Functionality & Injectivity
|
| + for (ValueIterator vt1 = T.values.begin(); vt1 != T.values.end(); ++vt1) {
|
| + for (ValueIterator vt2 = T.values.begin(); vt2 != T.values.end(); ++vt2) {
|
| + Handle<i::Object> val1 = *vt1;
|
| + Handle<i::Object> val2 = *vt2;
|
| + CHECK(T.Constant(val1)->Is(T.Constant(val2)) == (*val1 == *val2));
|
| + }
|
| + }
|
| }
|
|
|
| void Of() {
|
| - CHECK(T.Of(T.smi)->Is(T.SignedSmall));
|
| - CHECK(T.Of(T.signed32)->Is(T.Signed32));
|
| - CHECK(T.Of(T.object1)->Is(T.Object));
|
| - CHECK(T.Of(T.object2)->Is(T.Object));
|
| - CHECK(T.Of(T.array)->Is(T.Array));
|
| + // Constant(V)->Is(Of(V)) for all V
|
| + for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
|
| + Handle<i::Object> value = *vt;
|
| + CHECK(T.Constant(value)->Is(T.Of(value)));
|
| + }
|
| +
|
| + // Constant(V)->Is(T) implies Of(V)->Is(T) or T->Maybe(Constant(V))
|
| + for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
|
| + for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
|
| + Handle<i::Object> value = *vt;
|
| + TypeHandle type = *it;
|
| + CHECK(!T.Constant(value)->Is(type) ||
|
| + T.Of(value)->Is(type) || type->Maybe(T.Constant(value)));
|
| + }
|
| + }
|
| }
|
|
|
| void NowOf() {
|
| + // Constant(V)->NowIs(NowOf(V)) for all V
|
| + for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
|
| + Handle<i::Object> value = *vt;
|
| + CHECK(T.Constant(value)->NowIs(T.NowOf(value)));
|
| + }
|
| +
|
| // NowOf(V)->Is(Of(V)) for all V
|
| for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
|
| - Handle<i::Object> val = *vt;
|
| - CHECK(T.NowOf(val)->Is(T.Of(val)));
|
| + Handle<i::Object> value = *vt;
|
| + CHECK(T.NowOf(value)->Is(T.Of(value)));
|
| + }
|
| +
|
| + // Constant(V)->Is(T) implies NowOf(V)->Is(T) or T->Maybe(Constant(V))
|
| + for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
|
| + for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
|
| + Handle<i::Object> value = *vt;
|
| + TypeHandle type = *it;
|
| + CHECK(!T.Constant(value)->Is(type) ||
|
| + T.NowOf(value)->Is(type) || type->Maybe(T.Constant(value)));
|
| + }
|
| }
|
|
|
| - CHECK(T.NowOf(T.smi)->NowIs(T.SignedSmall));
|
| - CHECK(T.NowOf(T.signed32)->NowIs(T.Signed32));
|
| - CHECK(T.NowOf(T.object1)->NowIs(T.ObjectClass));
|
| - CHECK(T.NowOf(T.object2)->NowIs(T.ObjectClass));
|
| - CHECK(T.NowOf(T.array)->NowIs(T.Array));
|
| + // Constant(V)->NowIs(T) implies NowOf(V)->NowIs(T) or T->Maybe(Constant(V))
|
| + for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
|
| + for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
|
| + Handle<i::Object> value = *vt;
|
| + TypeHandle type = *it;
|
| + CHECK(!T.Constant(value)->NowIs(type) ||
|
| + T.NowOf(value)->NowIs(type) || type->Maybe(T.Constant(value)));
|
| + }
|
| + }
|
| }
|
|
|
| void Is() {
|
| @@ -371,22 +477,52 @@ struct Tests : Rep {
|
| TypeHandle type1 = *it1;
|
| TypeHandle type2 = *it2;
|
| TypeHandle type3 = *it3;
|
| - CHECK(!type1->Is(type2) ||
|
| - !type2->Is(type3) ||
|
| - type1->Is(type3));
|
| + CHECK(!(type1->Is(type2) && type2->Is(type3)) || type1->Is(type3));
|
| }
|
| }
|
| }
|
|
|
| - // Symmetry and Transitivity
|
| - CheckSub(T.None, T.Number);
|
| - CheckSub(T.None, T.Any);
|
| + // Constant(V1)->Is(Constant(V2)) iff V1 = V2
|
| + for (ValueIterator vt1 = T.values.begin(); vt1 != T.values.end(); ++vt1) {
|
| + for (ValueIterator vt2 = T.values.begin(); vt2 != T.values.end(); ++vt2) {
|
| + Handle<i::Object> val1 = *vt1;
|
| + Handle<i::Object> val2 = *vt2;
|
| + CHECK(T.Constant(val1)->Is(T.Constant(val2)) == (*val1 == *val2));
|
| + }
|
| + }
|
| +
|
| + // Class(M1)->Is(Class(M2)) iff M1 = M2
|
| + for (MapIterator mt1 = T.maps.begin(); mt1 != T.maps.end(); ++mt1) {
|
| + for (MapIterator mt2 = T.maps.begin(); mt2 != T.maps.end(); ++mt2) {
|
| + Handle<i::Map> map1 = *mt1;
|
| + Handle<i::Map> map2 = *mt2;
|
| + CHECK(T.Class(map1)->Is(T.Class(map2)) == (*map1 == *map2));
|
| + }
|
| + }
|
| +
|
| + // Constant(V)->Is(Class(M)) for no V,M
|
| + for (MapIterator mt = T.maps.begin(); mt != T.maps.end(); ++mt) {
|
| + for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
|
| + Handle<i::Map> map = *mt;
|
| + Handle<i::Object> value = *vt;
|
| + CHECK(!T.Constant(value)->Is(T.Class(map)));
|
| + }
|
| + }
|
| +
|
| + // Class(M)->Is(Constant(V)) for no V,M
|
| + for (MapIterator mt = T.maps.begin(); mt != T.maps.end(); ++mt) {
|
| + for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
|
| + Handle<i::Map> map = *mt;
|
| + Handle<i::Object> value = *vt;
|
| + CHECK(!T.Class(map)->Is(T.Constant(value)));
|
| + }
|
| + }
|
|
|
| + // Basic types
|
| CheckUnordered(T.Boolean, T.Null);
|
| CheckUnordered(T.Undefined, T.Null);
|
| CheckUnordered(T.Boolean, T.Undefined);
|
|
|
| - CheckSub(T.Number, T.Any);
|
| CheckSub(T.SignedSmall, T.Number);
|
| CheckSub(T.Signed32, T.Number);
|
| CheckSub(T.Float, T.Number);
|
| @@ -394,8 +530,6 @@ struct Tests : Rep {
|
| CheckUnordered(T.SignedSmall, T.Float);
|
| CheckUnordered(T.Signed32, T.Float);
|
|
|
| - CheckSub(T.Name, T.Any);
|
| - CheckSub(T.UniqueName, T.Any);
|
| CheckSub(T.UniqueName, T.Name);
|
| CheckSub(T.String, T.Name);
|
| CheckSub(T.InternalizedString, T.String);
|
| @@ -407,8 +541,6 @@ struct Tests : Rep {
|
| CheckUnordered(T.String, T.Symbol);
|
| CheckUnordered(T.InternalizedString, T.Symbol);
|
|
|
| - CheckSub(T.Receiver, T.Any);
|
| - CheckSub(T.Object, T.Any);
|
| CheckSub(T.Object, T.Receiver);
|
| CheckSub(T.Array, T.Object);
|
| CheckSub(T.Function, T.Object);
|
| @@ -416,12 +548,7 @@ struct Tests : Rep {
|
| CheckUnordered(T.Object, T.Proxy);
|
| CheckUnordered(T.Array, T.Function);
|
|
|
| - // Structured subtyping
|
| - CheckSub(T.None, T.ObjectClass);
|
| - CheckSub(T.None, T.ObjectConstant1);
|
| - CheckSub(T.ObjectClass, T.Any);
|
| - CheckSub(T.ObjectConstant1, T.Any);
|
| -
|
| + // Structural types
|
| CheckSub(T.ObjectClass, T.Object);
|
| CheckSub(T.ArrayClass, T.Object);
|
| CheckUnordered(T.ObjectClass, T.ArrayClass);
|
| @@ -497,8 +624,43 @@ struct Tests : Rep {
|
| }
|
| }
|
|
|
| - CHECK(T.ObjectConstant1->NowIs(T.ObjectClass));
|
| - CHECK(T.ObjectConstant2->NowIs(T.ObjectClass));
|
| + // Constant(V1)->NowIs(Constant(V2)) iff V1 = V2
|
| + for (ValueIterator vt1 = T.values.begin(); vt1 != T.values.end(); ++vt1) {
|
| + for (ValueIterator vt2 = T.values.begin(); vt2 != T.values.end(); ++vt2) {
|
| + Handle<i::Object> val1 = *vt1;
|
| + Handle<i::Object> val2 = *vt2;
|
| + CHECK(T.Constant(val1)->NowIs(T.Constant(val2)) == (*val1 == *val2));
|
| + }
|
| + }
|
| +
|
| + // Class(M1)->NowIs(Class(M2)) iff M1 = M2
|
| + for (MapIterator mt1 = T.maps.begin(); mt1 != T.maps.end(); ++mt1) {
|
| + for (MapIterator mt2 = T.maps.begin(); mt2 != T.maps.end(); ++mt2) {
|
| + Handle<i::Map> map1 = *mt1;
|
| + Handle<i::Map> map2 = *mt2;
|
| + CHECK(T.Class(map1)->NowIs(T.Class(map2)) == (*map1 == *map2));
|
| + }
|
| + }
|
| +
|
| + // Constant(V)->NowIs(Class(M)) iff V has map M
|
| + for (MapIterator mt = T.maps.begin(); mt != T.maps.end(); ++mt) {
|
| + for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
|
| + Handle<i::Map> map = *mt;
|
| + Handle<i::Object> value = *vt;
|
| + CHECK((value->IsHeapObject() &&
|
| + i::HeapObject::cast(*value)->map() == *map)
|
| + == T.Constant(value)->NowIs(T.Class(map)));
|
| + }
|
| + }
|
| +
|
| + // Class(M)->NowIs(Constant(V)) for no V,M
|
| + for (MapIterator mt = T.maps.begin(); mt != T.maps.end(); ++mt) {
|
| + for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
|
| + Handle<i::Map> map = *mt;
|
| + Handle<i::Object> value = *vt;
|
| + CHECK(!T.Class(map)->NowIs(T.Constant(value)));
|
| + }
|
| + }
|
| }
|
|
|
| void Contains() {
|
| @@ -506,8 +668,8 @@ struct Tests : Rep {
|
| for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
|
| for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
|
| TypeHandle type = *it;
|
| - Handle<i::Object> val = *vt;
|
| - CHECK(type->Contains(val) == T.Constant(val)->Is(type));
|
| + Handle<i::Object> value = *vt;
|
| + CHECK(type->Contains(value) == T.Constant(value)->Is(type));
|
| }
|
| }
|
|
|
| @@ -515,8 +677,8 @@ struct Tests : Rep {
|
| for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
|
| for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
|
| TypeHandle type = *it;
|
| - Handle<i::Object> val = *vt;
|
| - CHECK(!T.Of(val)->Is(type) || type->Contains(val));
|
| + Handle<i::Object> value = *vt;
|
| + CHECK(!T.Of(value)->Is(type) || type->Contains(value));
|
| }
|
| }
|
| }
|
| @@ -526,44 +688,56 @@ struct Tests : Rep {
|
| for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
|
| for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
|
| TypeHandle type = *it;
|
| - Handle<i::Object> val = *vt;
|
| - CHECK(type->NowContains(val) == T.Constant(val)->NowIs(type));
|
| + Handle<i::Object> value = *vt;
|
| + CHECK(type->NowContains(value) == T.Constant(value)->NowIs(type));
|
| }
|
| }
|
|
|
| - // NowOf(V)->Is(T) implies T->NowContains(V) for all T,V
|
| + // T->Contains(V) implies T->NowContains(V) for all T,V
|
| for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
|
| for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
|
| TypeHandle type = *it;
|
| Handle<i::Object> value = *vt;
|
| - CHECK(!T.NowOf(value)->NowIs(type) || type->NowContains(value));
|
| + CHECK(!type->Contains(value) || type->NowContains(value));
|
| }
|
| }
|
|
|
| - // NowOf(V)->NowIs(T) implies T->NowContains(V) for all T,V
|
| + // NowOf(V)->Is(T) implies T->NowContains(V) for all T,V
|
| for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
|
| for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
|
| TypeHandle type = *it;
|
| - Handle<i::Object> val = *vt;
|
| - CHECK(!T.NowOf(val)->NowIs(type) || type->NowContains(val));
|
| + Handle<i::Object> value = *vt;
|
| + CHECK(!T.NowOf(value)->NowIs(type) || type->NowContains(value));
|
| }
|
| }
|
|
|
| - // T->Contains(V) implies T->NowContains(V) for all T,V
|
| + // NowOf(V)->NowIs(T) implies T->NowContains(V) for all T,V
|
| for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
|
| for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
|
| TypeHandle type = *it;
|
| - Handle<i::Object> val = *vt;
|
| - CHECK(!type->Contains(val) || type->NowContains(val));
|
| + Handle<i::Object> value = *vt;
|
| + CHECK(!T.NowOf(value)->NowIs(type) || type->NowContains(value));
|
| }
|
| }
|
| }
|
|
|
| void Maybe() {
|
| - // T->Maybe(T) for all inhabited T
|
| + // T->Maybe(T) iff T inhabited
|
| + for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
|
| + TypeHandle type = *it;
|
| + CHECK(type->Maybe(type) == type->IsInhabited());
|
| + }
|
| +
|
| + // T->Maybe(Any) iff T inhabited
|
| + for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
|
| + TypeHandle type = *it;
|
| + CHECK(type->Maybe(T.Any) == type->IsInhabited());
|
| + }
|
| +
|
| + // T->Maybe(None) never
|
| for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
|
| TypeHandle type = *it;
|
| - CHECK(type->Maybe(type) || !type->IsInhabited());
|
| + CHECK(!type->Maybe(T.None));
|
| }
|
|
|
| // Symmetry
|
| @@ -575,31 +749,71 @@ struct Tests : Rep {
|
| }
|
| }
|
|
|
| - // T1->Is(T2) implies T1->Maybe(T2) or T1 is uninhabited for all T1,T2
|
| + // T1->Maybe(T2) only if T1, T2 inhabited
|
| + for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
|
| + for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
|
| + TypeHandle type1 = *it1;
|
| + TypeHandle type2 = *it2;
|
| + CHECK(!type1->Maybe(type2) ||
|
| + (type1->IsInhabited() && type2->IsInhabited()));
|
| + }
|
| + }
|
| +
|
| + // T1->Is(T2) and T1 inhabited implies T1->Maybe(T2) for all T1,T2
|
| for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
|
| for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
|
| TypeHandle type1 = *it1;
|
| TypeHandle type2 = *it2;
|
| - CHECK(!type1->Is(type2) ||
|
| - type1->Maybe(type2) ||
|
| - !type1->IsInhabited());
|
| + CHECK(!(type1->Is(type2) && type1->IsInhabited()) ||
|
| + type1->Maybe(type2));
|
| + }
|
| + }
|
| +
|
| + // Constant(V1)->Maybe(Constant(V2)) iff V1 = V2
|
| + for (ValueIterator vt1 = T.values.begin(); vt1 != T.values.end(); ++vt1) {
|
| + for (ValueIterator vt2 = T.values.begin(); vt2 != T.values.end(); ++vt2) {
|
| + Handle<i::Object> val1 = *vt1;
|
| + Handle<i::Object> val2 = *vt2;
|
| + CHECK(T.Constant(val1)->Maybe(T.Constant(val2)) == (*val1 == *val2));
|
| + }
|
| + }
|
| +
|
| + // Class(M1)->Maybe(Class(M2)) iff M1 = M2
|
| + for (MapIterator mt1 = T.maps.begin(); mt1 != T.maps.end(); ++mt1) {
|
| + for (MapIterator mt2 = T.maps.begin(); mt2 != T.maps.end(); ++mt2) {
|
| + Handle<i::Map> map1 = *mt1;
|
| + Handle<i::Map> map2 = *mt2;
|
| + CHECK(T.Class(map1)->Maybe(T.Class(map2)) == (*map1 == *map2));
|
| }
|
| }
|
|
|
| - CheckOverlap(T.Any, T.Any, T.Semantic);
|
| - CheckOverlap(T.Object, T.Object, T.Semantic);
|
| + // Constant(V)->Maybe(Class(M)) for no V,M
|
| + for (MapIterator mt = T.maps.begin(); mt != T.maps.end(); ++mt) {
|
| + for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
|
| + Handle<i::Map> map = *mt;
|
| + Handle<i::Object> value = *vt;
|
| + CHECK(!T.Constant(value)->Maybe(T.Class(map)));
|
| + }
|
| + }
|
| +
|
| + // Class(M)->Maybe(Constant(V)) for no V,M
|
| + for (MapIterator mt = T.maps.begin(); mt != T.maps.end(); ++mt) {
|
| + for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
|
| + Handle<i::Map> map = *mt;
|
| + Handle<i::Object> value = *vt;
|
| + CHECK(!T.Class(map)->Maybe(T.Constant(value)));
|
| + }
|
| + }
|
|
|
| + // Basic types
|
| CheckDisjoint(T.Boolean, T.Null, T.Semantic);
|
| CheckDisjoint(T.Undefined, T.Null, T.Semantic);
|
| CheckDisjoint(T.Boolean, T.Undefined, T.Semantic);
|
|
|
| - CheckOverlap(T.Number, T.Any, T.Semantic);
|
| CheckOverlap(T.SignedSmall, T.Number, T.Semantic);
|
| CheckOverlap(T.Float, T.Number, T.Semantic);
|
| CheckDisjoint(T.Signed32, T.Float, T.Semantic);
|
|
|
| - CheckOverlap(T.Name, T.Any, T.Semantic);
|
| - CheckOverlap(T.UniqueName, T.Any, T.Semantic);
|
| CheckOverlap(T.UniqueName, T.Name, T.Semantic);
|
| CheckOverlap(T.String, T.Name, T.Semantic);
|
| CheckOverlap(T.InternalizedString, T.String, T.Semantic);
|
| @@ -611,8 +825,6 @@ struct Tests : Rep {
|
| CheckDisjoint(T.String, T.Symbol, T.Semantic);
|
| CheckDisjoint(T.InternalizedString, T.Symbol, T.Semantic);
|
|
|
| - CheckOverlap(T.Receiver, T.Any, T.Semantic);
|
| - CheckOverlap(T.Object, T.Any, T.Semantic);
|
| CheckOverlap(T.Object, T.Receiver, T.Semantic);
|
| CheckOverlap(T.Array, T.Object, T.Semantic);
|
| CheckOverlap(T.Function, T.Object, T.Semantic);
|
| @@ -620,9 +832,7 @@ struct Tests : Rep {
|
| CheckDisjoint(T.Object, T.Proxy, T.Semantic);
|
| CheckDisjoint(T.Array, T.Function, T.Semantic);
|
|
|
| - CheckOverlap(T.ObjectClass, T.Any, T.Semantic);
|
| - CheckOverlap(T.ObjectConstant1, T.Any, T.Semantic);
|
| -
|
| + // Structural types
|
| CheckOverlap(T.ObjectClass, T.Object, T.Semantic);
|
| CheckOverlap(T.ArrayClass, T.Object, T.Semantic);
|
| CheckOverlap(T.ObjectClass, T.ObjectClass, T.Semantic);
|
|
|