Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(80)

Unified Diff: lib/compiler/implementation/ssa/types.dart

Issue 10389063: Implement PrimitiveOrNull types. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « lib/compiler/implementation/ssa/optimize.dart ('k') | tests/language/language.status » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/compiler/implementation/ssa/types.dart
===================================================================
--- lib/compiler/implementation/ssa/types.dart (revision 7534)
+++ lib/compiler/implementation/ssa/types.dart (working copy)
@@ -6,42 +6,34 @@
const HType();
/**
- * Returns a [HType] that represents all types that have [type] as a
- * supertype, or the type [type].
+ * Returns an [HType] that represents [type] and all types that have
+ * [type] as supertype.
*/
factory HType.fromBoundedType(Type type,
Compiler compiler,
[bool canBeNull = false]) {
Element element = type.element;
if (element.kind === ElementKind.TYPE_VARIABLE) {
- compiler.unimplemented("type variables");
+ // TODO(ngeoffray): Replace object type with [type].
+ 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();
+ 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,49 @@
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.isInteger()) return HType.INTEGER;
+ if (other.isDouble()) return HType.DOUBLE;
+ if (other.isNumber()) return HType.NUMBER;
+ if (other.isIntegerOrNull()) return HType.INTEGER_OR_NULL;
+ if (other.isDoubleOrNull()) return HType.DOUBLE_OR_NULL;
+ if (other.isNumberOrNull()) return HType.NUMBER_OR_NULL;
+ return HType.CONFLICTING;
+ }
+}
+
class HNumberType extends HPrimitiveType {
const HNumberType();
bool isNumber() => true;
@@ -169,17 +234,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 +290,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 +350,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;
}
}
@@ -259,6 +403,48 @@
}
}
+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;
+ if (other.isIndexablePrimitive()) {
+ // We don't have a type that represents the nullable indexable
+ // primitive.
+ return HType.CONFLICTING;
+ }
+ if (other is HBoundedPotentialPrimitiveString) {
+ if (other.canBeNull()) {
+ return other;
+ } else {
+ HBoundedType boundedType = other;
+ return new HBoundedPotentialPrimitiveString(boundedType.type, true);
+ }
+ }
+ return HType.CONFLICTING;
+ }
+
+ 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;
+ if (other is HBoundedPotentialPrimitiveString) {
+ return other.canBeNull() ? HType.STRING_OR_NULL : HType.STRING;
+ }
+ return HType.CONFLICTING;
+ }
+}
+
class HStringType extends HIndexablePrimitiveType {
const HStringType();
bool isString() => true;
@@ -271,6 +457,7 @@
HType union(HType other) {
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;
if (other is HBoundedPotentialPrimitiveString) return other;
return HType.CONFLICTING;
@@ -281,6 +468,7 @@
if (other.isString()) return HType.STRING;
if (other.isArray()) return HType.CONFLICTING;
if (other.isIndexablePrimitive()) return HType.STRING;
+ if (other.isStringOrNull()) return HType.STRING;
if (other is HBoundedPotentialPrimitiveString) return HType.STRING;
return HType.CONFLICTING;
}
@@ -408,11 +596,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 union(HType other) {
if (other.isString()) return HType.CONFLICTING;
if (other.isReadableArray()) return this;
@@ -429,13 +622,19 @@
}
}
-class HBoundedPotentialPrimitiveString extends HBoundedType {
+class HBoundedPotentialPrimitiveString extends HBoundedPotentialPrimitiveType {
const HBoundedPotentialPrimitiveString(Type type, bool canBeNull)
: super(type, canBeNull);
- bool canBePrimitive() => true;
HType union(HType other) {
if (other.isString()) return this;
+ if (other.isStringOrNull()) {
+ if (canBeNull()) {
+ return this;
+ } else {
+ return new HBoundedPotentialPrimitiveString(type, true);
+ }
+ }
// TODO(ngeoffray): implement union types.
if (other.isIndexablePrimitive()) return HType.CONFLICTING;
return super.union(other);
@@ -443,6 +642,9 @@
HType intersection(HType other) {
if (other.isString()) return HType.STRING;
+ if (other.isStringOrNull()) {
+ return canBeNull() ? HType.STRING_OR_NULL : HType.STRING;
+ }
if (other.isReadableArray()) return HType.CONFLICTING;
if (other.isIndexablePrimitive()) return HType.STRING;
return super.intersection(other);
« no previous file with comments | « lib/compiler/implementation/ssa/optimize.dart ('k') | tests/language/language.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698