| 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 class Constant implements Hashable { | 5 class Constant implements Hashable { |
| 6 const Constant(); | 6 const Constant(); |
| 7 | 7 |
| 8 bool isNull() => false; | 8 bool isNull() => false; |
| 9 /** [isInt] implies [isNum]. */ | 9 /** [isInt] implies [isNum]. */ |
| 10 bool isInt() => false; | 10 bool isInt() => false; |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 52 abstract void writeJsCode(StringBuffer buffer, ConstantHandler handler); | 52 abstract void writeJsCode(StringBuffer buffer, ConstantHandler handler); |
| 53 } | 53 } |
| 54 | 54 |
| 55 class PrimitiveConstant extends Constant { | 55 class PrimitiveConstant extends Constant { |
| 56 abstract get value(); | 56 abstract get value(); |
| 57 const PrimitiveConstant(); | 57 const PrimitiveConstant(); |
| 58 | 58 |
| 59 bool operator ==(var other) { | 59 bool operator ==(var other) { |
| 60 if (other is !PrimitiveConstant) return false; | 60 if (other is !PrimitiveConstant) return false; |
| 61 PrimitiveConstant otherPrimitive = other; | 61 PrimitiveConstant otherPrimitive = other; |
| 62 // We use == instead of === so that DartStrings compare correctly. | 62 // We use == instead of === so that DartStrings compare correctly. |
| 63 return value == otherPrimitive.value; | 63 return value == otherPrimitive.value; |
| 64 } | 64 } |
| 65 | 65 |
| 66 String toString() => value.toString(); | 66 String toString() => value.toString(); |
| 67 } | 67 } |
| 68 | 68 |
| 69 class NullConstant extends PrimitiveConstant { | 69 class NullConstant extends PrimitiveConstant { |
| 70 const NullConstant(); | 70 const NullConstant(); |
| 71 bool isNull() => true; | 71 bool isNull() => true; |
| 72 get value() => null; | 72 get value() => null; |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 112 if (other.isInt()) { | 112 if (other.isInt()) { |
| 113 int right = rightNum; | 113 int right = rightNum; |
| 114 switch (op) { | 114 switch (op) { |
| 115 case "+": return new IntConstant(value + right); | 115 case "+": return new IntConstant(value + right); |
| 116 case "-": return new IntConstant(value - right); | 116 case "-": return new IntConstant(value - right); |
| 117 case "*": return new IntConstant(value * right); | 117 case "*": return new IntConstant(value * right); |
| 118 case "%": return new IntConstant(value % right); | 118 case "%": return new IntConstant(value % right); |
| 119 case "~/": return new IntConstant(value ~/ right); | 119 case "~/": return new IntConstant(value ~/ right); |
| 120 case "|": return new IntConstant(value | right); | 120 case "|": return new IntConstant(value | right); |
| 121 case "&": return new IntConstant(value & right); | 121 case "&": return new IntConstant(value & right); |
| 122 case "^": return new IntConstant(value ^ right); | 122 case "^": return new IntConstant(value ^ right); |
| 123 case "<<": | 123 case "<<": |
| 124 // TODO(floitsch): find a better way to guard against shifts to the | 124 // TODO(floitsch): find a better way to guard against shifts to the |
| 125 // left. | 125 // left. |
| 126 if (right > 100) return null; | 126 if (right > 100) return null; |
| 127 if (right < 0) return null; | 127 if (right < 0) return null; |
| 128 return new IntConstant(value << right); | 128 return new IntConstant(value << right); |
| 129 case ">>": | 129 case ">>": |
| 130 if (right < 0) return null; | 130 if (right < 0) return null; |
| 131 return new IntConstant(value >> right); | 131 return new IntConstant(value >> right); |
| 132 } | 132 } |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 164 bool isDouble() => true; | 164 bool isDouble() => true; |
| 165 | 165 |
| 166 void writeJsCode(StringBuffer buffer, ConstantHandler handler) { | 166 void writeJsCode(StringBuffer buffer, ConstantHandler handler) { |
| 167 if (value.isNaN()) { | 167 if (value.isNaN()) { |
| 168 buffer.add("(0/0)"); | 168 buffer.add("(0/0)"); |
| 169 } else if (value == double.INFINITY) { | 169 } else if (value == double.INFINITY) { |
| 170 buffer.add("(1/0)"); | 170 buffer.add("(1/0)"); |
| 171 } else if (value == -double.INFINITY) { | 171 } else if (value == -double.INFINITY) { |
| 172 buffer.add("(-1/0)"); | 172 buffer.add("(-1/0)"); |
| 173 } else { | 173 } else { |
| 174 buffer.add("($value)"); | 174 buffer.add("($value)"); |
| 175 } | 175 } |
| 176 } | 176 } |
| 177 | 177 |
| 178 DoubleConstant unaryFold(String op) { | 178 DoubleConstant unaryFold(String op) { |
| 179 if (op == "-") return new DoubleConstant(-value); | 179 if (op == "-") return new DoubleConstant(-value); |
| 180 return null; | 180 return null; |
| 181 } | 181 } |
| 182 | 182 |
| 183 Constant binaryFold(String op, Constant other) { | 183 Constant binaryFold(String op, Constant other) { |
| 184 if (other.isNum()) { | 184 if (other.isNum()) { |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 262 ConstantHandler.writeEscapedString(value, buffer, (reason) { | 262 ConstantHandler.writeEscapedString(value, buffer, (reason) { |
| 263 throw new CompilerCancelledException(reason); | 263 throw new CompilerCancelledException(reason); |
| 264 }); | 264 }); |
| 265 buffer.add("'"); | 265 buffer.add("'"); |
| 266 } | 266 } |
| 267 | 267 |
| 268 Constant binaryFold(String op, Constant other) { | 268 Constant binaryFold(String op, Constant other) { |
| 269 if (other.isString() && op == "+") { | 269 if (other.isString() && op == "+") { |
| 270 StringConstant otherString = other; | 270 StringConstant otherString = other; |
| 271 DartString right = otherString.value; | 271 DartString right = otherString.value; |
| 272 return new StringConstant(new ConsDartString(value, right)); | 272 return new StringConstant(new DartString.cons(value, right)); |
| 273 } | 273 } |
| 274 // Visit super in case the [op] was "==", "===", "!=" or "!===". | 274 // Visit super in case the [op] was "==", "===", "!=" or "!===". |
| 275 return super.binaryFold(op, other); | 275 return super.binaryFold(op, other); |
| 276 } | 276 } |
| 277 | 277 |
| 278 bool operator ==(var other) { | 278 bool operator ==(var other) { |
| 279 if (other is !StringConstant) return false; | 279 if (other is !StringConstant) return false; |
| 280 StringConstant otherString = other; | 280 StringConstant otherString = other; |
| 281 return (_hashCode == otherString._hashCode) && (value == otherString.value); | 281 return (_hashCode == otherString._hashCode) && (value == otherString.value); |
| 282 } | 282 } |
| 283 | 283 |
| 284 int hashCode() => _hashCode; | 284 int hashCode() => _hashCode; |
| 285 } | 285 } |
| 286 | 286 |
| 287 class ObjectConstant extends Constant { | 287 class ObjectConstant extends Constant { |
| 288 final Type type; | 288 final Type type; |
| 289 | 289 |
| 290 ObjectConstant(this.type); | 290 ObjectConstant(this.type); |
| 291 } | 291 } |
| 292 | 292 |
| 293 class ListConstant extends ObjectConstant { | 293 class ListConstant extends ObjectConstant { |
| 294 final List<Constant> entries; | 294 final List<Constant> entries; |
| 295 int _hashCode; | 295 int _hashCode; |
| 296 | 296 |
| 297 ListConstant(Type type, this.entries) : super(type) { | 297 ListConstant(Type type, this.entries) : super(type) { |
| 298 // TODO(floitsch): create a better hash. | 298 // TODO(floitsch): create a better hash. |
| 299 int hash = 0; | 299 int hash = 0; |
| 300 for (Constant input in entries) hash ^= input.hashCode(); | 300 for (Constant input in entries) hash ^= input.hashCode(); |
| 301 _hashCode = hash; | 301 _hashCode = hash; |
| 302 } | 302 } |
| 303 bool isList() => true; | 303 bool isList() => true; |
| 304 | 304 |
| 305 void writeJsCode(StringBuffer buffer, ConstantHandler handler) { | 305 void writeJsCode(StringBuffer buffer, ConstantHandler handler) { |
| 306 // TODO(floitsch): we should not need to go through the compiler to make | 306 // TODO(floitsch): we should not need to go through the compiler to make |
| 307 // the list constant. | 307 // the list constant. |
| 308 String isolatePrototype = "${handler.compiler.namer.ISOLATE}.prototype"; | 308 String isolatePrototype = "${handler.compiler.namer.ISOLATE}.prototype"; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 335 | 335 |
| 336 int hashCode() => _hashCode; | 336 int hashCode() => _hashCode; |
| 337 } | 337 } |
| 338 | 338 |
| 339 class ConstructedConstant extends ObjectConstant { | 339 class ConstructedConstant extends ObjectConstant { |
| 340 final List<Constant> fields; | 340 final List<Constant> fields; |
| 341 int _hashCode; | 341 int _hashCode; |
| 342 | 342 |
| 343 ConstructedConstant(Type type, this.fields) : super(type) { | 343 ConstructedConstant(Type type, this.fields) : super(type) { |
| 344 assert(type !== null); | 344 assert(type !== null); |
| 345 // TODO(floitsch): create a better hash. | 345 // TODO(floitsch): create a better hash. |
| 346 int hash = 0; | 346 int hash = 0; |
| 347 for (Constant field in fields) { | 347 for (Constant field in fields) { |
| 348 hash ^= field.hashCode(); | 348 hash ^= field.hashCode(); |
| 349 } | 349 } |
| 350 hash ^= type.element.hashCode(); | 350 hash ^= type.element.hashCode(); |
| 351 _hashCode = hash; | 351 _hashCode = hash; |
| 352 } | 352 } |
| 353 bool isConstructedObject() => true; | 353 bool isConstructedObject() => true; |
| 354 | 354 |
| 355 void writeJsCode(StringBuffer buffer, ConstantHandler handler) { | 355 void writeJsCode(StringBuffer buffer, ConstantHandler handler) { |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 516 List<Constant> getConstantsForEmission() { | 516 List<Constant> getConstantsForEmission() { |
| 517 return compiledConstants.getKeys(); | 517 return compiledConstants.getKeys(); |
| 518 } | 518 } |
| 519 | 519 |
| 520 String getNameForConstant(Constant constant) { | 520 String getNameForConstant(Constant constant) { |
| 521 return compiledConstants[constant]; | 521 return compiledConstants[constant]; |
| 522 } | 522 } |
| 523 | 523 |
| 524 StringBuffer writeJsCode(StringBuffer buffer, Constant value) { | 524 StringBuffer writeJsCode(StringBuffer buffer, Constant value) { |
| 525 value.writeJsCode(buffer, this); | 525 value.writeJsCode(buffer, this); |
| 526 return buffer; | 526 return buffer; |
| 527 } | 527 } |
| 528 | 528 |
| 529 StringBuffer writeJsCodeForVariable(StringBuffer buffer, | 529 StringBuffer writeJsCodeForVariable(StringBuffer buffer, |
| 530 VariableElement element) { | 530 VariableElement element) { |
| 531 if (!initialVariableValues.containsKey(element)) { | 531 if (!initialVariableValues.containsKey(element)) { |
| 532 buffer.add("(void 0)"); | 532 buffer.add("(void 0)"); |
| 533 return buffer; | 533 return buffer; |
| 534 // TODO(floitsch): reenable the following lines, once we fixed the rest | 534 // TODO(floitsch): reenable the following lines, once we fixed the rest |
| 535 // of the compiler. | 535 // of the compiler. |
| 536 /* | 536 /* |
| 537 compiler.internalError("No initial value for given element", | 537 compiler.internalError("No initial value for given element", |
| 538 element: element); | 538 element: element); |
| 539 */ | 539 */ |
| 540 } | 540 } |
| 541 Constant constant = initialVariableValues[element]; | 541 Constant constant = initialVariableValues[element]; |
| 542 if (constant.isObject()) { | 542 if (constant.isObject()) { |
| 543 String name = compiledConstants[constant]; | 543 String name = compiledConstants[constant]; |
| 544 buffer.add("${compiler.namer.ISOLATE}.prototype.$name"); | 544 buffer.add("${compiler.namer.ISOLATE}.prototype.$name"); |
| 545 } else { | 545 } else { |
| 546 writeJsCode(buffer, constant); | 546 writeJsCode(buffer, constant); |
| 547 } | 547 } |
| 548 return buffer; | 548 return buffer; |
| 549 } | 549 } |
| 550 | 550 |
| 551 /** | 551 /** |
| 552 * Write the contents of the quoted string to a [StringBuffer] in | 552 * Write the contents of the quoted string to a [StringBuffer] in |
| 553 * a form that is valid as JavaScript string literal content. | 553 * a form that is valid as JavaScript string literal content. |
| 554 * The string is assumed quoted by single quote characters. | 554 * The string is assumed quoted by single quote characters. |
| 555 */ | 555 */ |
| 556 static void writeEscapedString(DartString string, | 556 static void writeEscapedString(DartString string, |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 622 | 622 |
| 623 visitNode(Node node) { | 623 visitNode(Node node) { |
| 624 compiler.unimplemented("CompileTimeConstantEvaluator", node: node); | 624 compiler.unimplemented("CompileTimeConstantEvaluator", node: node); |
| 625 } | 625 } |
| 626 | 626 |
| 627 Constant visitLiteralBool(LiteralBool node) { | 627 Constant visitLiteralBool(LiteralBool node) { |
| 628 // TODO(floitsch): make BoolConstant a factory and cache the two values | 628 // TODO(floitsch): make BoolConstant a factory and cache the two values |
| 629 // there. | 629 // there. |
| 630 return node.value ? const BoolConstant(true) : const BoolConstant(false); | 630 return node.value ? const BoolConstant(true) : const BoolConstant(false); |
| 631 } | 631 } |
| 632 | 632 |
| 633 Constant visitLiteralDouble(LiteralDouble node) { | 633 Constant visitLiteralDouble(LiteralDouble node) { |
| 634 return new DoubleConstant(node.value); | 634 return new DoubleConstant(node.value); |
| 635 } | 635 } |
| 636 | 636 |
| 637 Constant visitLiteralInt(LiteralInt node) { | 637 Constant visitLiteralInt(LiteralInt node) { |
| 638 return new IntConstant(node.value); | 638 return new IntConstant(node.value); |
| 639 } | 639 } |
| 640 | 640 |
| 641 Constant visitLiteralList(LiteralList node) { | 641 Constant visitLiteralList(LiteralList node) { |
| 642 if (!node.isConst()) error(node); | 642 if (!node.isConst()) error(node); |
| 643 List arguments = []; | 643 List arguments = []; |
| 644 for (Link<Node> link = node.elements.nodes; | 644 for (Link<Node> link = node.elements.nodes; |
| 645 !link.isEmpty(); | 645 !link.isEmpty(); |
| 646 link = link.tail) { | 646 link = link.tail) { |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 718 arguments); | 718 arguments); |
| 719 } | 719 } |
| 720 | 720 |
| 721 error(Node node) { | 721 error(Node node) { |
| 722 // TODO(floitsch): get the list of constants that are currently compiled | 722 // TODO(floitsch): get the list of constants that are currently compiled |
| 723 // and present some kind of stack-trace. | 723 // and present some kind of stack-trace. |
| 724 MessageKind kind = MessageKind.NOT_A_COMPILE_TIME_CONSTANT; | 724 MessageKind kind = MessageKind.NOT_A_COMPILE_TIME_CONSTANT; |
| 725 compiler.reportError(node, new CompileTimeConstantError(kind, const [])); | 725 compiler.reportError(node, new CompileTimeConstantError(kind, const [])); |
| 726 } | 726 } |
| 727 } | 727 } |
| OLD | NEW |