| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 abstract class HType { | 5 abstract class HType { |
| 6 const HType(); | 6 const HType(); |
| 7 | 7 |
| 8 /** | 8 /** |
| 9 * Returns an [HType] that represents [type] and all types that have | 9 * Returns an [HType] that represents [type] and all types that have |
| 10 * [type] as supertype. | 10 * [type] as supertype. |
| 11 */ | 11 */ |
| 12 factory HType.fromBoundedType(Type type, | 12 factory HType.fromBoundedType(DartType type, |
| 13 Compiler compiler, | 13 Compiler compiler, |
| 14 [bool canBeNull = false]) { | 14 [bool canBeNull = false]) { |
| 15 Element element = type.element; | 15 Element element = type.element; |
| 16 if (element.kind === ElementKind.TYPE_VARIABLE) { | 16 if (element.kind === ElementKind.TYPE_VARIABLE) { |
| 17 // TODO(ngeoffray): Replace object type with [type]. | 17 // TODO(ngeoffray): Replace object type with [type]. |
| 18 return new HBoundedPotentialPrimitiveType( | 18 return new HBoundedPotentialPrimitiveType( |
| 19 compiler.objectClass.computeType(compiler), canBeNull); | 19 compiler.objectClass.computeType(compiler), canBeNull); |
| 20 } | 20 } |
| 21 | 21 |
| 22 if (element === compiler.intClass) { | 22 if (element === compiler.intClass) { |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 80 bool isExact() => false; | 80 bool isExact() => false; |
| 81 | 81 |
| 82 bool canBePrimitive() => false; | 82 bool canBePrimitive() => false; |
| 83 bool canBeNull() => false; | 83 bool canBeNull() => false; |
| 84 | 84 |
| 85 /** A type is useful it is not unknown, not conflicting, and not null. */ | 85 /** A type is useful it is not unknown, not conflicting, and not null. */ |
| 86 bool isUseful() => !isUnknown() && !isConflicting() && !isNull(); | 86 bool isUseful() => !isUnknown() && !isConflicting() && !isNull(); |
| 87 /** Alias for isReadableArray. */ | 87 /** Alias for isReadableArray. */ |
| 88 bool isArray() => isReadableArray(); | 88 bool isArray() => isReadableArray(); |
| 89 | 89 |
| 90 abstract Type computeType(Compiler compiler); | 90 abstract DartType computeType(Compiler compiler); |
| 91 | 91 |
| 92 /** | 92 /** |
| 93 * The intersection of two types is the intersection of its values. For | 93 * The intersection of two types is the intersection of its values. For |
| 94 * example: | 94 * example: |
| 95 * * INTEGER.intersect(NUMBER) => INTEGER. | 95 * * INTEGER.intersect(NUMBER) => INTEGER. |
| 96 * * DOUBLE.intersect(INTEGER) => CONFLICTING. | 96 * * DOUBLE.intersect(INTEGER) => CONFLICTING. |
| 97 * * MUTABLE_ARRAY.intersect(READABLE_ARRAY) => MUTABLE_ARRAY. | 97 * * MUTABLE_ARRAY.intersect(READABLE_ARRAY) => MUTABLE_ARRAY. |
| 98 * | 98 * |
| 99 * When there is no predefined type to represent the intersection returns | 99 * When there is no predefined type to represent the intersection returns |
| 100 * [CONFLICTING]. | 100 * [CONFLICTING]. |
| (...skipping 17 matching lines...) Expand all Loading... |
| 118 */ | 118 */ |
| 119 abstract HType union(HType other); | 119 abstract HType union(HType other); |
| 120 } | 120 } |
| 121 | 121 |
| 122 /** Used to represent [HType.UNKNOWN] and [HType.CONFLICTING]. */ | 122 /** Used to represent [HType.UNKNOWN] and [HType.CONFLICTING]. */ |
| 123 abstract class HAnalysisType extends HType { | 123 abstract class HAnalysisType extends HType { |
| 124 final String name; | 124 final String name; |
| 125 const HAnalysisType(this.name); | 125 const HAnalysisType(this.name); |
| 126 String toString() => name; | 126 String toString() => name; |
| 127 | 127 |
| 128 Type computeType(Compiler compiler) => null; | 128 DartType computeType(Compiler compiler) => null; |
| 129 } | 129 } |
| 130 | 130 |
| 131 class HUnknownType extends HAnalysisType { | 131 class HUnknownType extends HAnalysisType { |
| 132 const HUnknownType() : super("unknown"); | 132 const HUnknownType() : super("unknown"); |
| 133 bool canBePrimitive() => true; | 133 bool canBePrimitive() => true; |
| 134 bool canBeNull() => true; | 134 bool canBeNull() => true; |
| 135 | 135 |
| 136 HType union(HType other) => this; | 136 HType union(HType other) => this; |
| 137 HType intersection(HType other) => other; | 137 HType intersection(HType other) => other; |
| 138 } | 138 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 151 bool isPrimitive() => true; | 151 bool isPrimitive() => true; |
| 152 bool canBePrimitive() => true; | 152 bool canBePrimitive() => true; |
| 153 } | 153 } |
| 154 | 154 |
| 155 class HNullType extends HPrimitiveType { | 155 class HNullType extends HPrimitiveType { |
| 156 const HNullType(); | 156 const HNullType(); |
| 157 bool canBeNull() => true; | 157 bool canBeNull() => true; |
| 158 bool isNull() => true; | 158 bool isNull() => true; |
| 159 String toString() => 'null'; | 159 String toString() => 'null'; |
| 160 | 160 |
| 161 Type computeType(Compiler compiler) => null; | 161 DartType computeType(Compiler compiler) => null; |
| 162 | 162 |
| 163 HType union(HType other) { | 163 HType union(HType other) { |
| 164 if (other.isConflicting()) return HType.NULL; | 164 if (other.isConflicting()) return HType.NULL; |
| 165 if (other.isUnknown()) return HType.UNKNOWN; | 165 if (other.isUnknown()) return HType.UNKNOWN; |
| 166 if (other.isString()) return HType.STRING_OR_NULL; | 166 if (other.isString()) return HType.STRING_OR_NULL; |
| 167 if (other.isInteger()) return HType.INTEGER_OR_NULL; | 167 if (other.isInteger()) return HType.INTEGER_OR_NULL; |
| 168 if (other.isDouble()) return HType.DOUBLE_OR_NULL; | 168 if (other.isDouble()) return HType.DOUBLE_OR_NULL; |
| 169 if (other.isNumber()) return HType.NUMBER_OR_NULL; | 169 if (other.isNumber()) return HType.NUMBER_OR_NULL; |
| 170 if (other.isBoolean()) return HType.BOOLEAN_OR_NULL; | 170 if (other.isBoolean()) return HType.BOOLEAN_OR_NULL; |
| 171 if (!other.canBeNull()) return HType.UNKNOWN; | 171 if (!other.canBeNull()) return HType.UNKNOWN; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 184 const HPrimitiveOrNullType(); | 184 const HPrimitiveOrNullType(); |
| 185 bool canBePrimitive() => true; | 185 bool canBePrimitive() => true; |
| 186 bool canBeNull() => true; | 186 bool canBeNull() => true; |
| 187 } | 187 } |
| 188 | 188 |
| 189 class HBooleanOrNullType extends HPrimitiveOrNullType { | 189 class HBooleanOrNullType extends HPrimitiveOrNullType { |
| 190 const HBooleanOrNullType(); | 190 const HBooleanOrNullType(); |
| 191 String toString() => "boolean or null"; | 191 String toString() => "boolean or null"; |
| 192 bool isBooleanOrNull() => true; | 192 bool isBooleanOrNull() => true; |
| 193 | 193 |
| 194 Type computeType(Compiler compiler) { | 194 DartType computeType(Compiler compiler) { |
| 195 return compiler.boolClass.computeType(compiler); | 195 return compiler.boolClass.computeType(compiler); |
| 196 } | 196 } |
| 197 | 197 |
| 198 HType union(HType other) { | 198 HType union(HType other) { |
| 199 if (other.isConflicting()) return HType.BOOLEAN_OR_NULL; | 199 if (other.isConflicting()) return HType.BOOLEAN_OR_NULL; |
| 200 if (other.isUnknown()) return HType.UNKNOWN; | 200 if (other.isUnknown()) return HType.UNKNOWN; |
| 201 if (other.isBooleanOrNull()) return HType.BOOLEAN_OR_NULL; | 201 if (other.isBooleanOrNull()) return HType.BOOLEAN_OR_NULL; |
| 202 if (other.isBoolean()) return HType.BOOLEAN_OR_NULL; | 202 if (other.isBoolean()) return HType.BOOLEAN_OR_NULL; |
| 203 if (other.isNull()) return HType.BOOLEAN_OR_NULL; | 203 if (other.isNull()) return HType.BOOLEAN_OR_NULL; |
| 204 return HType.UNKNOWN; | 204 return HType.UNKNOWN; |
| 205 } | 205 } |
| 206 | 206 |
| 207 HType intersection(HType other) { | 207 HType intersection(HType other) { |
| 208 if (other.isUnknown()) return HType.BOOLEAN_OR_NULL; | 208 if (other.isUnknown()) return HType.BOOLEAN_OR_NULL; |
| 209 if (other.isBooleanOrNull()) return HType.BOOLEAN_OR_NULL; | 209 if (other.isBooleanOrNull()) return HType.BOOLEAN_OR_NULL; |
| 210 if (other.isBoolean()) return HType.BOOLEAN; | 210 if (other.isBoolean()) return HType.BOOLEAN; |
| 211 if (other.canBeNull()) return HType.NULL; | 211 if (other.canBeNull()) return HType.NULL; |
| 212 return HType.CONFLICTING; | 212 return HType.CONFLICTING; |
| 213 } | 213 } |
| 214 } | 214 } |
| 215 | 215 |
| 216 class HBooleanType extends HPrimitiveType { | 216 class HBooleanType extends HPrimitiveType { |
| 217 const HBooleanType(); | 217 const HBooleanType(); |
| 218 bool isBoolean() => true; | 218 bool isBoolean() => true; |
| 219 String toString() => "boolean"; | 219 String toString() => "boolean"; |
| 220 | 220 |
| 221 Type computeType(Compiler compiler) { | 221 DartType computeType(Compiler compiler) { |
| 222 return compiler.boolClass.computeType(compiler); | 222 return compiler.boolClass.computeType(compiler); |
| 223 } | 223 } |
| 224 | 224 |
| 225 HType union(HType other) { | 225 HType union(HType other) { |
| 226 if (other.isConflicting()) return HType.BOOLEAN; | 226 if (other.isConflicting()) return HType.BOOLEAN; |
| 227 if (other.isUnknown()) return HType.UNKNOWN; | 227 if (other.isUnknown()) return HType.UNKNOWN; |
| 228 if (other.isBoolean()) return HType.BOOLEAN; | 228 if (other.isBoolean()) return HType.BOOLEAN; |
| 229 if (other.isBooleanOrNull()) return HType.BOOLEAN_OR_NULL; | 229 if (other.isBooleanOrNull()) return HType.BOOLEAN_OR_NULL; |
| 230 if (other.isNull()) return HType.BOOLEAN_OR_NULL; | 230 if (other.isNull()) return HType.BOOLEAN_OR_NULL; |
| 231 return HType.UNKNOWN; | 231 return HType.UNKNOWN; |
| 232 } | 232 } |
| 233 | 233 |
| 234 HType intersection(HType other) { | 234 HType intersection(HType other) { |
| 235 if (other.isUnknown()) return HType.BOOLEAN; | 235 if (other.isUnknown()) return HType.BOOLEAN; |
| 236 if (other.isBooleanOrNull()) return HType.BOOLEAN; | 236 if (other.isBooleanOrNull()) return HType.BOOLEAN; |
| 237 if (other.isBoolean()) return HType.BOOLEAN; | 237 if (other.isBoolean()) return HType.BOOLEAN; |
| 238 return HType.CONFLICTING; | 238 return HType.CONFLICTING; |
| 239 } | 239 } |
| 240 } | 240 } |
| 241 | 241 |
| 242 class HNumberOrNullType extends HPrimitiveOrNullType { | 242 class HNumberOrNullType extends HPrimitiveOrNullType { |
| 243 const HNumberOrNullType(); | 243 const HNumberOrNullType(); |
| 244 bool isNumberOrNull() => true; | 244 bool isNumberOrNull() => true; |
| 245 String toString() => "number or null"; | 245 String toString() => "number or null"; |
| 246 | 246 |
| 247 Type computeType(Compiler compiler) { | 247 DartType computeType(Compiler compiler) { |
| 248 return compiler.numClass.computeType(compiler); | 248 return compiler.numClass.computeType(compiler); |
| 249 } | 249 } |
| 250 | 250 |
| 251 HType union(HType other) { | 251 HType union(HType other) { |
| 252 if (other.isConflicting()) return HType.NUMBER_OR_NULL; | 252 if (other.isConflicting()) return HType.NUMBER_OR_NULL; |
| 253 if (other.isUnknown()) return HType.UNKNOWN; | 253 if (other.isUnknown()) return HType.UNKNOWN; |
| 254 if (other.isNumberOrNull()) return HType.NUMBER_OR_NULL; | 254 if (other.isNumberOrNull()) return HType.NUMBER_OR_NULL; |
| 255 if (other.isNumber()) return HType.NUMBER_OR_NULL; | 255 if (other.isNumber()) return HType.NUMBER_OR_NULL; |
| 256 if (other.isNull()) return HType.NUMBER_OR_NULL; | 256 if (other.isNull()) return HType.NUMBER_OR_NULL; |
| 257 return HType.UNKNOWN; | 257 return HType.UNKNOWN; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 268 if (other.canBeNull()) return HType.NULL; | 268 if (other.canBeNull()) return HType.NULL; |
| 269 return HType.CONFLICTING; | 269 return HType.CONFLICTING; |
| 270 } | 270 } |
| 271 } | 271 } |
| 272 | 272 |
| 273 class HNumberType extends HPrimitiveType { | 273 class HNumberType extends HPrimitiveType { |
| 274 const HNumberType(); | 274 const HNumberType(); |
| 275 bool isNumber() => true; | 275 bool isNumber() => true; |
| 276 String toString() => "number"; | 276 String toString() => "number"; |
| 277 | 277 |
| 278 Type computeType(Compiler compiler) { | 278 DartType computeType(Compiler compiler) { |
| 279 return compiler.numClass.computeType(compiler); | 279 return compiler.numClass.computeType(compiler); |
| 280 } | 280 } |
| 281 | 281 |
| 282 HType union(HType other) { | 282 HType union(HType other) { |
| 283 if (other.isConflicting()) return HType.NUMBER; | 283 if (other.isConflicting()) return HType.NUMBER; |
| 284 if (other.isUnknown()) return HType.UNKNOWN; | 284 if (other.isUnknown()) return HType.UNKNOWN; |
| 285 if (other.isNumber()) return HType.NUMBER; | 285 if (other.isNumber()) return HType.NUMBER; |
| 286 if (other.isNumberOrNull()) return HType.NUMBER_OR_NULL; | 286 if (other.isNumberOrNull()) return HType.NUMBER_OR_NULL; |
| 287 if (other.isNull()) return HType.NUMBER_OR_NULL; | 287 if (other.isNull()) return HType.NUMBER_OR_NULL; |
| 288 return HType.UNKNOWN; | 288 return HType.UNKNOWN; |
| 289 } | 289 } |
| 290 | 290 |
| 291 HType intersection(HType other) { | 291 HType intersection(HType other) { |
| 292 if (other.isUnknown()) return HType.NUMBER; | 292 if (other.isUnknown()) return HType.NUMBER; |
| 293 if (other.isNumber()) return other; | 293 if (other.isNumber()) return other; |
| 294 if (other.isIntegerOrNull()) return HType.INTEGER; | 294 if (other.isIntegerOrNull()) return HType.INTEGER; |
| 295 if (other.isDoubleOrNull()) return HType.DOUBLE; | 295 if (other.isDoubleOrNull()) return HType.DOUBLE; |
| 296 if (other.isNumberOrNull()) return HType.NUMBER; | 296 if (other.isNumberOrNull()) return HType.NUMBER; |
| 297 return HType.CONFLICTING; | 297 return HType.CONFLICTING; |
| 298 } | 298 } |
| 299 } | 299 } |
| 300 | 300 |
| 301 class HIntegerOrNullType extends HNumberOrNullType { | 301 class HIntegerOrNullType extends HNumberOrNullType { |
| 302 const HIntegerOrNullType(); | 302 const HIntegerOrNullType(); |
| 303 bool isIntegerOrNull() => true; | 303 bool isIntegerOrNull() => true; |
| 304 String toString() => "integer or null"; | 304 String toString() => "integer or null"; |
| 305 | 305 |
| 306 Type computeType(Compiler compiler) { | 306 DartType computeType(Compiler compiler) { |
| 307 return compiler.intClass.computeType(compiler); | 307 return compiler.intClass.computeType(compiler); |
| 308 } | 308 } |
| 309 | 309 |
| 310 HType union(HType other) { | 310 HType union(HType other) { |
| 311 if (other.isConflicting()) return HType.INTEGER_OR_NULL; | 311 if (other.isConflicting()) return HType.INTEGER_OR_NULL; |
| 312 if (other.isUnknown()) return HType.UNKNOWN; | 312 if (other.isUnknown()) return HType.UNKNOWN; |
| 313 if (other.isIntegerOrNull()) return HType.INTEGER_OR_NULL; | 313 if (other.isIntegerOrNull()) return HType.INTEGER_OR_NULL; |
| 314 if (other.isInteger()) return HType.INTEGER_OR_NULL; | 314 if (other.isInteger()) return HType.INTEGER_OR_NULL; |
| 315 if (other.isNumber()) return HType.NUMBER_OR_NULL; | 315 if (other.isNumber()) return HType.NUMBER_OR_NULL; |
| 316 if (other.isNumberOrNull()) return HType.NUMBER_OR_NULL; | 316 if (other.isNumberOrNull()) return HType.NUMBER_OR_NULL; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 329 if (other.canBeNull()) return HType.NULL; | 329 if (other.canBeNull()) return HType.NULL; |
| 330 return HType.CONFLICTING; | 330 return HType.CONFLICTING; |
| 331 } | 331 } |
| 332 } | 332 } |
| 333 | 333 |
| 334 class HIntegerType extends HNumberType { | 334 class HIntegerType extends HNumberType { |
| 335 const HIntegerType(); | 335 const HIntegerType(); |
| 336 bool isInteger() => true; | 336 bool isInteger() => true; |
| 337 String toString() => "integer"; | 337 String toString() => "integer"; |
| 338 | 338 |
| 339 Type computeType(Compiler compiler) { | 339 DartType computeType(Compiler compiler) { |
| 340 return compiler.intClass.computeType(compiler); | 340 return compiler.intClass.computeType(compiler); |
| 341 } | 341 } |
| 342 | 342 |
| 343 HType union(HType other) { | 343 HType union(HType other) { |
| 344 if (other.isConflicting()) return HType.INTEGER; | 344 if (other.isConflicting()) return HType.INTEGER; |
| 345 if (other.isUnknown()) return HType.UNKNOWN; | 345 if (other.isUnknown()) return HType.UNKNOWN; |
| 346 if (other.isInteger()) return HType.INTEGER; | 346 if (other.isInteger()) return HType.INTEGER; |
| 347 if (other.isIntegerOrNull()) return HType.INTEGER_OR_NULL; | 347 if (other.isIntegerOrNull()) return HType.INTEGER_OR_NULL; |
| 348 if (other.isNumber()) return HType.NUMBER; | 348 if (other.isNumber()) return HType.NUMBER; |
| 349 if (other.isNumberOrNull()) return HType.NUMBER_OR_NULL; | 349 if (other.isNumberOrNull()) return HType.NUMBER_OR_NULL; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 361 if (other.isNumberOrNull()) return HType.INTEGER; | 361 if (other.isNumberOrNull()) return HType.INTEGER; |
| 362 return HType.CONFLICTING; | 362 return HType.CONFLICTING; |
| 363 } | 363 } |
| 364 } | 364 } |
| 365 | 365 |
| 366 class HDoubleOrNullType extends HNumberOrNullType { | 366 class HDoubleOrNullType extends HNumberOrNullType { |
| 367 const HDoubleOrNullType(); | 367 const HDoubleOrNullType(); |
| 368 bool isDoubleOrNull() => true; | 368 bool isDoubleOrNull() => true; |
| 369 String toString() => "double or null"; | 369 String toString() => "double or null"; |
| 370 | 370 |
| 371 Type computeType(Compiler compiler) { | 371 DartType computeType(Compiler compiler) { |
| 372 return compiler.doubleClass.computeType(compiler); | 372 return compiler.doubleClass.computeType(compiler); |
| 373 } | 373 } |
| 374 | 374 |
| 375 HType union(HType other) { | 375 HType union(HType other) { |
| 376 if (other.isConflicting()) return HType.DOUBLE_OR_NULL; | 376 if (other.isConflicting()) return HType.DOUBLE_OR_NULL; |
| 377 if (other.isUnknown()) return HType.UNKNOWN; | 377 if (other.isUnknown()) return HType.UNKNOWN; |
| 378 if (other.isDoubleOrNull()) return HType.DOUBLE_OR_NULL; | 378 if (other.isDoubleOrNull()) return HType.DOUBLE_OR_NULL; |
| 379 if (other.isDouble()) return HType.DOUBLE_OR_NULL; | 379 if (other.isDouble()) return HType.DOUBLE_OR_NULL; |
| 380 if (other.isNumber()) return HType.NUMBER_OR_NULL; | 380 if (other.isNumber()) return HType.NUMBER_OR_NULL; |
| 381 if (other.isNumberOrNull()) return HType.NUMBER_OR_NULL; | 381 if (other.isNumberOrNull()) return HType.NUMBER_OR_NULL; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 394 if (other.canBeNull()) return HType.NULL; | 394 if (other.canBeNull()) return HType.NULL; |
| 395 return HType.CONFLICTING; | 395 return HType.CONFLICTING; |
| 396 } | 396 } |
| 397 } | 397 } |
| 398 | 398 |
| 399 class HDoubleType extends HNumberType { | 399 class HDoubleType extends HNumberType { |
| 400 const HDoubleType(); | 400 const HDoubleType(); |
| 401 bool isDouble() => true; | 401 bool isDouble() => true; |
| 402 String toString() => "double"; | 402 String toString() => "double"; |
| 403 | 403 |
| 404 Type computeType(Compiler compiler) { | 404 DartType computeType(Compiler compiler) { |
| 405 return compiler.doubleClass.computeType(compiler); | 405 return compiler.doubleClass.computeType(compiler); |
| 406 } | 406 } |
| 407 | 407 |
| 408 HType union(HType other) { | 408 HType union(HType other) { |
| 409 if (other.isConflicting()) return HType.DOUBLE; | 409 if (other.isConflicting()) return HType.DOUBLE; |
| 410 if (other.isUnknown()) return HType.UNKNOWN; | 410 if (other.isUnknown()) return HType.UNKNOWN; |
| 411 if (other.isDouble()) return HType.DOUBLE; | 411 if (other.isDouble()) return HType.DOUBLE; |
| 412 if (other.isDoubleOrNull()) return HType.DOUBLE_OR_NULL; | 412 if (other.isDoubleOrNull()) return HType.DOUBLE_OR_NULL; |
| 413 if (other.isNumber()) return HType.NUMBER; | 413 if (other.isNumber()) return HType.NUMBER; |
| 414 if (other.isNumberOrNull()) return HType.NUMBER_OR_NULL; | 414 if (other.isNumberOrNull()) return HType.NUMBER_OR_NULL; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 426 if (other.isNumberOrNull()) return HType.DOUBLE; | 426 if (other.isNumberOrNull()) return HType.DOUBLE; |
| 427 return HType.CONFLICTING; | 427 return HType.CONFLICTING; |
| 428 } | 428 } |
| 429 } | 429 } |
| 430 | 430 |
| 431 class HIndexablePrimitiveType extends HPrimitiveType { | 431 class HIndexablePrimitiveType extends HPrimitiveType { |
| 432 const HIndexablePrimitiveType(); | 432 const HIndexablePrimitiveType(); |
| 433 bool isIndexablePrimitive() => true; | 433 bool isIndexablePrimitive() => true; |
| 434 String toString() => "indexable"; | 434 String toString() => "indexable"; |
| 435 | 435 |
| 436 Type computeType(Compiler compiler) { | 436 DartType computeType(Compiler compiler) { |
| 437 // TODO(ngeoffray): Represent union types. | 437 // TODO(ngeoffray): Represent union types. |
| 438 return null; | 438 return null; |
| 439 } | 439 } |
| 440 | 440 |
| 441 HType union(HType other) { | 441 HType union(HType other) { |
| 442 if (other.isConflicting()) return HType.INDEXABLE_PRIMITIVE; | 442 if (other.isConflicting()) return HType.INDEXABLE_PRIMITIVE; |
| 443 if (other.isUnknown()) return HType.UNKNOWN; | 443 if (other.isUnknown()) return HType.UNKNOWN; |
| 444 if (other.isIndexablePrimitive()) return HType.INDEXABLE_PRIMITIVE; | 444 if (other.isIndexablePrimitive()) return HType.INDEXABLE_PRIMITIVE; |
| 445 if (other is HBoundedPotentialPrimitiveString) { | 445 if (other is HBoundedPotentialPrimitiveString) { |
| 446 // TODO(ngeoffray): Represent union types. | 446 // TODO(ngeoffray): Represent union types. |
| (...skipping 13 matching lines...) Expand all Loading... |
| 460 if (other is HBoundedPotentialPrimitiveArray) return HType.READABLE_ARRAY; | 460 if (other is HBoundedPotentialPrimitiveArray) return HType.READABLE_ARRAY; |
| 461 return HType.CONFLICTING; | 461 return HType.CONFLICTING; |
| 462 } | 462 } |
| 463 } | 463 } |
| 464 | 464 |
| 465 class HStringOrNullType extends HPrimitiveOrNullType { | 465 class HStringOrNullType extends HPrimitiveOrNullType { |
| 466 const HStringOrNullType(); | 466 const HStringOrNullType(); |
| 467 bool isStringOrNull() => true; | 467 bool isStringOrNull() => true; |
| 468 String toString() => "String or null"; | 468 String toString() => "String or null"; |
| 469 | 469 |
| 470 Type computeType(Compiler compiler) { | 470 DartType computeType(Compiler compiler) { |
| 471 return compiler.stringClass.computeType(compiler); | 471 return compiler.stringClass.computeType(compiler); |
| 472 } | 472 } |
| 473 | 473 |
| 474 HType union(HType other) { | 474 HType union(HType other) { |
| 475 if (other.isConflicting()) return HType.STRING_OR_NULL; | 475 if (other.isConflicting()) return HType.STRING_OR_NULL; |
| 476 if (other.isUnknown()) return HType.UNKNOWN; | 476 if (other.isUnknown()) return HType.UNKNOWN; |
| 477 if (other.isString()) return HType.STRING_OR_NULL; | 477 if (other.isString()) return HType.STRING_OR_NULL; |
| 478 if (other.isStringOrNull()) return HType.STRING_OR_NULL; | 478 if (other.isStringOrNull()) return HType.STRING_OR_NULL; |
| 479 if (other.isIndexablePrimitive()) { | 479 if (other.isIndexablePrimitive()) { |
| 480 // We don't have a type that represents the nullable indexable | 480 // We don't have a type that represents the nullable indexable |
| (...skipping 24 matching lines...) Expand all Loading... |
| 505 if (other.canBeNull()) return HType.NULL; | 505 if (other.canBeNull()) return HType.NULL; |
| 506 return HType.CONFLICTING; | 506 return HType.CONFLICTING; |
| 507 } | 507 } |
| 508 } | 508 } |
| 509 | 509 |
| 510 class HStringType extends HIndexablePrimitiveType { | 510 class HStringType extends HIndexablePrimitiveType { |
| 511 const HStringType(); | 511 const HStringType(); |
| 512 bool isString() => true; | 512 bool isString() => true; |
| 513 String toString() => "String"; | 513 String toString() => "String"; |
| 514 | 514 |
| 515 Type computeType(Compiler compiler) { | 515 DartType computeType(Compiler compiler) { |
| 516 return compiler.stringClass.computeType(compiler); | 516 return compiler.stringClass.computeType(compiler); |
| 517 } | 517 } |
| 518 | 518 |
| 519 HType union(HType other) { | 519 HType union(HType other) { |
| 520 if (other.isConflicting()) return HType.STRING; | 520 if (other.isConflicting()) return HType.STRING; |
| 521 if (other.isUnknown()) return HType.UNKNOWN; | 521 if (other.isUnknown()) return HType.UNKNOWN; |
| 522 if (other.isString()) return HType.STRING; | 522 if (other.isString()) return HType.STRING; |
| 523 if (other.isStringOrNull()) return HType.STRING_OR_NULL; | 523 if (other.isStringOrNull()) return HType.STRING_OR_NULL; |
| 524 if (other.isIndexablePrimitive()) return HType.INDEXABLE_PRIMITIVE; | 524 if (other.isIndexablePrimitive()) return HType.INDEXABLE_PRIMITIVE; |
| 525 if (other is HBoundedPotentialPrimitiveString) return other; | 525 if (other is HBoundedPotentialPrimitiveString) return other; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 536 if (other is HBoundedPotentialPrimitiveString) return HType.STRING; | 536 if (other is HBoundedPotentialPrimitiveString) return HType.STRING; |
| 537 return HType.CONFLICTING; | 537 return HType.CONFLICTING; |
| 538 } | 538 } |
| 539 } | 539 } |
| 540 | 540 |
| 541 class HReadableArrayType extends HIndexablePrimitiveType { | 541 class HReadableArrayType extends HIndexablePrimitiveType { |
| 542 const HReadableArrayType(); | 542 const HReadableArrayType(); |
| 543 bool isReadableArray() => true; | 543 bool isReadableArray() => true; |
| 544 String toString() => "readable array"; | 544 String toString() => "readable array"; |
| 545 | 545 |
| 546 Type computeType(Compiler compiler) { | 546 DartType computeType(Compiler compiler) { |
| 547 return compiler.listClass.computeType(compiler); | 547 return compiler.listClass.computeType(compiler); |
| 548 } | 548 } |
| 549 | 549 |
| 550 HType union(HType other) { | 550 HType union(HType other) { |
| 551 if (other.isConflicting()) return HType.READABLE_ARRAY; | 551 if (other.isConflicting()) return HType.READABLE_ARRAY; |
| 552 if (other.isUnknown()) return HType.UNKNOWN; | 552 if (other.isUnknown()) return HType.UNKNOWN; |
| 553 if (other.isReadableArray()) return HType.READABLE_ARRAY; | 553 if (other.isReadableArray()) return HType.READABLE_ARRAY; |
| 554 if (other.isIndexablePrimitive()) return HType.INDEXABLE_PRIMITIVE; | 554 if (other.isIndexablePrimitive()) return HType.INDEXABLE_PRIMITIVE; |
| 555 if (other is HBoundedPotentialPrimitiveArray) return other; | 555 if (other is HBoundedPotentialPrimitiveArray) return other; |
| 556 return HType.UNKNOWN; | 556 return HType.UNKNOWN; |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 611 if (other.isUnknown()) return HType.EXTENDABLE_ARRAY; | 611 if (other.isUnknown()) return HType.EXTENDABLE_ARRAY; |
| 612 if (other.isExtendableArray()) return HType.EXTENDABLE_ARRAY; | 612 if (other.isExtendableArray()) return HType.EXTENDABLE_ARRAY; |
| 613 if (other.isString()) return HType.CONFLICTING; | 613 if (other.isString()) return HType.CONFLICTING; |
| 614 if (other.isIndexablePrimitive()) return HType.EXTENDABLE_ARRAY; | 614 if (other.isIndexablePrimitive()) return HType.EXTENDABLE_ARRAY; |
| 615 if (other is HBoundedPotentialPrimitiveArray) return HType.EXTENDABLE_ARRAY; | 615 if (other is HBoundedPotentialPrimitiveArray) return HType.EXTENDABLE_ARRAY; |
| 616 return HType.CONFLICTING; | 616 return HType.CONFLICTING; |
| 617 } | 617 } |
| 618 } | 618 } |
| 619 | 619 |
| 620 class HBoundedType extends HType { | 620 class HBoundedType extends HType { |
| 621 final Type type; | 621 final DartType type; |
| 622 final bool _canBeNull; | 622 final bool _canBeNull; |
| 623 final bool _isExact; | 623 final bool _isExact; |
| 624 | 624 |
| 625 toString() { | 625 toString() { |
| 626 return 'BoundedType($type, $_canBeNull, $_isExact)'; | 626 return 'BoundedType($type, $_canBeNull, $_isExact)'; |
| 627 } | 627 } |
| 628 | 628 |
| 629 bool canBeNull() => _canBeNull; | 629 bool canBeNull() => _canBeNull; |
| 630 | 630 |
| 631 bool isExact() => _isExact; | 631 bool isExact() => _isExact; |
| 632 | 632 |
| 633 const HBoundedType(Type this.type, | 633 const HBoundedType(DartType this.type, |
| 634 [bool canBeNull = false, isExact = false]) | 634 [bool canBeNull = false, isExact = false]) |
| 635 : _canBeNull = canBeNull, _isExact = isExact; | 635 : _canBeNull = canBeNull, _isExact = isExact; |
| 636 const HBoundedType.exact(Type type) : this(type, isExact: true); | 636 const HBoundedType.exact(DartType type) : this(type, isExact: true); |
| 637 const HBoundedType.withNull(Type type) : this(type, canBeNull: true); | 637 const HBoundedType.withNull(DartType type) : this(type, canBeNull: true); |
| 638 const HBoundedType.nonNull(Type type) : this(type); | 638 const HBoundedType.nonNull(DartType type) : this(type); |
| 639 | 639 |
| 640 Type computeType(Compiler compiler) => type; | 640 DartType computeType(Compiler compiler) => type; |
| 641 | 641 |
| 642 Element lookupMember(SourceString name) { | 642 Element lookupMember(SourceString name) { |
| 643 if (!isExact()) return null; | 643 if (!isExact()) return null; |
| 644 ClassElement classElement = type.element; | 644 ClassElement classElement = type.element; |
| 645 return classElement.lookupMember(name); | 645 return classElement.lookupMember(name); |
| 646 } | 646 } |
| 647 | 647 |
| 648 HType intersection(HType other) { | 648 HType intersection(HType other) { |
| 649 assert(!(isExact() && canBeNull())); | 649 assert(!(isExact() && canBeNull())); |
| 650 if (other.isNull()) return canBeNull() ? HType.NULL : HType.CONFLICTING; | 650 if (other.isNull()) return canBeNull() ? HType.NULL : HType.CONFLICTING; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 688 if (isExact()) return other; | 688 if (isExact()) return other; |
| 689 if (other.isExact()) return this; | 689 if (other.isExact()) return this; |
| 690 return canBeNull() ? this : other; | 690 return canBeNull() ? this : other; |
| 691 } | 691 } |
| 692 if (other.isConflicting()) return this; | 692 if (other.isConflicting()) return this; |
| 693 return HType.UNKNOWN; | 693 return HType.UNKNOWN; |
| 694 } | 694 } |
| 695 } | 695 } |
| 696 | 696 |
| 697 class HBoundedPotentialPrimitiveType extends HBoundedType { | 697 class HBoundedPotentialPrimitiveType extends HBoundedType { |
| 698 const HBoundedPotentialPrimitiveType(Type type, bool canBeNull) | 698 const HBoundedPotentialPrimitiveType(DartType type, bool canBeNull) |
| 699 : super(type, canBeNull, false); | 699 : super(type, canBeNull, false); |
| 700 bool canBePrimitive() => true; | 700 bool canBePrimitive() => true; |
| 701 } | 701 } |
| 702 | 702 |
| 703 class HBoundedPotentialPrimitiveArray extends HBoundedPotentialPrimitiveType { | 703 class HBoundedPotentialPrimitiveArray extends HBoundedPotentialPrimitiveType { |
| 704 const HBoundedPotentialPrimitiveArray(Type type, bool canBeNull) | 704 const HBoundedPotentialPrimitiveArray(DartType type, bool canBeNull) |
| 705 : super(type, canBeNull); | 705 : super(type, canBeNull); |
| 706 | 706 |
| 707 HType union(HType other) { | 707 HType union(HType other) { |
| 708 if (other.isString()) return HType.UNKNOWN; | 708 if (other.isString()) return HType.UNKNOWN; |
| 709 if (other.isReadableArray()) return this; | 709 if (other.isReadableArray()) return this; |
| 710 // TODO(ngeoffray): implement union types. | 710 // TODO(ngeoffray): implement union types. |
| 711 if (other.isIndexablePrimitive()) return HType.UNKNOWN; | 711 if (other.isIndexablePrimitive()) return HType.UNKNOWN; |
| 712 if (other.isNull()) { | 712 if (other.isNull()) { |
| 713 if (canBeNull()) { | 713 if (canBeNull()) { |
| 714 return this; | 714 return this; |
| 715 } else { | 715 } else { |
| 716 return new HBoundedPotentialPrimitiveArray(type, true); | 716 return new HBoundedPotentialPrimitiveArray(type, true); |
| 717 } | 717 } |
| 718 } | 718 } |
| 719 return super.union(other); | 719 return super.union(other); |
| 720 } | 720 } |
| 721 | 721 |
| 722 HType intersection(HType other) { | 722 HType intersection(HType other) { |
| 723 if (other.isString()) return HType.CONFLICTING; | 723 if (other.isString()) return HType.CONFLICTING; |
| 724 if (other.isReadableArray()) return other; | 724 if (other.isReadableArray()) return other; |
| 725 if (other.isIndexablePrimitive()) return HType.READABLE_ARRAY; | 725 if (other.isIndexablePrimitive()) return HType.READABLE_ARRAY; |
| 726 return super.intersection(other); | 726 return super.intersection(other); |
| 727 } | 727 } |
| 728 } | 728 } |
| 729 | 729 |
| 730 class HBoundedPotentialPrimitiveString extends HBoundedPotentialPrimitiveType { | 730 class HBoundedPotentialPrimitiveString extends HBoundedPotentialPrimitiveType { |
| 731 const HBoundedPotentialPrimitiveString(Type type, bool canBeNull) | 731 const HBoundedPotentialPrimitiveString(DartType type, bool canBeNull) |
| 732 : super(type, canBeNull); | 732 : super(type, canBeNull); |
| 733 | 733 |
| 734 HType union(HType other) { | 734 HType union(HType other) { |
| 735 if (other.isString()) return this; | 735 if (other.isString()) return this; |
| 736 if (other.isStringOrNull()) { | 736 if (other.isStringOrNull()) { |
| 737 if (canBeNull()) { | 737 if (canBeNull()) { |
| 738 return this; | 738 return this; |
| 739 } else { | 739 } else { |
| 740 return new HBoundedPotentialPrimitiveString(type, true); | 740 return new HBoundedPotentialPrimitiveString(type, true); |
| 741 } | 741 } |
| (...skipping 29 matching lines...) Expand all Loading... |
| 771 operator [](HInstruction instruction) { | 771 operator [](HInstruction instruction) { |
| 772 HType result = _map[instruction]; | 772 HType result = _map[instruction]; |
| 773 if (result == null) return instruction.guaranteedType; | 773 if (result == null) return instruction.guaranteedType; |
| 774 return result; | 774 return result; |
| 775 } | 775 } |
| 776 | 776 |
| 777 operator []=(HInstruction instruction, HType value) { | 777 operator []=(HInstruction instruction, HType value) { |
| 778 _map[instruction] = value; | 778 _map[instruction] = value; |
| 779 } | 779 } |
| 780 } | 780 } |
| OLD | NEW |