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