| 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/resolution.dart' show Resolution; | 7 import 'common/resolution.dart' show Resolution; |
| 8 import 'common/tasks.dart' show CompilerTask, Measurer; | 8 import 'common/tasks.dart' show CompilerTask, Measurer; |
| 9 import 'common.dart'; | 9 import 'common.dart'; |
| 10 import 'compiler.dart' show Compiler; | 10 import 'compiler.dart' show Compiler; |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 194 VariableElement element, bool isConst, bool checkType) { | 194 VariableElement element, bool isConst, bool checkType) { |
| 195 if (initialVariableValues.containsKey(element.declaration)) { | 195 if (initialVariableValues.containsKey(element.declaration)) { |
| 196 ConstantExpression result = initialVariableValues[element.declaration]; | 196 ConstantExpression result = initialVariableValues[element.declaration]; |
| 197 return result; | 197 return result; |
| 198 } | 198 } |
| 199 if (element.hasConstant) { | 199 if (element.hasConstant) { |
| 200 if (element.constant != null) { | 200 if (element.constant != null) { |
| 201 if (compiler.serialization.supportsDeserialization) { | 201 if (compiler.serialization.supportsDeserialization) { |
| 202 evaluate(element.constant); | 202 evaluate(element.constant); |
| 203 } | 203 } |
| 204 assert(invariant(element, hasConstantValue(element.constant), | 204 assert( |
| 205 message: "Constant expression has not been evaluated: " | 205 hasConstantValue(element.constant), |
| 206 failedAt( |
| 207 element, |
| 208 "Constant expression has not been evaluated: " |
| 206 "${element.constant.toStructuredText()}.")); | 209 "${element.constant.toStructuredText()}.")); |
| 207 } | 210 } |
| 208 return element.constant; | 211 return element.constant; |
| 209 } | 212 } |
| 210 AstElement currentElement = element.analyzableElement; | 213 AstElement currentElement = element.analyzableElement; |
| 211 return reporter.withCurrentElement(element, () { | 214 return reporter.withCurrentElement(element, () { |
| 212 // TODO(johnniwinther): Avoid this eager analysis. | 215 // TODO(johnniwinther): Avoid this eager analysis. |
| 213 compiler.resolution.ensureResolved(currentElement.declaration); | 216 compiler.resolution.ensureResolved(currentElement.declaration); |
| 214 | 217 |
| 215 ConstantExpression constant = compileVariableWithDefinitions( | 218 ConstantExpression constant = compileVariableWithDefinitions( |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 286 expression = null; | 289 expression = null; |
| 287 } | 290 } |
| 288 } | 291 } |
| 289 } | 292 } |
| 290 } | 293 } |
| 291 } | 294 } |
| 292 if (expression != null) { | 295 if (expression != null) { |
| 293 element.constant = expression; | 296 element.constant = expression; |
| 294 initialVariableValues[element.declaration] = expression; | 297 initialVariableValues[element.declaration] = expression; |
| 295 } else { | 298 } else { |
| 296 assert(invariant(element, !isConst, | 299 assert( |
| 297 message: "Variable $element does not compile to a constant.")); | 300 !isConst, |
| 301 failedAt( |
| 302 element, "Variable $element does not compile to a constant.")); |
| 298 } | 303 } |
| 299 pendingVariables.remove(element); | 304 pendingVariables.remove(element); |
| 300 return expression; | 305 return expression; |
| 301 } | 306 } |
| 302 | 307 |
| 303 void cacheConstantValue(ConstantExpression expression, ConstantValue value) { | 308 void cacheConstantValue(ConstantExpression expression, ConstantValue value) { |
| 304 constantValueMap[expression] = value; | 309 constantValueMap[expression] = value; |
| 305 } | 310 } |
| 306 | 311 |
| 307 ConstantExpression compileNodeWithDefinitions( | 312 ConstantExpression compileNodeWithDefinitions( |
| (...skipping 10 matching lines...) Expand all Loading... |
| 318 } | 323 } |
| 319 return null; | 324 return null; |
| 320 } | 325 } |
| 321 | 326 |
| 322 bool hasConstantValue(ConstantExpression expression) { | 327 bool hasConstantValue(ConstantExpression expression) { |
| 323 return constantValueMap.containsKey(expression); | 328 return constantValueMap.containsKey(expression); |
| 324 } | 329 } |
| 325 | 330 |
| 326 @override | 331 @override |
| 327 ConstantValue getConstantValue(ConstantExpression expression) { | 332 ConstantValue getConstantValue(ConstantExpression expression) { |
| 328 assert(invariant(CURRENT_ELEMENT_SPANNABLE, expression != null, | 333 assert( |
| 329 message: "ConstantExpression is null in getConstantValue.")); | 334 expression != null, |
| 335 failedAt(CURRENT_ELEMENT_SPANNABLE, |
| 336 "ConstantExpression is null in getConstantValue.")); |
| 330 // TODO(johnniwinther): ensure expressions have been evaluated at this | 337 // TODO(johnniwinther): ensure expressions have been evaluated at this |
| 331 // point. This can't be enabled today due to dartbug.com/26406. | 338 // point. This can't be enabled today due to dartbug.com/26406. |
| 332 if (compiler.serialization.supportsDeserialization) { | 339 if (compiler.serialization.supportsDeserialization) { |
| 333 evaluate(expression); | 340 evaluate(expression); |
| 334 } | 341 } |
| 335 ConstantValue value = constantValueMap[expression]; | 342 ConstantValue value = constantValueMap[expression]; |
| 336 if (value == null && | 343 if (value == null && |
| 337 expression != null && | 344 expression != null && |
| 338 expression.kind == ConstantExpressionKind.ERRONEOUS) { | 345 expression.kind == ConstantExpressionKind.ERRONEOUS) { |
| 339 // TODO(johnniwinther): When the Dart constant system sees a constant | 346 // TODO(johnniwinther): When the Dart constant system sees a constant |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 399 | 406 |
| 400 ConstantSystem get constantSystem => handler.constantSystem; | 407 ConstantSystem get constantSystem => handler.constantSystem; |
| 401 Resolution get resolution => compiler.resolution; | 408 Resolution get resolution => compiler.resolution; |
| 402 CommonElements get commonElements => compiler.commonElements; | 409 CommonElements get commonElements => compiler.commonElements; |
| 403 DiagnosticReporter get reporter => compiler.reporter; | 410 DiagnosticReporter get reporter => compiler.reporter; |
| 404 | 411 |
| 405 AstConstant evaluate(Node node) { | 412 AstConstant evaluate(Node node) { |
| 406 // TODO(johnniwinther): should there be a visitErrorNode? | 413 // TODO(johnniwinther): should there be a visitErrorNode? |
| 407 if (node is ErrorNode) return new ErroneousAstConstant(context, node); | 414 if (node is ErrorNode) return new ErroneousAstConstant(context, node); |
| 408 AstConstant result = node.accept(this); | 415 AstConstant result = node.accept(this); |
| 409 assert(invariant(node, !isEvaluatingConstant || result != null, | 416 assert(!isEvaluatingConstant || result != null, |
| 410 message: "No AstConstant computed for the node.")); | 417 failedAt(node, "No AstConstant computed for the node.")); |
| 411 return result; | 418 return result; |
| 412 } | 419 } |
| 413 | 420 |
| 414 AstConstant evaluateConstant(Node node) { | 421 AstConstant evaluateConstant(Node node) { |
| 415 bool oldIsEvaluatingConstant = isEvaluatingConstant; | 422 bool oldIsEvaluatingConstant = isEvaluatingConstant; |
| 416 isEvaluatingConstant = true; | 423 isEvaluatingConstant = true; |
| 417 AstConstant result = node.accept(this); | 424 AstConstant result = node.accept(this); |
| 418 isEvaluatingConstant = oldIsEvaluatingConstant; | 425 isEvaluatingConstant = oldIsEvaluatingConstant; |
| 419 assert(invariant(node, result != null, | 426 assert(result != null, |
| 420 message: "No AstConstant computed for the node.")); | 427 failedAt(node, "No AstConstant computed for the node.")); |
| 421 return result; | 428 return result; |
| 422 } | 429 } |
| 423 | 430 |
| 424 AstConstant visitNode(Node node) { | 431 AstConstant visitNode(Node node) { |
| 425 return signalNotCompileTimeConstant(node); | 432 return signalNotCompileTimeConstant(node); |
| 426 } | 433 } |
| 427 | 434 |
| 428 AstConstant visitLiteralBool(LiteralBool node) { | 435 AstConstant visitLiteralBool(LiteralBool node) { |
| 429 return new AstConstant( | 436 return new AstConstant( |
| 430 context, | 437 context, |
| (...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 837 * omitted optional arguments. | 844 * omitted optional arguments. |
| 838 * | 845 * |
| 839 * Invariant: [target] must be an implementation element. | 846 * Invariant: [target] must be an implementation element. |
| 840 */ | 847 */ |
| 841 List<AstConstant> evaluateArgumentsToConstructor( | 848 List<AstConstant> evaluateArgumentsToConstructor( |
| 842 Node node, | 849 Node node, |
| 843 CallStructure callStructure, | 850 CallStructure callStructure, |
| 844 Link<Node> arguments, | 851 Link<Node> arguments, |
| 845 ConstructorElement target, | 852 ConstructorElement target, |
| 846 {AstConstant compileArgument(Node node)}) { | 853 {AstConstant compileArgument(Node node)}) { |
| 847 assert(invariant(node, target.isImplementation)); | 854 assert(target.isImplementation, failedAt(node)); |
| 848 | 855 |
| 849 AstConstant compileDefaultValue(VariableElement element) { | 856 AstConstant compileDefaultValue(VariableElement element) { |
| 850 ConstantExpression constant = handler.compileConstant(element); | 857 ConstantExpression constant = handler.compileConstant(element); |
| 851 return new AstConstant.fromDefaultValue( | 858 return new AstConstant.fromDefaultValue( |
| 852 element, constant, handler.getConstantValue(constant)); | 859 element, constant, handler.getConstantValue(constant)); |
| 853 } | 860 } |
| 854 | 861 |
| 855 target.computeType(resolution); | 862 target.computeType(resolution); |
| 856 | 863 |
| 857 if (!callStructure.signatureApplies(target.parameterStructure)) { | 864 if (!callStructure.signatureApplies(target.parameterStructure)) { |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1086 Node node, | 1093 Node node, |
| 1087 ResolutionInterfaceType type, | 1094 ResolutionInterfaceType type, |
| 1088 ConstructorElement constructor, | 1095 ConstructorElement constructor, |
| 1089 ResolutionInterfaceType constructedType, | 1096 ResolutionInterfaceType constructedType, |
| 1090 ConstructorElement target, | 1097 ConstructorElement target, |
| 1091 CallStructure callStructure, | 1098 CallStructure callStructure, |
| 1092 List<AstConstant> concreteArguments, | 1099 List<AstConstant> concreteArguments, |
| 1093 List<AstConstant> normalizedArguments) { | 1100 List<AstConstant> normalizedArguments) { |
| 1094 if (target.isRedirectingFactory) { | 1101 if (target.isRedirectingFactory) { |
| 1095 // This happens in case of cyclic redirection. | 1102 // This happens in case of cyclic redirection. |
| 1096 assert(invariant(node, compiler.compilationFailed, | 1103 assert( |
| 1097 message: "makeConstructedConstant can only be called with the " | 1104 compiler.compilationFailed, |
| 1105 failedAt( |
| 1106 node, |
| 1107 "makeConstructedConstant can only be called with the " |
| 1098 "effective target: $constructor")); | 1108 "effective target: $constructor")); |
| 1099 return new ErroneousAstConstant(context, node); | 1109 return new ErroneousAstConstant(context, node); |
| 1100 } | 1110 } |
| 1101 assert(invariant( | 1111 assert( |
| 1102 node, | |
| 1103 callStructure.signatureApplies(constructor.parameterStructure) || | 1112 callStructure.signatureApplies(constructor.parameterStructure) || |
| 1104 compiler.compilationFailed, | 1113 compiler.compilationFailed, |
| 1105 message: "Call structure $callStructure does not apply to constructor " | 1114 failedAt( |
| 1115 node, |
| 1116 "Call structure $callStructure does not apply to constructor " |
| 1106 "$constructor.")); | 1117 "$constructor.")); |
| 1107 | 1118 |
| 1108 ConstructorEvaluator evaluator = | 1119 ConstructorEvaluator evaluator = |
| 1109 new ConstructorEvaluator(constructedType, target, handler, compiler); | 1120 new ConstructorEvaluator(constructedType, target, handler, compiler); |
| 1110 evaluator.evaluateConstructorFieldValues(normalizedArguments); | 1121 evaluator.evaluateConstructorFieldValues(normalizedArguments); |
| 1111 Map<FieldElement, AstConstant> fieldConstants = | 1122 Map<FieldElement, AstConstant> fieldConstants = |
| 1112 evaluator.buildFieldConstants(target.enclosingClass); | 1123 evaluator.buildFieldConstants(target.enclosingClass); |
| 1113 Map<FieldElement, ConstantValue> fieldValues = | 1124 Map<FieldElement, ConstantValue> fieldValues = |
| 1114 <FieldElement, ConstantValue>{}; | 1125 <FieldElement, ConstantValue>{}; |
| 1115 fieldConstants.forEach((FieldElement field, AstConstant astConstant) { | 1126 fieldConstants.forEach((FieldElement field, AstConstant astConstant) { |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1170 ResolutionInterfaceType this.constructedType, | 1181 ResolutionInterfaceType this.constructedType, |
| 1171 ConstructorElement constructor, | 1182 ConstructorElement constructor, |
| 1172 ConstantCompiler handler, | 1183 ConstantCompiler handler, |
| 1173 Compiler compiler) | 1184 Compiler compiler) |
| 1174 : this.constructor = constructor, | 1185 : this.constructor = constructor, |
| 1175 this.definitions = new Map<Element, AstConstant>(), | 1186 this.definitions = new Map<Element, AstConstant>(), |
| 1176 this.fieldValues = new Map<Element, AstConstant>(), | 1187 this.fieldValues = new Map<Element, AstConstant>(), |
| 1177 this.resolvedAst = | 1188 this.resolvedAst = |
| 1178 compiler.resolution.computeResolvedAst(constructor.declaration), | 1189 compiler.resolution.computeResolvedAst(constructor.declaration), |
| 1179 super(handler, null, compiler, isConst: true) { | 1190 super(handler, null, compiler, isConst: true) { |
| 1180 assert(invariant(constructor, constructor.isImplementation)); | 1191 assert(constructor.isImplementation, failedAt(constructor)); |
| 1181 } | 1192 } |
| 1182 | 1193 |
| 1183 @override | 1194 @override |
| 1184 Element get context => resolvedAst.element; | 1195 Element get context => resolvedAst.element; |
| 1185 | 1196 |
| 1186 @override | 1197 @override |
| 1187 TreeElements get elements => resolvedAst.elements; | 1198 TreeElements get elements => resolvedAst.elements; |
| 1188 | 1199 |
| 1189 AstConstant visitSend(Send send) { | 1200 AstConstant visitSend(Send send) { |
| 1190 Element element = elements[send]; | 1201 Element element = elements[send]; |
| (...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1460 @override | 1471 @override |
| 1461 ConstantExpression getFieldConstant(FieldElement field) { | 1472 ConstantExpression getFieldConstant(FieldElement field) { |
| 1462 return field.constant; | 1473 return field.constant; |
| 1463 } | 1474 } |
| 1464 | 1475 |
| 1465 @override | 1476 @override |
| 1466 ConstantExpression getLocalConstant(LocalVariableElement local) { | 1477 ConstantExpression getLocalConstant(LocalVariableElement local) { |
| 1467 return local.constant; | 1478 return local.constant; |
| 1468 } | 1479 } |
| 1469 } | 1480 } |
| OLD | NEW |