| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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.expressions; | 5 library dart2js.constants.expressions; |
| 6 | 6 |
| 7 import '../dart2jslib.dart' show assertDebugMode; | 7 import '../dart2jslib.dart' show assertDebugMode; |
| 8 import '../dart_types.dart'; | 8 import '../dart_types.dart'; |
| 9 import '../elements/elements.dart' show | 9 import '../elements/elements.dart' show |
| 10 ConstructorElement, |
| 10 Element, | 11 Element, |
| 11 FunctionElement, | 12 FunctionElement, |
| 12 VariableElement; | 13 VariableElement; |
| 13 import '../resolution/operators.dart'; | 14 import '../resolution/operators.dart'; |
| 14 import '../universe/universe.dart' show CallStructure; | 15 import '../universe/universe.dart' show CallStructure; |
| 15 import 'values.dart'; | 16 import 'values.dart'; |
| 16 | 17 |
| 18 enum ConstantExpressionKind { |
| 19 BINARY, |
| 20 BOOL, |
| 21 CONCATENATE, |
| 22 CONDITIONAL, |
| 23 CONSTRUCTED, |
| 24 DOUBLE, |
| 25 ERRONEOUS, |
| 26 FUNCTION, |
| 27 IDENTICAL, |
| 28 INT, |
| 29 LIST, |
| 30 MAP, |
| 31 NULL, |
| 32 STRING, |
| 33 SYMBOL, |
| 34 TYPE, |
| 35 UNARY, |
| 36 VARIABLE, |
| 37 } |
| 38 |
| 17 /// An expression that is a compile-time constant. | 39 /// An expression that is a compile-time constant. |
| 18 /// | 40 /// |
| 19 /// Whereas [ConstantValue] represent a compile-time value, a | 41 /// Whereas [ConstantValue] represent a compile-time value, a |
| 20 /// [ConstantExpression] represents an expression for creating a constant. | 42 /// [ConstantExpression] represents an expression for creating a constant. |
| 21 /// | 43 /// |
| 22 /// There is no one-to-one mapping between [ConstantExpression] and | 44 /// There is no one-to-one mapping between [ConstantExpression] and |
| 23 /// [ConstantValue], because different expressions can denote the same constant. | 45 /// [ConstantValue], because different expressions can denote the same constant. |
| 24 /// For instance, multiple `const` constructors may be used to create the same | 46 /// For instance, multiple `const` constructors may be used to create the same |
| 25 /// object, and different `const` variables may hold the same value. | 47 /// object, and different `const` variables may hold the same value. |
| 26 abstract class ConstantExpression { | 48 abstract class ConstantExpression { |
| 49 int _hashCode; |
| 50 |
| 51 ConstantExpressionKind get kind; |
| 52 |
| 27 /// Returns the value of this constant expression. | 53 /// Returns the value of this constant expression. |
| 28 ConstantValue get value; | 54 ConstantValue get value; |
| 29 | 55 |
| 30 // TODO(johnniwinther): Unify precedence handled between constants, front-end | 56 // TODO(johnniwinther): Unify precedence handled between constants, front-end |
| 31 // and back-end. | 57 // and back-end. |
| 32 int get precedence => 16; | 58 int get precedence => 16; |
| 33 | 59 |
| 34 accept(ConstantExpressionVisitor visitor, [context]); | 60 accept(ConstantExpressionVisitor visitor, [context]); |
| 35 | 61 |
| 36 String getText() { | 62 String getText() { |
| 37 ConstExpPrinter printer = new ConstExpPrinter(); | 63 ConstExpPrinter printer = new ConstExpPrinter(); |
| 38 accept(printer); | 64 accept(printer); |
| 39 return printer.toString(); | 65 return printer.toString(); |
| 40 } | 66 } |
| 41 | 67 |
| 68 int _computeHashCode(); |
| 69 |
| 70 int get hashCode { |
| 71 if (_hashCode == null) { |
| 72 _hashCode = _computeHashCode(); |
| 73 } |
| 74 return _hashCode; |
| 75 } |
| 76 |
| 77 bool _equals(ConstantExpression other); |
| 78 |
| 79 bool operator ==(other) { |
| 80 if (identical(this, other)) return true; |
| 81 if (other is! ConstantExpression) return false; |
| 82 if (kind != other.kind) return false; |
| 83 if (hashCode != other.hashCode) return false; |
| 84 return _equals(other); |
| 85 } |
| 86 |
| 42 String toString() { | 87 String toString() { |
| 43 assertDebugMode('Use ConstantExpression.getText() instead of ' | 88 assertDebugMode('Use ConstantExpression.getText() instead of ' |
| 44 'ConstantExpression.toString()'); | 89 'ConstantExpression.toString()'); |
| 45 return getText(); | 90 return getText(); |
| 46 } | 91 } |
| 47 } | 92 } |
| 48 | 93 |
| 49 /// A synthetic constant used to recover from errors. | 94 /// A synthetic constant used to recover from errors. |
| 50 class ErroneousConstantExpression extends ConstantExpression { | 95 class ErroneousConstantExpression extends ConstantExpression { |
| 51 final PrimitiveConstantValue value = new NullConstantValue(); | 96 final PrimitiveConstantValue value = new NullConstantValue(); |
| 52 | 97 |
| 53 ErroneousConstantExpression(); | 98 ConstantExpressionKind get kind => ConstantExpressionKind.ERRONEOUS; |
| 54 | 99 |
| 55 accept(ConstantExpressionVisitor visitor, [context]) { | 100 accept(ConstantExpressionVisitor visitor, [context]) { |
| 56 // Do nothing. This is an error. | 101 // Do nothing. This is an error. |
| 57 } | 102 } |
| 103 |
| 104 @override |
| 105 int _computeHashCode() => 13; |
| 106 |
| 107 @override |
| 108 bool _equals(ErroneousConstantExpression other) => true; |
| 58 } | 109 } |
| 59 | 110 |
| 60 /// Boolean, int, double, string, or null constant. | 111 /// A boolean, int, double, string, or null constant. |
| 61 class PrimitiveConstantExpression extends ConstantExpression { | 112 abstract class PrimitiveConstantExpression extends ConstantExpression { |
| 62 final PrimitiveConstantValue value; | 113 final PrimitiveConstantValue value; |
| 63 | 114 |
| 64 PrimitiveConstantExpression(this.value) { | 115 PrimitiveConstantExpression(this.value); |
| 65 assert(value != null); | 116 |
| 66 } | 117 /// The primitive value of this contant expression. |
| 118 get primitiveValue; |
| 67 | 119 |
| 68 accept(ConstantExpressionVisitor visitor, [context]) { | 120 accept(ConstantExpressionVisitor visitor, [context]) { |
| 69 return visitor.visitPrimitive(this, context); | 121 return visitor.visitPrimitive(this, context); |
| 70 } | 122 } |
| 71 } | 123 } |
| 72 | 124 |
| 125 /// Boolean literal constant. |
| 126 class BoolConstantExpression extends PrimitiveConstantExpression { |
| 127 final bool primitiveValue; |
| 128 |
| 129 BoolConstantExpression(this.primitiveValue, |
| 130 PrimitiveConstantValue value) : super(value); |
| 131 |
| 132 ConstantExpressionKind get kind => ConstantExpressionKind.BOOL; |
| 133 |
| 134 @override |
| 135 int _computeHashCode() => 13 * primitiveValue.hashCode; |
| 136 |
| 137 @override |
| 138 bool _equals(BoolConstantExpression other) { |
| 139 return primitiveValue == other.primitiveValue; |
| 140 } |
| 141 } |
| 142 |
| 143 /// Integer literal constant. |
| 144 class IntConstantExpression extends PrimitiveConstantExpression { |
| 145 final int primitiveValue; |
| 146 |
| 147 IntConstantExpression(this.primitiveValue, |
| 148 PrimitiveConstantValue value) : super(value); |
| 149 |
| 150 ConstantExpressionKind get kind => ConstantExpressionKind.INT; |
| 151 |
| 152 @override |
| 153 int _computeHashCode() => 17 * primitiveValue.hashCode; |
| 154 |
| 155 @override |
| 156 bool _equals(IntConstantExpression other) { |
| 157 return primitiveValue == other.primitiveValue; |
| 158 } |
| 159 } |
| 160 |
| 161 /// Double literal constant. |
| 162 class DoubleConstantExpression extends PrimitiveConstantExpression { |
| 163 final double primitiveValue; |
| 164 |
| 165 DoubleConstantExpression(this.primitiveValue, |
| 166 PrimitiveConstantValue value) : super(value); |
| 167 |
| 168 ConstantExpressionKind get kind => ConstantExpressionKind.DOUBLE; |
| 169 |
| 170 @override |
| 171 int _computeHashCode() => 19 * primitiveValue.hashCode; |
| 172 |
| 173 @override |
| 174 bool _equals(DoubleConstantExpression other) { |
| 175 return primitiveValue == other.primitiveValue; |
| 176 } |
| 177 } |
| 178 |
| 179 /// String literal constant. |
| 180 class StringConstantExpression extends PrimitiveConstantExpression { |
| 181 final String primitiveValue; |
| 182 |
| 183 StringConstantExpression(this.primitiveValue, |
| 184 PrimitiveConstantValue value) : super(value); |
| 185 |
| 186 ConstantExpressionKind get kind => ConstantExpressionKind.STRING; |
| 187 |
| 188 @override |
| 189 int _computeHashCode() => 23 * primitiveValue.hashCode; |
| 190 |
| 191 @override |
| 192 bool _equals(StringConstantExpression other) { |
| 193 return primitiveValue == other.primitiveValue; |
| 194 } |
| 195 } |
| 196 |
| 197 /// Null literal constant. |
| 198 class NullConstantExpression extends PrimitiveConstantExpression { |
| 199 NullConstantExpression(PrimitiveConstantValue value) : super(value); |
| 200 |
| 201 ConstantExpressionKind get kind => ConstantExpressionKind.NULL; |
| 202 |
| 203 get primitiveValue => null; |
| 204 |
| 205 @override |
| 206 int _computeHashCode() => 29; |
| 207 |
| 208 @override |
| 209 bool _equals(NullConstantExpression other) => true; |
| 210 } |
| 211 |
| 73 /// Literal list constant. | 212 /// Literal list constant. |
| 74 class ListConstantExpression extends ConstantExpression { | 213 class ListConstantExpression extends ConstantExpression { |
| 75 final ListConstantValue value; | 214 final ListConstantValue value; |
| 76 final InterfaceType type; | 215 final InterfaceType type; |
| 77 final List<ConstantExpression> values; | 216 final List<ConstantExpression> values; |
| 78 | 217 |
| 79 ListConstantExpression(this.value, this.type, this.values); | 218 ListConstantExpression(this.value, this.type, this.values); |
| 80 | 219 |
| 220 ConstantExpressionKind get kind => ConstantExpressionKind.LIST; |
| 221 |
| 81 accept(ConstantExpressionVisitor visitor, [context]) { | 222 accept(ConstantExpressionVisitor visitor, [context]) { |
| 82 return visitor.visitList(this, context); | 223 return visitor.visitList(this, context); |
| 83 } | 224 } |
| 225 |
| 226 @override |
| 227 int _computeHashCode() { |
| 228 int hashCode = 13 * type.hashCode + 17 * values.length; |
| 229 for (ConstantExpression value in values) { |
| 230 hashCode ^= 19 * value.hashCode; |
| 231 } |
| 232 return hashCode; |
| 233 } |
| 234 |
| 235 @override |
| 236 bool _equals(ListConstantExpression other) { |
| 237 if (type != other.type) return false; |
| 238 if (values.length != other.values.length) return false; |
| 239 for (int i = 0; i < values.length; i++) { |
| 240 if (values[i] != other.values[i]) return false; |
| 241 } |
| 242 return true; |
| 243 } |
| 84 } | 244 } |
| 85 | 245 |
| 86 /// Literal map constant. | 246 /// Literal map constant. |
| 87 class MapConstantExpression extends ConstantExpression { | 247 class MapConstantExpression extends ConstantExpression { |
| 88 final MapConstantValue value; | 248 final MapConstantValue value; |
| 89 final InterfaceType type; | 249 final InterfaceType type; |
| 90 final List<ConstantExpression> keys; | 250 final List<ConstantExpression> keys; |
| 91 final List<ConstantExpression> values; | 251 final List<ConstantExpression> values; |
| 92 | 252 |
| 93 MapConstantExpression(this.value, this.type, this.keys, this.values); | 253 MapConstantExpression(this.value, this.type, this.keys, this.values); |
| 94 | 254 |
| 255 ConstantExpressionKind get kind => ConstantExpressionKind.MAP; |
| 256 |
| 95 accept(ConstantExpressionVisitor visitor, [context]) { | 257 accept(ConstantExpressionVisitor visitor, [context]) { |
| 96 return visitor.visitMap(this, context); | 258 return visitor.visitMap(this, context); |
| 97 } | 259 } |
| 260 |
| 261 @override |
| 262 int _computeHashCode() { |
| 263 int hashCode = 13 * type.hashCode + 17 * values.length; |
| 264 for (ConstantExpression value in values) { |
| 265 hashCode ^= 19 * value.hashCode; |
| 266 } |
| 267 return hashCode; |
| 268 } |
| 269 |
| 270 @override |
| 271 bool _equals(MapConstantExpression other) { |
| 272 if (type != other.type) return false; |
| 273 if (values.length != other.values.length) return false; |
| 274 for (int i = 0; i < values.length; i++) { |
| 275 if (keys[i] != other.keys[i]) return false; |
| 276 if (values[i] != other.values[i]) return false; |
| 277 } |
| 278 return true; |
| 279 } |
| 98 } | 280 } |
| 99 | 281 |
| 100 /// Invocation of a const constructor. | 282 /// Invocation of a const constructor. |
| 101 class ConstructedConstantExpression extends ConstantExpression { | 283 class ConstructedConstantExpression extends ConstantExpression { |
| 102 final ConstantValue value; | 284 final ConstantValue value; |
| 103 final InterfaceType type; | 285 final InterfaceType type; |
| 104 final FunctionElement target; | 286 final ConstructorElement target; |
| 105 final CallStructure callStructure; | 287 final CallStructure callStructure; |
| 106 final List<ConstantExpression> arguments; | 288 final List<ConstantExpression> arguments; |
| 107 | 289 |
| 108 ConstructedConstantExpression( | 290 ConstructedConstantExpression( |
| 109 this.value, | 291 this.value, |
| 110 this.type, | 292 this.type, |
| 111 this.target, | 293 this.target, |
| 112 this.callStructure, | 294 this.callStructure, |
| 113 this.arguments) { | 295 this.arguments) { |
| 114 assert(type.element == target.enclosingClass); | 296 assert(type.element == target.enclosingClass); |
| 115 } | 297 } |
| 116 | 298 |
| 299 ConstantExpressionKind get kind => ConstantExpressionKind.CONSTRUCTED; |
| 300 |
| 117 accept(ConstantExpressionVisitor visitor, [context]) { | 301 accept(ConstantExpressionVisitor visitor, [context]) { |
| 118 return visitor.visitConstructed(this, context); | 302 return visitor.visitConstructed(this, context); |
| 119 } | 303 } |
| 304 |
| 305 @override |
| 306 int _computeHashCode() { |
| 307 int hashCode = |
| 308 13 * type.hashCode + |
| 309 17 * target.hashCode + |
| 310 19 * callStructure.hashCode; |
| 311 for (ConstantExpression value in arguments) { |
| 312 hashCode ^= 23 * value.hashCode; |
| 313 } |
| 314 return hashCode; |
| 315 } |
| 316 |
| 317 @override |
| 318 bool _equals(ConstructedConstantExpression other) { |
| 319 if (type != other.type) return false; |
| 320 if (target != other.target) return false; |
| 321 if (callStructure != other.callStructure) return false; |
| 322 for (int i = 0; i < arguments.length; i++) { |
| 323 if (arguments[i] != other.arguments[i]) return false; |
| 324 } |
| 325 return true; |
| 326 } |
| 120 } | 327 } |
| 121 | 328 |
| 122 /// String literal with juxtaposition and/or interpolations. | 329 /// String literal with juxtaposition and/or interpolations. |
| 123 // TODO(johnniwinther): Do we need this? | |
| 124 class ConcatenateConstantExpression extends ConstantExpression { | 330 class ConcatenateConstantExpression extends ConstantExpression { |
| 125 final StringConstantValue value; | 331 final StringConstantValue value; |
| 126 final List<ConstantExpression> arguments; | 332 final List<ConstantExpression> arguments; |
| 127 | 333 |
| 128 ConcatenateConstantExpression(this.value, this.arguments); | 334 ConcatenateConstantExpression(this.value, this.arguments); |
| 129 | 335 |
| 336 ConstantExpressionKind get kind => ConstantExpressionKind.CONCATENATE; |
| 337 |
| 130 accept(ConstantExpressionVisitor visitor, [context]) { | 338 accept(ConstantExpressionVisitor visitor, [context]) { |
| 131 return visitor.visitConcatenate(this, context); | 339 return visitor.visitConcatenate(this, context); |
| 132 } | 340 } |
| 341 |
| 342 @override |
| 343 int _computeHashCode() { |
| 344 int hashCode = 17 * arguments.length; |
| 345 for (ConstantExpression value in arguments) { |
| 346 hashCode ^= 19 * value.hashCode; |
| 347 } |
| 348 return hashCode; |
| 349 } |
| 350 |
| 351 @override |
| 352 bool _equals(ConcatenateConstantExpression other) { |
| 353 if (arguments.length != other.arguments.length) return false; |
| 354 for (int i = 0; i < arguments.length; i++) { |
| 355 if (arguments[i] != other.arguments[i]) return false; |
| 356 } |
| 357 return true; |
| 358 } |
| 133 } | 359 } |
| 134 | 360 |
| 135 /// Symbol literal. | 361 /// Symbol literal. |
| 136 class SymbolConstantExpression extends ConstantExpression { | 362 class SymbolConstantExpression extends ConstantExpression { |
| 137 final ConstructedConstantValue value; | 363 final ConstructedConstantValue value; |
| 138 final String name; | 364 final String name; |
| 139 | 365 |
| 140 SymbolConstantExpression(this.value, this.name); | 366 SymbolConstantExpression(this.value, this.name); |
| 141 | 367 |
| 368 ConstantExpressionKind get kind => ConstantExpressionKind.SYMBOL; |
| 369 |
| 142 accept(ConstantExpressionVisitor visitor, [context]) { | 370 accept(ConstantExpressionVisitor visitor, [context]) { |
| 143 return visitor.visitSymbol(this, context); | 371 return visitor.visitSymbol(this, context); |
| 144 } | 372 } |
| 373 |
| 374 @override |
| 375 int _computeHashCode() => 13 * name.hashCode; |
| 376 |
| 377 @override |
| 378 bool _equals(SymbolConstantExpression other) { |
| 379 return name == other.name; |
| 380 } |
| 145 } | 381 } |
| 146 | 382 |
| 147 /// Type literal. | 383 /// Type literal. |
| 148 class TypeConstantExpression extends ConstantExpression { | 384 class TypeConstantExpression extends ConstantExpression { |
| 149 final TypeConstantValue value; | 385 final TypeConstantValue value; |
| 150 /// Either [DynamicType] or a raw [GenericType]. | 386 /// Either [DynamicType] or a raw [GenericType]. |
| 151 final DartType type; | 387 final DartType type; |
| 152 | 388 |
| 153 TypeConstantExpression(this.value, this.type) { | 389 TypeConstantExpression(this.value, this.type) { |
| 154 assert(type is GenericType || type is DynamicType); | 390 assert(type is GenericType || type is DynamicType); |
| 155 } | 391 } |
| 156 | 392 |
| 393 ConstantExpressionKind get kind => ConstantExpressionKind.TYPE; |
| 394 |
| 157 accept(ConstantExpressionVisitor visitor, [context]) { | 395 accept(ConstantExpressionVisitor visitor, [context]) { |
| 158 return visitor.visitType(this, context); | 396 return visitor.visitType(this, context); |
| 159 } | 397 } |
| 398 |
| 399 @override |
| 400 int _computeHashCode() => 13 * type.hashCode; |
| 401 |
| 402 @override |
| 403 bool _equals(TypeConstantExpression other) { |
| 404 return type == other.type; |
| 405 } |
| 160 } | 406 } |
| 161 | 407 |
| 162 /// Reference to a constant local, top-level, or static variable. | 408 /// Reference to a constant local, top-level, or static variable. |
| 163 class VariableConstantExpression extends ConstantExpression { | 409 class VariableConstantExpression extends ConstantExpression { |
| 164 final ConstantValue value; | 410 final ConstantValue value; |
| 165 final VariableElement element; | 411 final VariableElement element; |
| 166 | 412 |
| 167 VariableConstantExpression(this.value, this.element); | 413 VariableConstantExpression(this.value, this.element); |
| 168 | 414 |
| 415 ConstantExpressionKind get kind => ConstantExpressionKind.VARIABLE; |
| 416 |
| 169 accept(ConstantExpressionVisitor visitor, [context]) { | 417 accept(ConstantExpressionVisitor visitor, [context]) { |
| 170 return visitor.visitVariable(this, context); | 418 return visitor.visitVariable(this, context); |
| 171 } | 419 } |
| 420 |
| 421 @override |
| 422 int _computeHashCode() => 13 * element.hashCode; |
| 423 |
| 424 @override |
| 425 bool _equals(VariableConstantExpression other) { |
| 426 return element == other.element; |
| 427 } |
| 172 } | 428 } |
| 173 | 429 |
| 174 /// Reference to a top-level or static function. | 430 /// Reference to a top-level or static function. |
| 175 class FunctionConstantExpression extends ConstantExpression { | 431 class FunctionConstantExpression extends ConstantExpression { |
| 176 final FunctionConstantValue value; | 432 final FunctionConstantValue value; |
| 177 final FunctionElement element; | 433 final FunctionElement element; |
| 178 | 434 |
| 179 FunctionConstantExpression(this.value, this.element); | 435 FunctionConstantExpression(this.value, this.element); |
| 180 | 436 |
| 437 ConstantExpressionKind get kind => ConstantExpressionKind.FUNCTION; |
| 438 |
| 181 accept(ConstantExpressionVisitor visitor, [context]) { | 439 accept(ConstantExpressionVisitor visitor, [context]) { |
| 182 return visitor.visitFunction(this, context); | 440 return visitor.visitFunction(this, context); |
| 183 } | 441 } |
| 442 |
| 443 @override |
| 444 int _computeHashCode() => 13 * element.hashCode; |
| 445 |
| 446 @override |
| 447 bool _equals(FunctionConstantExpression other) { |
| 448 return element == other.element; |
| 449 } |
| 184 } | 450 } |
| 185 | 451 |
| 186 /// A constant binary expression like `a * b`. | 452 /// A constant binary expression like `a * b`. |
| 187 class BinaryConstantExpression extends ConstantExpression { | 453 class BinaryConstantExpression extends ConstantExpression { |
| 188 final ConstantValue value; | 454 final ConstantValue value; |
| 189 final ConstantExpression left; | 455 final ConstantExpression left; |
| 190 final BinaryOperator operator; | 456 final BinaryOperator operator; |
| 191 final ConstantExpression right; | 457 final ConstantExpression right; |
| 192 | 458 |
| 193 BinaryConstantExpression(this.value, this.left, this.operator, this.right) { | 459 BinaryConstantExpression(this.value, this.left, this.operator, this.right) { |
| 194 assert(PRECEDENCE_MAP[operator.kind] != null); | 460 assert(PRECEDENCE_MAP[operator.kind] != null); |
| 195 } | 461 } |
| 196 | 462 |
| 463 ConstantExpressionKind get kind => ConstantExpressionKind.BINARY; |
| 464 |
| 197 accept(ConstantExpressionVisitor visitor, [context]) { | 465 accept(ConstantExpressionVisitor visitor, [context]) { |
| 198 return visitor.visitBinary(this, context); | 466 return visitor.visitBinary(this, context); |
| 199 } | 467 } |
| 200 | 468 |
| 201 int get precedence => PRECEDENCE_MAP[operator.kind]; | 469 int get precedence => PRECEDENCE_MAP[operator.kind]; |
| 202 | 470 |
| 471 @override |
| 472 int _computeHashCode() { |
| 473 return 13 * operator.hashCode + |
| 474 17 * left.hashCode + |
| 475 19 * right.hashCode; |
| 476 } |
| 477 |
| 478 @override |
| 479 bool _equals(BinaryConstantExpression other) { |
| 480 return operator == other.operator && |
| 481 left == other.left && |
| 482 right == other.right; |
| 483 } |
| 484 |
| 203 static const Map<BinaryOperatorKind, int> PRECEDENCE_MAP = const { | 485 static const Map<BinaryOperatorKind, int> PRECEDENCE_MAP = const { |
| 204 BinaryOperatorKind.EQ: 6, | 486 BinaryOperatorKind.EQ: 6, |
| 205 BinaryOperatorKind.NOT_EQ: 6, | 487 BinaryOperatorKind.NOT_EQ: 6, |
| 206 BinaryOperatorKind.LOGICAL_AND: 5, | 488 BinaryOperatorKind.LOGICAL_AND: 5, |
| 207 BinaryOperatorKind.LOGICAL_OR: 4, | 489 BinaryOperatorKind.LOGICAL_OR: 4, |
| 208 BinaryOperatorKind.XOR: 9, | 490 BinaryOperatorKind.XOR: 9, |
| 209 BinaryOperatorKind.AND: 10, | 491 BinaryOperatorKind.AND: 10, |
| 210 BinaryOperatorKind.OR: 8, | 492 BinaryOperatorKind.OR: 8, |
| 211 BinaryOperatorKind.SHR: 11, | 493 BinaryOperatorKind.SHR: 11, |
| 212 BinaryOperatorKind.SHL: 11, | 494 BinaryOperatorKind.SHL: 11, |
| (...skipping 11 matching lines...) Expand all Loading... |
| 224 } | 506 } |
| 225 | 507 |
| 226 /// A constant identical invocation like `identical(a, b)`. | 508 /// A constant identical invocation like `identical(a, b)`. |
| 227 class IdenticalConstantExpression extends ConstantExpression { | 509 class IdenticalConstantExpression extends ConstantExpression { |
| 228 final ConstantValue value; | 510 final ConstantValue value; |
| 229 final ConstantExpression left; | 511 final ConstantExpression left; |
| 230 final ConstantExpression right; | 512 final ConstantExpression right; |
| 231 | 513 |
| 232 IdenticalConstantExpression(this.value, this.left, this.right); | 514 IdenticalConstantExpression(this.value, this.left, this.right); |
| 233 | 515 |
| 516 ConstantExpressionKind get kind => ConstantExpressionKind.IDENTICAL; |
| 517 |
| 234 accept(ConstantExpressionVisitor visitor, [context]) { | 518 accept(ConstantExpressionVisitor visitor, [context]) { |
| 235 return visitor.visitIdentical(this, context); | 519 return visitor.visitIdentical(this, context); |
| 236 } | 520 } |
| 237 | 521 |
| 238 int get precedence => 15; | 522 int get precedence => 15; |
| 523 |
| 524 @override |
| 525 int _computeHashCode() { |
| 526 return 17 * left.hashCode + |
| 527 19 * right.hashCode; |
| 528 } |
| 529 |
| 530 @override |
| 531 bool _equals(IdenticalConstantExpression other) { |
| 532 return left == other.left && |
| 533 right == other.right; |
| 534 } |
| 239 } | 535 } |
| 240 | 536 |
| 241 /// A unary constant expression like `-a`. | 537 /// A unary constant expression like `-a`. |
| 242 class UnaryConstantExpression extends ConstantExpression { | 538 class UnaryConstantExpression extends ConstantExpression { |
| 243 final ConstantValue value; | 539 final ConstantValue value; |
| 244 final UnaryOperator operator; | 540 final UnaryOperator operator; |
| 245 final ConstantExpression expression; | 541 final ConstantExpression expression; |
| 246 | 542 |
| 247 UnaryConstantExpression(this.value, this.operator, this.expression) { | 543 UnaryConstantExpression(this.value, this.operator, this.expression) { |
| 248 assert(PRECEDENCE_MAP[operator.kind] != null); | 544 assert(PRECEDENCE_MAP[operator.kind] != null); |
| 249 } | 545 } |
| 250 | 546 |
| 547 ConstantExpressionKind get kind => ConstantExpressionKind.UNARY; |
| 548 |
| 251 accept(ConstantExpressionVisitor visitor, [context]) { | 549 accept(ConstantExpressionVisitor visitor, [context]) { |
| 252 return visitor.visitUnary(this, context); | 550 return visitor.visitUnary(this, context); |
| 253 } | 551 } |
| 254 | 552 |
| 255 int get precedence => PRECEDENCE_MAP[operator.kind]; | 553 int get precedence => PRECEDENCE_MAP[operator.kind]; |
| 256 | 554 |
| 555 @override |
| 556 int _computeHashCode() { |
| 557 return 13 * operator.hashCode + |
| 558 17 * expression.hashCode; |
| 559 } |
| 560 |
| 561 @override |
| 562 bool _equals(UnaryConstantExpression other) { |
| 563 return operator == other.operator && |
| 564 expression == other.expression; |
| 565 } |
| 566 |
| 257 static const Map<UnaryOperatorKind, int> PRECEDENCE_MAP = const { | 567 static const Map<UnaryOperatorKind, int> PRECEDENCE_MAP = const { |
| 258 UnaryOperatorKind.NOT: 14, | 568 UnaryOperatorKind.NOT: 14, |
| 259 UnaryOperatorKind.COMPLEMENT: 14, | 569 UnaryOperatorKind.COMPLEMENT: 14, |
| 260 UnaryOperatorKind.NEGATE: 14, | 570 UnaryOperatorKind.NEGATE: 14, |
| 261 }; | 571 }; |
| 262 } | 572 } |
| 263 | 573 |
| 264 /// A constant conditional expression like `a ? b : c`. | 574 /// A constant conditional expression like `a ? b : c`. |
| 265 class ConditionalConstantExpression extends ConstantExpression { | 575 class ConditionalConstantExpression extends ConstantExpression { |
| 266 final ConstantValue value; | 576 final ConstantValue value; |
| 267 final ConstantExpression condition; | 577 final ConstantExpression condition; |
| 268 final ConstantExpression trueExp; | 578 final ConstantExpression trueExp; |
| 269 final ConstantExpression falseExp; | 579 final ConstantExpression falseExp; |
| 270 | 580 |
| 271 ConditionalConstantExpression(this.value, | 581 ConditionalConstantExpression(this.value, |
| 272 this.condition, | 582 this.condition, |
| 273 this.trueExp, | 583 this.trueExp, |
| 274 this.falseExp); | 584 this.falseExp); |
| 275 | 585 |
| 586 ConstantExpressionKind get kind => ConstantExpressionKind.CONDITIONAL; |
| 587 |
| 276 accept(ConstantExpressionVisitor visitor, [context]) { | 588 accept(ConstantExpressionVisitor visitor, [context]) { |
| 277 return visitor.visitConditional(this, context); | 589 return visitor.visitConditional(this, context); |
| 278 } | 590 } |
| 279 | 591 |
| 280 int get precedence => 3; | 592 int get precedence => 3; |
| 593 |
| 594 @override |
| 595 int _computeHashCode() { |
| 596 return 13 * condition.hashCode + |
| 597 17 * trueExp.hashCode + |
| 598 19 * falseExp.hashCode; |
| 599 } |
| 600 |
| 601 @override |
| 602 bool _equals(ConditionalConstantExpression other) { |
| 603 return condition == other.condition && |
| 604 trueExp == other.trueExp && |
| 605 falseExp == other.falseExp; |
| 606 } |
| 281 } | 607 } |
| 282 | 608 |
| 283 abstract class ConstantExpressionVisitor<C, R> { | 609 abstract class ConstantExpressionVisitor<C, R> { |
| 284 const ConstantExpressionVisitor(); | 610 const ConstantExpressionVisitor(); |
| 285 | 611 |
| 286 R visit(ConstantExpression constant, C context) { | 612 R visit(ConstantExpression constant, C context) { |
| 287 return constant.accept(this, context); | 613 return constant.accept(this, context); |
| 288 } | 614 } |
| 289 | 615 |
| 290 R visitPrimitive(PrimitiveConstantExpression exp, C context); | 616 R visitPrimitive(PrimitiveConstantExpression exp, C context); |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 477 void visitConditional(ConditionalConstantExpression exp, [_]) { | 803 void visitConditional(ConditionalConstantExpression exp, [_]) { |
| 478 write(exp, exp.condition, leftAssociative: false); | 804 write(exp, exp.condition, leftAssociative: false); |
| 479 sb.write(' ? '); | 805 sb.write(' ? '); |
| 480 write(exp, exp.trueExp); | 806 write(exp, exp.trueExp); |
| 481 sb.write(' : '); | 807 sb.write(' : '); |
| 482 write(exp, exp.falseExp); | 808 write(exp, exp.falseExp); |
| 483 } | 809 } |
| 484 | 810 |
| 485 String toString() => sb.toString(); | 811 String toString() => sb.toString(); |
| 486 } | 812 } |
| OLD | NEW |