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 |