Chromium Code Reviews| Index: sdk/lib/_internal/compiler/implementation/types/type_mask.dart |
| diff --git a/sdk/lib/_internal/compiler/implementation/types/type_mask.dart b/sdk/lib/_internal/compiler/implementation/types/type_mask.dart |
| index e1c158b22b94d77f60c58877176d1e7b2a187fd8..351d298cbfe3ce8f9703fbf4cd38bcaecc6f4228 100644 |
| --- a/sdk/lib/_internal/compiler/implementation/types/type_mask.dart |
| +++ b/sdk/lib/_internal/compiler/implementation/types/type_mask.dart |
| @@ -11,9 +11,10 @@ part of types; |
| */ |
| class TypeMask { |
| - static const int EXACT = 0; |
| - static const int SUBCLASS = 1; |
| - static const int SUBTYPE = 2; |
| + static const int EMPTY = 0; |
| + static const int EXACT = 1; |
| + static const int SUBCLASS = 2; |
| + static const int SUBTYPE = 3; |
| final DartType base; |
| final int flags; |
| @@ -21,6 +22,8 @@ class TypeMask { |
| TypeMask(DartType base, int kind, bool isNullable) |
| : this.internal(base, (kind << 1) | (isNullable ? 1 : 0)); |
| + const TypeMask.empty() |
| + : this.internal(null, (EMPTY << 1) | 1); |
| const TypeMask.exact(DartType base) |
| : this.internal(base, (EXACT << 1) | 1); |
| const TypeMask.subclass(DartType base) |
| @@ -28,6 +31,8 @@ class TypeMask { |
| const TypeMask.subtype(DartType base) |
| : this.internal(base, (SUBTYPE << 1) | 1); |
| + const TypeMask.nonNullEmpty() |
| + : this.internal(null, EMPTY << 1); |
| const TypeMask.nonNullExact(DartType base) |
| : this.internal(base, EXACT << 1); |
| const TypeMask.nonNullSubclass(DartType base) |
| @@ -37,8 +42,9 @@ class TypeMask { |
| const TypeMask.internal(this.base, this.flags); |
| - bool get isNullable => (flags & 1) != 0; |
| + bool get isEmpty => (flags >> 1) == EMPTY; |
| bool get isExact => (flags >> 1) == EXACT; |
| + bool get isNullable => (flags & 1) != 0; |
| // TODO(kasperl): Get rid of these. They should not be a visible |
| // part of the implementation because they make it hard to add |
| @@ -46,6 +52,8 @@ class TypeMask { |
| bool get isSubclass => (flags >> 1) == SUBCLASS; |
| bool get isSubtype => (flags >> 1) == SUBTYPE; |
| + DartType get exactType => isExact ? base : null; |
| + |
| /** |
| * Returns a nullable variant of [this] type mask. |
| */ |
| @@ -53,13 +61,20 @@ class TypeMask { |
| return isNullable ? this : new TypeMask.internal(base, flags | 1); |
| } |
| - DartType get exactType => isExact ? base : null; |
| + /** |
| + * Returns a non-nullable variant of [this] type mask. |
| + */ |
| + TypeMask nonNullable() { |
| + return isNullable ? new TypeMask.internal(base, flags & ~1) : this; |
| + } |
| /** |
| * Returns whether or not this type mask contains the given type. |
| */ |
| bool contains(DartType type, Compiler compiler) { |
| - if (identical(base.element, type.element)) { |
| + if (isEmpty) { |
| + return false; |
|
ngeoffray
2013/03/11 14:52:28
Should it say false to JSNull? Also I guess the ot
kasperl
2013/03/12 05:56:56
I'll try to move more of the code from TypedSelect
|
| + } else if (identical(base.element, type.element)) { |
| return true; |
| } else if (isExact) { |
| return false; |
| @@ -71,20 +86,23 @@ class TypeMask { |
| } |
| } |
| - // TODO(kasperl): Try to get rid of this method. It shouldn't really |
| +// TODO(kasperl): Try to get rid of this method. It shouldn't really |
| // be necessary. |
| bool containsAll(Compiler compiler) { |
| + if (isEmpty || isExact) return false; |
| // TODO(kasperl): Do this error handling earlier. |
| if (base.kind != TypeKind.INTERFACE) return false; |
| - // TODO(kasperl): Should we take nullability into account here? |
| - if (isExact) return false; |
| ClassElement baseElement = base.element; |
| return identical(baseElement, compiler.objectClass) |
| || identical(baseElement, compiler.dynamicClass); |
| } |
| TypeMask union(TypeMask other, Compiler compiler) { |
| - if (base.asRaw() == other.base.asRaw()) { |
| + if (isEmpty) { |
| + return isNullable ? other.nullable() : other; |
| + } else if (other.isEmpty) { |
| + return other.isNullable ? nullable() : this; |
| + } else if (base.asRaw() == other.base.asRaw()) { |
| return unionSame(other, compiler); |
| } else if (isSubclassOf(other.base, base, compiler)) { |
| return unionSubclass(other, compiler); |
| @@ -204,7 +222,11 @@ class TypeMask { |
| } |
| TypeMask intersection(TypeMask other, Compiler compiler) { |
| - if (base.asRaw() == other.base.asRaw()) { |
| + if (isEmpty) { |
| + return other.isNullable ? this : nonNullable(); |
| + } else if (other.isEmpty) { |
| + return isNullable ? other : other.nonNullable(); |
| + } else if (base.asRaw() == other.base.asRaw()) { |
| return intersectionSame(other, compiler); |
| } else if (isSubclassOf(other.base, base, compiler)) { |
| return intersectionSubclass(other, compiler); |
| @@ -337,6 +359,7 @@ class TypeMask { |
| } |
| String toString() { |
| + if (isEmpty) return isNullable ? '[null]' : '[empty]'; |
| StringBuffer buffer = new StringBuffer(); |
| if (isNullable) buffer.write('null|'); |
| if (isExact) buffer.write('exact='); |