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 703 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
714 compiler.resolver.resolveRedirectionChain(constructor, node); | 714 compiler.resolver.resolveRedirectionChain(constructor, node); |
715 InterfaceType constructedType = constructor.computeTargetType(type); | 715 InterfaceType constructedType = constructor.computeTargetType(type); |
716 constructor = constructor.redirectionTarget; | 716 constructor = constructor.redirectionTarget; |
717 ClassElement classElement = constructor.getEnclosingClass(); | 717 ClassElement classElement = constructor.getEnclosingClass(); |
718 // The constructor must be an implementation to ensure that field | 718 // The constructor must be an implementation to ensure that field |
719 // initializers are handled correctly. | 719 // initializers are handled correctly. |
720 constructor = constructor.implementation; | 720 constructor = constructor.implementation; |
721 assert(invariant(node, constructor.isImplementation)); | 721 assert(invariant(node, constructor.isImplementation)); |
722 | 722 |
723 List<Constant> arguments = getArguments(constructor); | 723 List<Constant> arguments = getArguments(constructor); |
724 ConstructorEvaluator evaluator = | 724 ConstructorEvaluator evaluator = new ConstructorEvaluator( |
725 new ConstructorEvaluator(constructor, handler, compiler); | 725 constructedType, constructor, handler, compiler); |
726 evaluator.evaluateConstructorFieldValues(arguments); | 726 evaluator.evaluateConstructorFieldValues(arguments); |
727 List<Constant> jsNewArguments = evaluator.buildJsNewArguments(classElement); | 727 List<Constant> jsNewArguments = evaluator.buildJsNewArguments(classElement); |
728 | 728 |
729 return new ConstructedConstant(constructedType, jsNewArguments); | 729 return new ConstructedConstant(constructedType, jsNewArguments); |
730 } | 730 } |
731 | 731 |
732 Constant visitParenthesizedExpression(ParenthesizedExpression node) { | 732 Constant visitParenthesizedExpression(ParenthesizedExpression node) { |
733 return node.expression.accept(this); | 733 return node.expression.accept(this); |
734 } | 734 } |
735 | 735 |
(...skipping 25 matching lines...) Expand all Loading... | |
761 | 761 |
762 error(Node node) { | 762 error(Node node) { |
763 // Just fail without reporting it anywhere. | 763 // Just fail without reporting it anywhere. |
764 throw new CompileTimeConstantError( | 764 throw new CompileTimeConstantError( |
765 MessageKind.NOT_A_COMPILE_TIME_CONSTANT, const {}, | 765 MessageKind.NOT_A_COMPILE_TIME_CONSTANT, const {}, |
766 compiler.terseDiagnostics); | 766 compiler.terseDiagnostics); |
767 } | 767 } |
768 } | 768 } |
769 | 769 |
770 class ConstructorEvaluator extends CompileTimeConstantEvaluator { | 770 class ConstructorEvaluator extends CompileTimeConstantEvaluator { |
771 final InterfaceType constructedType; | |
771 final FunctionElement constructor; | 772 final FunctionElement constructor; |
772 final Map<Element, Constant> definitions; | 773 final Map<Element, Constant> definitions; |
773 final Map<Element, Constant> fieldValues; | 774 final Map<Element, Constant> fieldValues; |
774 | 775 |
775 /** | 776 /** |
776 * Documentation wanted -- johnniwinther | 777 * Documentation wanted -- johnniwinther |
777 * | 778 * |
778 * Invariant: [constructor] must be an implementation element. | 779 * Invariant: [constructor] must be an implementation element. |
779 */ | 780 */ |
780 ConstructorEvaluator(FunctionElement constructor, | 781 ConstructorEvaluator(InterfaceType this.constructedType, |
782 FunctionElement constructor, | |
781 ConstantHandler handler, | 783 ConstantHandler handler, |
782 Compiler compiler) | 784 Compiler compiler) |
783 : this.constructor = constructor, | 785 : this.constructor = constructor, |
784 this.definitions = new Map<Element, Constant>(), | 786 this.definitions = new Map<Element, Constant>(), |
785 this.fieldValues = new Map<Element, Constant>(), | 787 this.fieldValues = new Map<Element, Constant>(), |
786 super(handler, | 788 super(handler, |
787 compiler.resolver.resolveMethodElement(constructor.declaration), | 789 compiler.resolver.resolveMethodElement(constructor.declaration), |
788 compiler, | 790 compiler, |
789 isConst: true) { | 791 isConst: true) { |
790 assert(invariant(constructor, constructor.isImplementation)); | 792 assert(invariant(constructor, constructor.isImplementation)); |
791 } | 793 } |
792 | 794 |
793 Constant visitSend(Send send) { | 795 Constant visitSend(Send send) { |
794 Element element = elements[send]; | 796 Element element = elements[send]; |
795 if (Elements.isLocal(element)) { | 797 if (Elements.isLocal(element)) { |
796 Constant constant = definitions[element]; | 798 Constant constant = definitions[element]; |
797 if (constant == null) { | 799 if (constant == null) { |
798 compiler.internalError("Local variable without value", node: send); | 800 compiler.internalError("Local variable without value", node: send); |
799 } | 801 } |
800 return constant; | 802 return constant; |
801 } | 803 } |
802 return super.visitSend(send); | 804 return super.visitSend(send); |
803 } | 805 } |
804 | 806 |
805 void potentiallyCheckType(Node node, Element element, Constant constant) { | 807 void potentiallyCheckType(Node node, |
karlklose
2014/01/29 10:44:23
'elementType' -> 'type'?
I think the name of the
Johnni Winther
2014/01/30 08:25:23
Done.
| |
808 DartType elementType, | |
809 Constant constant) { | |
806 if (compiler.enableTypeAssertions) { | 810 if (compiler.enableTypeAssertions) { |
807 DartType elementType = element.computeType(compiler); | |
808 DartType constantType = constant.computeType(compiler); | 811 DartType constantType = constant.computeType(compiler); |
809 // TODO(ngeoffray): Handle type parameters. | 812 if (!compiler.types.isSubtype(constantType, elementType)) { |
810 if (elementType.element.isTypeVariable()) return; | |
811 if (!constantSystem.isSubtype(compiler, constantType, elementType)) { | |
812 compiler.reportFatalError( | 813 compiler.reportFatalError( |
813 node, MessageKind.NOT_ASSIGNABLE.error, | 814 node, MessageKind.NOT_ASSIGNABLE.error, |
814 {'fromType': elementType, 'toType': constantType}); | 815 {'fromType': constantType, 'toType': elementType}); |
815 } | 816 } |
816 } | 817 } |
817 } | 818 } |
818 | 819 |
819 void updateFieldValue(Node node, Element element, Constant constant) { | 820 void updateFieldValue(Node node, |
karlklose
2014/01/29 10:44:23
Still fits on one line.
Johnni Winther
2014/01/30 08:25:23
Done.
| |
820 potentiallyCheckType(node, element, constant); | 821 Element element, |
822 Constant constant) { | |
823 DartType elementType = | |
824 element.computeType(compiler).substByContext(constructedType); | |
825 potentiallyCheckType(node, elementType, constant); | |
821 fieldValues[element] = constant; | 826 fieldValues[element] = constant; |
822 } | 827 } |
823 | 828 |
824 /** | 829 /** |
825 * Given the arguments (a list of constants) assigns them to the parameters, | 830 * Given the arguments (a list of constants) assigns them to the parameters, |
826 * updating the definitions map. If the constructor has field-initializer | 831 * updating the definitions map. If the constructor has field-initializer |
827 * parameters (like [:this.x:]), also updates the [fieldValues] map. | 832 * parameters (like [:this.x:]), also updates the [fieldValues] map. |
828 */ | 833 */ |
829 void assignArgumentsToParameters(List<Constant> arguments) { | 834 void assignArgumentsToParameters(List<Constant> arguments) { |
830 // Assign arguments to parameters. | 835 // Assign arguments to parameters. |
831 FunctionSignature parameters = constructor.computeSignature(compiler); | 836 FunctionSignature signature = constructor.computeSignature(compiler); |
832 int index = 0; | 837 int index = 0; |
833 parameters.orderedForEachParameter((Element parameter) { | 838 signature.orderedForEachParameter((Element parameter) { |
839 DartType parameterType = | |
840 parameter.computeType(compiler).substByContext(constructedType); | |
834 Constant argument = arguments[index++]; | 841 Constant argument = arguments[index++]; |
835 Node node = parameter.parseNode(compiler); | 842 Node node = parameter.parseNode(compiler); |
836 potentiallyCheckType(node, parameter, argument); | 843 potentiallyCheckType(node, parameterType, argument); |
837 definitions[parameter] = argument; | 844 definitions[parameter] = argument; |
838 if (parameter.kind == ElementKind.FIELD_PARAMETER) { | 845 if (parameter.kind == ElementKind.FIELD_PARAMETER) { |
839 FieldParameterElement fieldParameterElement = parameter; | 846 FieldParameterElement fieldParameterElement = parameter; |
840 updateFieldValue(node, fieldParameterElement.fieldElement, argument); | 847 updateFieldValue(node, fieldParameterElement.fieldElement, argument); |
841 } | 848 } |
842 }); | 849 }); |
843 } | 850 } |
844 | 851 |
845 void evaluateSuperOrRedirectSend(List<Constant> compiledArguments, | 852 void evaluateSuperOrRedirectSend(List<Constant> compiledArguments, |
846 FunctionElement targetConstructor) { | 853 FunctionElement targetConstructor) { |
847 ConstructorEvaluator evaluator = new ConstructorEvaluator( | 854 ConstructorEvaluator evaluator = new ConstructorEvaluator( |
855 constructedType.asInstanceOf(targetConstructor.getEnclosingClass()), | |
848 targetConstructor, handler, compiler); | 856 targetConstructor, handler, compiler); |
849 evaluator.evaluateConstructorFieldValues(compiledArguments); | 857 evaluator.evaluateConstructorFieldValues(compiledArguments); |
850 // Copy over the fieldValues from the super/redirect-constructor. | 858 // Copy over the fieldValues from the super/redirect-constructor. |
851 // No need to go through [updateFieldValue] because the | 859 // No need to go through [updateFieldValue] because the |
852 // assignments have already been checked in checked mode. | 860 // assignments have already been checked in checked mode. |
853 evaluator.fieldValues.forEach((key, value) => fieldValues[key] = value); | 861 evaluator.fieldValues.forEach((key, value) => fieldValues[key] = value); |
854 } | 862 } |
855 | 863 |
856 /** | 864 /** |
857 * Runs through the initializers of the given [constructor] and updates | 865 * Runs through the initializers of the given [constructor] and updates |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
947 if (fieldValue == null) { | 955 if (fieldValue == null) { |
948 // Use the default value. | 956 // Use the default value. |
949 fieldValue = handler.compileConstant(field); | 957 fieldValue = handler.compileConstant(field); |
950 } | 958 } |
951 jsNewArguments.add(fieldValue); | 959 jsNewArguments.add(fieldValue); |
952 }, | 960 }, |
953 includeSuperAndInjectedMembers: true); | 961 includeSuperAndInjectedMembers: true); |
954 return jsNewArguments; | 962 return jsNewArguments; |
955 } | 963 } |
956 } | 964 } |
OLD | NEW |