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 |