| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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 class TreeElements { | 5 class TreeElements { |
| 6 Map<Node, Element> map; | 6 Map<Node, Element> map; |
| 7 TreeElements() : map = new LinkedHashMap<Node, Element>(); | 7 TreeElements() : map = new LinkedHashMap<Node, Element>(); |
| 8 operator []=(Node node, Element element) => map[node] = element; | 8 operator []=(Node node, Element element) => map[node] = element; |
| 9 operator [](Node node) => map[node]; | 9 operator [](Node node) => map[node]; |
| 10 } | 10 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 35 } | 35 } |
| 36 | 36 |
| 37 TreeElements resolveMethodElement(FunctionElement element) { | 37 TreeElements resolveMethodElement(FunctionElement element) { |
| 38 FunctionExpression tree = element.parseNode(compiler, compiler); | 38 FunctionExpression tree = element.parseNode(compiler, compiler); |
| 39 // TODO(ahe): Can this be cleaned up to use resolveSignature? | 39 // TODO(ahe): Can this be cleaned up to use resolveSignature? |
| 40 ResolverVisitor visitor = new SignatureResolverVisitor(compiler, element); | 40 ResolverVisitor visitor = new SignatureResolverVisitor(compiler, element); |
| 41 visitor.visit(tree); | 41 visitor.visit(tree); |
| 42 | 42 |
| 43 visitor = new FullResolverVisitor.from(visitor); | 43 visitor = new FullResolverVisitor.from(visitor); |
| 44 if (tree.initializers != null) { | 44 if (tree.initializers != null) { |
| 45 resolveInitializers(element, tree, visitor); | 45 new InitializerResolver(visitor, element).resolveInitializers(tree); |
| 46 } | 46 } |
| 47 visitor.visit(tree.body); | 47 visitor.visit(tree.body); |
| 48 | 48 |
| 49 // Resolve the type annotations encountered in the method. | 49 // Resolve the type annotations encountered in the method. |
| 50 while (!toResolve.isEmpty()) { | 50 while (!toResolve.isEmpty()) { |
| 51 toResolve.removeFirst().resolve(compiler); | 51 toResolve.removeFirst().resolve(compiler); |
| 52 } | 52 } |
| 53 return visitor.mapping; | 53 return visitor.mapping; |
| 54 } | 54 } |
| 55 | 55 |
| 56 TreeElements resolveFieldElement(Element element) { | 56 TreeElements resolveFieldElement(Element element) { |
| 57 Node tree = element.parseNode(compiler, compiler); | 57 Node tree = element.parseNode(compiler, compiler); |
| 58 ResolverVisitor visitor = new FullResolverVisitor(compiler, element); | 58 ResolverVisitor visitor = new FullResolverVisitor(compiler, element); |
| 59 if (tree is SendSet) { | 59 if (tree is SendSet) { |
| 60 SendSet send = tree; | 60 SendSet send = tree; |
| 61 visitor.visit(send.arguments.head); | 61 visitor.visit(send.arguments.head); |
| 62 } | 62 } |
| 63 return visitor.mapping; | 63 return visitor.mapping; |
| 64 } | 64 } |
| 65 | 65 |
| 66 bool isInitializer(SendSet node) { | |
| 67 if (node.selector.asIdentifier() == null) return false; | |
| 68 if (node.receiver == null) return true; | |
| 69 if (node.receiver.asIdentifier() == null) return false; | |
| 70 return node.receiver.asIdentifier().isThis(); | |
| 71 } | |
| 72 | |
| 73 SourceString getInitializerFieldName(SendSet node, onError(node)) { | |
| 74 if (!isInitializer(node)) onError(node); | |
| 75 return node.selector.asIdentifier().source; | |
| 76 } | |
| 77 | |
| 78 void resolveInitializers(Element element, FunctionExpression node, | |
| 79 ResolverVisitor visitor) { | |
| 80 void onError(node) { | |
| 81 visitor.error(node, MessageKind.INVALID_RECEIVER_IN_INITIALIZER); | |
| 82 } | |
| 83 Map<SourceString, Node> initialized = new Map<SourceString, Node>(); | |
| 84 for (Link<Node> link = node.initializers.nodes; | |
| 85 !link.isEmpty(); | |
| 86 link = link.tail) { | |
| 87 if (link.head.asSendSet() != null) { | |
| 88 SendSet init = link.head; | |
| 89 SourceString name = getInitializerFieldName(init, onError); | |
| 90 ClassElement classElement = element.enclosingElement; | |
| 91 Element target = classElement.lookupLocalMember(name); | |
| 92 Node selector = init.selector; | |
| 93 if (target == null) { | |
| 94 visitor.error(selector, MessageKind.CANNOT_RESOLVE, [name]); | |
| 95 } else if (target.kind != ElementKind.FIELD) { | |
| 96 visitor.error(selector, MessageKind.NOT_A_FIELD, [name]); | |
| 97 } else if (!target.isInstanceMember()) { | |
| 98 visitor.error(selector, MessageKind.INIT_STATIC_FIELD, [name]); | |
| 99 } | |
| 100 visitor.useElement(init, target); | |
| 101 if (initialized.containsKey(name)) { | |
| 102 visitor.error(init, MessageKind.DUPLICATE_INITIALIZER, [name]); | |
| 103 visitor.warning(initialized[name], MessageKind.ALREADY_INITIALIZED, | |
| 104 [name]); | |
| 105 } | |
| 106 initialized[name] = init; | |
| 107 Node value = init.arguments.head; | |
| 108 visitor.visitInStaticContext(value); | |
| 109 } else if (link.head.asSend() !== null) { | |
| 110 // TODO(karlklose): super(...), this(...). | |
| 111 compiler.cancel('uniplemented', node:link.head); | |
| 112 } else { | |
| 113 compiler.cancel('internal error: invalid initializer', | |
| 114 node: link.head); | |
| 115 } | |
| 116 } | |
| 117 } | |
| 118 | |
| 119 void resolveType(ClassElement element) { | 66 void resolveType(ClassElement element) { |
| 120 measure(() { | 67 measure(() { |
| 121 ClassNode tree = element.parseNode(compiler, compiler); | 68 ClassNode tree = element.parseNode(compiler, compiler); |
| 122 ClassResolverVisitor visitor = new ClassResolverVisitor(compiler); | 69 ClassResolverVisitor visitor = new ClassResolverVisitor(compiler); |
| 123 visitor.visit(tree); | 70 visitor.visit(tree); |
| 124 }); | 71 }); |
| 125 } | 72 } |
| 126 | 73 |
| 127 void resolveSignature(FunctionElement element) { | 74 void resolveSignature(FunctionElement element) { |
| 128 measure(() { | 75 measure(() { |
| 129 FunctionExpression node = element.parseNode(compiler, compiler); | 76 FunctionExpression node = element.parseNode(compiler, compiler); |
| 130 SignatureResolverVisitor visitor = | 77 SignatureResolverVisitor visitor = |
| 131 new SignatureResolverVisitor(compiler, element); | 78 new SignatureResolverVisitor(compiler, element); |
| 132 visitor.visitFunctionExpression(node); | 79 visitor.visitFunctionExpression(node); |
| 133 }); | 80 }); |
| 134 } | 81 } |
| 135 } | 82 } |
| 136 | 83 |
| 84 |
| 85 class InitializerResolver { |
| 86 final ResolverVisitor visitor; |
| 87 final FunctionElement constructor; |
| 88 final Map<SourceString, Node> initialized; |
| 89 Link<Node> initializers; |
| 90 bool hasSuper; |
| 91 |
| 92 bool isSuperConstructorCall(Send node) { |
| 93 return (node.receiver === null && |
| 94 node.selector.asIdentifier() !== null && |
| 95 node.selector.asIdentifier().isSuper()) || |
| 96 (node.receiver !== null && |
| 97 node.receiver.asIdentifier() !== null && |
| 98 node.receiver.asIdentifier().isSuper() && |
| 99 node.selector.asIdentifier() !== null); |
| 100 } |
| 101 |
| 102 bool isConstructorRedirect(Send node) { |
| 103 return (node.receiver === null && |
| 104 node.selector.asIdentifier() !== null && |
| 105 node.selector.asIdentifier().isThis()) || |
| 106 (node.receiver !== null && |
| 107 node.receiver.asIdentifier() !== null && |
| 108 node.receiver.asIdentifier().isThis() && |
| 109 node.selector.asIdentifier() !== null); |
| 110 } |
| 111 |
| 112 InitializerResolver(this.visitor, this.constructor) |
| 113 : initialized = new Map<SourceString, Node>(), hasSuper = false; |
| 114 |
| 115 error(Node node, MessageKind kind, [arguments = const []]) { |
| 116 visitor.error(node, kind, arguments); |
| 117 } |
| 118 |
| 119 warning(Node node, MessageKind kind, [arguments = const []]) { |
| 120 visitor.warning(node, kind, arguments); |
| 121 } |
| 122 |
| 123 bool isFieldInitializer(SendSet node) { |
| 124 if (node.selector.asIdentifier() == null) return false; |
| 125 if (node.receiver == null) return true; |
| 126 if (node.receiver.asIdentifier() == null) return false; |
| 127 return node.receiver.asIdentifier().isThis(); |
| 128 } |
| 129 |
| 130 void resolveFieldInitializer(SendSet init) { |
| 131 // init is of the form [this.]field = value. |
| 132 final Node selector = init.selector; |
| 133 final SourceString name = selector.asIdentifier().source; |
| 134 // Lookup target field. |
| 135 Element target; |
| 136 if (isFieldInitializer(init)) { |
| 137 final ClassElement classElement = constructor.enclosingElement; |
| 138 target = classElement.lookupLocalMember(name); |
| 139 if (target === null) { |
| 140 error(selector, MessageKind.CANNOT_RESOLVE, [name]); |
| 141 } else if (target.kind != ElementKind.FIELD) { |
| 142 error(selector, MessageKind.NOT_A_FIELD, [name]); |
| 143 } else if (!target.isInstanceMember()) { |
| 144 error(selector, MessageKind.INIT_STATIC_FIELD, [name]); |
| 145 } |
| 146 } else { |
| 147 error(init, MessageKind.INVALID_RECEIVER_IN_INITIALIZER); |
| 148 } |
| 149 visitor.useElement(init, target); |
| 150 // Check for duplicate initializers. |
| 151 if (initialized.containsKey(name)) { |
| 152 error(init, MessageKind.DUPLICATE_INITIALIZER, [name]); |
| 153 warning(initialized[name], MessageKind.ALREADY_INITIALIZED, [name]); |
| 154 } |
| 155 initialized[name] = init; |
| 156 // Resolve initializing value. |
| 157 visitor.visitInStaticContext(init.arguments.head); |
| 158 } |
| 159 |
| 160 SourceString getConstructorName(ClassElement cls, Send node) { |
| 161 SourceString constructor = node.selector.asIdentifier().source; |
| 162 if (node.receiver !== null) { |
| 163 return new SourceString('${cls.name}.$constructor'); |
| 164 } else { |
| 165 return cls.name; |
| 166 } |
| 167 } |
| 168 |
| 169 void resolveSuperOrThis(Send call) { |
| 170 noConstructor(e) { |
| 171 if (e !== null) error(call, MessageKind.NO_CONSTRUCTOR, [e.name, e.kind]); |
| 172 } |
| 173 |
| 174 ClassElement lookupTarget = constructor.enclosingElement; |
| 175 bool validTarget = true; |
| 176 if (isSuperConstructorCall(call)) { |
| 177 // Check for invalid initializers. |
| 178 if (hasSuper) { |
| 179 error(call, MessageKind.DUPLICATE_SUPER_INITIALIZER); |
| 180 } |
| 181 hasSuper = true; |
| 182 // Calculate correct lookup target and constructor name. |
| 183 if (lookupTarget.name == Types.OBJECT) { |
| 184 error(call, MessageKind.SUPER_INITIALIZER_IN_OBJECT); |
| 185 } else { |
| 186 lookupTarget = lookupTarget.supertype.element; |
| 187 } |
| 188 } else if (isConstructorRedirect(call)) { |
| 189 // Check that there are no other initializers. |
| 190 if (!initializers.tail.isEmpty()) { |
| 191 error(call, MessageKind.REDIRECTING_CTOR_HAS_INITIALIZER); |
| 192 } |
| 193 } else { |
| 194 visitor.error(call, MessageKind.CONSTRUCTOR_CALL_EXPECTED); |
| 195 validTarget = false; |
| 196 } |
| 197 |
| 198 if (validTarget) { |
| 199 final SourceString name = getConstructorName(lookupTarget, call); |
| 200 FunctionElement target = |
| 201 lookupTarget.lookupConstructor(name, noConstructor); |
| 202 if (target === null && call.arguments.isEmpty()) { |
| 203 target = lookupTarget.getSynthesizedConstructor(); |
| 204 } |
| 205 if (target === null) { |
| 206 error(call, MessageKind.CANNOT_RESOLVE_CONSTRUCTOR, [name]); |
| 207 } else { |
| 208 final Compiler compiler = visitor.compiler; |
| 209 // TODO(karlklose): support optional arguments. |
| 210 if (target.parameterCount(compiler) != call.argumentCount()) { |
| 211 error(call, MessageKind.NO_MATCHING_CONSTRUCTOR); |
| 212 } |
| 213 } |
| 214 visitor.useElement(call, target); |
| 215 } |
| 216 // Resolve the arguments of the call. |
| 217 for (Link<Node> arguments = call.arguments; |
| 218 !arguments.isEmpty(); |
| 219 arguments = arguments.tail) { |
| 220 visitor.visitInStaticContext(arguments.head); |
| 221 } |
| 222 } |
| 223 |
| 224 void resolveInitializers(FunctionExpression node) { |
| 225 if (node.initializers === null) return; |
| 226 initializers = node.initializers.nodes; |
| 227 Compiler compiler = visitor.compiler; |
| 228 for (Link<Node> link = initializers; |
| 229 !link.isEmpty(); |
| 230 link = link.tail) { |
| 231 if (link.head.asSendSet() != null) { |
| 232 final SendSet init = link.head.asSendSet(); |
| 233 resolveFieldInitializer(init); |
| 234 } else if (link.head.asSend() !== null) { |
| 235 final Send call = link.head.asSend(); |
| 236 resolveSuperOrThis(call); |
| 237 } else { |
| 238 visitor.compiler.cancel('internal error: invalid initializer', |
| 239 node: link.head); |
| 240 } |
| 241 } |
| 242 } |
| 243 } |
| 244 |
| 245 |
| 137 // TODO(ahe): Frog cannot handle generic types. | 246 // TODO(ahe): Frog cannot handle generic types. |
| 138 class ResolverVisitor extends AbstractVisitor/*<Element>*/ { | 247 class ResolverVisitor extends AbstractVisitor/*<Element>*/ { |
| 139 final Compiler compiler; | 248 final Compiler compiler; |
| 140 final TreeElements mapping; | 249 final TreeElements mapping; |
| 141 final Element enclosingElement; | 250 final Element enclosingElement; |
| 142 bool inInstanceContext; | 251 bool inInstanceContext; |
| 143 Scope context; | 252 Scope context; |
| 144 ClassElement currentClass; | 253 ClassElement currentClass; |
| 145 bool typeRequired = false; | 254 bool typeRequired = false; |
| 146 | 255 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 173 compiler.reportWarning(node, warning); | 282 compiler.reportWarning(node, warning); |
| 174 } | 283 } |
| 175 | 284 |
| 176 cancel(Node node, String message) { | 285 cancel(Node node, String message) { |
| 177 compiler.cancel(message, node: node); | 286 compiler.cancel(message, node: node); |
| 178 } | 287 } |
| 179 | 288 |
| 180 Element lookup(Node node, SourceString name) { | 289 Element lookup(Node node, SourceString name) { |
| 181 Element result = context.lookup(name); | 290 Element result = context.lookup(name); |
| 182 if (!inInstanceContext && result != null && result.isInstanceMember()) { | 291 if (!inInstanceContext && result != null && result.isInstanceMember()) { |
| 183 error(node, MessageKind.NOT_STATIC, [node]); | 292 error(node, MessageKind.NO_INSTANCE_AVAILABLE, [node]); |
| 184 } | 293 } |
| 185 return result; | 294 return result; |
| 186 } | 295 } |
| 187 | 296 |
| 188 visitInStaticContext(Node node) { | 297 visitInStaticContext(Node node) { |
| 189 bool wasInstanceContext = inInstanceContext; | 298 bool wasInstanceContext = inInstanceContext; |
| 190 inInstanceContext = false; | 299 inInstanceContext = false; |
| 191 visit(node); | 300 visit(node); |
| 192 inInstanceContext = wasInstanceContext; | 301 inInstanceContext = wasInstanceContext; |
| 193 } | 302 } |
| 194 | 303 |
| 195 visit(Node node) { | 304 visit(Node node) { |
| 196 if (node == null) return null; | 305 if (node == null) return null; |
| 197 return node.accept(this); | 306 return node.accept(this); |
| 198 } | 307 } |
| 199 | 308 |
| 200 visitIdentifier(Identifier node) { | 309 visitIdentifier(Identifier node) { |
| 201 if (node.isThis()) { | 310 if (node.isThis()) { |
| 202 if (!inInstanceContext) error(node, MessageKind.NO_THIS_IN_STATIC); | 311 if (!inInstanceContext) { |
| 312 error(node, MessageKind.NO_INSTANCE_AVAILABLE, [node]); |
| 313 } |
| 203 return null; | 314 return null; |
| 204 } else if (node.isSuper()) { | 315 } else if (node.isSuper()) { |
| 205 if (!inInstanceContext) error(node, MessageKind.NO_SUPER_IN_STATIC); | 316 if (!inInstanceContext) error(node, MessageKind.NO_SUPER_IN_STATIC); |
| 206 return null; | 317 return null; |
| 207 } else { | 318 } else { |
| 208 Element element = lookup(node, node.source); | 319 Element element = lookup(node, node.source); |
| 209 if (element == null) { | 320 if (element == null) { |
| 210 error(node, MessageKind.CANNOT_RESOLVE, [node]); | 321 error(node, MessageKind.CANNOT_RESOLVE, [node]); |
| 211 } | 322 } |
| 212 return useElement(node, element); | 323 return useElement(node, element); |
| 213 } | 324 } |
| 214 } | 325 } |
| 215 | 326 |
| 216 visitTypeAnnotation(TypeAnnotation node) { | 327 visitTypeAnnotation(TypeAnnotation node) { |
| 217 Identifier name = node.typeName.asIdentifier(); | 328 SourceString className; |
| 218 if (name === null) { | 329 if (node.typeName.asSend() !== null) { |
| 219 // TODO(karlklose): In progress. | 330 // In new and const expressions, the type name can be a Send to |
| 220 cancel(node.typeName, "not implemented"); | 331 // denote named constructors or library prefixes. |
| 332 Send send = node.typeName.asSend(); |
| 333 className = send.receiver.asIdentifier().source; |
| 334 } else { |
| 335 className = node.typeName.asIdentifier().source; |
| 221 } | 336 } |
| 222 if (name.source == const SourceString('var')) return null; | 337 if (className == const SourceString('var')) return null; |
| 223 if (name.source == const SourceString('void')) return null; | 338 if (className == const SourceString('void')) return null; |
| 224 Element element = context.lookup(name.source); | 339 Element element = context.lookup(className); |
| 225 if (element === null) { | 340 if (element === null) { |
| 226 if (typeRequired) { | 341 if (typeRequired) { |
| 227 error(node, MessageKind.CANNOT_RESOLVE_TYPE, [name]); | 342 error(node, MessageKind.CANNOT_RESOLVE_TYPE, [className]); |
| 228 } else { | 343 } else { |
| 229 warning(node, MessageKind.CANNOT_RESOLVE_TYPE, [name]); | 344 warning(node, MessageKind.CANNOT_RESOLVE_TYPE, [className]); |
| 230 } | 345 } |
| 231 } else if (element.kind !== ElementKind.CLASS) { | 346 } else if (element.kind !== ElementKind.CLASS) { |
| 232 if (typeRequired) { | 347 if (typeRequired) { |
| 233 error(node, MessageKind.NOT_A_TYPE, [name]); | 348 error(node, MessageKind.NOT_A_TYPE, [className]); |
| 234 } else { | 349 } else { |
| 235 warning(node, MessageKind.NOT_A_TYPE, [name]); | 350 warning(node, MessageKind.NOT_A_TYPE, [className]); |
| 236 } | 351 } |
| 237 } else { | 352 } else { |
| 238 ClassElement cls = element; | 353 ClassElement cls = element; |
| 239 compiler.resolver.toResolve.add(element); | 354 compiler.resolver.toResolve.add(element); |
| 240 // TODO(ahe): This should be a Type. | 355 // TODO(ahe): This should be a Type. |
| 241 useElement(node, element); | 356 useElement(node, element); |
| 242 } | 357 } |
| 243 return element; | 358 return element; |
| 244 } | 359 } |
| 245 | 360 |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 326 visitFor(For node) { | 441 visitFor(For node) { |
| 327 Scope scope = new BlockScope(context); | 442 Scope scope = new BlockScope(context); |
| 328 visitIn(node.initializer, scope); | 443 visitIn(node.initializer, scope); |
| 329 visitIn(node.condition, scope); | 444 visitIn(node.condition, scope); |
| 330 visitIn(node.update, scope); | 445 visitIn(node.update, scope); |
| 331 visitIn(node.body, scope); | 446 visitIn(node.body, scope); |
| 332 } | 447 } |
| 333 | 448 |
| 334 visitFunctionExpression(FunctionExpression node) { | 449 visitFunctionExpression(FunctionExpression node) { |
| 335 visit(node.returnType); | 450 visit(node.returnType); |
| 451 SourceString name; |
| 336 if (node.name === null) { | 452 if (node.name === null) { |
| 337 cancel(node, "anonymous functions are not implemented"); | 453 cancel(node, "anonymous functions are not implemented"); |
| 338 } | 454 } |
| 339 if (node.name.asIdentifier() === null) { | 455 name = node.name.asIdentifier().source; |
| 340 cancel(node.name, "named constructors are not implemented"); | |
| 341 } | |
| 342 FunctionElement enclosingElement = new FunctionElement.node( | 456 FunctionElement enclosingElement = new FunctionElement.node( |
| 343 node, ElementKind.FUNCTION, null, context.element); | 457 name, node, ElementKind.FUNCTION, null, context.element); |
| 344 defineElement(node, enclosingElement); | 458 defineElement(node, enclosingElement); |
| 345 context = new MethodScope(context, enclosingElement); | 459 context = new MethodScope(context, enclosingElement); |
| 346 | 460 |
| 347 // TODO(ahe): Can this be cleaned up to use resolveSignature? | 461 // TODO(ahe): Can this be cleaned up to use resolveSignature? |
| 348 ParametersVisitor visitor = new ParametersVisitor(this); | 462 ParametersVisitor visitor = new ParametersVisitor(this); |
| 349 visitor.visit(node.parameters); | 463 visitor.visit(node.parameters); |
| 350 enclosingElement.parameters = visitor.elements.toLink(); | 464 enclosingElement.parameters = visitor.elements.toLink(); |
| 351 | 465 |
| 352 visit(node.body); | 466 visit(node.body); |
| 353 context = context.parent; | 467 context = context.parent; |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 510 | 624 |
| 511 visitParenthesizedExpression(ParenthesizedExpression node) { | 625 visitParenthesizedExpression(ParenthesizedExpression node) { |
| 512 visit(node.expression); | 626 visit(node.expression); |
| 513 } | 627 } |
| 514 | 628 |
| 515 visitNewExpression(NewExpression node) { | 629 visitNewExpression(NewExpression node) { |
| 516 if (node.isConst()) cancel(node, 'const expressions are not implemented'); | 630 if (node.isConst()) cancel(node, 'const expressions are not implemented'); |
| 517 | 631 |
| 518 visit(node.send.argumentsNode); | 632 visit(node.send.argumentsNode); |
| 519 | 633 |
| 634 SourceString constructorName; |
| 635 Node typeName = node.send.selector.asTypeAnnotation().typeName; |
| 636 if (typeName.asSend() !== null) { |
| 637 Identifier receiver = typeName.asSend().receiver.asIdentifier(); |
| 638 Identifier selector = typeName.asSend().selector.asIdentifier(); |
| 639 SourceString className = receiver.source; |
| 640 SourceString name = selector.source; |
| 641 constructorName = new SourceString('$className.$name'); |
| 642 } else { |
| 643 constructorName = typeName.asIdentifier().source; |
| 644 } |
| 520 ClassElement cls = resolveTypeRequired(node.send.selector); | 645 ClassElement cls = resolveTypeRequired(node.send.selector); |
| 521 Element constructor = null; | 646 Element constructor = null; |
| 522 if (cls !== null) { | 647 if (cls !== null) { |
| 523 // TODO(ngeoffray): set constructor-name correctly. | 648 constructor = cls.resolve(compiler).lookupConstructor(constructorName); |
| 524 SourceString name = cls.name; | 649 if (constructorName == cls.name |
| 525 constructor = cls.resolve(compiler).lookupConstructor(name); | |
| 526 if (name == cls.name | |
| 527 && constructor === null | 650 && constructor === null |
| 528 && node.send.argumentsNode.isEmpty()) { | 651 && node.send.argumentsNode.isEmpty()) { |
| 529 constructor = cls.getSynthesizedConstructor(); | 652 constructor = cls.getSynthesizedConstructor(); |
| 530 } | 653 } |
| 531 if (constructor === null) { | 654 if (constructor === null) { |
| 532 error(node, MessageKind.CANNOT_FIND_CONSTRUCTOR, [node]); | 655 error(node.send, MessageKind.CANNOT_FIND_CONSTRUCTOR, [node.send]); |
| 656 } else { |
| 657 FunctionElement function = constructor; |
| 658 // TODO(karlklose): handle optional arguments. |
| 659 if (node.send.argumentCount() != function.parameterCount(compiler)) { |
| 660 error(node.send, MessageKind.CANNOT_FIND_CONSTRUCTOR, [node.send]); |
| 661 } |
| 533 } | 662 } |
| 663 } else { |
| 664 Node selector = node.send.selector; |
| 665 error(selector, MessageKind.CANNOT_RESOLVE_TYPE, [selector]); |
| 534 } | 666 } |
| 535 | |
| 536 useElement(node.send, constructor); | 667 useElement(node.send, constructor); |
| 537 return null; | 668 return null; |
| 538 } | 669 } |
| 539 | 670 |
| 540 ClassElement resolveTypeRequired(Node node) { | 671 ClassElement resolveTypeRequired(Node node) { |
| 541 bool old = typeRequired; | 672 bool old = typeRequired; |
| 542 typeRequired = true; | 673 typeRequired = true; |
| 543 ClassElement cls = visit(node); | 674 ClassElement cls = visit(node); |
| 544 typeRequired = old; | 675 typeRequired = old; |
| 545 return cls; | 676 return cls; |
| (...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 826 class TopScope extends Scope { | 957 class TopScope extends Scope { |
| 827 Universe universe; | 958 Universe universe; |
| 828 | 959 |
| 829 TopScope(Universe this.universe) : super(null, null); | 960 TopScope(Universe this.universe) : super(null, null); |
| 830 Element lookup(SourceString name) => universe.find(name); | 961 Element lookup(SourceString name) => universe.find(name); |
| 831 | 962 |
| 832 Element add(Element element) { | 963 Element add(Element element) { |
| 833 throw "Cannot add an element in the top scope"; | 964 throw "Cannot add an element in the top scope"; |
| 834 } | 965 } |
| 835 } | 966 } |
| OLD | NEW |