| 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 a [HType] that represents all types that have [type] as a | 9 * Returns an [HType] that represents [type] and all types that have |
| 10 * supertype, or the type [type]. | 10 * [type] as supertype. |
| 11 */ | 11 */ |
| 12 factory HType.fromBoundedType(Type type, | 12 factory HType.fromBoundedType(Type 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 compiler.unimplemented("type variables"); | 17 // TODO(ngeoffray): Replace object type with [type]. |
| 18 return new HBoundedPotentialPrimitiveType( |
| 19 compiler.objectClass.computeType(compiler), canBeNull); |
| 18 } | 20 } |
| 19 | 21 |
| 20 if (!canBeNull) { | 22 if (element === compiler.intClass) { |
| 21 if (element === compiler.intClass) { | 23 return canBeNull ? HType.INTEGER_OR_NULL : HType.INTEGER; |
| 22 return HType.INTEGER; | 24 } else if (element === compiler.numClass) { |
| 23 } else if (element === compiler.numClass) { | 25 return canBeNull ? HType.NUMBER_OR_NULL : HType.NUMBER; |
| 24 return HType.NUMBER; | 26 } else if (element === compiler.doubleClass) { |
| 25 } else if (element === compiler.doubleClass) { | 27 return canBeNull ? HType.DOUBLE_OR_NULL : HType.DOUBLE; |
| 26 return HType.DOUBLE; | 28 } else if (element === compiler.stringClass) { |
| 27 } else if (element === compiler.stringClass) { | 29 return canBeNull ? HType.STRING_OR_NULL : HType.STRING; |
| 28 return HType.STRING; | 30 } else if (element === compiler.boolClass) { |
| 29 } else if (element === compiler.boolClass) { | 31 return canBeNull ? HType.BOOLEAN_OR_NULL : HType.BOOLEAN; |
| 30 return HType.BOOLEAN; | 32 } else if (element === compiler.listClass |
| 31 } | |
| 32 } | |
| 33 if (element === compiler.listClass | |
| 34 || Elements.isListSupertype(element, compiler)) { | 33 || Elements.isListSupertype(element, compiler)) { |
| 35 return new HBoundedPotentialPrimitiveArray(type, canBeNull); | 34 return new HBoundedPotentialPrimitiveArray(type, canBeNull); |
| 36 } else if (Elements.isStringSupertype(element, compiler)) { | 35 } else if (Elements.isStringSupertype(element, compiler)) { |
| 37 return new HBoundedPotentialPrimitiveString(type, canBeNull); | 36 return new HBoundedPotentialPrimitiveString(type, canBeNull); |
| 38 } else if (element === compiler.intClass | |
| 39 || element === compiler.boolClass | |
| 40 || element === compiler.numClass | |
| 41 || element === compiler.doubleClass | |
| 42 || element === compiler.stringClass) { | |
| 43 // TODO(ngeoffray): Create primitive nullable types. | |
| 44 return null; | |
| 45 } else { | 37 } else { |
| 46 return new HBoundedType(type, canBeNull); | 38 return new HBoundedType(type, canBeNull); |
| 47 } | 39 } |
| 48 } | 40 } |
| 49 | 41 |
| 50 static final HType CONFLICTING = const HAnalysisType("conflicting"); | 42 static final HType CONFLICTING = const HAnalysisType("conflicting"); |
| 51 static final HType UNKNOWN = const HAnalysisType("unknown"); | 43 static final HType UNKNOWN = const HAnalysisType("unknown"); |
| 52 static final HType BOOLEAN = const HBooleanType(); | 44 static final HType BOOLEAN = const HBooleanType(); |
| 53 static final HType NUMBER = const HNumberType(); | 45 static final HType NUMBER = const HNumberType(); |
| 54 static final HType INTEGER = const HIntegerType(); | 46 static final HType INTEGER = const HIntegerType(); |
| 55 static final HType DOUBLE = const HDoubleType(); | 47 static final HType DOUBLE = const HDoubleType(); |
| 56 static final HType INDEXABLE_PRIMITIVE = const HIndexablePrimitiveType(); | 48 static final HType INDEXABLE_PRIMITIVE = const HIndexablePrimitiveType(); |
| 57 static final HType STRING = const HStringType(); | 49 static final HType STRING = const HStringType(); |
| 58 static final HType READABLE_ARRAY = const HReadableArrayType(); | 50 static final HType READABLE_ARRAY = const HReadableArrayType(); |
| 59 static final HType MUTABLE_ARRAY = const HMutableArrayType(); | 51 static final HType MUTABLE_ARRAY = const HMutableArrayType(); |
| 60 static final HType EXTENDABLE_ARRAY = const HExtendableArrayType(); | 52 static final HType EXTENDABLE_ARRAY = const HExtendableArrayType(); |
| 61 | 53 |
| 54 static final HType BOOLEAN_OR_NULL = const HBooleanOrNullType(); |
| 55 static final HType NUMBER_OR_NULL = const HNumberOrNullType(); |
| 56 static final HType INTEGER_OR_NULL = const HIntegerOrNullType(); |
| 57 static final HType DOUBLE_OR_NULL = const HDoubleOrNullType(); |
| 58 static final HType STRING_OR_NULL = const HStringOrNullType(); |
| 59 |
| 62 bool isConflicting() => this === CONFLICTING; | 60 bool isConflicting() => this === CONFLICTING; |
| 63 bool isUnknown() => this === UNKNOWN; | 61 bool isUnknown() => this === UNKNOWN; |
| 64 bool isBoolean() => false; | 62 bool isBoolean() => false; |
| 65 bool isNumber() => false; | 63 bool isNumber() => false; |
| 66 bool isInteger() => false; | 64 bool isInteger() => false; |
| 67 bool isDouble() => false; | 65 bool isDouble() => false; |
| 68 bool isString() => false; | 66 bool isString() => false; |
| 67 bool isBooleanOrNull() => false; |
| 68 bool isNumberOrNull() => false; |
| 69 bool isIntegerOrNull() => false; |
| 70 bool isDoubleOrNull() => false; |
| 71 bool isStringOrNull() => false; |
| 69 bool isIndexablePrimitive() => false; | 72 bool isIndexablePrimitive() => false; |
| 70 bool isReadableArray() => false; | 73 bool isReadableArray() => false; |
| 71 bool isMutableArray() => false; | 74 bool isMutableArray() => false; |
| 72 bool isExtendableArray() => false; | 75 bool isExtendableArray() => false; |
| 73 bool isPrimitive() => false; | 76 bool isPrimitive() => false; |
| 74 bool isExact() => false; | 77 bool isExact() => false; |
| 75 | 78 |
| 76 bool canBePrimitive() => false; | 79 bool canBePrimitive() => false; |
| 77 bool canBeNull() => false; | 80 bool canBeNull() => false; |
| 78 | 81 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 132 HType union(HType other) => combine(other); | 135 HType union(HType other) => combine(other); |
| 133 HType intersection(HType other) => combine(other); | 136 HType intersection(HType other) => combine(other); |
| 134 } | 137 } |
| 135 | 138 |
| 136 abstract class HPrimitiveType extends HType { | 139 abstract class HPrimitiveType extends HType { |
| 137 const HPrimitiveType(); | 140 const HPrimitiveType(); |
| 138 bool isPrimitive() => true; | 141 bool isPrimitive() => true; |
| 139 bool canBePrimitive() => true; | 142 bool canBePrimitive() => true; |
| 140 } | 143 } |
| 141 | 144 |
| 145 abstract class HPrimitiveOrNullType extends HType { |
| 146 const HPrimitiveOrNullType(); |
| 147 bool canBePrimitive() => true; |
| 148 bool canBeNull() => true; |
| 149 } |
| 150 |
| 151 class HBooleanOrNullType extends HPrimitiveOrNullType { |
| 152 const HBooleanOrNullType(); |
| 153 String toString() => "boolean or null"; |
| 154 bool isBooleanOrNull() => true; |
| 155 |
| 156 Type computeType(Compiler compiler) { |
| 157 return compiler.boolClass.computeType(compiler); |
| 158 } |
| 159 |
| 160 HType union(HType other) { |
| 161 if (other.isUnknown()) return HType.BOOLEAN_OR_NULL; |
| 162 if (other.isBooleanOrNull()) return HType.BOOLEAN_OR_NULL; |
| 163 if (other.isBoolean()) return HType.BOOLEAN_OR_NULL; |
| 164 return HType.CONFLICTING; |
| 165 } |
| 166 |
| 167 HType intersection(HType other) { |
| 168 if (other.isUnknown()) return HType.BOOLEAN_OR_NULL; |
| 169 if (other.isBooleanOrNull()) return HType.BOOLEAN_OR_NULL; |
| 170 if (other.isBoolean()) return HType.BOOLEAN; |
| 171 return HType.CONFLICTING; |
| 172 } |
| 173 } |
| 174 |
| 142 class HBooleanType extends HPrimitiveType { | 175 class HBooleanType extends HPrimitiveType { |
| 143 const HBooleanType(); | 176 const HBooleanType(); |
| 144 bool isBoolean() => true; | 177 bool isBoolean() => true; |
| 145 String toString() => "boolean"; | 178 String toString() => "boolean"; |
| 146 | 179 |
| 147 Type computeType(Compiler compiler) { | 180 Type computeType(Compiler compiler) { |
| 148 return compiler.boolClass.computeType(compiler); | 181 return compiler.boolClass.computeType(compiler); |
| 149 } | 182 } |
| 150 | 183 |
| 151 HType combine(HType other) { | 184 HType union(HType other) { |
| 152 if (other.isBoolean() || other.isUnknown()) return HType.BOOLEAN; | 185 if (other.isUnknown()) return HType.BOOLEAN; |
| 186 if (other.isBoolean()) return HType.BOOLEAN; |
| 187 if (other.isBooleanOrNull()) return HType.BOOLEAN_OR_NULL; |
| 153 return HType.CONFLICTING; | 188 return HType.CONFLICTING; |
| 154 } | 189 } |
| 155 | 190 |
| 156 // Since the boolean type is a one-element set the union and intersection are | 191 HType intersection(HType other) { |
| 157 // the same. | 192 if (other.isUnknown()) return HType.BOOLEAN; |
| 158 HType union(HType other) => combine(other); | 193 if (other.isBooleanOrNull()) return HType.BOOLEAN; |
| 159 HType intersection(HType other) => combine(other); | 194 if (other.isBoolean()) return HType.BOOLEAN; |
| 195 return HType.CONFLICTING; |
| 196 } |
| 197 } |
| 198 |
| 199 class HNumberOrNullType extends HPrimitiveOrNullType { |
| 200 const HNumberOrNullType(); |
| 201 bool isNumberOrNull() => true; |
| 202 String toString() => "number or null"; |
| 203 |
| 204 Type computeType(Compiler compiler) { |
| 205 return compiler.numClass.computeType(compiler); |
| 206 } |
| 207 |
| 208 HType union(HType other) { |
| 209 if (other.isUnknown()) return HType.NUMBER_OR_NULL; |
| 210 if (other.isNumberOrNull()) return HType.NUMBER_OR_NULL; |
| 211 if (other.isNumber()) return HType.NUMBER_OR_NULL; |
| 212 return HType.CONFLICTING; |
| 213 } |
| 214 |
| 215 HType intersection(HType other) { |
| 216 if (other.isUnknown()) return HType.NUMBER_OR_NULL; |
| 217 if (other.isInteger()) return HType.INTEGER; |
| 218 if (other.isDouble()) return HType.DOUBLE; |
| 219 if (other.isNumber()) return HType.NUMBER; |
| 220 if (other.isIntegerOrNull()) return HType.INTEGER_OR_NULL; |
| 221 if (other.isDoubleOrNull()) return HType.DOUBLE_OR_NULL; |
| 222 if (other.isNumberOrNull()) return HType.NUMBER_OR_NULL; |
| 223 return HType.CONFLICTING; |
| 224 } |
| 160 } | 225 } |
| 161 | 226 |
| 162 class HNumberType extends HPrimitiveType { | 227 class HNumberType extends HPrimitiveType { |
| 163 const HNumberType(); | 228 const HNumberType(); |
| 164 bool isNumber() => true; | 229 bool isNumber() => true; |
| 165 String toString() => "number"; | 230 String toString() => "number"; |
| 166 | 231 |
| 167 Type computeType(Compiler compiler) { | 232 Type computeType(Compiler compiler) { |
| 168 return compiler.numClass.computeType(compiler); | 233 return compiler.numClass.computeType(compiler); |
| 169 } | 234 } |
| 170 | 235 |
| 171 HType union(HType other) { | 236 HType union(HType other) { |
| 172 if (other.isNumber() || other.isUnknown()) return HType.NUMBER; | 237 if (other.isNumber()) return HType.NUMBER; |
| 238 if (other.isUnknown()) return HType.NUMBER; |
| 239 if (other.isNumberOrNull()) return HType.NUMBER_OR_NULL; |
| 173 return HType.CONFLICTING; | 240 return HType.CONFLICTING; |
| 174 } | 241 } |
| 175 | 242 |
| 176 HType intersection(HType other) { | 243 HType intersection(HType other) { |
| 177 if (other.isUnknown()) return HType.NUMBER; | 244 if (other.isUnknown()) return HType.NUMBER; |
| 178 if (other.isNumber()) return other; | 245 if (other.isNumber()) return other; |
| 246 if (other.isIntegerOrNull()) return HType.INTEGER; |
| 247 if (other.isDoubleOrNull()) return HType.DOUBLE; |
| 248 if (other.isNumberOrNull()) return HType.NUMBER; |
| 249 return HType.CONFLICTING; |
| 250 } |
| 251 } |
| 252 |
| 253 class HIntegerOrNullType extends HNumberOrNullType { |
| 254 const HIntegerOrNullType(); |
| 255 bool isIntegerOrNull() => true; |
| 256 String toString() => "integer or null"; |
| 257 |
| 258 Type computeType(Compiler compiler) { |
| 259 return compiler.intClass.computeType(compiler); |
| 260 } |
| 261 |
| 262 HType union(HType other) { |
| 263 if (other.isUnknown()) return HType.INTEGER_OR_NULL; |
| 264 if (other.isIntegerOrNull()) return HType.INTEGER_OR_NULL; |
| 265 if (other.isInteger()) return HType.INTEGER_OR_NULL; |
| 266 if (other.isNumber()) return HType.NUMBER_OR_NULL; |
| 267 if (other.isNumberOrNull()) return HType.NUMBER_OR_NULL; |
| 268 return HType.CONFLICTING; |
| 269 } |
| 270 |
| 271 HType intersection(HType other) { |
| 272 if (other.isUnknown()) return HType.INTEGER_OR_NULL; |
| 273 if (other.isIntegerOrNull()) return HType.INTEGER_OR_NULL; |
| 274 if (other.isInteger()) return HType.INTEGER; |
| 275 if (other.isDouble()) return HType.CONFLICTING; |
| 276 if (other.isDoubleOrNull()) return HType.CONFLICTING; |
| 277 if (other.isNumber()) return HType.INTEGER; |
| 278 if (other.isNumberOrNull()) return HType.INTEGER_OR_NULL; |
| 179 return HType.CONFLICTING; | 279 return HType.CONFLICTING; |
| 180 } | 280 } |
| 181 } | 281 } |
| 182 | 282 |
| 183 class HIntegerType extends HNumberType { | 283 class HIntegerType extends HNumberType { |
| 184 const HIntegerType(); | 284 const HIntegerType(); |
| 185 bool isInteger() => true; | 285 bool isInteger() => true; |
| 186 String toString() => "integer"; | 286 String toString() => "integer"; |
| 187 | 287 |
| 188 Type computeType(Compiler compiler) { | 288 Type computeType(Compiler compiler) { |
| 189 return compiler.intClass.computeType(compiler); | 289 return compiler.intClass.computeType(compiler); |
| 190 } | 290 } |
| 191 | 291 |
| 192 HType union(HType other) { | 292 HType union(HType other) { |
| 193 if (other.isInteger() || other.isUnknown()) return HType.INTEGER; | 293 if (other.isUnknown()) return HType.INTEGER; |
| 294 if (other.isInteger()) return HType.INTEGER; |
| 295 if (other.isIntegerOrNull()) return HType.INTEGER_OR_NULL; |
| 194 if (other.isNumber()) return HType.NUMBER; | 296 if (other.isNumber()) return HType.NUMBER; |
| 297 if (other.isNumberOrNull()) return HType.NUMBER_OR_NULL; |
| 195 return HType.CONFLICTING; | 298 return HType.CONFLICTING; |
| 196 } | 299 } |
| 197 | 300 |
| 198 HType intersection(HType other) { | 301 HType intersection(HType other) { |
| 199 if (other.isUnknown()) return HType.INTEGER; | 302 if (other.isUnknown()) return HType.INTEGER; |
| 303 if (other.isIntegerOrNull()) return HType.INTEGER; |
| 304 if (other.isInteger()) return HType.INTEGER; |
| 200 if (other.isDouble()) return HType.CONFLICTING; | 305 if (other.isDouble()) return HType.CONFLICTING; |
| 201 if (other.isNumber()) return this; | 306 if (other.isDoubleOrNull()) return HType.CONFLICTING; |
| 307 if (other.isNumber()) return HType.INTEGER; |
| 308 if (other.isNumberOrNull()) return HType.INTEGER; |
| 309 return HType.CONFLICTING; |
| 310 } |
| 311 } |
| 312 |
| 313 class HDoubleOrNullType extends HNumberOrNullType { |
| 314 const HDoubleOrNullType(); |
| 315 bool isDoubleOrNull() => true; |
| 316 String toString() => "double or null"; |
| 317 |
| 318 Type computeType(Compiler compiler) { |
| 319 return compiler.doubleClass.computeType(compiler); |
| 320 } |
| 321 |
| 322 HType union(HType other) { |
| 323 if (other.isUnknown()) return HType.DOUBLE_OR_NULL; |
| 324 if (other.isDoubleOrNull()) return HType.DOUBLE_OR_NULL; |
| 325 if (other.isDouble()) return HType.DOUBLE_OR_NULL; |
| 326 if (other.isNumber()) return HType.NUMBER_OR_NULL; |
| 327 if (other.isNumberOrNull()) return HType.NUMBER_OR_NULL; |
| 328 return HType.CONFLICTING; |
| 329 } |
| 330 |
| 331 HType intersection(HType other) { |
| 332 if (other.isUnknown()) return HType.DOUBLE_OR_NULL; |
| 333 if (other.isIntegerOrNull()) return HType.CONFLICTING; |
| 334 if (other.isInteger()) return HType.CONFLICTING; |
| 335 if (other.isDouble()) return HType.DOUBLE; |
| 336 if (other.isDoubleOrNull()) return HType.DOUBLE_OR_NULL; |
| 337 if (other.isNumber()) return HType.DOUBLE; |
| 338 if (other.isNumberOrNull()) return HType.DOUBLE_OR_NULL; |
| 202 return HType.CONFLICTING; | 339 return HType.CONFLICTING; |
| 203 } | 340 } |
| 204 } | 341 } |
| 205 | 342 |
| 206 class HDoubleType extends HNumberType { | 343 class HDoubleType extends HNumberType { |
| 207 const HDoubleType(); | 344 const HDoubleType(); |
| 208 bool isDouble() => true; | 345 bool isDouble() => true; |
| 209 String toString() => "double"; | 346 String toString() => "double"; |
| 210 | 347 |
| 211 Type computeType(Compiler compiler) { | 348 Type computeType(Compiler compiler) { |
| 212 return compiler.doubleClass.computeType(compiler); | 349 return compiler.doubleClass.computeType(compiler); |
| 213 } | 350 } |
| 214 | 351 |
| 215 HType union(HType other) { | 352 HType union(HType other) { |
| 216 if (other.isDouble() || other.isUnknown()) return HType.DOUBLE; | 353 if (other.isUnknown()) return HType.DOUBLE; |
| 354 if (other.isDouble()) return HType.DOUBLE; |
| 355 if (other.isDoubleOrNull()) return HType.DOUBLE_OR_NULL; |
| 217 if (other.isNumber()) return HType.NUMBER; | 356 if (other.isNumber()) return HType.NUMBER; |
| 357 if (other.isNumberOrNull()) return HType.NUMBER_OR_NULL; |
| 218 return HType.CONFLICTING; | 358 return HType.CONFLICTING; |
| 219 } | 359 } |
| 220 | 360 |
| 221 HType intersection(HType other) { | 361 HType intersection(HType other) { |
| 222 if (other.isUnknown()) return HType.DOUBLE; | 362 if (other.isUnknown()) return HType.DOUBLE; |
| 363 if (other.isIntegerOrNull()) return HType.CONFLICTING; |
| 223 if (other.isInteger()) return HType.CONFLICTING; | 364 if (other.isInteger()) return HType.CONFLICTING; |
| 224 if (other.isNumber()) return this; | 365 if (other.isDouble()) return HType.DOUBLE; |
| 366 if (other.isDoubleOrNull()) return HType.DOUBLE; |
| 367 if (other.isNumber()) return HType.DOUBLE; |
| 368 if (other.isNumberOrNull()) return HType.DOUBLE; |
| 225 return HType.CONFLICTING; | 369 return HType.CONFLICTING; |
| 226 } | 370 } |
| 227 } | 371 } |
| 228 | 372 |
| 229 class HIndexablePrimitiveType extends HPrimitiveType { | 373 class HIndexablePrimitiveType extends HPrimitiveType { |
| 230 const HIndexablePrimitiveType(); | 374 const HIndexablePrimitiveType(); |
| 231 bool isIndexablePrimitive() => true; | 375 bool isIndexablePrimitive() => true; |
| 232 String toString() => "indexable"; | 376 String toString() => "indexable"; |
| 233 | 377 |
| 234 Type computeType(Compiler compiler) { | 378 Type computeType(Compiler compiler) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 252 | 396 |
| 253 HType intersection(HType other) { | 397 HType intersection(HType other) { |
| 254 if (other.isUnknown()) return HType.INDEXABLE_PRIMITIVE; | 398 if (other.isUnknown()) return HType.INDEXABLE_PRIMITIVE; |
| 255 if (other.isIndexablePrimitive()) return other; | 399 if (other.isIndexablePrimitive()) return other; |
| 256 if (other is HBoundedPotentialPrimitiveString) return HType.STRING; | 400 if (other is HBoundedPotentialPrimitiveString) return HType.STRING; |
| 257 if (other is HBoundedPotentialPrimitiveArray) return HType.READABLE_ARRAY; | 401 if (other is HBoundedPotentialPrimitiveArray) return HType.READABLE_ARRAY; |
| 258 return HType.CONFLICTING; | 402 return HType.CONFLICTING; |
| 259 } | 403 } |
| 260 } | 404 } |
| 261 | 405 |
| 406 class HStringOrNullType extends HPrimitiveOrNullType { |
| 407 const HStringOrNullType(); |
| 408 bool isStringOrNull() => true; |
| 409 String toString() => "String or null"; |
| 410 |
| 411 Type computeType(Compiler compiler) { |
| 412 return compiler.stringClass.computeType(compiler); |
| 413 } |
| 414 |
| 415 HType union(HType other) { |
| 416 if (other.isUnknown()) return HType.STRING_OR_NULL; |
| 417 if (other.isString()) return HType.STRING_OR_NULL; |
| 418 if (other.isStringOrNull()) return HType.STRING_OR_NULL; |
| 419 if (other.isIndexablePrimitive()) { |
| 420 // We don't have a type that represents the nullable indexable |
| 421 // primitive. |
| 422 return HType.CONFLICTING; |
| 423 } |
| 424 if (other is HBoundedPotentialPrimitiveString) { |
| 425 if (other.canBeNull()) { |
| 426 return other; |
| 427 } else { |
| 428 HBoundedType boundedType = other; |
| 429 return new HBoundedPotentialPrimitiveString(boundedType.type, true); |
| 430 } |
| 431 } |
| 432 return HType.CONFLICTING; |
| 433 } |
| 434 |
| 435 HType intersection(HType other) { |
| 436 if (other.isUnknown()) return HType.STRING_OR_NULL; |
| 437 if (other.isString()) return HType.STRING; |
| 438 if (other.isStringOrNull()) return HType.STRING_OR_NULL; |
| 439 if (other.isArray()) return HType.CONFLICTING; |
| 440 if (other.isIndexablePrimitive()) return HType.STRING; |
| 441 if (other is HBoundedPotentialPrimitiveString) { |
| 442 return other.canBeNull() ? HType.STRING_OR_NULL : HType.STRING; |
| 443 } |
| 444 return HType.CONFLICTING; |
| 445 } |
| 446 } |
| 447 |
| 262 class HStringType extends HIndexablePrimitiveType { | 448 class HStringType extends HIndexablePrimitiveType { |
| 263 const HStringType(); | 449 const HStringType(); |
| 264 bool isString() => true; | 450 bool isString() => true; |
| 265 String toString() => "String"; | 451 String toString() => "String"; |
| 266 | 452 |
| 267 Type computeType(Compiler compiler) { | 453 Type computeType(Compiler compiler) { |
| 268 return compiler.stringClass.computeType(compiler); | 454 return compiler.stringClass.computeType(compiler); |
| 269 } | 455 } |
| 270 | 456 |
| 271 HType union(HType other) { | 457 HType union(HType other) { |
| 272 if (other.isUnknown()) return HType.STRING; | 458 if (other.isUnknown()) return HType.STRING; |
| 273 if (other.isString()) return HType.STRING; | 459 if (other.isString()) return HType.STRING; |
| 460 if (other.isStringOrNull()) return HType.STRING_OR_NULL; |
| 274 if (other.isIndexablePrimitive()) return HType.INDEXABLE_PRIMITIVE; | 461 if (other.isIndexablePrimitive()) return HType.INDEXABLE_PRIMITIVE; |
| 275 if (other is HBoundedPotentialPrimitiveString) return other; | 462 if (other is HBoundedPotentialPrimitiveString) return other; |
| 276 return HType.CONFLICTING; | 463 return HType.CONFLICTING; |
| 277 } | 464 } |
| 278 | 465 |
| 279 HType intersection(HType other) { | 466 HType intersection(HType other) { |
| 280 if (other.isUnknown()) return HType.STRING; | 467 if (other.isUnknown()) return HType.STRING; |
| 281 if (other.isString()) return HType.STRING; | 468 if (other.isString()) return HType.STRING; |
| 282 if (other.isArray()) return HType.CONFLICTING; | 469 if (other.isArray()) return HType.CONFLICTING; |
| 283 if (other.isIndexablePrimitive()) return HType.STRING; | 470 if (other.isIndexablePrimitive()) return HType.STRING; |
| 471 if (other.isStringOrNull()) return HType.STRING; |
| 284 if (other is HBoundedPotentialPrimitiveString) return HType.STRING; | 472 if (other is HBoundedPotentialPrimitiveString) return HType.STRING; |
| 285 return HType.CONFLICTING; | 473 return HType.CONFLICTING; |
| 286 } | 474 } |
| 287 } | 475 } |
| 288 | 476 |
| 289 class HReadableArrayType extends HIndexablePrimitiveType { | 477 class HReadableArrayType extends HIndexablePrimitiveType { |
| 290 const HReadableArrayType(); | 478 const HReadableArrayType(); |
| 291 bool isReadableArray() => true; | 479 bool isReadableArray() => true; |
| 292 String toString() => "readable array"; | 480 String toString() => "readable array"; |
| 293 | 481 |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 401 HType combine(HType other) { | 589 HType combine(HType other) { |
| 402 if (other.isExact()) { | 590 if (other.isExact()) { |
| 403 HExactType concrete = other; | 591 HExactType concrete = other; |
| 404 if (this.type === concrete.type) return this; | 592 if (this.type === concrete.type) return this; |
| 405 } | 593 } |
| 406 if (other.isUnknown()) return this; | 594 if (other.isUnknown()) return this; |
| 407 return HType.CONFLICTING; | 595 return HType.CONFLICTING; |
| 408 } | 596 } |
| 409 } | 597 } |
| 410 | 598 |
| 411 class HBoundedPotentialPrimitiveArray extends HBoundedType { | 599 class HBoundedPotentialPrimitiveType extends HBoundedType { |
| 600 const HBoundedPotentialPrimitiveType(Type type, bool canBeNull) |
| 601 : super(type, canBeNull); |
| 602 bool canBePrimitive() => true; |
| 603 } |
| 604 |
| 605 class HBoundedPotentialPrimitiveArray extends HBoundedPotentialPrimitiveType { |
| 412 const HBoundedPotentialPrimitiveArray(Type type, bool canBeNull) | 606 const HBoundedPotentialPrimitiveArray(Type type, bool canBeNull) |
| 413 : super(type, canBeNull); | 607 : super(type, canBeNull); |
| 414 bool canBePrimitive() => true; | |
| 415 | 608 |
| 416 HType union(HType other) { | 609 HType union(HType other) { |
| 417 if (other.isString()) return HType.CONFLICTING; | 610 if (other.isString()) return HType.CONFLICTING; |
| 418 if (other.isReadableArray()) return this; | 611 if (other.isReadableArray()) return this; |
| 419 // TODO(ngeoffray): implement union types. | 612 // TODO(ngeoffray): implement union types. |
| 420 if (other.isIndexablePrimitive()) return HType.CONFLICTING; | 613 if (other.isIndexablePrimitive()) return HType.CONFLICTING; |
| 421 return super.union(other); | 614 return super.union(other); |
| 422 } | 615 } |
| 423 | 616 |
| 424 HType intersection(HType other) { | 617 HType intersection(HType other) { |
| 425 if (other.isString()) return HType.CONFLICTING; | 618 if (other.isString()) return HType.CONFLICTING; |
| 426 if (other.isReadableArray()) return other; | 619 if (other.isReadableArray()) return other; |
| 427 if (other.isIndexablePrimitive()) return HType.READABLE_ARRAY; | 620 if (other.isIndexablePrimitive()) return HType.READABLE_ARRAY; |
| 428 return super.intersection(other); | 621 return super.intersection(other); |
| 429 } | 622 } |
| 430 } | 623 } |
| 431 | 624 |
| 432 class HBoundedPotentialPrimitiveString extends HBoundedType { | 625 class HBoundedPotentialPrimitiveString extends HBoundedPotentialPrimitiveType { |
| 433 const HBoundedPotentialPrimitiveString(Type type, bool canBeNull) | 626 const HBoundedPotentialPrimitiveString(Type type, bool canBeNull) |
| 434 : super(type, canBeNull); | 627 : super(type, canBeNull); |
| 435 bool canBePrimitive() => true; | |
| 436 | 628 |
| 437 HType union(HType other) { | 629 HType union(HType other) { |
| 438 if (other.isString()) return this; | 630 if (other.isString()) return this; |
| 631 if (other.isStringOrNull()) { |
| 632 if (canBeNull()) { |
| 633 return this; |
| 634 } else { |
| 635 return new HBoundedPotentialPrimitiveString(type, true); |
| 636 } |
| 637 } |
| 439 // TODO(ngeoffray): implement union types. | 638 // TODO(ngeoffray): implement union types. |
| 440 if (other.isIndexablePrimitive()) return HType.CONFLICTING; | 639 if (other.isIndexablePrimitive()) return HType.CONFLICTING; |
| 441 return super.union(other); | 640 return super.union(other); |
| 442 } | 641 } |
| 443 | 642 |
| 444 HType intersection(HType other) { | 643 HType intersection(HType other) { |
| 445 if (other.isString()) return HType.STRING; | 644 if (other.isString()) return HType.STRING; |
| 645 if (other.isStringOrNull()) { |
| 646 return canBeNull() ? HType.STRING_OR_NULL : HType.STRING; |
| 647 } |
| 446 if (other.isReadableArray()) return HType.CONFLICTING; | 648 if (other.isReadableArray()) return HType.CONFLICTING; |
| 447 if (other.isIndexablePrimitive()) return HType.STRING; | 649 if (other.isIndexablePrimitive()) return HType.STRING; |
| 448 return super.intersection(other); | 650 return super.intersection(other); |
| 449 } | 651 } |
| 450 } | 652 } |
| OLD | NEW |