| 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 library dart2js.compile_time_constant_evaluator; | 5 library dart2js.compile_time_constant_evaluator; |
| 6 | 6 |
| 7 import 'common.dart'; | 7 import 'common.dart'; |
| 8 import 'common/resolution.dart' show | 8 import 'common/resolution.dart' show |
| 9 Resolution; | 9 Resolution; |
| 10 import 'common/tasks.dart' show | 10 import 'common/tasks.dart' show |
| 11 CompilerTask; | 11 CompilerTask; |
| 12 import 'compiler.dart' show | 12 import 'compiler.dart' show |
| 13 Compiler; | 13 Compiler; |
| 14 import 'constant_system_dart.dart'; | 14 import 'constant_system_dart.dart'; |
| 15 import 'constants/constant_system.dart'; | 15 import 'constants/constant_system.dart'; |
| 16 import 'constants/evaluation.dart'; | 16 import 'constants/evaluation.dart'; |
| 17 import 'constants/expressions.dart'; | 17 import 'constants/expressions.dart'; |
| 18 import 'constants/values.dart'; | 18 import 'constants/values.dart'; |
| 19 import 'core_types.dart' show |
| 20 CoreTypes; |
| 19 import 'dart_types.dart'; | 21 import 'dart_types.dart'; |
| 20 import 'elements/elements.dart'; | 22 import 'elements/elements.dart'; |
| 21 import 'elements/modelx.dart' show | 23 import 'elements/modelx.dart' show |
| 22 FunctionElementX; | 24 FunctionElementX; |
| 23 import 'helpers/helpers.dart'; | |
| 24 import 'resolution/tree_elements.dart' show | 25 import 'resolution/tree_elements.dart' show |
| 25 TreeElements; | 26 TreeElements; |
| 26 import 'resolution/operators.dart'; | 27 import 'resolution/operators.dart'; |
| 27 import 'tree/tree.dart'; | 28 import 'tree/tree.dart'; |
| 28 import 'util/util.dart' show | 29 import 'util/util.dart' show |
| 29 Link; | 30 Link; |
| 30 import 'universe/call_structure.dart' show | 31 import 'universe/call_structure.dart' show |
| 31 CallStructure; | 32 CallStructure; |
| 32 | 33 |
| 33 /// A [ConstantEnvironment] provides access for constants compiled for variable | 34 /// A [ConstantEnvironment] provides access for constants compiled for variable |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 154 /** The set of variable elements that are in the process of being computed. */ | 155 /** The set of variable elements that are in the process of being computed. */ |
| 155 final Set<VariableElement> pendingVariables = new Set<VariableElement>(); | 156 final Set<VariableElement> pendingVariables = new Set<VariableElement>(); |
| 156 | 157 |
| 157 final Map<ConstantExpression, ConstantValue> constantValueMap = | 158 final Map<ConstantExpression, ConstantValue> constantValueMap = |
| 158 <ConstantExpression, ConstantValue>{}; | 159 <ConstantExpression, ConstantValue>{}; |
| 159 | 160 |
| 160 ConstantCompilerBase(this.compiler, this.constantSystem); | 161 ConstantCompilerBase(this.compiler, this.constantSystem); |
| 161 | 162 |
| 162 DiagnosticReporter get reporter => compiler.reporter; | 163 DiagnosticReporter get reporter => compiler.reporter; |
| 163 | 164 |
| 165 CoreTypes get coreTypes => compiler.coreTypes; |
| 166 |
| 164 @override | 167 @override |
| 165 ConstantValue getConstantValueForVariable(VariableElement element) { | 168 ConstantValue getConstantValueForVariable(VariableElement element) { |
| 166 return getConstantValue(initialVariableValues[element.declaration]); | 169 return getConstantValue(initialVariableValues[element.declaration]); |
| 167 } | 170 } |
| 168 | 171 |
| 169 @override | 172 @override |
| 170 ConstantExpression getConstantForVariable(VariableElement element) { | 173 ConstantExpression getConstantForVariable(VariableElement element) { |
| 171 return initialVariableValues[element.declaration]; | 174 return initialVariableValues[element.declaration]; |
| 172 } | 175 } |
| 173 | 176 |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 249 if (elementType.isMalformed && !value.isNull) { | 252 if (elementType.isMalformed && !value.isNull) { |
| 250 if (isConst) { | 253 if (isConst) { |
| 251 ErroneousElement element = elementType.element; | 254 ErroneousElement element = elementType.element; |
| 252 reporter.reportErrorMessage( | 255 reporter.reportErrorMessage( |
| 253 node, element.messageKind, element.messageArguments); | 256 node, element.messageKind, element.messageArguments); |
| 254 } else { | 257 } else { |
| 255 // We need to throw an exception at runtime. | 258 // We need to throw an exception at runtime. |
| 256 expression = null; | 259 expression = null; |
| 257 } | 260 } |
| 258 } else { | 261 } else { |
| 259 DartType constantType = value.getType(compiler.coreTypes); | 262 DartType constantType = value.getType(coreTypes); |
| 260 if (!constantSystem.isSubtype( | 263 if (!constantSystem.isSubtype( |
| 261 compiler.types, constantType, elementType)) { | 264 compiler.types, constantType, elementType)) { |
| 262 if (isConst) { | 265 if (isConst) { |
| 263 reporter.reportErrorMessage( | 266 reporter.reportErrorMessage( |
| 264 node, | 267 node, |
| 265 MessageKind.NOT_ASSIGNABLE, | 268 MessageKind.NOT_ASSIGNABLE, |
| 266 {'fromType': constantType, | 269 {'fromType': constantType, |
| 267 'toType': elementType}); | 270 'toType': elementType}); |
| 268 } else { | 271 } else { |
| 269 // If the field cannot be lazily initialized, we will throw | 272 // If the field cannot be lazily initialized, we will throw |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 360 final Compiler compiler; | 363 final Compiler compiler; |
| 361 | 364 |
| 362 Element get context => elements.analyzedElement; | 365 Element get context => elements.analyzedElement; |
| 363 | 366 |
| 364 CompileTimeConstantEvaluator(this.handler, this.elements, this.compiler, | 367 CompileTimeConstantEvaluator(this.handler, this.elements, this.compiler, |
| 365 {bool isConst: false}) | 368 {bool isConst: false}) |
| 366 : this.isEvaluatingConstant = isConst; | 369 : this.isEvaluatingConstant = isConst; |
| 367 | 370 |
| 368 ConstantSystem get constantSystem => handler.constantSystem; | 371 ConstantSystem get constantSystem => handler.constantSystem; |
| 369 Resolution get resolution => compiler.resolution; | 372 Resolution get resolution => compiler.resolution; |
| 370 | 373 CoreTypes get coreTypes => compiler.coreTypes; |
| 371 DiagnosticReporter get reporter => compiler.reporter; | 374 DiagnosticReporter get reporter => compiler.reporter; |
| 372 | 375 |
| 373 AstConstant evaluate(Node node) { | 376 AstConstant evaluate(Node node) { |
| 374 // TODO(johnniwinther): should there be a visitErrorNode? | 377 // TODO(johnniwinther): should there be a visitErrorNode? |
| 375 if (node is ErrorNode) return new ErroneousAstConstant(context, node); | 378 if (node is ErrorNode) return new ErroneousAstConstant(context, node); |
| 376 return node.accept(this); | 379 return node.accept(this); |
| 377 } | 380 } |
| 378 | 381 |
| 379 AstConstant evaluateConstant(Node node) { | 382 AstConstant evaluateConstant(Node node) { |
| 380 bool oldIsEvaluatingConstant = isEvaluatingConstant; | 383 bool oldIsEvaluatingConstant = isEvaluatingConstant; |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 525 accumulator = | 528 accumulator = |
| 526 new DartString.concat(accumulator, partStringValue.primitiveValue); | 529 new DartString.concat(accumulator, partStringValue.primitiveValue); |
| 527 } | 530 } |
| 528 ; | 531 ; |
| 529 return new AstConstant(context, node, | 532 return new AstConstant(context, node, |
| 530 new ConcatenateConstantExpression(subexpressions), | 533 new ConcatenateConstantExpression(subexpressions), |
| 531 constantSystem.createString(accumulator)); | 534 constantSystem.createString(accumulator)); |
| 532 } | 535 } |
| 533 | 536 |
| 534 AstConstant visitLiteralSymbol(LiteralSymbol node) { | 537 AstConstant visitLiteralSymbol(LiteralSymbol node) { |
| 535 InterfaceType type = compiler.symbolClass.rawType; | 538 InterfaceType type = coreTypes.symbolType; |
| 536 String text = node.slowNameString; | 539 String text = node.slowNameString; |
| 537 List<AstConstant> arguments = <AstConstant>[ | 540 List<AstConstant> arguments = <AstConstant>[ |
| 538 new AstConstant(context, node, new StringConstantExpression(text), | 541 new AstConstant(context, node, new StringConstantExpression(text), |
| 539 constantSystem.createString(new LiteralDartString(text))) | 542 constantSystem.createString(new LiteralDartString(text))) |
| 540 ]; | 543 ]; |
| 541 ConstructorElement constructor = compiler.symbolConstructor; | 544 ConstructorElement constructor = compiler.symbolConstructor; |
| 542 AstConstant constant = createConstructorInvocation( | 545 AstConstant constant = createConstructorInvocation( |
| 543 node, type, constructor, CallStructure.ONE_ARG, | 546 node, type, constructor, CallStructure.ONE_ARG, |
| 544 normalizedArguments: arguments); | 547 normalizedArguments: arguments); |
| 545 return new AstConstant( | 548 return new AstConstant( |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 717 left.expression, operator, right.expression), folded); | 720 left.expression, operator, right.expression), folded); |
| 718 } | 721 } |
| 719 return signalNotCompileTimeConstant(send); | 722 return signalNotCompileTimeConstant(send); |
| 720 } | 723 } |
| 721 | 724 |
| 722 AstConstant visitConditional(Conditional node) { | 725 AstConstant visitConditional(Conditional node) { |
| 723 AstConstant condition = evaluate(node.condition); | 726 AstConstant condition = evaluate(node.condition); |
| 724 if (condition == null) { | 727 if (condition == null) { |
| 725 return null; | 728 return null; |
| 726 } else if (!condition.value.isBool) { | 729 } else if (!condition.value.isBool) { |
| 727 DartType conditionType = condition.value.getType(compiler.coreTypes); | 730 DartType conditionType = condition.value.getType(coreTypes); |
| 728 if (isEvaluatingConstant) { | 731 if (isEvaluatingConstant) { |
| 729 reporter.reportErrorMessage( | 732 reporter.reportErrorMessage( |
| 730 node.condition, | 733 node.condition, |
| 731 MessageKind.NOT_ASSIGNABLE, | 734 MessageKind.NOT_ASSIGNABLE, |
| 732 {'fromType': conditionType, | 735 {'fromType': conditionType, |
| 733 'toType': compiler.boolClass.rawType}); | 736 'toType': coreTypes.boolType}); |
| 734 return new ErroneousAstConstant(context, node); | 737 return new ErroneousAstConstant(context, node); |
| 735 } | 738 } |
| 736 return null; | 739 return null; |
| 737 } | 740 } |
| 738 AstConstant thenExpression = evaluate(node.thenExpression); | 741 AstConstant thenExpression = evaluate(node.thenExpression); |
| 739 AstConstant elseExpression = evaluate(node.elseExpression); | 742 AstConstant elseExpression = evaluate(node.elseExpression); |
| 740 if (thenExpression == null || elseExpression == null) { | 743 if (thenExpression == null || elseExpression == null) { |
| 741 return null; | 744 return null; |
| 742 } | 745 } |
| 743 BoolConstantValue boolCondition = condition.value; | 746 BoolConstantValue boolCondition = condition.value; |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 878 var firstArgument = normalizedArguments[0].value; | 881 var firstArgument = normalizedArguments[0].value; |
| 879 ConstantValue defaultValue = normalizedArguments[1].value; | 882 ConstantValue defaultValue = normalizedArguments[1].value; |
| 880 | 883 |
| 881 if (firstArgument.isNull) { | 884 if (firstArgument.isNull) { |
| 882 reporter.reportErrorMessage( | 885 reporter.reportErrorMessage( |
| 883 normalizedArguments[0].node, MessageKind.NULL_NOT_ALLOWED); | 886 normalizedArguments[0].node, MessageKind.NULL_NOT_ALLOWED); |
| 884 return null; | 887 return null; |
| 885 } | 888 } |
| 886 | 889 |
| 887 if (!firstArgument.isString) { | 890 if (!firstArgument.isString) { |
| 888 DartType type = defaultValue.getType(compiler.coreTypes); | 891 DartType type = defaultValue.getType(coreTypes); |
| 889 reporter.reportErrorMessage( | 892 reporter.reportErrorMessage( |
| 890 normalizedArguments[0].node, | 893 normalizedArguments[0].node, |
| 891 MessageKind.NOT_ASSIGNABLE, | 894 MessageKind.NOT_ASSIGNABLE, |
| 892 {'fromType': type, | 895 {'fromType': type, |
| 893 'toType': compiler.stringClass.rawType}); | 896 'toType': coreTypes.stringType}); |
| 894 return null; | 897 return null; |
| 895 } | 898 } |
| 896 | 899 |
| 897 if (constructor == compiler.intEnvironment && | 900 if (constructor == compiler.intEnvironment && |
| 898 !(defaultValue.isNull || defaultValue.isInt)) { | 901 !(defaultValue.isNull || defaultValue.isInt)) { |
| 899 DartType type = defaultValue.getType(compiler.coreTypes); | 902 DartType type = defaultValue.getType(coreTypes); |
| 900 reporter.reportErrorMessage( | 903 reporter.reportErrorMessage( |
| 901 normalizedArguments[1].node, | 904 normalizedArguments[1].node, |
| 902 MessageKind.NOT_ASSIGNABLE, | 905 MessageKind.NOT_ASSIGNABLE, |
| 903 {'fromType': type, | 906 {'fromType': type, |
| 904 'toType': compiler.intClass.rawType}); | 907 'toType': coreTypes.intType}); |
| 905 return null; | 908 return null; |
| 906 } | 909 } |
| 907 | 910 |
| 908 if (constructor == compiler.boolEnvironment && | 911 if (constructor == compiler.boolEnvironment && |
| 909 !(defaultValue.isNull || defaultValue.isBool)) { | 912 !(defaultValue.isNull || defaultValue.isBool)) { |
| 910 DartType type = defaultValue.getType(compiler.coreTypes); | 913 DartType type = defaultValue.getType(coreTypes); |
| 911 reporter.reportErrorMessage( | 914 reporter.reportErrorMessage( |
| 912 normalizedArguments[1].node, | 915 normalizedArguments[1].node, |
| 913 MessageKind.NOT_ASSIGNABLE, | 916 MessageKind.NOT_ASSIGNABLE, |
| 914 {'fromType': type, | 917 {'fromType': type, |
| 915 'toType': compiler.boolClass.rawType}); | 918 'toType': coreTypes.boolType}); |
| 916 return null; | 919 return null; |
| 917 } | 920 } |
| 918 | 921 |
| 919 if (constructor == compiler.stringEnvironment && | 922 if (constructor == compiler.stringEnvironment && |
| 920 !(defaultValue.isNull || defaultValue.isString)) { | 923 !(defaultValue.isNull || defaultValue.isString)) { |
| 921 DartType type = defaultValue.getType(compiler.coreTypes); | 924 DartType type = defaultValue.getType(coreTypes); |
| 922 reporter.reportErrorMessage( | 925 reporter.reportErrorMessage( |
| 923 normalizedArguments[1].node, | 926 normalizedArguments[1].node, |
| 924 MessageKind.NOT_ASSIGNABLE, | 927 MessageKind.NOT_ASSIGNABLE, |
| 925 {'fromType': type, | 928 {'fromType': type, |
| 926 'toType': compiler.stringClass.rawType}); | 929 'toType': coreTypes.stringType}); |
| 927 return null; | 930 return null; |
| 928 } | 931 } |
| 929 | 932 |
| 930 String name = firstArgument.primitiveValue.slowToString(); | 933 String name = firstArgument.primitiveValue.slowToString(); |
| 931 String value = compiler.fromEnvironment(name); | 934 String value = compiler.fromEnvironment(name); |
| 932 | 935 |
| 933 AstConstant createEvaluatedConstant(ConstantValue value) { | 936 AstConstant createEvaluatedConstant(ConstantValue value) { |
| 934 ConstantExpression expression; | 937 ConstantExpression expression; |
| 935 ConstantExpression name = concreteArguments[0].expression; | 938 ConstantExpression name = concreteArguments[0].expression; |
| 936 ConstantExpression defaultValue; | 939 ConstantExpression defaultValue; |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1057 reporter.internalError(send, "Local variable without value."); | 1060 reporter.internalError(send, "Local variable without value."); |
| 1058 } | 1061 } |
| 1059 return constant; | 1062 return constant; |
| 1060 } | 1063 } |
| 1061 return super.visitSend(send); | 1064 return super.visitSend(send); |
| 1062 } | 1065 } |
| 1063 | 1066 |
| 1064 void potentiallyCheckType(TypedElement element, AstConstant constant) { | 1067 void potentiallyCheckType(TypedElement element, AstConstant constant) { |
| 1065 if (compiler.enableTypeAssertions) { | 1068 if (compiler.enableTypeAssertions) { |
| 1066 DartType elementType = element.type.substByContext(constructedType); | 1069 DartType elementType = element.type.substByContext(constructedType); |
| 1067 DartType constantType = constant.value.getType(compiler.coreTypes); | 1070 DartType constantType = constant.value.getType(coreTypes); |
| 1068 if (!constantSystem.isSubtype( | 1071 if (!constantSystem.isSubtype( |
| 1069 compiler.types, constantType, elementType)) { | 1072 compiler.types, constantType, elementType)) { |
| 1070 reporter.withCurrentElement(constant.element, () { | 1073 reporter.withCurrentElement(constant.element, () { |
| 1071 reporter.reportErrorMessage( | 1074 reporter.reportErrorMessage( |
| 1072 constant.node, | 1075 constant.node, |
| 1073 MessageKind.NOT_ASSIGNABLE, | 1076 MessageKind.NOT_ASSIGNABLE, |
| 1074 {'fromType': constantType, | 1077 {'fromType': constantType, |
| 1075 'toType': elementType}); | 1078 'toType': elementType}); |
| 1076 }); | 1079 }); |
| 1077 } | 1080 } |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1162 updateFieldValue(init, elements[init], fieldValue); | 1165 updateFieldValue(init, elements[init], fieldValue); |
| 1163 } | 1166 } |
| 1164 } | 1167 } |
| 1165 } | 1168 } |
| 1166 | 1169 |
| 1167 if (!foundSuperOrRedirect) { | 1170 if (!foundSuperOrRedirect) { |
| 1168 // No super initializer found. Try to find the default constructor if | 1171 // No super initializer found. Try to find the default constructor if |
| 1169 // the class is not Object. | 1172 // the class is not Object. |
| 1170 ClassElement enclosingClass = constructor.enclosingClass; | 1173 ClassElement enclosingClass = constructor.enclosingClass; |
| 1171 ClassElement superClass = enclosingClass.superclass; | 1174 ClassElement superClass = enclosingClass.superclass; |
| 1172 if (enclosingClass != compiler.objectClass) { | 1175 if (!enclosingClass.isObject) { |
| 1173 assert(superClass != null); | 1176 assert(superClass != null); |
| 1174 assert(superClass.isResolved); | 1177 assert(superClass.isResolved); |
| 1175 | 1178 |
| 1176 FunctionElement targetConstructor = | 1179 FunctionElement targetConstructor = |
| 1177 superClass.lookupDefaultConstructor(); | 1180 superClass.lookupDefaultConstructor(); |
| 1178 // If we do not find a default constructor, an error was reported | 1181 // If we do not find a default constructor, an error was reported |
| 1179 // already and compilation will fail anyway. So just ignore that case. | 1182 // already and compilation will fail anyway. So just ignore that case. |
| 1180 if (targetConstructor != null) { | 1183 if (targetConstructor != null) { |
| 1181 List<AstConstant> compiledArguments = evaluateArgumentsToConstructor( | 1184 List<AstConstant> compiledArguments = evaluateArgumentsToConstructor( |
| 1182 functionNode, CallStructure.NO_ARGS, const Link<Node>(), | 1185 functionNode, CallStructure.NO_ARGS, const Link<Node>(), |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1269 class _CompilerEnvironment implements Environment { | 1272 class _CompilerEnvironment implements Environment { |
| 1270 final Compiler compiler; | 1273 final Compiler compiler; |
| 1271 | 1274 |
| 1272 _CompilerEnvironment(this.compiler); | 1275 _CompilerEnvironment(this.compiler); |
| 1273 | 1276 |
| 1274 @override | 1277 @override |
| 1275 String readFromEnvironment(String name) { | 1278 String readFromEnvironment(String name) { |
| 1276 return compiler.fromEnvironment(name); | 1279 return compiler.fromEnvironment(name); |
| 1277 } | 1280 } |
| 1278 } | 1281 } |
| OLD | NEW |