| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 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 | 
|  | 3 // BSD-style license that can be found in the LICENSE file. | 
|  | 4 | 
|  | 5 const JAVA_SCRIPT_CONSTANT_SYSTEM = const JavaScriptConstantSystem(); | 
|  | 6 | 
|  | 7 class JavaScriptBitNotOperation extends BitNotOperation { | 
|  | 8   const JavaScriptBitNotOperation(); | 
|  | 9   Constant fold(Constant constant) { | 
|  | 10     if (JAVA_SCRIPT_CONSTANT_SYSTEM.isInt(constant)) { | 
|  | 11       // In JavaScript we don't check for -0 and treat it as if it was zero. | 
|  | 12       if (constant.isMinusZero()) constant = DART_CONSTANT_SYSTEM.createInt(0); | 
|  | 13       IntConstant intConstant = constant; | 
|  | 14       // We convert the result of bit-operations to 32 bit unsigned integers. | 
|  | 15       return JAVA_SCRIPT_CONSTANT_SYSTEM.createInt32(~intConstant.value); | 
|  | 16     } | 
|  | 17     return null; | 
|  | 18   } | 
|  | 19 } | 
|  | 20 | 
|  | 21 /** | 
|  | 22  * In JavaScript we truncate the result to an unsigned 32 bit integer. Also, -0 | 
|  | 23  * is treated as if it was the integer 0. | 
|  | 24  */ | 
|  | 25 class JavaScriptBinaryBitOperation implements BinaryOperation { | 
|  | 26   final BinaryBitOperation dartBitOperation; | 
|  | 27   const JavaScriptBinaryBitOperation(this.dartBitOperation); | 
|  | 28 | 
|  | 29   bool isUserDefinable() => dartBitOperation.isUserDefinable(); | 
|  | 30   SourceString get name() => dartBitOperation.name; | 
|  | 31 | 
|  | 32   Constant fold(Constant left, Constant right) { | 
|  | 33     // In JavaScript we don't check for -0 and treat it as if it was zero. | 
|  | 34     if (left.isMinusZero()) left = DART_CONSTANT_SYSTEM.createInt(0); | 
|  | 35     if (right.isMinusZero()) right = DART_CONSTANT_SYSTEM.createInt(0); | 
|  | 36     IntConstant result = dartBitOperation.fold(left, right); | 
|  | 37     if (result != null) { | 
|  | 38       // We convert the result of bit-operations to 32 bit unsigned integers. | 
|  | 39       return JAVA_SCRIPT_CONSTANT_SYSTEM.createInt32(result.value); | 
|  | 40     } | 
|  | 41     return result; | 
|  | 42   } | 
|  | 43 } | 
|  | 44 | 
|  | 45 class JavaScriptShiftRightOperation extends JavaScriptBinaryBitOperation { | 
|  | 46   const JavaScriptShiftRightOperation() : super(const ShiftRightOperation()); | 
|  | 47 | 
|  | 48   Constant fold(Constant left, Constant right) { | 
|  | 49     // Truncate the input value to 32 bits if necessary. | 
|  | 50     if (left.isInt()) { | 
|  | 51       IntConstant intConstant = left; | 
|  | 52       int value = intConstant.value; | 
|  | 53       int truncatedValue = value & JAVA_SCRIPT_CONSTANT_SYSTEM.BITS32; | 
|  | 54       if (value != truncatedValue) { | 
|  | 55         left = DART_CONSTANT_SYSTEM.createInt(truncatedValue); | 
|  | 56       } | 
|  | 57     } | 
|  | 58     super.fold(left, right); | 
|  | 59   } | 
|  | 60 } | 
|  | 61 | 
|  | 62 class JavaScriptNegateOperation implements UnaryOperation { | 
|  | 63   final NegateOperation dartNegateOperation = const NegateOperation(); | 
|  | 64   const JavaScriptNegateOperation(); | 
|  | 65 | 
|  | 66   bool isUserDefinable() => dartNegateOperation.isUserDefinable(); | 
|  | 67   SourceString get name() => dartNegateOperation.name; | 
|  | 68 | 
|  | 69   Constant fold(Constant constant) { | 
|  | 70     if (constant.isInt()) { | 
|  | 71       IntConstant intConstant = constant; | 
|  | 72       if (intConstant.value == 0) { | 
|  | 73         return JAVA_SCRIPT_CONSTANT_SYSTEM.createDouble(-0.0); | 
|  | 74       } | 
|  | 75     } | 
|  | 76     return dartNegateOperation.fold(constant); | 
|  | 77   } | 
|  | 78 } | 
|  | 79 | 
|  | 80 class JavaScriptBinaryArithmeticOperation implements BinaryOperation { | 
|  | 81   final BinaryOperation dartArithmeticOperation; | 
|  | 82   const JavaScriptBinaryArithmeticOperation(this.dartArithmeticOperation); | 
|  | 83 | 
|  | 84   bool isUserDefinable() => dartArithmeticOperation.isUserDefinable(); | 
|  | 85   SourceString get name() => dartArithmeticOperation.name; | 
|  | 86 | 
|  | 87   Constant fold(Constant left, Constant right) { | 
|  | 88     Constant result = dartArithmeticOperation.fold(left, right); | 
|  | 89     if (result == null) return result; | 
|  | 90     return JAVA_SCRIPT_CONSTANT_SYSTEM.convertToJavaScriptConstant(result); | 
|  | 91   } | 
|  | 92 } | 
|  | 93 | 
|  | 94 class JavaScriptIdentityOperation implements BinaryOperation { | 
|  | 95   final IdentityOperation dartIdentityOperation = const IdentityOperation(); | 
|  | 96 | 
|  | 97   const JavaScriptIdentityOperation(); | 
|  | 98 | 
|  | 99   bool isUserDefinable() => dartIdentityOperation.isUserDefinable(); | 
|  | 100   SourceString get name() => dartIdentityOperation.name; | 
|  | 101 | 
|  | 102   BoolConstant fold(Constant left, Constant right) { | 
|  | 103     BoolConstant result = dartIdentityOperation.fold(left, right); | 
|  | 104     if (result == null || result.value) return result; | 
|  | 105     // In JavaScript -0.0 === 0 and all doubles are equal to their integer | 
|  | 106     // values. Furthermore NaN !== NaN. | 
|  | 107     if (left.isNum() && right.isNum()) { | 
|  | 108       NumConstant leftNum = left; | 
|  | 109       NumConstant rightNum = right; | 
|  | 110       double leftDouble = leftNum.value.toDouble(); | 
|  | 111       double rightDouble = rightNum.value.toDouble(); | 
|  | 112       return new BoolConstant(leftDouble == rightDouble); | 
|  | 113     } | 
|  | 114     return result; | 
|  | 115   } | 
|  | 116 } | 
|  | 117 | 
|  | 118 /** | 
|  | 119  * Constant system following the semantics for Dart code that has been | 
|  | 120  * compiled to JavaScript. | 
|  | 121  */ | 
|  | 122 class JavaScriptConstantSystem implements ConstantSystem { | 
|  | 123   const int BITS31 = 0x8FFFFFFF; | 
|  | 124   const int BITS32 = 0xFFFFFFFF; | 
|  | 125   // The maximum integer value a double can represent without losing | 
|  | 126   // precision. | 
|  | 127   const int BITS53 = 0x1FFFFFFFFFFFFF; | 
|  | 128 | 
|  | 129   final add = const JavaScriptBinaryArithmeticOperation(const AddOperation()); | 
|  | 130   final bitAnd = const JavaScriptBinaryBitOperation(const BitAndOperation()); | 
|  | 131   final bitNot = const JavaScriptBitNotOperation(); | 
|  | 132   final bitOr = const JavaScriptBinaryBitOperation(const BitOrOperation()); | 
|  | 133   final bitXor = const JavaScriptBinaryBitOperation(const BitXorOperation()); | 
|  | 134   final booleanAnd = const BooleanAndOperation(); | 
|  | 135   final booleanOr = const BooleanOrOperation(); | 
|  | 136   final divide = | 
|  | 137       const JavaScriptBinaryArithmeticOperation(const DivideOperation()); | 
|  | 138   final equal = const EqualsOperation(); | 
|  | 139   final greaterEqual = const GreaterEqualOperation(); | 
|  | 140   final greater = const GreaterOperation(); | 
|  | 141   final identity = const JavaScriptIdentityOperation(); | 
|  | 142   final lessEqual = const LessEqualOperation(); | 
|  | 143   final less = const LessOperation(); | 
|  | 144   final modulo = | 
|  | 145       const JavaScriptBinaryArithmeticOperation(const ModuloOperation()); | 
|  | 146   final multiply = | 
|  | 147       const JavaScriptBinaryArithmeticOperation(const MultiplyOperation()); | 
|  | 148   final negate = const JavaScriptNegateOperation(); | 
|  | 149   final not = const NotOperation(); | 
|  | 150   final shiftLeft = | 
|  | 151       const JavaScriptBinaryBitOperation(const ShiftLeftOperation()); | 
|  | 152   final shiftRight = const JavaScriptShiftRightOperation(); | 
|  | 153   final subtract = | 
|  | 154       const JavaScriptBinaryArithmeticOperation(const SubtractOperation()); | 
|  | 155   final truncatingDivide = const JavaScriptBinaryArithmeticOperation( | 
|  | 156       const TruncatingDivideOperation()); | 
|  | 157 | 
|  | 158   const JavaScriptConstantSystem(); | 
|  | 159 | 
|  | 160   /** | 
|  | 161    * Returns true if the given [value] fits into a double without losing | 
|  | 162    * precision. | 
|  | 163    */ | 
|  | 164   bool integerFitsIntoDouble(int value) { | 
|  | 165     int absValue = value.abs(); | 
|  | 166     return (absValue & BITS53) == absValue; | 
|  | 167   } | 
|  | 168 | 
|  | 169   NumConstant convertToJavaScriptConstant(NumConstant constant) { | 
|  | 170     if (constant.isInt()) { | 
|  | 171       IntConstant intConstant = constant; | 
|  | 172       int intValue = intConstant.value; | 
|  | 173       if (!integerFitsIntoDouble(intValue)) { | 
|  | 174         return new DoubleConstant(intValue.toDouble()); | 
|  | 175       } | 
|  | 176     } else if (constant.isDouble()) { | 
|  | 177       DoubleConstant doubleResult = constant; | 
|  | 178       double doubleValue = doubleResult.value; | 
|  | 179       if (!doubleValue.isInfinite() && !doubleValue.isNaN() && | 
|  | 180           !constant.isMinusZero()) { | 
|  | 181         int intValue = doubleValue.toInt(); | 
|  | 182         if (intValue == doubleValue && integerFitsIntoDouble(intValue)) { | 
|  | 183           return new IntConstant(intValue); | 
|  | 184         } | 
|  | 185       } | 
|  | 186     } | 
|  | 187     return constant; | 
|  | 188   } | 
|  | 189 | 
|  | 190   NumConstant createInt(int i) | 
|  | 191       => convertToJavaScriptConstant(new IntConstant(i)); | 
|  | 192   NumConstant createInt32(int i) => new IntConstant(i & BITS32); | 
|  | 193   NumConstant createDouble(double d) | 
|  | 194       => convertToJavaScriptConstant(new DoubleConstant(d)); | 
|  | 195   StringConstant createString(DartString string, Node diagnosticNode) | 
|  | 196       => new StringConstant(string, diagnosticNode); | 
|  | 197   BoolConstant createBool(bool value) => new BoolConstant(value); | 
|  | 198   NullConstant createNull() => new NullConstant(); | 
|  | 199 | 
|  | 200   // Integer checks don't verify that the number is not -0.0. | 
|  | 201   bool isInt(Constant constant) => constant.isInt() || constant.isMinusZero(); | 
|  | 202   bool isDouble(Constant constant) | 
|  | 203       => constant.isDouble() && !constant.isMinusZero(); | 
|  | 204   bool isString(Constant constant) => constant.isString(); | 
|  | 205   bool isBool(Constant constant) => constant.isBool(); | 
|  | 206   bool isNull(Constant constant) => constant.isNull(); | 
|  | 207 } | 
| OLD | NEW | 
|---|