| 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 /** | 5 /** |
| 6 * The [ConstantHandler] keeps track of compile-time constants, | 6 * The [ConstantHandler] keeps track of compile-time constants, |
| 7 * initializations of global and static fields, and default values of | 7 * initializations of global and static fields, and default values of |
| 8 * optional parameters. | 8 * optional parameters. |
| 9 */ | 9 */ |
| 10 class ConstantHandler extends CompilerTask { | 10 class ConstantHandler extends CompilerTask { |
| (...skipping 624 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 635 if (Elements.isLocal(element)) { | 635 if (Elements.isLocal(element)) { |
| 636 Constant constant = definitions[element]; | 636 Constant constant = definitions[element]; |
| 637 if (constant === null) { | 637 if (constant === null) { |
| 638 compiler.internalError("Local variable without value", node: send); | 638 compiler.internalError("Local variable without value", node: send); |
| 639 } | 639 } |
| 640 return constant; | 640 return constant; |
| 641 } | 641 } |
| 642 return super.visitSend(send); | 642 return super.visitSend(send); |
| 643 } | 643 } |
| 644 | 644 |
| 645 void potentiallyCheckType(Node node, Element element, Constant constant) { |
| 646 if (compiler.enableTypeAssertions) { |
| 647 DartType elementType = element.computeType(compiler); |
| 648 DartType constantType = constant.computeType(compiler); |
| 649 // TODO(ngeoffray): Handle type parameters. |
| 650 if (elementType.element.isTypeVariable()) return; |
| 651 if (!constantSystem.isSubtype(compiler, constantType, elementType)) { |
| 652 MessageKind kind = MessageKind.NOT_ASSIGNABLE; |
| 653 compiler.reportError(node, new CompileTimeConstantError( |
| 654 kind, [elementType, constantType])); |
| 655 } |
| 656 } |
| 657 } |
| 658 |
| 659 void updateFieldValue(Node node, Element element, Constant constant) { |
| 660 potentiallyCheckType(node, element, constant); |
| 661 fieldValues[element] = constant; |
| 662 } |
| 663 |
| 645 /** | 664 /** |
| 646 * Given the arguments (a list of constants) assigns them to the parameters, | 665 * Given the arguments (a list of constants) assigns them to the parameters, |
| 647 * updating the definitions map. If the constructor has field-initializer | 666 * updating the definitions map. If the constructor has field-initializer |
| 648 * parameters (like [:this.x:]), also updates the [fieldValues] map. | 667 * parameters (like [:this.x:]), also updates the [fieldValues] map. |
| 649 */ | 668 */ |
| 650 void assignArgumentsToParameters(List<Constant> arguments) { | 669 void assignArgumentsToParameters(List<Constant> arguments) { |
| 651 // Assign arguments to parameters. | 670 // Assign arguments to parameters. |
| 652 FunctionSignature parameters = constructor.computeSignature(compiler); | 671 FunctionSignature parameters = constructor.computeSignature(compiler); |
| 653 int index = 0; | 672 int index = 0; |
| 654 parameters.forEachParameter((Element parameter) { | 673 parameters.forEachParameter((Element parameter) { |
| 655 Constant argument = arguments[index++]; | 674 Constant argument = arguments[index++]; |
| 675 Node node = parameter.parseNode(compiler); |
| 676 potentiallyCheckType(node, parameter, argument); |
| 656 definitions[parameter] = argument; | 677 definitions[parameter] = argument; |
| 657 if (parameter.kind == ElementKind.FIELD_PARAMETER) { | 678 if (parameter.kind == ElementKind.FIELD_PARAMETER) { |
| 658 FieldParameterElement fieldParameterElement = parameter; | 679 FieldParameterElement fieldParameterElement = parameter; |
| 659 fieldValues[fieldParameterElement.fieldElement] = argument; | 680 updateFieldValue(node, fieldParameterElement.fieldElement, argument); |
| 660 } | 681 } |
| 661 }); | 682 }); |
| 662 } | 683 } |
| 663 | 684 |
| 664 void evaluateSuperOrRedirectSend(Selector selector, | 685 void evaluateSuperOrRedirectSend(Selector selector, |
| 665 Link<Node> arguments, | 686 Link<Node> arguments, |
| 666 FunctionElement targetConstructor) { | 687 FunctionElement targetConstructor) { |
| 667 List<Constant> compiledArguments = | 688 List<Constant> compiledArguments = |
| 668 evaluateArgumentsToConstructor(selector, arguments, targetConstructor); | 689 evaluateArgumentsToConstructor(selector, arguments, targetConstructor); |
| 669 | 690 |
| 670 ConstructorEvaluator evaluator = new ConstructorEvaluator( | 691 ConstructorEvaluator evaluator = new ConstructorEvaluator( |
| 671 targetConstructor, constantSystem, compiler); | 692 targetConstructor, constantSystem, compiler); |
| 672 evaluator.evaluateConstructorFieldValues(compiledArguments); | 693 evaluator.evaluateConstructorFieldValues(compiledArguments); |
| 673 // Copy over the fieldValues from the super/redirect-constructor. | 694 // Copy over the fieldValues from the super/redirect-constructor. |
| 695 // No need to go through [updateFieldValue] because the |
| 696 // assignments have already been checked in checked mode. |
| 674 evaluator.fieldValues.forEach((key, value) => fieldValues[key] = value); | 697 evaluator.fieldValues.forEach((key, value) => fieldValues[key] = value); |
| 675 } | 698 } |
| 676 | 699 |
| 677 /** | 700 /** |
| 678 * Runs through the initializers of the given [constructor] and updates | 701 * Runs through the initializers of the given [constructor] and updates |
| 679 * the [fieldValues] map. | 702 * the [fieldValues] map. |
| 680 */ | 703 */ |
| 681 void evaluateConstructorInitializers() { | 704 void evaluateConstructorInitializers() { |
| 682 FunctionExpression functionNode = constructor.parseNode(compiler); | 705 FunctionExpression functionNode = constructor.parseNode(compiler); |
| 683 NodeList initializerList = functionNode.initializers; | 706 NodeList initializerList = functionNode.initializers; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 696 Selector selector = elements.getSelector(call); | 719 Selector selector = elements.getSelector(call); |
| 697 Link<Node> arguments = call.arguments; | 720 Link<Node> arguments = call.arguments; |
| 698 evaluateSuperOrRedirectSend(selector, arguments, targetConstructor); | 721 evaluateSuperOrRedirectSend(selector, arguments, targetConstructor); |
| 699 foundSuperOrRedirect = true; | 722 foundSuperOrRedirect = true; |
| 700 } else { | 723 } else { |
| 701 // A field initializer. | 724 // A field initializer. |
| 702 SendSet init = link.head; | 725 SendSet init = link.head; |
| 703 Link<Node> initArguments = init.arguments; | 726 Link<Node> initArguments = init.arguments; |
| 704 assert(!initArguments.isEmpty() && initArguments.tail.isEmpty()); | 727 assert(!initArguments.isEmpty() && initArguments.tail.isEmpty()); |
| 705 Constant fieldValue = evaluate(initArguments.head); | 728 Constant fieldValue = evaluate(initArguments.head); |
| 706 fieldValues[elements[init]] = fieldValue; | 729 updateFieldValue(init, elements[init], fieldValue); |
| 707 } | 730 } |
| 708 } | 731 } |
| 709 } | 732 } |
| 710 | 733 |
| 711 if (!foundSuperOrRedirect) { | 734 if (!foundSuperOrRedirect) { |
| 712 // No super initializer found. Try to find the default constructor if | 735 // No super initializer found. Try to find the default constructor if |
| 713 // the class is not Object. | 736 // the class is not Object. |
| 714 ClassElement enclosingClass = constructor.getEnclosingClass(); | 737 ClassElement enclosingClass = constructor.getEnclosingClass(); |
| 715 ClassElement superClass = enclosingClass.superclass; | 738 ClassElement superClass = enclosingClass.superclass; |
| 716 if (enclosingClass != compiler.objectClass) { | 739 if (enclosingClass != compiler.objectClass) { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 754 Constant fieldValue = fieldValues[field]; | 777 Constant fieldValue = fieldValues[field]; |
| 755 if (fieldValue === null) { | 778 if (fieldValue === null) { |
| 756 // Use the default value. | 779 // Use the default value. |
| 757 fieldValue = compiler.compileConstant(field); | 780 fieldValue = compiler.compileConstant(field); |
| 758 } | 781 } |
| 759 jsNewArguments.add(fieldValue); | 782 jsNewArguments.add(fieldValue); |
| 760 }); | 783 }); |
| 761 return jsNewArguments; | 784 return jsNewArguments; |
| 762 } | 785 } |
| 763 } | 786 } |
| OLD | NEW |