Chromium Code Reviews| Index: lib/compiler/implementation/ssa/types.dart |
| =================================================================== |
| --- lib/compiler/implementation/ssa/types.dart (revision 7482) |
| +++ lib/compiler/implementation/ssa/types.dart (working copy) |
| @@ -14,34 +14,26 @@ |
| [bool canBeNull = false]) { |
| Element element = type.element; |
| if (element.kind === ElementKind.TYPE_VARIABLE) { |
| - compiler.unimplemented("type variables"); |
| + // TODO(ngeoffray): Replace object type type [type]. |
|
floitsch
2012/05/10 10:29:43
type type [type] ?
ngeoffray
2012/05/11 10:17:54
Done.
|
| + return new HBoundedPotentialPrimitiveType( |
| + compiler.objectClass.computeType(compiler), canBeNull); |
| } |
| - if (!canBeNull) { |
| - if (element === compiler.intClass) { |
| - return HType.INTEGER; |
| - } else if (element === compiler.numClass) { |
| - return HType.NUMBER; |
| - } else if (element === compiler.doubleClass) { |
| - return HType.DOUBLE; |
| - } else if (element === compiler.stringClass) { |
| - return HType.STRING; |
| - } else if (element === compiler.boolClass) { |
| - return HType.BOOLEAN; |
| - } |
| - } |
| - if (element === compiler.listClass |
| + if (element === compiler.intClass) { |
| + return canBeNull ? HType.INTEGER_OR_NULL : HType.INTEGER; |
| + } else if (element === compiler.numClass) { |
| + return canBeNull ? HType.NUMBER_OR_NULL : HType.NUMBER; |
| + } else if (element === compiler.doubleClass) { |
| + return canBeNull ? HType.DOUBLE_OR_NULL : HType.DOUBLE; |
| + } else if (element === compiler.stringClass) { |
| + return canBeNull ? HType.STRING_OR_NULL : HType.STRING; |
| + } else if (element === compiler.boolClass) { |
| + return canBeNull ? HType.BOOLEAN_OR_NULL : HType.BOOLEAN; |
| + } else if (element === compiler.listClass |
| || Elements.isListSupertype(element, compiler)) { |
| return new HBoundedPotentialPrimitiveArray(type, canBeNull); |
| } else if (Elements.isStringSupertype(element, compiler)) { |
| return new HBoundedPotentialPrimitiveString(type, canBeNull); |
| - } else if (element === compiler.intClass |
| - || element === compiler.boolClass |
| - || element === compiler.numClass |
| - || element === compiler.doubleClass |
| - || element === compiler.stringClass) { |
| - // TODO(ngeoffray): Create primitive nullable types. |
| - return null; |
| } else { |
| return new HBoundedType(type, canBeNull); |
| } |
| @@ -59,6 +51,12 @@ |
| static final HType MUTABLE_ARRAY = const HMutableArrayType(); |
| static final HType EXTENDABLE_ARRAY = const HExtendableArrayType(); |
| + static final HType BOOLEAN_OR_NULL = const HBooleanOrNullType(); |
|
Lasse Reichstein Nielsen
2012/05/10 10:15:20
DO you think it will eventually be worth it to hav
ngeoffray
2012/05/11 10:17:54
Yes. As discussed, I preferred special casing thes
|
| + static final HType NUMBER_OR_NULL = const HNumberOrNullType(); |
| + static final HType INTEGER_OR_NULL = const HIntegerOrNullType(); |
| + static final HType DOUBLE_OR_NULL = const HDoubleOrNullType(); |
| + static final HType STRING_OR_NULL = const HStringOrNullType(); |
| + |
| bool isConflicting() => this === CONFLICTING; |
| bool isUnknown() => this === UNKNOWN; |
| bool isBoolean() => false; |
| @@ -66,6 +64,11 @@ |
| bool isInteger() => false; |
| bool isDouble() => false; |
| bool isString() => false; |
| + bool isBooleanOrNull() => false; |
| + bool isNumberOrNull() => false; |
| + bool isIntegerOrNull() => false; |
| + bool isDoubleOrNull() => false; |
| + bool isStringOrNull() => false; |
| bool isIndexablePrimitive() => false; |
| bool isReadableArray() => false; |
| bool isMutableArray() => false; |
| @@ -139,6 +142,36 @@ |
| bool canBePrimitive() => true; |
| } |
| +abstract class HPrimitiveOrNullType extends HType { |
| + const HPrimitiveOrNullType(); |
| + bool canBePrimitive() => true; |
| + bool canBeNull() => true; |
| +} |
| + |
| +class HBooleanOrNullType extends HPrimitiveOrNullType { |
| + const HBooleanOrNullType(); |
| + String toString() => "boolean or null"; |
| + bool isBooleanOrNull() => true; |
| + |
| + Type computeType(Compiler compiler) { |
| + return compiler.boolClass.computeType(compiler); |
| + } |
| + |
| + HType union(HType other) { |
| + if (other.isUnknown()) return HType.BOOLEAN_OR_NULL; |
| + if (other.isBooleanOrNull()) return HType.BOOLEAN_OR_NULL; |
| + if (other.isBoolean()) return HType.BOOLEAN_OR_NULL; |
| + return HType.CONFLICTING; |
| + } |
| + |
| + HType intersection(HType other) { |
| + if (other.isUnknown()) return HType.BOOLEAN_OR_NULL; |
| + if (other.isBooleanOrNull()) return HType.BOOLEAN_OR_NULL; |
| + if (other.isBoolean()) return HType.BOOLEAN; |
| + return HType.CONFLICTING; |
| + } |
| +} |
| + |
| class HBooleanType extends HPrimitiveType { |
| const HBooleanType(); |
| bool isBoolean() => true; |
| @@ -148,17 +181,45 @@ |
| return compiler.boolClass.computeType(compiler); |
| } |
| - HType combine(HType other) { |
| - if (other.isBoolean() || other.isUnknown()) return HType.BOOLEAN; |
| + HType union(HType other) { |
| + if (other.isUnknown()) return HType.BOOLEAN; |
| + if (other.isBoolean()) return HType.BOOLEAN; |
| + if (other.isBooleanOrNull()) return HType.BOOLEAN_OR_NULL; |
| return HType.CONFLICTING; |
| } |
| - // Since the boolean type is a one-element set the union and intersection are |
| - // the same. |
| - HType union(HType other) => combine(other); |
| - HType intersection(HType other) => combine(other); |
| + HType intersection(HType other) { |
| + if (other.isUnknown()) return HType.BOOLEAN; |
| + if (other.isBooleanOrNull()) return HType.BOOLEAN; |
| + if (other.isBoolean()) return HType.BOOLEAN; |
| + return HType.CONFLICTING; |
| + } |
| } |
| +class HNumberOrNullType extends HPrimitiveOrNullType { |
| + const HNumberOrNullType(); |
| + bool isNumberOrNull() => true; |
| + String toString() => "number or null"; |
| + |
| + Type computeType(Compiler compiler) { |
| + return compiler.numClass.computeType(compiler); |
| + } |
| + |
| + HType union(HType other) { |
| + if (other.isUnknown()) return HType.NUMBER_OR_NULL; |
| + if (other.isNumberOrNull()) return HType.NUMBER_OR_NULL; |
| + if (other.isNumber()) return HType.NUMBER_OR_NULL; |
| + return HType.CONFLICTING; |
| + } |
| + |
| + HType intersection(HType other) { |
| + if (other.isUnknown()) return HType.NUMBER_OR_NULL; |
| + if (other.isNumberOrNull()) return HType.NUMBER_OR_NULL; |
|
floitsch
2012/05/10 10:29:43
not correct for integers or doubles.
ngeoffray
2012/05/11 10:17:54
Done.
|
| + if (other.isNumber()) return HType.NUMBER; |
| + return HType.CONFLICTING; |
| + } |
| +} |
| + |
| class HNumberType extends HPrimitiveType { |
| const HNumberType(); |
| bool isNumber() => true; |
| @@ -169,17 +230,52 @@ |
| } |
| HType union(HType other) { |
| - if (other.isNumber() || other.isUnknown()) return HType.NUMBER; |
| + if (other.isNumber()) return HType.NUMBER; |
| + if (other.isUnknown()) return HType.NUMBER; |
| + if (other.isNumberOrNull()) return HType.NUMBER_OR_NULL; |
| return HType.CONFLICTING; |
| } |
| HType intersection(HType other) { |
| if (other.isUnknown()) return HType.NUMBER; |
| if (other.isNumber()) return other; |
| + if (other.isIntegerOrNull()) return HType.INTEGER; |
| + if (other.isDoubleOrNull()) return HType.DOUBLE; |
| + if (other.isNumberOrNull()) return HType.NUMBER; |
| return HType.CONFLICTING; |
| } |
| } |
| +class HIntegerOrNullType extends HNumberOrNullType { |
| + const HIntegerOrNullType(); |
| + bool isIntegerOrNull() => true; |
| + String toString() => "integer or null"; |
| + |
| + Type computeType(Compiler compiler) { |
| + return compiler.intClass.computeType(compiler); |
| + } |
| + |
| + HType union(HType other) { |
| + if (other.isUnknown()) return HType.INTEGER_OR_NULL; |
| + if (other.isIntegerOrNull()) return HType.INTEGER_OR_NULL; |
| + if (other.isInteger()) return HType.INTEGER_OR_NULL; |
| + if (other.isNumber()) return HType.NUMBER_OR_NULL; |
| + if (other.isNumberOrNull()) return HType.NUMBER_OR_NULL; |
| + return HType.CONFLICTING; |
| + } |
| + |
| + HType intersection(HType other) { |
| + if (other.isUnknown()) return HType.INTEGER_OR_NULL; |
| + if (other.isIntegerOrNull()) return HType.INTEGER_OR_NULL; |
| + if (other.isInteger()) return HType.INTEGER; |
| + if (other.isDouble()) return HType.CONFLICTING; |
| + if (other.isDoubleOrNull()) return HType.CONFLICTING; |
| + if (other.isNumber()) return HType.INTEGER; |
| + if (other.isNumberOrNull()) return HType.INTEGER_OR_NULL; |
| + return HType.CONFLICTING; |
| + } |
| +} |
| + |
| class HIntegerType extends HNumberType { |
| const HIntegerType(); |
| bool isInteger() => true; |
| @@ -190,19 +286,56 @@ |
| } |
| HType union(HType other) { |
| - if (other.isInteger() || other.isUnknown()) return HType.INTEGER; |
| + if (other.isUnknown()) return HType.INTEGER; |
| + if (other.isInteger()) return HType.INTEGER; |
| + if (other.isIntegerOrNull()) return HType.INTEGER_OR_NULL; |
| if (other.isNumber()) return HType.NUMBER; |
| + if (other.isNumberOrNull()) return HType.NUMBER_OR_NULL; |
| return HType.CONFLICTING; |
| } |
| HType intersection(HType other) { |
| if (other.isUnknown()) return HType.INTEGER; |
| + if (other.isIntegerOrNull()) return HType.INTEGER; |
| + if (other.isInteger()) return HType.INTEGER; |
| if (other.isDouble()) return HType.CONFLICTING; |
| - if (other.isNumber()) return this; |
| + if (other.isDoubleOrNull()) return HType.CONFLICTING; |
| + if (other.isNumber()) return HType.INTEGER; |
| + if (other.isNumberOrNull()) return HType.INTEGER; |
| return HType.CONFLICTING; |
| } |
| } |
| +class HDoubleOrNullType extends HNumberOrNullType { |
| + const HDoubleOrNullType(); |
| + bool isDoubleOrNull() => true; |
| + String toString() => "double or null"; |
| + |
| + Type computeType(Compiler compiler) { |
| + return compiler.doubleClass.computeType(compiler); |
| + } |
| + |
| + HType union(HType other) { |
| + if (other.isUnknown()) return HType.DOUBLE_OR_NULL; |
| + if (other.isDoubleOrNull()) return HType.DOUBLE_OR_NULL; |
| + if (other.isDouble()) return HType.DOUBLE_OR_NULL; |
| + if (other.isNumber()) return HType.NUMBER_OR_NULL; |
| + if (other.isNumberOrNull()) return HType.NUMBER_OR_NULL; |
| + return HType.CONFLICTING; |
| + } |
| + |
| + HType intersection(HType other) { |
| + if (other.isUnknown()) return HType.DOUBLE_OR_NULL; |
| + if (other.isIntegerOrNull()) return HType.CONFLICTING; |
| + if (other.isInteger()) return HType.CONFLICTING; |
| + if (other.isDouble()) return HType.DOUBLE; |
| + if (other.isDoubleOrNull()) return HType.DOUBLE_OR_NULL; |
| + if (other.isNumber()) return HType.DOUBLE; |
| + if (other.isNumberOrNull()) return HType.DOUBLE_OR_NULL; |
| + return HType.CONFLICTING; |
| + } |
| +} |
| + |
| class HDoubleType extends HNumberType { |
| const HDoubleType(); |
| bool isDouble() => true; |
| @@ -213,15 +346,22 @@ |
| } |
| HType union(HType other) { |
| - if (other.isDouble() || other.isUnknown()) return HType.DOUBLE; |
| + if (other.isUnknown()) return HType.DOUBLE; |
| + if (other.isDouble()) return HType.DOUBLE; |
| + if (other.isDoubleOrNull()) return HType.DOUBLE_OR_NULL; |
| if (other.isNumber()) return HType.NUMBER; |
| + if (other.isNumberOrNull()) return HType.NUMBER_OR_NULL; |
| return HType.CONFLICTING; |
| } |
| HType intersection(HType other) { |
| if (other.isUnknown()) return HType.DOUBLE; |
| + if (other.isIntegerOrNull()) return HType.CONFLICTING; |
| if (other.isInteger()) return HType.CONFLICTING; |
| - if (other.isNumber()) return this; |
| + if (other.isDouble()) return HType.DOUBLE; |
| + if (other.isDoubleOrNull()) return HType.DOUBLE; |
| + if (other.isNumber()) return HType.DOUBLE; |
| + if (other.isNumberOrNull()) return HType.DOUBLE; |
| return HType.CONFLICTING; |
| } |
| } |
| @@ -250,6 +390,32 @@ |
| } |
| } |
| +class HStringOrNullType extends HPrimitiveOrNullType { |
| + const HStringOrNullType(); |
| + bool isStringOrNull() => true; |
| + String toString() => "String or null"; |
| + |
| + Type computeType(Compiler compiler) { |
| + return compiler.stringClass.computeType(compiler); |
| + } |
| + |
| + HType union(HType other) { |
| + if (other.isUnknown()) return HType.STRING_OR_NULL; |
| + if (other.isString()) return HType.STRING_OR_NULL; |
| + if (other.isStringOrNull()) return HType.STRING_OR_NULL; |
| + return HType.CONFLICTING; |
|
floitsch
2012/05/10 10:29:43
Add comment why indexable + null-string is conflic
ngeoffray
2012/05/11 10:17:54
Done.
|
| + } |
| + |
| + HType intersection(HType other) { |
| + if (other.isUnknown()) return HType.STRING_OR_NULL; |
| + if (other.isString()) return HType.STRING; |
| + if (other.isStringOrNull()) return HType.STRING_OR_NULL; |
| + if (other.isArray()) return HType.CONFLICTING; |
| + if (other.isIndexablePrimitive()) return HType.STRING; |
| + return HType.CONFLICTING; |
| + } |
| +} |
| + |
| class HStringType extends HIndexablePrimitiveType { |
| const HStringType(); |
| bool isString() => true; |
| @@ -260,15 +426,19 @@ |
| } |
| HType union(HType other) { |
| - if (other.isString() || other.isUnknown()) return HType.STRING; |
| + if (other.isUnknown()) return HType.STRING; |
| + if (other.isString()) return HType.STRING; |
| + if (other.isStringOrNull()) return HType.STRING_OR_NULL; |
| if (other.isIndexablePrimitive()) return HType.INDEXABLE_PRIMITIVE; |
| return HType.CONFLICTING; |
| } |
| HType intersection(HType other) { |
| - if (other.isString() || other.isUnknown()) return HType.STRING; |
| + if (other.isUnknown()) return HType.STRING; |
| + if (other.isString()) return HType.STRING; |
| if (other.isArray()) return HType.CONFLICTING; |
| if (other.isIndexablePrimitive()) return HType.STRING; |
| + if (other.isStringOrNull()) return HType.STRING; |
| return HType.CONFLICTING; |
| } |
| } |
| @@ -391,11 +561,16 @@ |
| } |
| } |
| -class HBoundedPotentialPrimitiveArray extends HBoundedType { |
| - const HBoundedPotentialPrimitiveArray(Type type, bool canBeNull) |
| +class HBoundedPotentialPrimitiveType extends HBoundedType { |
| + const HBoundedPotentialPrimitiveType(Type type, bool canBeNull) |
| : super(type, canBeNull); |
| bool canBePrimitive() => true; |
| +} |
| +class HBoundedPotentialPrimitiveArray extends HBoundedPotentialPrimitiveType { |
| + const HBoundedPotentialPrimitiveArray(Type type, bool canBeNull) |
| + : super(type, canBeNull); |
| + |
| HType combine(HType other) { |
| if (other.isReadableArray()) return other; |
| if (other.isIndexablePrimitive()) return HType.READABLE_ARRAY; |
|
floitsch
2012/05/10 10:29:43
no. If other isString and combine is used for inte
ngeoffray
2012/05/11 10:17:54
Done.
|
| @@ -403,10 +578,9 @@ |
| } |
| } |
| -class HBoundedPotentialPrimitiveString extends HBoundedType { |
| +class HBoundedPotentialPrimitiveString extends HBoundedPotentialPrimitiveType { |
| const HBoundedPotentialPrimitiveString(Type type, bool canBeNull) |
| : super(type, canBeNull); |
| - bool canBePrimitive() => true; |
| HType combine(HType other) { |
| if (other.isString()) return other; |