| OLD | NEW | 
|---|
|  | (Empty) | 
| 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 |  | 
| 3 // BSD-style license that can be found in the LICENSE file. |  | 
| 4 |  | 
| 5 library dart2js.constants.expressions; |  | 
| 6 |  | 
| 7 import '../dart2jslib.dart' show assertDebugMode; |  | 
| 8 import '../dart_types.dart'; |  | 
| 9 import '../elements/elements.dart' show |  | 
| 10     Element, |  | 
| 11     FunctionElement, |  | 
| 12     VariableElement; |  | 
| 13 import '../universe/universe.dart' show Selector; |  | 
| 14 import 'values.dart'; |  | 
| 15 |  | 
| 16 /// An expression that is a compile-time constant. |  | 
| 17 /// |  | 
| 18 /// Whereas [ConstantValue] represent a compile-time value, a |  | 
| 19 /// [ConstantExpression] represents an expression for creating a constant. |  | 
| 20 /// |  | 
| 21 /// There is no one-to-one mapping between [ConstantExpression] and |  | 
| 22 /// [ConstantValue], because different expressions can denote the same constant. |  | 
| 23 /// For instance, multiple `const` constructors may be used to create the same |  | 
| 24 /// object, and different `const` variables may hold the same value. |  | 
| 25 abstract class ConstantExpression { |  | 
| 26   /// Returns the value of this constant expression. |  | 
| 27   ConstantValue get value; |  | 
| 28 |  | 
| 29   // TODO(johnniwinther): Unify precedence handled between constants, front-end |  | 
| 30   // and back-end. |  | 
| 31   int get precedence => 16; |  | 
| 32 |  | 
| 33   accept(ConstantExpressionVisitor visitor); |  | 
| 34 |  | 
| 35   String getText() { |  | 
| 36     ConstExpPrinter printer = new ConstExpPrinter(); |  | 
| 37     accept(printer); |  | 
| 38     return printer.toString(); |  | 
| 39   } |  | 
| 40 |  | 
| 41   String toString() { |  | 
| 42     assertDebugMode('Use ConstantExpression.getText() instead of ' |  | 
| 43                     'ConstantExpression.toString()'); |  | 
| 44     return getText(); |  | 
| 45   } |  | 
| 46 } |  | 
| 47 |  | 
| 48 /// Boolean, int, double, string, or null constant. |  | 
| 49 class PrimitiveConstantExpression extends ConstantExpression { |  | 
| 50   final PrimitiveConstantValue value; |  | 
| 51 |  | 
| 52   PrimitiveConstantExpression(this.value) { |  | 
| 53     assert(value != null); |  | 
| 54   } |  | 
| 55 |  | 
| 56   accept(ConstantExpressionVisitor visitor) => visitor.visitPrimitive(this); |  | 
| 57 } |  | 
| 58 |  | 
| 59 /// Literal list constant. |  | 
| 60 class ListConstantExpression extends ConstantExpression { |  | 
| 61   final ListConstantValue value; |  | 
| 62   final InterfaceType type; |  | 
| 63   final List<ConstantExpression> values; |  | 
| 64 |  | 
| 65   ListConstantExpression(this.value, this.type, this.values); |  | 
| 66 |  | 
| 67   accept(ConstantExpressionVisitor visitor) => visitor.visitList(this); |  | 
| 68 } |  | 
| 69 |  | 
| 70 /// Literal map constant. |  | 
| 71 class MapConstantExpression extends ConstantExpression { |  | 
| 72   final MapConstantValue value; |  | 
| 73   final InterfaceType type; |  | 
| 74   final List<ConstantExpression> keys; |  | 
| 75   final List<ConstantExpression> values; |  | 
| 76 |  | 
| 77   MapConstantExpression(this.value, this.type, this.keys, this.values); |  | 
| 78 |  | 
| 79   accept(ConstantExpressionVisitor visitor) => visitor.visitMap(this); |  | 
| 80 } |  | 
| 81 |  | 
| 82 /// Invocation of a const constructor. |  | 
| 83 class ConstructedConstantExpresssion extends ConstantExpression { |  | 
| 84   final ConstantValue value; |  | 
| 85   final InterfaceType type; |  | 
| 86   final FunctionElement target; |  | 
| 87   final Selector selector; |  | 
| 88   final List<ConstantExpression> arguments; |  | 
| 89 |  | 
| 90   ConstructedConstantExpresssion(this.value, |  | 
| 91                       this.type, |  | 
| 92                       this.target, |  | 
| 93                       this.selector, |  | 
| 94                       this.arguments) { |  | 
| 95     assert(type.element == target.enclosingClass); |  | 
| 96   } |  | 
| 97 |  | 
| 98   accept(ConstantExpressionVisitor visitor) => visitor.visitConstructor(this); |  | 
| 99 } |  | 
| 100 |  | 
| 101 /// String literal with juxtaposition and/or interpolations. |  | 
| 102 // TODO(johnniwinther): Do we need this? |  | 
| 103 class ConcatenateConstantExpression extends ConstantExpression { |  | 
| 104   final StringConstantValue value; |  | 
| 105   final List<ConstantExpression> arguments; |  | 
| 106 |  | 
| 107   ConcatenateConstantExpression(this.value, this.arguments); |  | 
| 108 |  | 
| 109   accept(ConstantExpressionVisitor visitor) => visitor.visitConcatenate(this); |  | 
| 110 } |  | 
| 111 |  | 
| 112 /// Symbol literal. |  | 
| 113 class SymbolConstantExpression extends ConstantExpression { |  | 
| 114   final ConstructedConstantValue value; |  | 
| 115   final String name; |  | 
| 116 |  | 
| 117   SymbolConstantExpression(this.value, this.name); |  | 
| 118 |  | 
| 119   accept(ConstantExpressionVisitor visitor) => visitor.visitSymbol(this); |  | 
| 120 } |  | 
| 121 |  | 
| 122 /// Type literal. |  | 
| 123 class TypeConstantExpression extends ConstantExpression { |  | 
| 124   final TypeConstantValue value; |  | 
| 125   /// Either [DynamicType] or a raw [GenericType]. |  | 
| 126   final DartType type; |  | 
| 127 |  | 
| 128   TypeConstantExpression(this.value, this.type) { |  | 
| 129     assert(type is GenericType || type is DynamicType); |  | 
| 130   } |  | 
| 131 |  | 
| 132   accept(ConstantExpressionVisitor visitor) => visitor.visitType(this); |  | 
| 133 } |  | 
| 134 |  | 
| 135 /// Reference to a constant local, top-level, or static variable. |  | 
| 136 class VariableConstantExpression extends ConstantExpression { |  | 
| 137   final ConstantValue value; |  | 
| 138   final VariableElement element; |  | 
| 139 |  | 
| 140   VariableConstantExpression(this.value, this.element); |  | 
| 141 |  | 
| 142   accept(ConstantExpressionVisitor visitor) => visitor.visitVariable(this); |  | 
| 143 } |  | 
| 144 |  | 
| 145 /// Reference to a top-level or static function. |  | 
| 146 class FunctionConstantExpression extends ConstantExpression { |  | 
| 147   final FunctionConstantValue value; |  | 
| 148   final FunctionElement element; |  | 
| 149 |  | 
| 150   FunctionConstantExpression(this.value, this.element); |  | 
| 151 |  | 
| 152   accept(ConstantExpressionVisitor visitor) => visitor.visitFunction(this); |  | 
| 153 } |  | 
| 154 |  | 
| 155 /// A constant binary expression like `a * b` or `identical(a, b)`. |  | 
| 156 class BinaryConstantExpression extends ConstantExpression { |  | 
| 157   final ConstantValue value; |  | 
| 158   final ConstantExpression left; |  | 
| 159   final String operator; |  | 
| 160   final ConstantExpression right; |  | 
| 161 |  | 
| 162   BinaryConstantExpression(this.value, this.left, this.operator, this.right) { |  | 
| 163     assert(PRECEDENCE_MAP[operator] != null); |  | 
| 164   } |  | 
| 165 |  | 
| 166   accept(ConstantExpressionVisitor visitor) => visitor.visitBinary(this); |  | 
| 167 |  | 
| 168   int get precedence => PRECEDENCE_MAP[operator]; |  | 
| 169 |  | 
| 170   static const Map<String, int> PRECEDENCE_MAP = const { |  | 
| 171     'identical': 15, |  | 
| 172     '==': 6, |  | 
| 173     '!=': 6, |  | 
| 174     '&&': 5, |  | 
| 175     '||': 4, |  | 
| 176     '^': 9, |  | 
| 177     '&': 10, |  | 
| 178     '|': 8, |  | 
| 179     '>>': 11, |  | 
| 180     '<<': 11, |  | 
| 181     '+': 12, |  | 
| 182     '-': 12, |  | 
| 183     '*': 13, |  | 
| 184     '/': 13, |  | 
| 185     '~/': 13, |  | 
| 186     '>': 7, |  | 
| 187     '<': 7, |  | 
| 188     '>=': 7, |  | 
| 189     '<=': 7, |  | 
| 190     '%': 13, |  | 
| 191   }; |  | 
| 192 } |  | 
| 193 |  | 
| 194 /// A unary constant expression like `-a`. |  | 
| 195 class UnaryConstantExpression extends ConstantExpression { |  | 
| 196   final ConstantValue value; |  | 
| 197   final String operator; |  | 
| 198   final ConstantExpression expression; |  | 
| 199 |  | 
| 200   UnaryConstantExpression(this.value, this.operator, this.expression) { |  | 
| 201     assert(PRECEDENCE_MAP[operator] != null); |  | 
| 202   } |  | 
| 203 |  | 
| 204   accept(ConstantExpressionVisitor visitor) => visitor.visitUnary(this); |  | 
| 205 |  | 
| 206   int get precedence => PRECEDENCE_MAP[operator]; |  | 
| 207 |  | 
| 208   static const Map<String, int> PRECEDENCE_MAP = const { |  | 
| 209     '!': 14, |  | 
| 210     '~': 14, |  | 
| 211     '-': 14, |  | 
| 212   }; |  | 
| 213 } |  | 
| 214 |  | 
| 215 /// A constant conditional expression like `a ? b : c`. |  | 
| 216 class ConditionalConstantExpression extends ConstantExpression { |  | 
| 217   final ConstantValue value; |  | 
| 218   final ConstantExpression condition; |  | 
| 219   final ConstantExpression trueExp; |  | 
| 220   final ConstantExpression falseExp; |  | 
| 221 |  | 
| 222   ConditionalConstantExpression(this.value, |  | 
| 223                                 this.condition, |  | 
| 224                                 this.trueExp, |  | 
| 225                                 this.falseExp); |  | 
| 226 |  | 
| 227   accept(ConstantExpressionVisitor visitor) => visitor.visitConditional(this); |  | 
| 228 |  | 
| 229   int get precedence => 3; |  | 
| 230 } |  | 
| 231 |  | 
| 232 abstract class ConstantExpressionVisitor<T> { |  | 
| 233   T visit(ConstantExpression constant) => constant.accept(this); |  | 
| 234 |  | 
| 235   T visitPrimitive(PrimitiveConstantExpression exp); |  | 
| 236   T visitList(ListConstantExpression exp); |  | 
| 237   T visitMap(MapConstantExpression exp); |  | 
| 238   T visitConstructor(ConstructedConstantExpresssion exp); |  | 
| 239   T visitConcatenate(ConcatenateConstantExpression exp); |  | 
| 240   T visitSymbol(SymbolConstantExpression exp); |  | 
| 241   T visitType(TypeConstantExpression exp); |  | 
| 242   T visitVariable(VariableConstantExpression exp); |  | 
| 243   T visitFunction(FunctionConstantExpression exp); |  | 
| 244   T visitBinary(BinaryConstantExpression exp); |  | 
| 245   T visitUnary(UnaryConstantExpression exp); |  | 
| 246   T visitConditional(ConditionalConstantExpression exp); |  | 
| 247 } |  | 
| 248 |  | 
| 249 /// Represents the declaration of a constant [element] with value [expression]. |  | 
| 250 // TODO(johnniwinther): Where does this class belong? |  | 
| 251 class ConstDeclaration { |  | 
| 252   final VariableElement element; |  | 
| 253   final ConstantExpression expression; |  | 
| 254 |  | 
| 255   ConstDeclaration(this.element, this.expression); |  | 
| 256 } |  | 
| 257 |  | 
| 258 class ConstExpPrinter extends ConstantExpressionVisitor { |  | 
| 259   final StringBuffer sb = new StringBuffer(); |  | 
| 260 |  | 
| 261   write(ConstantExpression parent, |  | 
| 262         ConstantExpression child, |  | 
| 263         {bool leftAssociative: true}) { |  | 
| 264     if (child.precedence < parent.precedence || |  | 
| 265         !leftAssociative && child.precedence == parent.precedence) { |  | 
| 266       sb.write('('); |  | 
| 267       child.accept(this); |  | 
| 268       sb.write(')'); |  | 
| 269     } else { |  | 
| 270       child.accept(this); |  | 
| 271     } |  | 
| 272   } |  | 
| 273 |  | 
| 274   writeTypeArguments(InterfaceType type) { |  | 
| 275     if (type.treatAsRaw) return; |  | 
| 276     sb.write('<'); |  | 
| 277     bool needsComma = false; |  | 
| 278     for (DartType value in type.typeArguments) { |  | 
| 279       if (needsComma) { |  | 
| 280         sb.write(', '); |  | 
| 281       } |  | 
| 282       sb.write(value); |  | 
| 283       needsComma = true; |  | 
| 284     } |  | 
| 285     sb.write('>'); |  | 
| 286   } |  | 
| 287 |  | 
| 288   visitPrimitive(PrimitiveConstantExpression exp) { |  | 
| 289     sb.write(exp.value.unparse()); |  | 
| 290   } |  | 
| 291 |  | 
| 292   visitList(ListConstantExpression exp) { |  | 
| 293     sb.write('const '); |  | 
| 294     writeTypeArguments(exp.type); |  | 
| 295     sb.write('['); |  | 
| 296     bool needsComma = false; |  | 
| 297     for (ConstantExpression value in exp.values) { |  | 
| 298       if (needsComma) { |  | 
| 299         sb.write(', '); |  | 
| 300       } |  | 
| 301       visit(value); |  | 
| 302       needsComma = true; |  | 
| 303     } |  | 
| 304     sb.write(']'); |  | 
| 305   } |  | 
| 306 |  | 
| 307   visitMap(MapConstantExpression exp) { |  | 
| 308     sb.write('const '); |  | 
| 309     writeTypeArguments(exp.type); |  | 
| 310     sb.write('{'); |  | 
| 311     for (int index = 0; index < exp.keys.length; index++) { |  | 
| 312       if (index > 0) { |  | 
| 313         sb.write(', '); |  | 
| 314       } |  | 
| 315       visit(exp.keys[index]); |  | 
| 316       sb.write(': '); |  | 
| 317       visit(exp.values[index]); |  | 
| 318     } |  | 
| 319     sb.write('}'); |  | 
| 320   } |  | 
| 321 |  | 
| 322   visitConstructor(ConstructedConstantExpresssion exp) { |  | 
| 323     sb.write('const '); |  | 
| 324     sb.write(exp.target.enclosingClass.name); |  | 
| 325     if (exp.target.name != '') { |  | 
| 326       sb.write('.'); |  | 
| 327       sb.write(exp.target.name); |  | 
| 328     } |  | 
| 329     writeTypeArguments(exp.type); |  | 
| 330     sb.write('('); |  | 
| 331     bool needsComma = false; |  | 
| 332 |  | 
| 333     int namedOffset = exp.selector.positionalArgumentCount; |  | 
| 334     for (int index = 0; index < namedOffset; index++) { |  | 
| 335       if (needsComma) { |  | 
| 336         sb.write(', '); |  | 
| 337       } |  | 
| 338       visit(exp.arguments[index]); |  | 
| 339       needsComma = true; |  | 
| 340     } |  | 
| 341     for (int index = 0; index < exp.selector.namedArgumentCount; index++) { |  | 
| 342       if (needsComma) { |  | 
| 343         sb.write(', '); |  | 
| 344       } |  | 
| 345       sb.write(exp.selector.namedArguments[index]); |  | 
| 346       sb.write(': '); |  | 
| 347       visit(exp.arguments[namedOffset + index]); |  | 
| 348       needsComma = true; |  | 
| 349     } |  | 
| 350     sb.write(')'); |  | 
| 351   } |  | 
| 352 |  | 
| 353   visitConcatenate(ConcatenateConstantExpression exp) { |  | 
| 354     sb.write(exp.value.unparse()); |  | 
| 355   } |  | 
| 356 |  | 
| 357   visitSymbol(SymbolConstantExpression exp) { |  | 
| 358     sb.write('#'); |  | 
| 359     sb.write(exp.name); |  | 
| 360   } |  | 
| 361 |  | 
| 362   visitType(TypeConstantExpression exp) { |  | 
| 363     sb.write(exp.type.name); |  | 
| 364   } |  | 
| 365 |  | 
| 366   visitVariable(VariableConstantExpression exp) { |  | 
| 367     if (exp.element.isStatic) { |  | 
| 368       sb.write(exp.element.enclosingClass.name); |  | 
| 369       sb.write('.'); |  | 
| 370     } |  | 
| 371     sb.write(exp.element.name); |  | 
| 372   } |  | 
| 373 |  | 
| 374   visitFunction(FunctionConstantExpression exp) { |  | 
| 375     if (exp.element.isStatic) { |  | 
| 376       sb.write(exp.element.enclosingClass.name); |  | 
| 377       sb.write('.'); |  | 
| 378     } |  | 
| 379     sb.write(exp.element.name); |  | 
| 380   } |  | 
| 381 |  | 
| 382   visitBinary(BinaryConstantExpression exp) { |  | 
| 383     if (exp.operator == 'identical') { |  | 
| 384       sb.write('identical('); |  | 
| 385       visit(exp.left); |  | 
| 386       sb.write(', '); |  | 
| 387       visit(exp.right); |  | 
| 388       sb.write(')'); |  | 
| 389     } else { |  | 
| 390       write(exp, exp.left); |  | 
| 391       sb.write(' '); |  | 
| 392       sb.write(exp.operator); |  | 
| 393       sb.write(' '); |  | 
| 394       write(exp, exp.right); |  | 
| 395     } |  | 
| 396   } |  | 
| 397 |  | 
| 398   visitUnary(UnaryConstantExpression exp) { |  | 
| 399     sb.write(exp.operator); |  | 
| 400     write(exp, exp.expression); |  | 
| 401   } |  | 
| 402 |  | 
| 403   visitConditional(ConditionalConstantExpression exp) { |  | 
| 404     write(exp, exp.condition, leftAssociative: false); |  | 
| 405     sb.write(' ? '); |  | 
| 406     write(exp, exp.trueExp); |  | 
| 407     sb.write(' : '); |  | 
| 408     write(exp, exp.falseExp); |  | 
| 409   } |  | 
| 410 |  | 
| 411   String toString() => sb.toString(); |  | 
| 412 } |  | 
| OLD | NEW | 
|---|