| 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 'constant_system_dart.dart'; | 7 import 'constant_system_dart.dart'; |
| 8 import 'constants/constant_system.dart'; | 8 import 'constants/constant_system.dart'; |
| 9 import 'constants/expressions.dart'; | 9 import 'constants/expressions.dart'; |
| 10 import 'constants/values.dart'; | 10 import 'constants/values.dart'; |
| 11 import 'dart_types.dart'; | 11 import 'dart_types.dart'; |
| 12 import 'dart2jslib.dart' show Compiler, CompilerTask, MessageKind, invariant; | 12 import 'dart2jslib.dart' show Compiler, CompilerTask, MessageKind, WorldImpact,
invariant; |
| 13 import 'elements/elements.dart'; | 13 import 'elements/elements.dart'; |
| 14 import 'elements/modelx.dart' show FunctionElementX; | 14 import 'elements/modelx.dart' show FunctionElementX; |
| 15 import 'helpers/helpers.dart'; | 15 import 'helpers/helpers.dart'; |
| 16 import 'resolution/resolution.dart'; | 16 import 'resolution/resolution.dart'; |
| 17 import 'resolution/operators.dart'; | 17 import 'resolution/operators.dart'; |
| 18 import 'tree/tree.dart'; | 18 import 'tree/tree.dart'; |
| 19 import 'util/util.dart' show Link; | 19 import 'util/util.dart' show Link; |
| 20 import 'universe/universe.dart' show CallStructure; | 20 import 'universe/universe.dart' show CallStructure; |
| 21 | 21 |
| 22 /// A [ConstantEnvironment] provides access for constants compiled for variable | 22 /// A [ConstantEnvironment] provides access for constants compiled for variable |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 129 | 129 |
| 130 ConstantExpression compileVariable(VariableElement element, | 130 ConstantExpression compileVariable(VariableElement element, |
| 131 {bool isConst: false}) { | 131 {bool isConst: false}) { |
| 132 | 132 |
| 133 if (initialVariableValues.containsKey(element.declaration)) { | 133 if (initialVariableValues.containsKey(element.declaration)) { |
| 134 ConstantExpression result = initialVariableValues[element.declaration]; | 134 ConstantExpression result = initialVariableValues[element.declaration]; |
| 135 return result; | 135 return result; |
| 136 } | 136 } |
| 137 AstElement currentElement = element.analyzableElement; | 137 AstElement currentElement = element.analyzableElement; |
| 138 return compiler.withCurrentElement(currentElement, () { | 138 return compiler.withCurrentElement(currentElement, () { |
| 139 compiler.analyzeElement(currentElement.declaration); | 139 // TODO(johnniwinther): Avoid this eager analysis. |
| 140 _analyzeElementEagerly(compiler, currentElement); |
| 141 |
| 140 ConstantExpression constant = compileVariableWithDefinitions( | 142 ConstantExpression constant = compileVariableWithDefinitions( |
| 141 element, currentElement.resolvedAst.elements, isConst: isConst); | 143 element, currentElement.resolvedAst.elements, isConst: isConst); |
| 142 return constant; | 144 return constant; |
| 143 }); | 145 }); |
| 144 } | 146 } |
| 145 | 147 |
| 146 /** | 148 /** |
| 147 * Returns the a compile-time constant if the variable could be compiled | 149 * Returns the a compile-time constant if the variable could be compiled |
| 148 * eagerly. If the variable needs to be initialized lazily returns `null`. | 150 * eagerly. If the variable needs to be initialized lazily returns `null`. |
| 149 * If the variable is `const` but cannot be compiled eagerly reports an | 151 * If the variable is `const` but cannot be compiled eagerly reports an |
| (...skipping 601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 751 AstConstant createConstructorInvocation( | 753 AstConstant createConstructorInvocation( |
| 752 Node node, | 754 Node node, |
| 753 InterfaceType type, | 755 InterfaceType type, |
| 754 ConstructorElement constructor, | 756 ConstructorElement constructor, |
| 755 CallStructure callStructure, | 757 CallStructure callStructure, |
| 756 {Link<Node> arguments, | 758 {Link<Node> arguments, |
| 757 List<AstConstant> normalizedArguments}) { | 759 List<AstConstant> normalizedArguments}) { |
| 758 // TODO(ahe): This is nasty: we must eagerly analyze the | 760 // TODO(ahe): This is nasty: we must eagerly analyze the |
| 759 // constructor to ensure the redirectionTarget has been computed | 761 // constructor to ensure the redirectionTarget has been computed |
| 760 // correctly. Find a way to avoid this. | 762 // correctly. Find a way to avoid this. |
| 761 compiler.analyzeElement(constructor.declaration); | 763 _analyzeElementEagerly(compiler, constructor); |
| 762 | 764 |
| 763 // The redirection chain of this element may not have been resolved through | 765 // The redirection chain of this element may not have been resolved through |
| 764 // a post-process action, so we have to make sure it is done here. | 766 // a post-process action, so we have to make sure it is done here. |
| 765 compiler.resolver.resolveRedirectionChain(constructor, node); | 767 compiler.resolver.resolveRedirectionChain(constructor, node); |
| 766 InterfaceType constructedType = | 768 InterfaceType constructedType = |
| 767 constructor.computeEffectiveTargetType(type); | 769 constructor.computeEffectiveTargetType(type); |
| 768 ConstructorElement target = constructor.effectiveTarget; | 770 ConstructorElement target = constructor.effectiveTarget; |
| 769 // The constructor must be an implementation to ensure that field | 771 // The constructor must be an implementation to ensure that field |
| 770 // initializers are handled correctly. | 772 // initializers are handled correctly. |
| 771 ConstructorElement implementation = target.implementation; | 773 ConstructorElement implementation = target.implementation; |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 997 * Invariant: [constructor] must be an implementation element. | 999 * Invariant: [constructor] must be an implementation element. |
| 998 */ | 1000 */ |
| 999 ConstructorEvaluator(InterfaceType this.constructedType, | 1001 ConstructorEvaluator(InterfaceType this.constructedType, |
| 1000 FunctionElement constructor, | 1002 FunctionElement constructor, |
| 1001 ConstantCompiler handler, | 1003 ConstantCompiler handler, |
| 1002 Compiler compiler) | 1004 Compiler compiler) |
| 1003 : this.constructor = constructor, | 1005 : this.constructor = constructor, |
| 1004 this.definitions = new Map<Element, AstConstant>(), | 1006 this.definitions = new Map<Element, AstConstant>(), |
| 1005 this.fieldValues = new Map<Element, AstConstant>(), | 1007 this.fieldValues = new Map<Element, AstConstant>(), |
| 1006 super(handler, | 1008 super(handler, |
| 1007 compiler.resolver.resolveMethodElement(constructor.declaration), | 1009 _analyzeElementEagerly(compiler, constructor), |
| 1008 compiler, | 1010 compiler, |
| 1009 isConst: true) { | 1011 isConst: true) { |
| 1010 assert(invariant(constructor, constructor.isImplementation)); | 1012 assert(invariant(constructor, constructor.isImplementation)); |
| 1011 } | 1013 } |
| 1012 | 1014 |
| 1013 AstConstant visitSend(Send send) { | 1015 AstConstant visitSend(Send send) { |
| 1014 Element element = elements[send]; | 1016 Element element = elements[send]; |
| 1015 if (Elements.isLocal(element)) { | 1017 if (Elements.isLocal(element)) { |
| 1016 AstConstant constant = definitions[element]; | 1018 AstConstant constant = definitions[element]; |
| 1017 if (constant == null) { | 1019 if (constant == null) { |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1133 } | 1135 } |
| 1134 } | 1136 } |
| 1135 | 1137 |
| 1136 if (!foundSuperOrRedirect) { | 1138 if (!foundSuperOrRedirect) { |
| 1137 // No super initializer found. Try to find the default constructor if | 1139 // No super initializer found. Try to find the default constructor if |
| 1138 // the class is not Object. | 1140 // the class is not Object. |
| 1139 ClassElement enclosingClass = constructor.enclosingClass; | 1141 ClassElement enclosingClass = constructor.enclosingClass; |
| 1140 ClassElement superClass = enclosingClass.superclass; | 1142 ClassElement superClass = enclosingClass.superclass; |
| 1141 if (enclosingClass != compiler.objectClass) { | 1143 if (enclosingClass != compiler.objectClass) { |
| 1142 assert(superClass != null); | 1144 assert(superClass != null); |
| 1143 assert(superClass.resolutionState == STATE_DONE); | 1145 assert(superClass.isResolved); |
| 1144 | 1146 |
| 1145 FunctionElement targetConstructor = | 1147 FunctionElement targetConstructor = |
| 1146 superClass.lookupDefaultConstructor(); | 1148 superClass.lookupDefaultConstructor(); |
| 1147 // If we do not find a default constructor, an error was reported | 1149 // If we do not find a default constructor, an error was reported |
| 1148 // already and compilation will fail anyway. So just ignore that case. | 1150 // already and compilation will fail anyway. So just ignore that case. |
| 1149 if (targetConstructor != null) { | 1151 if (targetConstructor != null) { |
| 1150 List<AstConstant> compiledArguments = evaluateArgumentsToConstructor( | 1152 List<AstConstant> compiledArguments = evaluateArgumentsToConstructor( |
| 1151 functionNode, CallStructure.NO_ARGS, | 1153 functionNode, CallStructure.NO_ARGS, |
| 1152 const Link<Node>(), targetConstructor); | 1154 const Link<Node>(), targetConstructor); |
| 1153 evaluateSuperOrRedirectSend(compiledArguments, targetConstructor); | 1155 evaluateSuperOrRedirectSend(compiledArguments, targetConstructor); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1218 ConstantValue get value => expression.value; | 1220 ConstantValue get value => expression.value; |
| 1219 | 1221 |
| 1220 String toString() => expression.toString(); | 1222 String toString() => expression.toString(); |
| 1221 } | 1223 } |
| 1222 | 1224 |
| 1223 /// A synthetic constant used to recover from errors. | 1225 /// A synthetic constant used to recover from errors. |
| 1224 class ErroneousAstConstant extends AstConstant { | 1226 class ErroneousAstConstant extends AstConstant { |
| 1225 ErroneousAstConstant(Element element, Node node) | 1227 ErroneousAstConstant(Element element, Node node) |
| 1226 : super(element, node, new ErroneousConstantExpression()); | 1228 : super(element, node, new ErroneousConstantExpression()); |
| 1227 } | 1229 } |
| 1230 |
| 1231 // TODO(johnniwinther): Avoid the need for this hack. |
| 1232 TreeElements _analyzeElementEagerly(Compiler compiler, AstElement element) { |
| 1233 WorldImpact worldImpact = compiler.analyzeElement(element.declaration); |
| 1234 compiler.enqueuer.resolution.applyImpact(element.declaration, worldImpact); |
| 1235 return element.resolvedAst.elements; |
| 1236 } |
| OLD | NEW |