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 class JavaScriptBitNotOperation extends BitNotOperation { | |
6 static const int BITS32 = 0xFFFFFFFF; | |
7 | |
8 const JavaScriptBitNotOperation(); | |
9 Constant fold(Constant constant) { | |
10 // In JavaScript we don't check for -0 and treat it as if it was zero. | |
11 if (constant.isMinusZero()) constant = new IntConstant(0); | |
12 if (constant.isInt()) { | |
13 IntConstant intConstant = constant; | |
14 // We convert the result of bit-operations to 32 bit unsigned integers. | |
15 return new IntConstant((~intConstant.value) & BITS32); | |
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 static const int BITS32 = 0xFFFFFFFF; | |
ngeoffray
2012/08/17 08:32:59
Share it with JavaScriptBitNotOperation?
floitsch
2012/09/03 14:34:52
Done.
| |
27 | |
28 final BinaryBitOperation dartBitOperation; | |
29 const JavaScriptBinaryBitOperation(this.dartBitOperation); | |
30 | |
31 bool isUserDefinable() => dartBitOperation.isUserDefinable(); | |
32 SourceString get name() => dartBitOperation.name; | |
33 | |
34 Constant fold(Constant left, Constant right) { | |
35 // In JavaScript we don't check for -0 and treat it as if it was zero. | |
36 if (left.isMinusZero()) left = new IntConstant(0); | |
37 if (right.isMinusZero()) right = new IntConstant(0); | |
38 IntConstant result = dartBitOperation.fold(left, right); | |
39 if (result != null) { | |
40 // We convert the result of bit-operations to 32 bit unsigned integers. | |
41 int clampedValue = result.value & BITS32; | |
42 if (clampedValue != result.value) { | |
43 result = new IntConstant(clampedValue); | |
44 } | |
45 } | |
46 return result; | |
47 } | |
48 } | |
49 | |
50 class JavaScriptNegateOperation implements UnaryOperation { | |
51 final NegateOperation dartNegateOperation = const NegateOperation(); | |
52 const JavaScriptNegateOperation(); | |
53 | |
54 bool isUserDefinable() => dartNegateOperation.isUserDefinable(); | |
55 SourceString get name() => dartNegateOperation.name; | |
56 | |
57 Constant fold(Constant constant) { | |
58 if (constant.isInt()) { | |
59 IntConstant intConstant = constant; | |
60 if (intConstant.value == 0) return new DoubleConstant(-0.0); | |
61 } | |
62 return dartNegateOperation.fold(constant); | |
63 } | |
64 } | |
65 | |
66 class JavaScriptBinaryArithmeticOperation implements BinaryOperation { | |
67 final BinaryOperation dartArithmeticOperation; | |
68 const JavaScriptBinaryArithmeticOperation(this.dartArithmeticOperation); | |
69 | |
70 bool isUserDefinable() => dartArithmeticOperation.isUserDefinable(); | |
71 SourceString get name() => dartArithmeticOperation.name; | |
72 | |
73 /** | |
74 * Returns true if the given [value] fits into a double without losing | |
75 * precision. | |
76 */ | |
77 bool integerFitsIntoDouble(int value) { | |
78 // The maximum integer value a double can represent without losing | |
79 // precision. | |
80 final int BITS53 = 0x1FFFFFFFFFFFFF; | |
81 | |
82 int absValue = value.abs(); | |
83 return (absValue & BITS53) == absValue; | |
84 } | |
85 | |
86 Constant fold(Constant left, Constant right) { | |
87 Constant result = dartArithmeticOperation.fold(left, right); | |
88 if (result == null) return result; | |
89 if (result.isInt()) { | |
90 // TODO(floitsch): make sure that the constant folding operation has the | |
91 // same semantics as during runtime. | |
92 IntConstant intResult = result; | |
93 int intValue = intResult.value; | |
94 if (!integerFitsIntoDouble(intValue)) { | |
95 return new DoubleConstant(intValue.toDouble()); | |
96 } | |
97 } else if (result.isDouble()) { | |
98 DoubleConstant doubleResult = result; | |
99 double doubleValue = doubleResult.value; | |
100 if (!doubleValue.isInfinite() && !doubleValue.isNaN()) { | |
101 int intValue = doubleValue.toInt(); | |
102 if (intValue == doubleValue && integerFitsIntoDouble(intValue)) { | |
103 return new IntConstant(intValue); | |
104 } | |
105 } | |
106 } | |
107 return result; | |
108 } | |
109 } | |
110 | |
111 class JavaScriptIdentityOperation implements BinaryOperation { | |
112 final IdentityOperation dartIdentityOperation = const IdentityOperation(); | |
113 | |
114 const JavaScriptIdentityOperation(); | |
115 | |
116 bool isUserDefinable() => dartIdentityOperation.isUserDefinable(); | |
117 SourceString get name() => dartIdentityOperation.name; | |
118 | |
119 BoolConstant fold(Constant left, Constant right) { | |
120 BoolConstant result = dartIdentityOperation.fold(left, right); | |
121 if (result == null || result.value) return result; | |
122 // In JavaScript -0.0 === 0 and all doubles are equal to their integer | |
123 // values. | |
124 if (left.isNum() && right.isNum()) { | |
125 NumConstant leftNum = left; | |
126 NumConstant rightNum = right; | |
127 double leftDouble = leftNum.value.toDouble(); | |
128 double rightDouble = rightNum.value.toDouble(); | |
129 return new BoolConstant(leftDouble == rightDouble); | |
130 } | |
131 return result; | |
132 } | |
133 } | |
134 | |
135 /** | |
136 * Folding operations following the semantics for Dart code that has been | |
137 * compiled to JavaScript. | |
138 */ | |
139 class JavaScriptFoldingOperations implements FoldingOperations { | |
140 final add = const JavaScriptBinaryArithmeticOperation(const AddOperation()); | |
141 final bitAnd = const JavaScriptBinaryBitOperation(const BitAndOperation()); | |
142 final bitNot = const JavaScriptBitNotOperation(); | |
143 final bitOr = const JavaScriptBinaryBitOperation(const BitOrOperation()); | |
144 final bitXor = const JavaScriptBinaryBitOperation(const BitXorOperation()); | |
145 final booleanAnd = const BooleanAndOperation(); | |
146 final booleanOr = const BooleanOrOperation(); | |
147 final divide = | |
148 const JavaScriptBinaryArithmeticOperation(const DivideOperation()); | |
149 final equal = const EqualsOperation(); | |
150 final greaterEqual = const GreaterEqualOperation(); | |
151 final greater = const GreaterOperation(); | |
152 final identity = const JavaScriptIdentityOperation(); | |
153 final lessEqual = const LessEqualOperation(); | |
154 final less = const LessOperation(); | |
155 final modulo = | |
156 const JavaScriptBinaryArithmeticOperation(const ModuloOperation()); | |
157 final multiply = | |
158 const JavaScriptBinaryArithmeticOperation(const MultiplyOperation()); | |
159 final negate = const JavaScriptNegateOperation(); | |
160 final not = const NotOperation(); | |
161 final shiftLeft = | |
162 const JavaScriptBinaryBitOperation(const ShiftLeftOperation()); | |
163 final shiftRight = | |
164 const JavaScriptBinaryBitOperation(const ShiftRightOperation()); | |
165 final subtract = | |
166 const JavaScriptBinaryArithmeticOperation(const SubtractOperation()); | |
167 final truncatingDivide = const JavaScriptBinaryArithmeticOperation( | |
168 const TruncatingDivideOperation()); | |
169 | |
170 const JavaScriptFoldingOperations(); | |
171 } | |
OLD | NEW |