| 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 /// A [ConstantEnvironment] provides access for constants compiled for variable | 7 /// A [ConstantEnvironment] provides access for constants compiled for variable |
| 8 /// initializers. | 8 /// initializers. |
| 9 abstract class ConstantEnvironment { | 9 abstract class ConstantEnvironment { |
| 10 /// Returns the constant for the initializer of [element]. | 10 /// Returns the constant for the initializer of [element]. |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 126 * eagerly. If the variable needs to be initialized lazily returns `null`. | 126 * eagerly. If the variable needs to be initialized lazily returns `null`. |
| 127 * If the variable is `const` but cannot be compiled eagerly reports an | 127 * If the variable is `const` but cannot be compiled eagerly reports an |
| 128 * error. | 128 * error. |
| 129 */ | 129 */ |
| 130 ConstantExpression compileVariableWithDefinitions(VariableElement element, | 130 ConstantExpression compileVariableWithDefinitions(VariableElement element, |
| 131 TreeElements definitions, | 131 TreeElements definitions, |
| 132 {bool isConst: false}) { | 132 {bool isConst: false}) { |
| 133 Node node = element.node; | 133 Node node = element.node; |
| 134 if (pendingVariables.contains(element)) { | 134 if (pendingVariables.contains(element)) { |
| 135 if (isConst) { | 135 if (isConst) { |
| 136 compiler.reportFatalError( | 136 compiler.reportError( |
| 137 node, MessageKind.CYCLIC_COMPILE_TIME_CONSTANTS); | 137 node, MessageKind.CYCLIC_COMPILE_TIME_CONSTANTS); |
| 138 // TODO(ahe): Don't throw, recover from error. |
| 139 throw new CompilerCancelledException(null); |
| 138 } | 140 } |
| 139 return null; | 141 return null; |
| 140 } | 142 } |
| 141 pendingVariables.add(element); | 143 pendingVariables.add(element); |
| 142 | 144 |
| 143 Expression initializer = element.initializer; | 145 Expression initializer = element.initializer; |
| 144 ConstantExpression value; | 146 ConstantExpression value; |
| 145 if (initializer == null) { | 147 if (initializer == null) { |
| 146 // No initial value. | 148 // No initial value. |
| 147 value = new PrimitiveConstantExpression(new NullConstantValue()); | 149 value = new PrimitiveConstantExpression(new NullConstantValue()); |
| 148 } else { | 150 } else { |
| 149 value = compileNodeWithDefinitions( | 151 value = compileNodeWithDefinitions( |
| 150 initializer, definitions, isConst: isConst); | 152 initializer, definitions, isConst: isConst); |
| 151 if (compiler.enableTypeAssertions && | 153 if (compiler.enableTypeAssertions && |
| 152 value != null && | 154 value != null && |
| 153 element.isField) { | 155 element.isField) { |
| 154 DartType elementType = element.type; | 156 DartType elementType = element.type; |
| 155 if (elementType.isMalformed && !value.value.isNull) { | 157 if (elementType.isMalformed && !value.value.isNull) { |
| 156 if (isConst) { | 158 if (isConst) { |
| 157 ErroneousElement element = elementType.element; | 159 ErroneousElement element = elementType.element; |
| 158 compiler.reportFatalError( | 160 compiler.reportError( |
| 159 node, element.messageKind, element.messageArguments); | 161 node, element.messageKind, element.messageArguments); |
| 160 } else { | 162 } else { |
| 161 // We need to throw an exception at runtime. | 163 // We need to throw an exception at runtime. |
| 162 value = null; | 164 value = null; |
| 163 } | 165 } |
| 164 } else { | 166 } else { |
| 165 DartType constantType = value.value.getType(compiler.coreTypes); | 167 DartType constantType = value.value.getType(compiler.coreTypes); |
| 166 if (!constantSystem.isSubtype(compiler.types, | 168 if (!constantSystem.isSubtype(compiler.types, |
| 167 constantType, elementType)) { | 169 constantType, elementType)) { |
| 168 if (isConst) { | 170 if (isConst) { |
| 169 compiler.reportFatalError( | 171 compiler.reportError( |
| 170 node, MessageKind.NOT_ASSIGNABLE, | 172 node, MessageKind.NOT_ASSIGNABLE, |
| 171 {'fromType': constantType, 'toType': elementType}); | 173 {'fromType': constantType, 'toType': elementType}); |
| 172 } else { | 174 } else { |
| 173 // If the field cannot be lazily initialized, we will throw | 175 // If the field cannot be lazily initialized, we will throw |
| 174 // the exception at runtime. | 176 // the exception at runtime. |
| 175 value = null; | 177 value = null; |
| 176 } | 178 } |
| 177 } | 179 } |
| 178 } | 180 } |
| 179 } | 181 } |
| (...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 598 return signalNotCompileTimeConstant(send); | 600 return signalNotCompileTimeConstant(send); |
| 599 } | 601 } |
| 600 | 602 |
| 601 AstConstant visitConditional(Conditional node) { | 603 AstConstant visitConditional(Conditional node) { |
| 602 AstConstant condition = evaluate(node.condition); | 604 AstConstant condition = evaluate(node.condition); |
| 603 if (condition == null) { | 605 if (condition == null) { |
| 604 return null; | 606 return null; |
| 605 } else if (!condition.value.isBool) { | 607 } else if (!condition.value.isBool) { |
| 606 DartType conditionType = condition.value.getType(compiler.coreTypes); | 608 DartType conditionType = condition.value.getType(compiler.coreTypes); |
| 607 if (isEvaluatingConstant) { | 609 if (isEvaluatingConstant) { |
| 608 compiler.reportFatalError( | 610 compiler.reportError( |
| 609 node.condition, MessageKind.NOT_ASSIGNABLE, | 611 node.condition, MessageKind.NOT_ASSIGNABLE, |
| 610 {'fromType': conditionType, 'toType': compiler.boolClass.rawType}); | 612 {'fromType': conditionType, 'toType': compiler.boolClass.rawType}); |
| 611 } | 613 } |
| 612 return null; | 614 return null; |
| 613 } | 615 } |
| 614 AstConstant thenExpression = evaluate(node.thenExpression); | 616 AstConstant thenExpression = evaluate(node.thenExpression); |
| 615 AstConstant elseExpression = evaluate(node.elseExpression); | 617 AstConstant elseExpression = evaluate(node.elseExpression); |
| 616 if (thenExpression == null || elseExpression == null) { | 618 if (thenExpression == null || elseExpression == null) { |
| 617 return null; | 619 return null; |
| 618 } | 620 } |
| (...skipping 29 matching lines...) Expand all Loading... |
| 648 | 650 |
| 649 AstConstant compileDefaultValue(VariableElement element) { | 651 AstConstant compileDefaultValue(VariableElement element) { |
| 650 ConstantExpression constant = handler.compileConstant(element); | 652 ConstantExpression constant = handler.compileConstant(element); |
| 651 return new AstConstant.fromDefaultValue(element, constant); | 653 return new AstConstant.fromDefaultValue(element, constant); |
| 652 } | 654 } |
| 653 target.computeSignature(compiler); | 655 target.computeSignature(compiler); |
| 654 | 656 |
| 655 if (!selector.applies(target, compiler.world)) { | 657 if (!selector.applies(target, compiler.world)) { |
| 656 String name = Elements.constructorNameForDiagnostics( | 658 String name = Elements.constructorNameForDiagnostics( |
| 657 target.enclosingClass.name, target.name); | 659 target.enclosingClass.name, target.name); |
| 658 compiler.reportFatalError( | 660 compiler.reportError( |
| 659 node, | 661 node, |
| 660 MessageKind.INVALID_CONSTRUCTOR_ARGUMENTS, | 662 MessageKind.INVALID_CONSTRUCTOR_ARGUMENTS, |
| 661 {'constructorName': name}); | 663 {'constructorName': name}); |
| 664 // TODO(ahe): Don't throw, recover from error. |
| 665 throw new CompilerCancelledException(null); |
| 662 } | 666 } |
| 663 return selector.makeArgumentsList2(arguments, | 667 return selector.makeArgumentsList2(arguments, |
| 664 target, | 668 target, |
| 665 compileArgument, | 669 compileArgument, |
| 666 compileDefaultValue); | 670 compileDefaultValue); |
| 667 } | 671 } |
| 668 | 672 |
| 669 AstConstant visitNewExpression(NewExpression node) { | 673 AstConstant visitNewExpression(NewExpression node) { |
| 670 if (!node.isConst) { | 674 if (!node.isConst) { |
| 671 return signalNotCompileTimeConstant(node); | 675 return signalNotCompileTimeConstant(node); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 721 type, | 725 type, |
| 722 constructor, | 726 constructor, |
| 723 elements.getSelector(send), | 727 elements.getSelector(send), |
| 724 concreteArguments.map((e) => e.expression).toList())); | 728 concreteArguments.map((e) => e.expression).toList())); |
| 725 } | 729 } |
| 726 | 730 |
| 727 var firstArgument = normalizedArguments[0].value; | 731 var firstArgument = normalizedArguments[0].value; |
| 728 ConstantValue defaultValue = normalizedArguments[1].value; | 732 ConstantValue defaultValue = normalizedArguments[1].value; |
| 729 | 733 |
| 730 if (firstArgument.isNull) { | 734 if (firstArgument.isNull) { |
| 731 compiler.reportFatalError( | 735 compiler.reportError( |
| 732 send.arguments.head, MessageKind.NULL_NOT_ALLOWED); | 736 send.arguments.head, MessageKind.NULL_NOT_ALLOWED); |
| 733 return null; | 737 return null; |
| 734 } | 738 } |
| 735 | 739 |
| 736 if (!firstArgument.isString) { | 740 if (!firstArgument.isString) { |
| 737 DartType type = defaultValue.getType(compiler.coreTypes); | 741 DartType type = defaultValue.getType(compiler.coreTypes); |
| 738 compiler.reportFatalError( | 742 compiler.reportError( |
| 739 send.arguments.head, MessageKind.NOT_ASSIGNABLE, | 743 send.arguments.head, MessageKind.NOT_ASSIGNABLE, |
| 740 {'fromType': type, 'toType': compiler.stringClass.rawType}); | 744 {'fromType': type, 'toType': compiler.stringClass.rawType}); |
| 741 return null; | 745 return null; |
| 742 } | 746 } |
| 743 | 747 |
| 744 if (constructor == compiler.intEnvironment && | 748 if (constructor == compiler.intEnvironment && |
| 745 !(defaultValue.isNull || defaultValue.isInt)) { | 749 !(defaultValue.isNull || defaultValue.isInt)) { |
| 746 DartType type = defaultValue.getType(compiler.coreTypes); | 750 DartType type = defaultValue.getType(compiler.coreTypes); |
| 747 compiler.reportFatalError( | 751 compiler.reportError( |
| 748 send.arguments.tail.head, MessageKind.NOT_ASSIGNABLE, | 752 send.arguments.tail.head, MessageKind.NOT_ASSIGNABLE, |
| 749 {'fromType': type, 'toType': compiler.intClass.rawType}); | 753 {'fromType': type, 'toType': compiler.intClass.rawType}); |
| 750 return null; | 754 return null; |
| 751 } | 755 } |
| 752 | 756 |
| 753 if (constructor == compiler.boolEnvironment && | 757 if (constructor == compiler.boolEnvironment && |
| 754 !(defaultValue.isNull || defaultValue.isBool)) { | 758 !(defaultValue.isNull || defaultValue.isBool)) { |
| 755 DartType type = defaultValue.getType(compiler.coreTypes); | 759 DartType type = defaultValue.getType(compiler.coreTypes); |
| 756 compiler.reportFatalError( | 760 compiler.reportError( |
| 757 send.arguments.tail.head, MessageKind.NOT_ASSIGNABLE, | 761 send.arguments.tail.head, MessageKind.NOT_ASSIGNABLE, |
| 758 {'fromType': type, 'toType': compiler.boolClass.rawType}); | 762 {'fromType': type, 'toType': compiler.boolClass.rawType}); |
| 759 return null; | 763 return null; |
| 760 } | 764 } |
| 761 | 765 |
| 762 if (constructor == compiler.stringEnvironment && | 766 if (constructor == compiler.stringEnvironment && |
| 763 !(defaultValue.isNull || defaultValue.isString)) { | 767 !(defaultValue.isNull || defaultValue.isString)) { |
| 764 DartType type = defaultValue.getType(compiler.coreTypes); | 768 DartType type = defaultValue.getType(compiler.coreTypes); |
| 765 compiler.reportFatalError( | 769 compiler.reportError( |
| 766 send.arguments.tail.head, MessageKind.NOT_ASSIGNABLE, | 770 send.arguments.tail.head, MessageKind.NOT_ASSIGNABLE, |
| 767 {'fromType': type, 'toType': compiler.stringClass.rawType}); | 771 {'fromType': type, 'toType': compiler.stringClass.rawType}); |
| 768 return null; | 772 return null; |
| 769 } | 773 } |
| 770 | 774 |
| 771 String value = | 775 String value = |
| 772 compiler.fromEnvironment(firstArgument.primitiveValue.slowToString()); | 776 compiler.fromEnvironment(firstArgument.primitiveValue.slowToString()); |
| 773 | 777 |
| 774 if (value == null) { | 778 if (value == null) { |
| 775 return createEvaluatedConstant(defaultValue); | 779 return createEvaluatedConstant(defaultValue); |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 843 concreteArguments.map((e) => e.expression).toList())); | 847 concreteArguments.map((e) => e.expression).toList())); |
| 844 } | 848 } |
| 845 | 849 |
| 846 AstConstant visitParenthesizedExpression(ParenthesizedExpression node) { | 850 AstConstant visitParenthesizedExpression(ParenthesizedExpression node) { |
| 847 return node.expression.accept(this); | 851 return node.expression.accept(this); |
| 848 } | 852 } |
| 849 | 853 |
| 850 error(Node node, MessageKind message) { | 854 error(Node node, MessageKind message) { |
| 851 // TODO(floitsch): get the list of constants that are currently compiled | 855 // TODO(floitsch): get the list of constants that are currently compiled |
| 852 // and present some kind of stack-trace. | 856 // and present some kind of stack-trace. |
| 853 compiler.reportFatalError(node, message); | 857 compiler.reportError(node, message); |
| 854 } | 858 } |
| 855 | 859 |
| 856 AstConstant signalNotCompileTimeConstant(Node node, | 860 AstConstant signalNotCompileTimeConstant(Node node, |
| 857 {MessageKind message: MessageKind.NOT_A_COMPILE_TIME_CONSTANT}) { | 861 {MessageKind message: MessageKind.NOT_A_COMPILE_TIME_CONSTANT}) { |
| 858 if (isEvaluatingConstant) { | 862 if (isEvaluatingConstant) { |
| 859 error(node, message); | 863 error(node, message); |
| 864 |
| 865 return new AstConstant( |
| 866 null, node, new PrimitiveConstantExpression(new NullConstantValue())); |
| 860 } | 867 } |
| 861 // Else we don't need to do anything. The final handler is only | 868 // Else we don't need to do anything. The final handler is only |
| 862 // optimistically trying to compile constants. So it is normal that we | 869 // optimistically trying to compile constants. So it is normal that we |
| 863 // sometimes see non-compile time constants. | 870 // sometimes see non-compile time constants. |
| 864 // Simply return [:null:] which is used to propagate a failing | 871 // Simply return [:null:] which is used to propagate a failing |
| 865 // compile-time compilation. | 872 // compile-time compilation. |
| 866 return null; | 873 return null; |
| 867 } | 874 } |
| 868 } | 875 } |
| 869 | 876 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 906 | 913 |
| 907 void potentiallyCheckType(Node node, | 914 void potentiallyCheckType(Node node, |
| 908 TypedElement element, | 915 TypedElement element, |
| 909 AstConstant constant) { | 916 AstConstant constant) { |
| 910 if (compiler.enableTypeAssertions) { | 917 if (compiler.enableTypeAssertions) { |
| 911 DartType elementType = element.type.substByContext(constructedType); | 918 DartType elementType = element.type.substByContext(constructedType); |
| 912 DartType constantType = constant.value.getType(compiler.coreTypes); | 919 DartType constantType = constant.value.getType(compiler.coreTypes); |
| 913 if (!constantSystem.isSubtype(compiler.types, | 920 if (!constantSystem.isSubtype(compiler.types, |
| 914 constantType, elementType)) { | 921 constantType, elementType)) { |
| 915 compiler.withCurrentElement(constant.element, () { | 922 compiler.withCurrentElement(constant.element, () { |
| 916 compiler.reportFatalError( | 923 compiler.reportError( |
| 917 constant.node, MessageKind.NOT_ASSIGNABLE, | 924 constant.node, MessageKind.NOT_ASSIGNABLE, |
| 918 {'fromType': constantType, 'toType': elementType}); | 925 {'fromType': constantType, 'toType': elementType}); |
| 919 }); | 926 }); |
| 920 } | 927 } |
| 921 } | 928 } |
| 922 } | 929 } |
| 923 | 930 |
| 924 void updateFieldValue(Node node, | 931 void updateFieldValue(Node node, |
| 925 TypedElement element, | 932 TypedElement element, |
| 926 AstConstant constant) { | 933 AstConstant constant) { |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1092 return new AstConstant( | 1099 return new AstConstant( |
| 1093 element, | 1100 element, |
| 1094 element.initializer != null ? element.initializer : element.node, | 1101 element.initializer != null ? element.initializer : element.node, |
| 1095 constant); | 1102 constant); |
| 1096 } | 1103 } |
| 1097 | 1104 |
| 1098 ConstantValue get value => expression.value; | 1105 ConstantValue get value => expression.value; |
| 1099 | 1106 |
| 1100 String toString() => expression.toString(); | 1107 String toString() => expression.toString(); |
| 1101 } | 1108 } |
| OLD | NEW |