| 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 library dart2js.constants.values; | 5 library dart2js.constants.values; |
| 6 | 6 |
| 7 import '../core_types.dart'; |
| 7 import '../dart_types.dart'; | 8 import '../dart_types.dart'; |
| 8 import '../dart2jslib.dart' | 9 import '../dart2jslib.dart' |
| 9 show assertDebugMode, | 10 show assertDebugMode; |
| 10 Compiler; | |
| 11 import '../elements/elements.dart' | 11 import '../elements/elements.dart' |
| 12 show ClassElement, | 12 show ClassElement, |
| 13 Element, | 13 Element, |
| 14 FunctionElement, | 14 FunctionElement, |
| 15 PrefixElement; | 15 PrefixElement; |
| 16 import '../tree/tree.dart' hide unparse; | 16 import '../tree/tree.dart' hide unparse; |
| 17 import '../types/types.dart' as ti show TypeMask; | 17 import '../types/types.dart' as ti show TypeMask; |
| 18 import '../util/util.dart' show SMI_MASK; | 18 import '../util/util.dart' show SMI_MASK; |
| 19 | 19 |
| 20 abstract class ConstantValueVisitor<R, A> { | 20 abstract class ConstantValueVisitor<R, A> { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 57 bool get isType => false; | 57 bool get isType => false; |
| 58 bool get isInterceptor => false; | 58 bool get isInterceptor => false; |
| 59 bool get isDummy => false; | 59 bool get isDummy => false; |
| 60 | 60 |
| 61 bool get isNaN => false; | 61 bool get isNaN => false; |
| 62 bool get isMinusZero => false; | 62 bool get isMinusZero => false; |
| 63 bool get isZero => false; | 63 bool get isZero => false; |
| 64 bool get isOne => false; | 64 bool get isOne => false; |
| 65 | 65 |
| 66 // TODO(johnniwinther): Replace with a 'type' getter. | 66 // TODO(johnniwinther): Replace with a 'type' getter. |
| 67 DartType computeType(Compiler compiler); | 67 DartType getType(CoreTypes types); |
| 68 | 68 |
| 69 List<ConstantValue> getDependencies(); | 69 List<ConstantValue> getDependencies(); |
| 70 | 70 |
| 71 accept(ConstantValueVisitor visitor, arg); | 71 accept(ConstantValueVisitor visitor, arg); |
| 72 | 72 |
| 73 /// The value of this constant in Dart syntax, if possible. | 73 /// The value of this constant in Dart syntax, if possible. |
| 74 /// | 74 /// |
| 75 /// For [ConstructedConstantValue]s there is no way to create a valid const | 75 /// For [ConstructedConstantValue]s there is no way to create a valid const |
| 76 /// expression from the value so the unparse of these is best effort. | 76 /// expression from the value so the unparse of these is best effort. |
| 77 /// | 77 /// |
| 78 /// For the synthetic constants, [DeferredConstantValue], | 78 /// For the synthetic constants, [DeferredConstantValue], |
| 79 /// [DummyConstantValue], [InterceptorConstantValue] the unparse is | 79 /// [DummyConstantValue], [InterceptorConstantValue] the unparse is |
| 80 /// descriptive only. | 80 /// descriptive only. |
| 81 String unparse(); | 81 String unparse(); |
| 82 | 82 |
| 83 /// Returns a structured representation of this constant suited for debugging. | 83 /// Returns a structured representation of this constant suited for debugging. |
| 84 String toStructuredString(); | 84 String toStructuredString(); |
| 85 | 85 |
| 86 String toString() { | 86 String toString() { |
| 87 assertDebugMode("Use Constant.unparse() or Constant.toStructuredString() " | 87 assertDebugMode("Use Constant.unparse() or Constant.toStructuredString() " |
| 88 "instead of Constant.toString()."); | 88 "instead of Constant.toString()."); |
| 89 return toStructuredString(); | 89 return toStructuredString(); |
| 90 } | 90 } |
| 91 } | 91 } |
| 92 | 92 |
| 93 class FunctionConstantValue extends ConstantValue { | 93 class FunctionConstantValue extends ConstantValue { |
| 94 Element element; | 94 FunctionElement element; |
| 95 | 95 |
| 96 FunctionConstantValue(this.element); | 96 FunctionConstantValue(this.element) { |
| 97 assert(element.type != null); |
| 98 } |
| 97 | 99 |
| 98 bool get isFunction => true; | 100 bool get isFunction => true; |
| 99 | 101 |
| 100 bool operator ==(var other) { | 102 bool operator ==(var other) { |
| 101 if (other is !FunctionConstantValue) return false; | 103 if (other is !FunctionConstantValue) return false; |
| 102 return identical(other.element, element); | 104 return identical(other.element, element); |
| 103 } | 105 } |
| 104 | 106 |
| 105 List<ConstantValue> getDependencies() => const <ConstantValue>[]; | 107 List<ConstantValue> getDependencies() => const <ConstantValue>[]; |
| 106 | 108 |
| 107 DartString toDartString() { | 109 DartString toDartString() { |
| 108 return new DartString.literal(element.name); | 110 return new DartString.literal(element.name); |
| 109 } | 111 } |
| 110 | 112 |
| 111 // TODO(johnniwinther): remove computeType. | 113 DartType getType(CoreTypes types) => element.type; |
| 112 DartType computeType(Compiler compiler) => element.computeType(compiler); | |
| 113 | 114 |
| 114 int get hashCode => (17 * element.hashCode) & 0x7fffffff; | 115 int get hashCode => (17 * element.hashCode) & 0x7fffffff; |
| 115 | 116 |
| 116 accept(ConstantValueVisitor visitor, arg) => visitor.visitFunction(this, arg); | 117 accept(ConstantValueVisitor visitor, arg) => visitor.visitFunction(this, arg); |
| 117 | 118 |
| 118 String unparse() { | 119 String unparse() { |
| 119 if (element.isStatic) { | 120 if (element.isStatic) { |
| 120 return '${element.enclosingClass.name}.${element.name}'; | 121 return '${element.enclosingClass.name}.${element.name}'; |
| 121 } else { | 122 } else { |
| 122 return '${element.name}'; | 123 return '${element.name}'; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 158 static const String JsNull = "null"; | 159 static const String JsNull = "null"; |
| 159 | 160 |
| 160 factory NullConstantValue() => const NullConstantValue._internal(); | 161 factory NullConstantValue() => const NullConstantValue._internal(); |
| 161 | 162 |
| 162 const NullConstantValue._internal(); | 163 const NullConstantValue._internal(); |
| 163 | 164 |
| 164 bool get isNull => true; | 165 bool get isNull => true; |
| 165 | 166 |
| 166 get primitiveValue => null; | 167 get primitiveValue => null; |
| 167 | 168 |
| 168 DartType computeType(Compiler compiler) { | 169 DartType getType(CoreTypes types) => types.nullType; |
| 169 return compiler.nullClass.computeType(compiler); | |
| 170 } | |
| 171 | 170 |
| 172 // The magic constant has no meaning. It is just a random value. | 171 // The magic constant has no meaning. It is just a random value. |
| 173 int get hashCode => 785965825; | 172 int get hashCode => 785965825; |
| 174 | 173 |
| 175 DartString toDartString() => const LiteralDartString("null"); | 174 DartString toDartString() => const LiteralDartString("null"); |
| 176 | 175 |
| 177 accept(ConstantValueVisitor visitor, arg) => visitor.visitNull(this, arg); | 176 accept(ConstantValueVisitor visitor, arg) => visitor.visitNull(this, arg); |
| 178 | 177 |
| 179 String toStructuredString() => 'NullConstant'; | 178 String toStructuredString() => 'NullConstant'; |
| 180 } | 179 } |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 216 bool isUInt31() => primitiveValue >= 0 && primitiveValue < (1 << 31); | 215 bool isUInt31() => primitiveValue >= 0 && primitiveValue < (1 << 31); |
| 217 | 216 |
| 218 bool isUInt32() => primitiveValue >= 0 && primitiveValue < (1 << 32); | 217 bool isUInt32() => primitiveValue >= 0 && primitiveValue < (1 << 32); |
| 219 | 218 |
| 220 bool isPositive() => primitiveValue >= 0; | 219 bool isPositive() => primitiveValue >= 0; |
| 221 | 220 |
| 222 bool get isZero => primitiveValue == 0; | 221 bool get isZero => primitiveValue == 0; |
| 223 | 222 |
| 224 bool get isOne => primitiveValue == 1; | 223 bool get isOne => primitiveValue == 1; |
| 225 | 224 |
| 226 DartType computeType(Compiler compiler) { | 225 DartType getType(CoreTypes types) => types.intType; |
| 227 return compiler.intClass.rawType; | |
| 228 } | |
| 229 | 226 |
| 230 // We have to override the equality operator so that ints and doubles are | 227 // We have to override the equality operator so that ints and doubles are |
| 231 // treated as separate constants. | 228 // treated as separate constants. |
| 232 // The is [:!IntConstant:] check at the beginning of the function makes sure | 229 // The is [:!IntConstant:] check at the beginning of the function makes sure |
| 233 // that we compare only equal to integer constants. | 230 // that we compare only equal to integer constants. |
| 234 bool operator ==(var other) { | 231 bool operator ==(var other) { |
| 235 if (other is !IntConstantValue) return false; | 232 if (other is !IntConstantValue) return false; |
| 236 IntConstantValue otherInt = other; | 233 IntConstantValue otherInt = other; |
| 237 return primitiveValue == otherInt.primitiveValue; | 234 return primitiveValue == otherInt.primitiveValue; |
| 238 } | 235 } |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 273 | 270 |
| 274 bool get isNaN => primitiveValue.isNaN; | 271 bool get isNaN => primitiveValue.isNaN; |
| 275 | 272 |
| 276 // We need to check for the negative sign since -0.0 == 0.0. | 273 // We need to check for the negative sign since -0.0 == 0.0. |
| 277 bool get isMinusZero => primitiveValue == 0.0 && primitiveValue.isNegative; | 274 bool get isMinusZero => primitiveValue == 0.0 && primitiveValue.isNegative; |
| 278 | 275 |
| 279 bool get isZero => primitiveValue == 0.0; | 276 bool get isZero => primitiveValue == 0.0; |
| 280 | 277 |
| 281 bool get isOne => primitiveValue == 1.0; | 278 bool get isOne => primitiveValue == 1.0; |
| 282 | 279 |
| 283 DartType computeType(Compiler compiler) { | 280 DartType getType(CoreTypes types) => types.doubleType; |
| 284 return compiler.doubleClass.rawType; | |
| 285 } | |
| 286 | 281 |
| 287 bool operator ==(var other) { | 282 bool operator ==(var other) { |
| 288 if (other is !DoubleConstantValue) return false; | 283 if (other is !DoubleConstantValue) return false; |
| 289 DoubleConstantValue otherDouble = other; | 284 DoubleConstantValue otherDouble = other; |
| 290 double otherValue = otherDouble.primitiveValue; | 285 double otherValue = otherDouble.primitiveValue; |
| 291 if (primitiveValue == 0.0 && otherValue == 0.0) { | 286 if (primitiveValue == 0.0 && otherValue == 0.0) { |
| 292 return primitiveValue.isNegative == otherValue.isNegative; | 287 return primitiveValue.isNegative == otherValue.isNegative; |
| 293 } else if (primitiveValue.isNaN) { | 288 } else if (primitiveValue.isNaN) { |
| 294 return otherValue.isNaN; | 289 return otherValue.isNaN; |
| 295 } else { | 290 } else { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 310 | 305 |
| 311 abstract class BoolConstantValue extends PrimitiveConstantValue { | 306 abstract class BoolConstantValue extends PrimitiveConstantValue { |
| 312 factory BoolConstantValue(value) { | 307 factory BoolConstantValue(value) { |
| 313 return value ? new TrueConstantValue() : new FalseConstantValue(); | 308 return value ? new TrueConstantValue() : new FalseConstantValue(); |
| 314 } | 309 } |
| 315 | 310 |
| 316 const BoolConstantValue._internal(); | 311 const BoolConstantValue._internal(); |
| 317 | 312 |
| 318 bool get isBool => true; | 313 bool get isBool => true; |
| 319 | 314 |
| 320 DartType computeType(Compiler compiler) { | 315 DartType getType(CoreTypes types) => types.boolType; |
| 321 return compiler.boolClass.rawType; | |
| 322 } | |
| 323 | 316 |
| 324 BoolConstantValue negate(); | 317 BoolConstantValue negate(); |
| 325 | 318 |
| 326 accept(ConstantValueVisitor visitor, arg) => visitor.visitBool(this, arg); | 319 accept(ConstantValueVisitor visitor, arg) => visitor.visitBool(this, arg); |
| 327 | 320 |
| 328 String toStructuredString() => 'BoolConstant(${unparse()})'; | 321 String toStructuredString() => 'BoolConstant(${unparse()})'; |
| 329 } | 322 } |
| 330 | 323 |
| 331 class TrueConstantValue extends BoolConstantValue { | 324 class TrueConstantValue extends BoolConstantValue { |
| 332 factory TrueConstantValue() => const TrueConstantValue._internal(); | 325 factory TrueConstantValue() => const TrueConstantValue._internal(); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 375 | 368 |
| 376 // TODO(floitsch): cache StringConstants. | 369 // TODO(floitsch): cache StringConstants. |
| 377 // TODO(floitsch): compute hashcode without calling toString() on the | 370 // TODO(floitsch): compute hashcode without calling toString() on the |
| 378 // DartString. | 371 // DartString. |
| 379 StringConstantValue(DartString value) | 372 StringConstantValue(DartString value) |
| 380 : this.primitiveValue = value, | 373 : this.primitiveValue = value, |
| 381 this.hashCode = value.slowToString().hashCode; | 374 this.hashCode = value.slowToString().hashCode; |
| 382 | 375 |
| 383 bool get isString => true; | 376 bool get isString => true; |
| 384 | 377 |
| 385 DartType computeType(Compiler compiler) { | 378 DartType getType(CoreTypes types) => types.stringType; |
| 386 return compiler.stringClass.rawType; | |
| 387 } | |
| 388 | 379 |
| 389 bool operator ==(var other) { | 380 bool operator ==(var other) { |
| 390 if (other is !StringConstantValue) return false; | 381 if (other is !StringConstantValue) return false; |
| 391 StringConstantValue otherString = other; | 382 StringConstantValue otherString = other; |
| 392 return hashCode == otherString.hashCode && | 383 return hashCode == otherString.hashCode && |
| 393 primitiveValue == otherString.primitiveValue; | 384 primitiveValue == otherString.primitiveValue; |
| 394 } | 385 } |
| 395 | 386 |
| 396 DartString toDartString() => primitiveValue; | 387 DartString toDartString() => primitiveValue; |
| 397 | 388 |
| 398 int get length => primitiveValue.length; | 389 int get length => primitiveValue.length; |
| 399 | 390 |
| 400 accept(ConstantValueVisitor visitor, arg) => visitor.visitString(this, arg); | 391 accept(ConstantValueVisitor visitor, arg) => visitor.visitString(this, arg); |
| 401 | 392 |
| 402 // TODO(johnniwinther): Ensure correct escaping. | 393 // TODO(johnniwinther): Ensure correct escaping. |
| 403 String unparse() => '"${primitiveValue.slowToString()}"'; | 394 String unparse() => '"${primitiveValue.slowToString()}"'; |
| 404 | 395 |
| 405 String toStructuredString() => 'StringConstant(${unparse()})'; | 396 String toStructuredString() => 'StringConstant(${unparse()})'; |
| 406 } | 397 } |
| 407 | 398 |
| 408 abstract class ObjectConstantValue extends ConstantValue { | 399 abstract class ObjectConstantValue extends ConstantValue { |
| 409 final InterfaceType type; | 400 final InterfaceType type; |
| 410 | 401 |
| 411 ObjectConstantValue(this.type); | 402 ObjectConstantValue(this.type); |
| 412 | 403 |
| 413 bool get isObject => true; | 404 bool get isObject => true; |
| 414 | 405 |
| 415 DartType computeType(Compiler compiler) => type; | 406 DartType getType(CoreTypes types) => type; |
| 416 | 407 |
| 417 void _unparseTypeArguments(StringBuffer sb) { | 408 void _unparseTypeArguments(StringBuffer sb) { |
| 418 if (!type.treatAsRaw) { | 409 if (!type.treatAsRaw) { |
| 419 sb.write('<'); | 410 sb.write('<'); |
| 420 sb.write(type.typeArguments.join(', ')); | 411 sb.write(type.typeArguments.join(', ')); |
| 421 sb.write('>'); | 412 sb.write('>'); |
| 422 } | 413 } |
| 423 } | 414 } |
| 424 } | 415 } |
| 425 | 416 |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 609 } | 600 } |
| 610 | 601 |
| 611 int get hashCode => dispatchedType.hashCode * 43; | 602 int get hashCode => dispatchedType.hashCode * 43; |
| 612 | 603 |
| 613 List<ConstantValue> getDependencies() => const <ConstantValue>[]; | 604 List<ConstantValue> getDependencies() => const <ConstantValue>[]; |
| 614 | 605 |
| 615 accept(ConstantValueVisitor visitor, arg) { | 606 accept(ConstantValueVisitor visitor, arg) { |
| 616 return visitor.visitInterceptor(this, arg); | 607 return visitor.visitInterceptor(this, arg); |
| 617 } | 608 } |
| 618 | 609 |
| 619 DartType computeType(Compiler compiler) => const DynamicType(); | 610 DartType getType(CoreTypes types) => const DynamicType(); |
| 620 | 611 |
| 621 String unparse() { | 612 String unparse() { |
| 622 return 'interceptor($dispatchedType)'; | 613 return 'interceptor($dispatchedType)'; |
| 623 } | 614 } |
| 624 | 615 |
| 625 String toStructuredString() { | 616 String toStructuredString() { |
| 626 return 'InterceptorConstant(${dispatchedType.getStringAsDeclared("o")})'; | 617 return 'InterceptorConstant(${dispatchedType.getStringAsDeclared("o")})'; |
| 627 } | 618 } |
| 628 } | 619 } |
| 629 | 620 |
| 630 // TODO(johnniwinther): Remove this class. | 621 // TODO(johnniwinther): Remove this class. |
| 631 class DummyConstantValue extends ConstantValue { | 622 class DummyConstantValue extends ConstantValue { |
| 632 final ti.TypeMask typeMask; | 623 final ti.TypeMask typeMask; |
| 633 | 624 |
| 634 DummyConstantValue(this.typeMask); | 625 DummyConstantValue(this.typeMask); |
| 635 | 626 |
| 636 bool get isDummy => true; | 627 bool get isDummy => true; |
| 637 | 628 |
| 638 bool operator ==(other) { | 629 bool operator ==(other) { |
| 639 return other is DummyConstantValue | 630 return other is DummyConstantValue |
| 640 && typeMask == other.typeMask; | 631 && typeMask == other.typeMask; |
| 641 } | 632 } |
| 642 | 633 |
| 643 get hashCode => typeMask.hashCode; | 634 get hashCode => typeMask.hashCode; |
| 644 | 635 |
| 645 List<ConstantValue> getDependencies() => const <ConstantValue>[]; | 636 List<ConstantValue> getDependencies() => const <ConstantValue>[]; |
| 646 | 637 |
| 647 accept(ConstantValueVisitor visitor, arg) => visitor.visitDummy(this, arg); | 638 accept(ConstantValueVisitor visitor, arg) => visitor.visitDummy(this, arg); |
| 648 | 639 |
| 649 DartType computeType(Compiler compiler) => const DynamicType(); | 640 DartType getType(CoreTypes types) => const DynamicType(); |
| 650 | 641 |
| 651 String unparse() => 'dummy($typeMask)'; | 642 String unparse() => 'dummy($typeMask)'; |
| 652 | 643 |
| 653 String toStructuredString() => 'DummyConstant($typeMask)'; | 644 String toStructuredString() => 'DummyConstant($typeMask)'; |
| 654 } | 645 } |
| 655 | 646 |
| 656 class ConstructedConstantValue extends ObjectConstantValue { | 647 class ConstructedConstantValue extends ObjectConstantValue { |
| 657 final List<ConstantValue> fields; | 648 final List<ConstantValue> fields; |
| 658 final int hashCode; | 649 final int hashCode; |
| 659 | 650 |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 755 && referenced == other.referenced | 746 && referenced == other.referenced |
| 756 && prefix == other.prefix; | 747 && prefix == other.prefix; |
| 757 } | 748 } |
| 758 | 749 |
| 759 get hashCode => (referenced.hashCode * 17 + prefix.hashCode) & 0x3fffffff; | 750 get hashCode => (referenced.hashCode * 17 + prefix.hashCode) & 0x3fffffff; |
| 760 | 751 |
| 761 List<ConstantValue> getDependencies() => <ConstantValue>[referenced]; | 752 List<ConstantValue> getDependencies() => <ConstantValue>[referenced]; |
| 762 | 753 |
| 763 accept(ConstantValueVisitor visitor, arg) => visitor.visitDeferred(this, arg); | 754 accept(ConstantValueVisitor visitor, arg) => visitor.visitDeferred(this, arg); |
| 764 | 755 |
| 765 DartType computeType(Compiler compiler) => referenced.computeType(compiler); | 756 DartType getType(CoreTypes types) => referenced.getType(types); |
| 766 | 757 |
| 767 String unparse() => 'deferred(${referenced.unparse()})'; | 758 String unparse() => 'deferred(${referenced.unparse()})'; |
| 768 | 759 |
| 769 String toStructuredString() => 'DeferredConstant($referenced)'; | 760 String toStructuredString() => 'DeferredConstant($referenced)'; |
| 770 } | 761 } |
| OLD | NEW |