| 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 part of resolution; | 5 part of resolution; |
| 6 | 6 |
| 7 abstract class TreeElements { | 7 abstract class TreeElements { |
| 8 Element get currentElement; | 8 Element get currentElement; |
| 9 Setlet<Node> get superUses; | 9 Setlet<Node> get superUses; |
| 10 | 10 |
| 11 /// Iterables of the dependencies that this [TreeElement] records of | 11 /// Iterables of the dependencies that this [TreeElement] records of |
| 12 /// [currentElement]. | 12 /// [currentElement]. |
| 13 Iterable<Element> get allElements; | 13 Iterable<Element> get allElements; |
| 14 Iterable<Constant> get allConstants; | 14 void forEachConstantNode(f(Node n, Constant c)); |
| 15 | 15 |
| 16 /// A set of additional dependencies. See [registerDependency] below. | 16 /// A set of additional dependencies. See [registerDependency] below. |
| 17 Setlet<Element> get otherDependencies; | 17 Setlet<Element> get otherDependencies; |
| 18 | 18 |
| 19 Element operator[](Node node); | 19 Element operator[](Node node); |
| 20 Selector getSelector(Send send); | 20 Selector getSelector(Send send); |
| 21 Selector getGetterSelectorInComplexSendSet(SendSet node); | 21 Selector getGetterSelectorInComplexSendSet(SendSet node); |
| 22 Selector getOperatorSelectorInComplexSendSet(SendSet node); | 22 Selector getOperatorSelectorInComplexSendSet(SendSet node); |
| 23 DartType getType(Node node); | 23 DartType getType(Node node); |
| 24 void setSelector(Node node, Selector selector); | 24 void setSelector(Node node, Selector selector); |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 238 Map<VariableElement, List<Node>> accessMap = | 238 Map<VariableElement, List<Node>> accessMap = |
| 239 accessedByClosureIn.putIfAbsent(contextNode, | 239 accessedByClosureIn.putIfAbsent(contextNode, |
| 240 () => new Map<VariableElement, List<Node>>()); | 240 () => new Map<VariableElement, List<Node>>()); |
| 241 accessMap.putIfAbsent(element, () => <Node>[]).add(accessNode); | 241 accessMap.putIfAbsent(element, () => <Node>[]).add(accessNode); |
| 242 } | 242 } |
| 243 | 243 |
| 244 String toString() => 'TreeElementMapping($currentElement)'; | 244 String toString() => 'TreeElementMapping($currentElement)'; |
| 245 | 245 |
| 246 Iterable<Element> get allElements => elements; | 246 Iterable<Element> get allElements => elements; |
| 247 | 247 |
| 248 Iterable<Constant> get allConstants => constants.values; | 248 void forEachConstantNode(f(Node n, Constant c)) => constants.forEach(f); |
| 249 } | 249 } |
| 250 | 250 |
| 251 class ResolverTask extends CompilerTask { | 251 class ResolverTask extends CompilerTask { |
| 252 ResolverTask(Compiler compiler) : super(compiler); | 252 final ConstantCompiler constantCompiler; |
| 253 |
| 254 ResolverTask(Compiler compiler, this.constantCompiler) : super(compiler); |
| 253 | 255 |
| 254 String get name => 'Resolver'; | 256 String get name => 'Resolver'; |
| 255 | 257 |
| 256 TreeElements resolve(Element element) { | 258 TreeElements resolve(Element element) { |
| 257 return measure(() { | 259 return measure(() { |
| 258 if (Elements.isErroneousElement(element)) return null; | 260 if (Elements.isErroneousElement(element)) return null; |
| 259 | 261 |
| 260 for (MetadataAnnotation metadata in element.metadata) { | 262 for (MetadataAnnotation metadata in element.metadata) { |
| 261 metadata.ensureResolved(compiler); | 263 metadata.ensureResolved(compiler); |
| 262 } | 264 } |
| (...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 573 compiler.reportError(element, MessageKind.CONST_WITHOUT_INITIALIZER); | 575 compiler.reportError(element, MessageKind.CONST_WITHOUT_INITIALIZER); |
| 574 } else if (modifiers.isFinal() && !element.isInstanceMember()) { | 576 } else if (modifiers.isFinal() && !element.isInstanceMember()) { |
| 575 compiler.reportError(element, MessageKind.FINAL_WITHOUT_INITIALIZER); | 577 compiler.reportError(element, MessageKind.FINAL_WITHOUT_INITIALIZER); |
| 576 } else { | 578 } else { |
| 577 compiler.enqueuer.resolution.registerInstantiatedClass( | 579 compiler.enqueuer.resolution.registerInstantiatedClass( |
| 578 compiler.nullClass, visitor.mapping); | 580 compiler.nullClass, visitor.mapping); |
| 579 } | 581 } |
| 580 | 582 |
| 581 if (Elements.isStaticOrTopLevelField(element)) { | 583 if (Elements.isStaticOrTopLevelField(element)) { |
| 582 visitor.addDeferredAction(element, () { | 584 visitor.addDeferredAction(element, () { |
| 583 compiler.constantHandler.compileVariable( | 585 if (element.modifiers.isConst()) { |
| 584 element, isConst: element.modifiers.isConst()); | 586 constantCompiler.compileConstant(element); |
| 587 } else { |
| 588 constantCompiler.compileVariable(element); |
| 589 } |
| 585 }); | 590 }); |
| 586 if (initializer != null) { | 591 if (initializer != null) { |
| 587 if (!element.modifiers.isConst()) { | 592 if (!element.modifiers.isConst()) { |
| 588 // TODO(johnniwinther): Determine the const-ness eagerly to avoid | 593 // TODO(johnniwinther): Determine the const-ness eagerly to avoid |
| 589 // unnecessary registrations. | 594 // unnecessary registrations. |
| 590 compiler.backend.registerLazyField(visitor.mapping); | 595 compiler.backend.registerLazyField(visitor.mapping); |
| 591 } | 596 } |
| 592 } | 597 } |
| 593 } | 598 } |
| 594 | 599 |
| (...skipping 574 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1169 Node node = annotation.parseNode(compiler); | 1174 Node node = annotation.parseNode(compiler); |
| 1170 // TODO(johnniwinther): Find the right analyzable element to hold the | 1175 // TODO(johnniwinther): Find the right analyzable element to hold the |
| 1171 // [TreeElements] for the annotation. | 1176 // [TreeElements] for the annotation. |
| 1172 Element annotatedElement = annotation.annotatedElement; | 1177 Element annotatedElement = annotation.annotatedElement; |
| 1173 Element context = annotatedElement.enclosingElement; | 1178 Element context = annotatedElement.enclosingElement; |
| 1174 if (context == null) { | 1179 if (context == null) { |
| 1175 context = annotatedElement; | 1180 context = annotatedElement; |
| 1176 } | 1181 } |
| 1177 ResolverVisitor visitor = visitorFor(context); | 1182 ResolverVisitor visitor = visitorFor(context); |
| 1178 node.accept(visitor); | 1183 node.accept(visitor); |
| 1179 annotation.value = compiler.constantHandler.compileNodeWithDefinitions( | 1184 annotation.value = |
| 1180 node, visitor.mapping, isConst: true); | 1185 constantCompiler.compileMetadata(annotation, node, visitor.mapping); |
| 1181 compiler.backend.registerMetadataConstant(annotation.value, | 1186 // TODO(johnniwinther): Register the relation between the annotation |
| 1182 visitor.mapping); | 1187 // and the annotated element instead. This will allow the backed to |
| 1183 | 1188 // retrieve the backend constant and only registered metadata on the |
| 1189 // elements for which it is needed. (Issue 17732). |
| 1190 compiler.backend.registerMetadataConstant( |
| 1191 annotation.value, visitor.mapping); |
| 1184 annotation.resolutionState = STATE_DONE; | 1192 annotation.resolutionState = STATE_DONE; |
| 1185 })); | 1193 })); |
| 1186 } | 1194 } |
| 1187 | 1195 |
| 1188 error(Spannable node, MessageKind kind, [arguments = const {}]) { | 1196 error(Spannable node, MessageKind kind, [arguments = const {}]) { |
| 1189 // TODO(ahe): Make non-fatal. | 1197 // TODO(ahe): Make non-fatal. |
| 1190 compiler.reportFatalError(node, kind, arguments); | 1198 compiler.reportFatalError(node, kind, arguments); |
| 1191 } | 1199 } |
| 1192 | 1200 |
| 1193 Link<MetadataAnnotation> resolveMetadata(Element element, | 1201 Link<MetadataAnnotation> resolveMetadata(Element element, |
| 1194 VariableDefinitions node) { | 1202 VariableDefinitions node) { |
| 1195 LinkBuilder<MetadataAnnotation> metadata = | 1203 LinkBuilder<MetadataAnnotation> metadata = |
| 1196 new LinkBuilder<MetadataAnnotation>(); | 1204 new LinkBuilder<MetadataAnnotation>(); |
| 1197 for (Metadata annotation in node.metadata.nodes) { | 1205 for (Metadata annotation in node.metadata.nodes) { |
| 1198 ParameterMetadataAnnotation metadataAnnotation = | 1206 ParameterMetadataAnnotation metadataAnnotation = |
| 1199 new ParameterMetadataAnnotation(annotation); | 1207 new ParameterMetadataAnnotation(annotation); |
| 1200 metadataAnnotation.annotatedElement = element; | 1208 metadataAnnotation.annotatedElement = element; |
| 1201 metadata.addLast(metadataAnnotation.ensureResolved(compiler)); | 1209 metadata.addLast(metadataAnnotation.ensureResolved(compiler)); |
| 1202 } | 1210 } |
| 1203 return metadata.toLink(); | 1211 return metadata.toLink(); |
| 1204 } | 1212 } |
| 1205 } | 1213 } |
| 1206 | 1214 |
| 1207 class ConstantMapper extends Visitor { | |
| 1208 final Map<Constant, Node> constantToNodeMap = new Map<Constant, Node>(); | |
| 1209 final CompileTimeConstantEvaluator evaluator; | |
| 1210 | |
| 1211 ConstantMapper(ConstantHandler handler, | |
| 1212 TreeElements elements, | |
| 1213 Compiler compiler) | |
| 1214 : evaluator = new CompileTimeConstantEvaluator( | |
| 1215 handler, elements, compiler, isConst: false); | |
| 1216 | |
| 1217 visitNode(Node node) { | |
| 1218 Constant constant = evaluator.evaluate(node); | |
| 1219 if (constant != null) constantToNodeMap[constant] = node; | |
| 1220 node.visitChildren(this); | |
| 1221 } | |
| 1222 } | |
| 1223 | |
| 1224 class InitializerResolver { | 1215 class InitializerResolver { |
| 1225 final ResolverVisitor visitor; | 1216 final ResolverVisitor visitor; |
| 1226 final Map<Element, Node> initialized; | 1217 final Map<Element, Node> initialized; |
| 1227 Link<Node> initializers; | 1218 Link<Node> initializers; |
| 1228 bool hasSuper; | 1219 bool hasSuper; |
| 1229 | 1220 |
| 1230 InitializerResolver(this.visitor) | 1221 InitializerResolver(this.visitor) |
| 1231 : initialized = new Map<Element, Node>(), hasSuper = false; | 1222 : initialized = new Map<Element, Node>(), hasSuper = false; |
| 1232 | 1223 |
| 1233 error(Node node, MessageKind kind, [arguments = const {}]) { | 1224 error(Node node, MessageKind kind, [arguments = const {}]) { |
| (...skipping 963 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2197 // fields they reference are visible, but must be resolved independently. | 2188 // fields they reference are visible, but must be resolved independently. |
| 2198 if (element.kind == ElementKind.FIELD_PARAMETER) { | 2189 if (element.kind == ElementKind.FIELD_PARAMETER) { |
| 2199 useElement(parameterNode, element); | 2190 useElement(parameterNode, element); |
| 2200 } else { | 2191 } else { |
| 2201 defineElement(parameterNode, element); | 2192 defineElement(parameterNode, element); |
| 2202 } | 2193 } |
| 2203 parameterNodes = parameterNodes.tail; | 2194 parameterNodes = parameterNodes.tail; |
| 2204 }); | 2195 }); |
| 2205 addDeferredAction(enclosingElement, () { | 2196 addDeferredAction(enclosingElement, () { |
| 2206 functionParameters.forEachOptionalParameter((Element parameter) { | 2197 functionParameters.forEachOptionalParameter((Element parameter) { |
| 2207 compiler.constantHandler.compileConstant(parameter); | 2198 compiler.resolver.constantCompiler.compileConstant(parameter); |
| 2208 }); | 2199 }); |
| 2209 }); | 2200 }); |
| 2210 if (inCheckContext) { | 2201 if (inCheckContext) { |
| 2211 functionParameters.forEachParameter((Element element) { | 2202 functionParameters.forEachParameter((Element element) { |
| 2212 compiler.enqueuer.resolution.registerIsCheck( | 2203 compiler.enqueuer.resolution.registerIsCheck( |
| 2213 element.computeType(compiler), mapping); | 2204 element.computeType(compiler), mapping); |
| 2214 }); | 2205 }); |
| 2215 } | 2206 } |
| 2216 } | 2207 } |
| 2217 | 2208 |
| (...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2577 // type variable expression. | 2568 // type variable expression. |
| 2578 mapping.setType(node, compiler.typeClass.computeType(compiler)); | 2569 mapping.setType(node, compiler.typeClass.computeType(compiler)); |
| 2579 world.registerTypeLiteral(target, mapping); | 2570 world.registerTypeLiteral(target, mapping); |
| 2580 } else if (target.impliesType() && (!sendIsMemberAccess || node.isCall)) { | 2571 } else if (target.impliesType() && (!sendIsMemberAccess || node.isCall)) { |
| 2581 // Set the type of the node to [Type] to mark this send as a | 2572 // Set the type of the node to [Type] to mark this send as a |
| 2582 // type literal. | 2573 // type literal. |
| 2583 mapping.setType(node, compiler.typeClass.computeType(compiler)); | 2574 mapping.setType(node, compiler.typeClass.computeType(compiler)); |
| 2584 world.registerTypeLiteral(target, mapping); | 2575 world.registerTypeLiteral(target, mapping); |
| 2585 | 2576 |
| 2586 // Don't try to make constants of calls to type literals. | 2577 // Don't try to make constants of calls to type literals. |
| 2587 analyzeConstant(node, isConst: !node.isCall); | 2578 if (!node.isCall) { |
| 2579 analyzeConstant(node); |
| 2580 } else { |
| 2581 // The node itself is not a constant but we register the selector (the |
| 2582 // identifier that refers to the class/typedef) as a constant. |
| 2583 analyzeConstant(node.selector); |
| 2584 } |
| 2588 } | 2585 } |
| 2589 if (isPotentiallyMutableTarget(target)) { | 2586 if (isPotentiallyMutableTarget(target)) { |
| 2590 if (enclosingElement != target.enclosingElement) { | 2587 if (enclosingElement != target.enclosingElement) { |
| 2591 for (Node scope in promotionScope) { | 2588 for (Node scope in promotionScope) { |
| 2592 mapping.setAccessedByClosureIn(scope, target, node); | 2589 mapping.setAccessedByClosureIn(scope, target, node); |
| 2593 } | 2590 } |
| 2594 } | 2591 } |
| 2595 } | 2592 } |
| 2596 } | 2593 } |
| 2597 | 2594 |
| (...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3047 world.registerFactoryWithTypeArguments(mapping); | 3044 world.registerFactoryWithTypeArguments(mapping); |
| 3048 } | 3045 } |
| 3049 if (constructor.isGenerativeConstructor() && cls.isAbstract) { | 3046 if (constructor.isGenerativeConstructor() && cls.isAbstract) { |
| 3050 warning(node, MessageKind.ABSTRACT_CLASS_INSTANTIATION); | 3047 warning(node, MessageKind.ABSTRACT_CLASS_INSTANTIATION); |
| 3051 compiler.backend.registerAbstractClassInstantiation(mapping); | 3048 compiler.backend.registerAbstractClassInstantiation(mapping); |
| 3052 } | 3049 } |
| 3053 | 3050 |
| 3054 if (isSymbolConstructor) { | 3051 if (isSymbolConstructor) { |
| 3055 if (node.isConst()) { | 3052 if (node.isConst()) { |
| 3056 Node argumentNode = node.send.arguments.head; | 3053 Node argumentNode = node.send.arguments.head; |
| 3057 Constant name = compiler.constantHandler.compileNodeWithDefinitions( | 3054 Constant name = compiler.resolver.constantCompiler.compileNode( |
| 3058 argumentNode, mapping, isConst: true); | 3055 argumentNode, mapping); |
| 3059 if (!name.isString) { | 3056 if (!name.isString) { |
| 3060 DartType type = name.computeType(compiler); | 3057 DartType type = name.computeType(compiler); |
| 3061 compiler.reportError(argumentNode, MessageKind.STRING_EXPECTED, | 3058 compiler.reportError(argumentNode, MessageKind.STRING_EXPECTED, |
| 3062 {'type': type}); | 3059 {'type': type}); |
| 3063 } else { | 3060 } else { |
| 3064 StringConstant stringConstant = name; | 3061 StringConstant stringConstant = name; |
| 3065 String nameString = stringConstant.toDartString().slowToString(); | 3062 String nameString = stringConstant.toDartString().slowToString(); |
| 3066 if (validateSymbol(argumentNode, nameString)) { | 3063 if (validateSymbol(argumentNode, nameString)) { |
| 3067 world.registerConstSymbol(nameString, mapping); | 3064 world.registerConstSymbol(nameString, mapping); |
| 3068 } | 3065 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 3096 if (cls == compiler.stringClass) continue; | 3093 if (cls == compiler.stringClass) continue; |
| 3097 Element equals = cls.lookupMember('=='); | 3094 Element equals = cls.lookupMember('=='); |
| 3098 if (equals.getEnclosingClass() != compiler.objectClass) { | 3095 if (equals.getEnclosingClass() != compiler.objectClass) { |
| 3099 compiler.reportError(spannable, | 3096 compiler.reportError(spannable, |
| 3100 MessageKind.CONST_MAP_KEY_OVERRIDES_EQUALS, | 3097 MessageKind.CONST_MAP_KEY_OVERRIDES_EQUALS, |
| 3101 {'type': keyType}); | 3098 {'type': keyType}); |
| 3102 } | 3099 } |
| 3103 } | 3100 } |
| 3104 } | 3101 } |
| 3105 | 3102 |
| 3106 void analyzeConstant(Node node, {bool isConst: true}) { | 3103 void analyzeConstant(Node node) { |
| 3107 addDeferredAction(enclosingElement, () { | 3104 addDeferredAction(enclosingElement, () { |
| 3108 Constant constant = compiler.constantHandler.compileNodeWithDefinitions( | 3105 Constant constant = |
| 3109 node, mapping, isConst: isConst); | 3106 compiler.resolver.constantCompiler.compileNode(node, mapping); |
| 3110 | 3107 |
| 3111 if (isConst && constant != null && constant.isMap) { | 3108 if (constant.isMap) { |
| 3112 checkConstMapKeysDontOverrideEquals(node, constant); | 3109 checkConstMapKeysDontOverrideEquals(node, constant); |
| 3113 } | 3110 } |
| 3114 | 3111 |
| 3115 // The type constant that is an argument to JS_INTERCEPTOR_CONSTANT names | 3112 // The type constant that is an argument to JS_INTERCEPTOR_CONSTANT names |
| 3116 // a class that will be instantiated outside the program by attaching a | 3113 // a class that will be instantiated outside the program by attaching a |
| 3117 // native class dispatch record referencing the interceptor. | 3114 // native class dispatch record referencing the interceptor. |
| 3118 if (argumentsToJsInterceptorConstant != null && | 3115 if (argumentsToJsInterceptorConstant != null && |
| 3119 argumentsToJsInterceptorConstant.contains(node)) { | 3116 argumentsToJsInterceptorConstant.contains(node)) { |
| 3120 if (constant.isType) { | 3117 if (constant.isType) { |
| 3121 TypeConstant typeConstant = constant; | 3118 TypeConstant typeConstant = constant; |
| (...skipping 1329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4451 | 4448 |
| 4452 visitNodeList(NodeList node) { | 4449 visitNodeList(NodeList node) { |
| 4453 for (Link<Node> link = node.nodes; !link.isEmpty; link = link.tail) { | 4450 for (Link<Node> link = node.nodes; !link.isEmpty; link = link.tail) { |
| 4454 Identifier name = visit(link.head); | 4451 Identifier name = visit(link.head); |
| 4455 VariableElement element = new VariableElementX( | 4452 VariableElement element = new VariableElementX( |
| 4456 name.source, kind, resolver.enclosingElement, | 4453 name.source, kind, resolver.enclosingElement, |
| 4457 variables, name.token); | 4454 variables, name.token); |
| 4458 resolver.defineElement(link.head, element); | 4455 resolver.defineElement(link.head, element); |
| 4459 if (definitions.modifiers.isConst()) { | 4456 if (definitions.modifiers.isConst()) { |
| 4460 compiler.enqueuer.resolution.addDeferredAction(element, () { | 4457 compiler.enqueuer.resolution.addDeferredAction(element, () { |
| 4461 compiler.constantHandler.compileVariable(element, isConst: true); | 4458 compiler.resolver.constantCompiler.compileConstant(element); |
| 4462 }); | 4459 }); |
| 4463 } | 4460 } |
| 4464 } | 4461 } |
| 4465 } | 4462 } |
| 4466 } | 4463 } |
| 4467 | 4464 |
| 4468 class ConstructorResolver extends CommonResolverVisitor<Element> { | 4465 class ConstructorResolver extends CommonResolverVisitor<Element> { |
| 4469 final ResolverVisitor resolver; | 4466 final ResolverVisitor resolver; |
| 4470 bool inConstContext; | 4467 bool inConstContext; |
| 4471 DartType type; | 4468 DartType type; |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4658 TreeElements _treeElements; | 4655 TreeElements _treeElements; |
| 4659 | 4656 |
| 4660 bool get hasTreeElements => _treeElements != null; | 4657 bool get hasTreeElements => _treeElements != null; |
| 4661 | 4658 |
| 4662 TreeElements get treeElements { | 4659 TreeElements get treeElements { |
| 4663 assert(invariant(this, _treeElements !=null, | 4660 assert(invariant(this, _treeElements !=null, |
| 4664 message: "TreeElements have not been computed for $this.")); | 4661 message: "TreeElements have not been computed for $this.")); |
| 4665 return _treeElements; | 4662 return _treeElements; |
| 4666 } | 4663 } |
| 4667 } | 4664 } |
| OLD | NEW |