| 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 part of dart2js; | 5 part of dart2js; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * The [ConstantHandler] keeps track of compile-time constants, | 8 * The [ConstantHandler] keeps track of compile-time constants, |
| 9 * initializations of global and static fields, and default values of | 9 * initializations of global and static fields, and default values of |
| 10 * optional parameters. | 10 * optional parameters. |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 84 /** | 84 /** |
| 85 * Returns the a compile-time constant if the variable could be compiled | 85 * Returns the a compile-time constant if the variable could be compiled |
| 86 * eagerly. If the variable needs to be initialized lazily returns `null`. | 86 * eagerly. If the variable needs to be initialized lazily returns `null`. |
| 87 * If the variable is `const` but cannot be compiled eagerly reports an | 87 * If the variable is `const` but cannot be compiled eagerly reports an |
| 88 * error. | 88 * error. |
| 89 */ | 89 */ |
| 90 Constant compileVariableWithDefinitions(VariableElement element, | 90 Constant compileVariableWithDefinitions(VariableElement element, |
| 91 TreeElements definitions, | 91 TreeElements definitions, |
| 92 {bool isConst: false}) { | 92 {bool isConst: false}) { |
| 93 return measure(() { | 93 return measure(() { |
| 94 // Initializers for parameters must be const. | |
| 95 isConst = isConst || element.modifiers.isConst() | |
| 96 || !Elements.isStaticOrTopLevel(element); | |
| 97 if (!isConst && lazyStatics.contains(element)) return null; | 94 if (!isConst && lazyStatics.contains(element)) return null; |
| 98 | 95 |
| 99 Node node = element.parseNode(compiler); | 96 Node node = element.parseNode(compiler); |
| 100 if (pendingVariables.contains(element)) { | 97 if (pendingVariables.contains(element)) { |
| 101 if (isConst) { | 98 if (isConst) { |
| 102 compiler.reportFatalError( | 99 compiler.reportFatalError( |
| 103 node, MessageKind.CYCLIC_COMPILE_TIME_CONSTANTS); | 100 node, MessageKind.CYCLIC_COMPILE_TIME_CONSTANTS); |
| 104 } else { | 101 } else { |
| 105 lazyStatics.add(element); | 102 lazyStatics.add(element); |
| 106 return null; | 103 return null; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 144 pendingVariables.remove(element); | 141 pendingVariables.remove(element); |
| 145 return value; | 142 return value; |
| 146 }); | 143 }); |
| 147 } | 144 } |
| 148 | 145 |
| 149 Constant compileNodeWithDefinitions(Node node, | 146 Constant compileNodeWithDefinitions(Node node, |
| 150 TreeElements definitions, | 147 TreeElements definitions, |
| 151 {bool isConst: false}) { | 148 {bool isConst: false}) { |
| 152 return measure(() { | 149 return measure(() { |
| 153 assert(node != null); | 150 assert(node != null); |
| 151 Constant constant = definitions.getConstant(node); |
| 152 if (constant != null) { |
| 153 return constant; |
| 154 } |
| 154 CompileTimeConstantEvaluator evaluator = new CompileTimeConstantEvaluator( | 155 CompileTimeConstantEvaluator evaluator = new CompileTimeConstantEvaluator( |
| 155 this, definitions, compiler, isConst: isConst); | 156 this, definitions, compiler, isConst: isConst); |
| 156 return evaluator.evaluate(node); | 157 constant = evaluator.evaluate(node); |
| 158 if (constant != null) { |
| 159 definitions.setConstant(node, constant); |
| 160 } |
| 161 return constant; |
| 157 }); | 162 }); |
| 158 } | 163 } |
| 159 | 164 |
| 160 /** | 165 /** |
| 161 * Returns an [Iterable] of static non final fields that need to be | 166 * Returns an [Iterable] of static non final fields that need to be |
| 162 * initialized. The fields list must be evaluated in order since they might | 167 * initialized. The fields list must be evaluated in order since they might |
| 163 * depend on each other. | 168 * depend on each other. |
| 164 */ | 169 */ |
| 165 Iterable<VariableElement> getStaticNonFinalFieldsForEmission() { | 170 Iterable<VariableElement> getStaticNonFinalFieldsForEmission() { |
| 166 return initialVariableValues.keys.where((element) { | 171 return initialVariableValues.keys.where((element) { |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 390 List<Constant> createArguments(_) { | 395 List<Constant> createArguments(_) { |
| 391 return [constantSystem.createString( | 396 return [constantSystem.createString( |
| 392 new DartString.literal(node.slowNameString), node)]; | 397 new DartString.literal(node.slowNameString), node)]; |
| 393 } | 398 } |
| 394 return makeConstructedConstant( | 399 return makeConstructedConstant( |
| 395 node, type, compiler.symbolConstructor, createArguments); | 400 node, type, compiler.symbolConstructor, createArguments); |
| 396 } | 401 } |
| 397 | 402 |
| 398 Constant makeTypeConstant(Element element) { | 403 Constant makeTypeConstant(Element element) { |
| 399 DartType elementType = element.computeType(compiler).asRaw(); | 404 DartType elementType = element.computeType(compiler).asRaw(); |
| 400 compiler.backend.registerTypeLiteral( | |
| 401 element, compiler.enqueuer.codegen, elements); | |
| 402 DartType constantType = | 405 DartType constantType = |
| 403 compiler.backend.typeImplementation.computeType(compiler); | 406 compiler.backend.typeImplementation.computeType(compiler); |
| 404 return new TypeConstant(elementType, constantType); | 407 return new TypeConstant(elementType, constantType); |
| 405 } | 408 } |
| 406 | 409 |
| 407 // TODO(floitsch): provide better error-messages. | 410 // TODO(floitsch): provide better error-messages. |
| 408 Constant visitSend(Send send) { | 411 Constant visitSend(Send send) { |
| 409 Element element = elements[send]; | 412 Element element = elements[send]; |
| 410 if (send.isPropertyAccess) { | 413 if (send.isPropertyAccess) { |
| 411 if (Elements.isStaticOrTopLevelFunction(element)) { | 414 if (Elements.isStaticOrTopLevelFunction(element)) { |
| 412 return new FunctionConstant(element); | 415 return new FunctionConstant(element); |
| 413 } else if (Elements.isStaticOrTopLevelField(element)) { | 416 } else if (Elements.isStaticOrTopLevelField(element)) { |
| 414 Constant result; | 417 Constant result; |
| 415 if (element.modifiers.isConst()) { | 418 if (element.modifiers.isConst()) { |
| 416 result = handler.compileConstant(element); | 419 result = handler.compileConstant(element); |
| 417 } else if (element.modifiers.isFinal() && !isEvaluatingConstant) { | 420 } else if (element.modifiers.isFinal() && !isEvaluatingConstant) { |
| 418 result = handler.compileVariable(element); | 421 result = handler.compileVariable(element); |
| 419 } | 422 } |
| 420 if (result != null) return result; | 423 if (result != null) return result; |
| 421 } else if (Elements.isClass(element) || Elements.isTypedef(element)) { | 424 } else if (Elements.isClass(element) || Elements.isTypedef(element)) { |
| 425 assert(elements.isTypeLiteral(send)); |
| 422 return makeTypeConstant(element); | 426 return makeTypeConstant(element); |
| 423 } else if (send.receiver != null) { | 427 } else if (send.receiver != null) { |
| 424 // Fall through to error handling. | 428 // Fall through to error handling. |
| 425 } else if (!Elements.isUnresolved(element) | 429 } else if (!Elements.isUnresolved(element) |
| 426 && element.isVariable() | 430 && element.isVariable() |
| 427 && element.modifiers.isConst()) { | 431 && element.modifiers.isConst()) { |
| 428 Constant result = handler.compileConstant(element); | 432 Constant result = handler.compileConstant(element); |
| 429 if (result != null) return result; | 433 if (result != null) return result; |
| 430 } | 434 } |
| 431 return signalNotCompileTimeConstant(send); | 435 return signalNotCompileTimeConstant(send); |
| 432 } else if (send.isCall) { | 436 } else if (send.isCall) { |
| 433 if (identical(element, compiler.identicalFunction) | 437 if (identical(element, compiler.identicalFunction) |
| 434 && send.argumentCount() == 2) { | 438 && send.argumentCount() == 2) { |
| 435 Constant left = evaluate(send.argumentsNode.nodes.head); | 439 Constant left = evaluate(send.argumentsNode.nodes.head); |
| 436 Constant right = evaluate(send.argumentsNode.nodes.tail.head); | 440 Constant right = evaluate(send.argumentsNode.nodes.tail.head); |
| 437 Constant result = constantSystem.identity.fold(left, right); | 441 Constant result = constantSystem.identity.fold(left, right); |
| 438 if (result != null) return result; | 442 if (result != null) return result; |
| 439 } else if (Elements.isClass(element) || Elements.isTypedef(element)) { | 443 } else if (Elements.isClass(element) || Elements.isTypedef(element)) { |
| 440 return makeTypeConstant(element); | 444 // The node itself is not a constant but we register the selector (the |
| 445 // identifier that refers to the class/typedef) as a constant. |
| 446 Constant typeConstant = makeTypeConstant(element); |
| 447 elements.setConstant(send.selector, typeConstant); |
| 441 } | 448 } |
| 442 return signalNotCompileTimeConstant(send); | 449 return signalNotCompileTimeConstant(send); |
| 443 } else if (send.isPrefix) { | 450 } else if (send.isPrefix) { |
| 444 assert(send.isOperator); | 451 assert(send.isOperator); |
| 445 Constant receiverConstant = evaluate(send.receiver); | 452 Constant receiverConstant = evaluate(send.receiver); |
| 446 if (receiverConstant == null) return null; | 453 if (receiverConstant == null) return null; |
| 447 Operator op = send.selector; | 454 Operator op = send.selector; |
| 448 Constant folded; | 455 Constant folded; |
| 449 switch (op.source.stringValue) { | 456 switch (op.source.stringValue) { |
| 450 case "!": | 457 case "!": |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 548 folded = areIdentical.negate(); | 555 folded = areIdentical.negate(); |
| 549 } | 556 } |
| 550 break; | 557 break; |
| 551 } | 558 } |
| 552 if (folded == null) return signalNotCompileTimeConstant(send); | 559 if (folded == null) return signalNotCompileTimeConstant(send); |
| 553 return folded; | 560 return folded; |
| 554 } | 561 } |
| 555 return signalNotCompileTimeConstant(send); | 562 return signalNotCompileTimeConstant(send); |
| 556 } | 563 } |
| 557 | 564 |
| 565 Constant visitConditional(Conditional node) { |
| 566 Constant condition = evaluate(node.condition); |
| 567 if (condition == null) { |
| 568 return null; |
| 569 } else if (!condition.isBool()) { |
| 570 DartType conditionType = condition.computeType(compiler); |
| 571 if (isEvaluatingConstant) { |
| 572 compiler.reportFatalError( |
| 573 node.condition, MessageKind.NOT_ASSIGNABLE.error, |
| 574 {'fromType': conditionType, 'toType': compiler.boolClass.rawType}); |
| 575 } |
| 576 return null; |
| 577 } |
| 578 Constant thenExpression = evaluate(node.thenExpression); |
| 579 Constant elseExpression = evaluate(node.elseExpression); |
| 580 BoolConstant boolCondition = condition; |
| 581 return boolCondition.value ? thenExpression : elseExpression; |
| 582 } |
| 583 |
| 558 Constant visitSendSet(SendSet node) { | 584 Constant visitSendSet(SendSet node) { |
| 559 return signalNotCompileTimeConstant(node); | 585 return signalNotCompileTimeConstant(node); |
| 560 } | 586 } |
| 561 | 587 |
| 562 /** | 588 /** |
| 563 * Returns the list of constants that are passed to the static function. | 589 * Returns the list of constants that are passed to the static function. |
| 564 * | 590 * |
| 565 * Invariant: [target] must be an implementation element. | 591 * Invariant: [target] must be an implementation element. |
| 566 */ | 592 */ |
| 567 List<Constant> evaluateArgumentsToConstructor(Node node, | 593 List<Constant> evaluateArgumentsToConstructor(Node node, |
| (...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 852 if (fieldValue == null) { | 878 if (fieldValue == null) { |
| 853 // Use the default value. | 879 // Use the default value. |
| 854 fieldValue = handler.compileConstant(field); | 880 fieldValue = handler.compileConstant(field); |
| 855 } | 881 } |
| 856 jsNewArguments.add(fieldValue); | 882 jsNewArguments.add(fieldValue); |
| 857 }, | 883 }, |
| 858 includeSuperAndInjectedMembers: true); | 884 includeSuperAndInjectedMembers: true); |
| 859 return jsNewArguments; | 885 return jsNewArguments; |
| 860 } | 886 } |
| 861 } | 887 } |
| OLD | NEW |