Chromium Code Reviews| 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 Map<SourceString, Node> initialized; | |
|
ngeoffray
2012/01/19 08:56:12
Make initialized final?
karlklose
2012/01/19 13:51:24
Done.
| |
| 89 Node initializerOrSuper; | |
|
ngeoffray
2012/01/19 08:56:12
Instead of having initializerOrSuper, I suggest ke
karlklose
2012/01/19 13:51:24
Done.
| |
| 90 bool hasSuper; | |
| 91 | |
| 92 InitializerResolver(this.visitor, this.constructor) | |
| 93 : initialized = new Map<SourceString, Node>(), hasSuper = false; | |
| 94 | |
| 95 Universe get universe() => visitor.compiler.universe; | |
|
ngeoffray
2012/01/19 08:56:12
Unused?
karlklose
2012/01/19 13:51:24
Done, removed.
| |
| 96 | |
| 97 error(Node node, MessageKind kind, [arguments = const []]) { | |
| 98 visitor.error(node, kind, arguments); | |
| 99 } | |
| 100 | |
| 101 warning(Node node, MessageKind kind, [arguments = const []]) { | |
| 102 visitor.warning(node, kind, arguments); | |
| 103 } | |
| 104 | |
| 105 bool isFieldInitializer(SendSet node) { | |
| 106 if (node.selector.asIdentifier() == null) return false; | |
| 107 if (node.receiver == null) return true; | |
| 108 if (node.receiver.asIdentifier() == null) return false; | |
| 109 return node.receiver.asIdentifier().isThis(); | |
| 110 } | |
| 111 | |
| 112 void resolveFieldInitializer(SendSet init) { | |
| 113 // init is of the form [this.]field = value. | |
| 114 final Node selector = init.selector; | |
| 115 final SourceString name = selector.asIdentifier().source; | |
| 116 // Lookup target field. | |
| 117 Element target; | |
| 118 if (isFieldInitializer(init)) { | |
| 119 final ClassElement classElement = constructor.enclosingElement; | |
| 120 target = classElement.lookupLocalMember(name); | |
| 121 if (target === null) { | |
| 122 error(selector, MessageKind.CANNOT_RESOLVE, [name]); | |
| 123 } else if (target.kind != ElementKind.FIELD) { | |
| 124 error(selector, MessageKind.NOT_A_FIELD, [name]); | |
| 125 } else if (!target.isInstanceMember()) { | |
| 126 error(selector, MessageKind.INIT_STATIC_FIELD, [name]); | |
| 127 } | |
| 128 } else { | |
| 129 error(init, MessageKind.INVALID_RECEIVER_IN_INITIALIZER); | |
| 130 } | |
| 131 visitor.useElement(init, target); | |
| 132 // Check for duplicate initializers. | |
| 133 if (initialized.containsKey(name)) { | |
| 134 error(init, MessageKind.DUPLICATE_INITIALIZER, [name]); | |
|
ngeoffray
2012/01/19 08:56:12
Why error + warning? Shouldn't it be just one of t
karlklose
2012/01/19 13:51:24
The warning gives additional feedback.
ngeoffray
2012/01/19 14:36:33
So why not putting all the feedback in a single er
| |
| 135 warning(initialized[name], MessageKind.ALREADY_INITIALIZED, [name]); | |
| 136 } | |
| 137 initialized[name] = init; | |
| 138 // Resolve initializing value. | |
| 139 visitor.visitInStaticContext(init.arguments.head); | |
| 140 if (initializerOrSuper == null) initializerOrSuper = init; | |
| 141 } | |
| 142 | |
| 143 SourceString getConstructorName(ClassElement cls, Send node) { | |
| 144 SourceString constructor = node.selector.asIdentifier().source; | |
| 145 if (node.receiver !== null) { | |
| 146 return new SourceString('${cls.name}.$constructor'); | |
| 147 } else { | |
| 148 return cls.name; | |
| 149 } | |
| 150 } | |
| 151 | |
| 152 void resolveSuperOrThis(Send call, Node next) { | |
| 153 noConstructor(e) { | |
| 154 if (e !== null) error(call, MessageKind.NO_CONSTRUCTOR, [e.name, e.kind]); | |
| 155 } | |
| 156 | |
| 157 ClassElement lookupTarget = constructor.enclosingElement; | |
| 158 if (call.isSuperConstructorCall) { | |
| 159 // Check for invalid initializers. | |
| 160 if (hasSuper) { | |
| 161 error(call, MessageKind.DUPLICATE_SUPER_INITIALIZER); | |
| 162 } | |
| 163 if (initializerOrSuper == null) initializerOrSuper = call; | |
| 164 hasSuper = true; | |
| 165 // Calculate correct lookup target and constructor name. | |
| 166 if (constructor.name === Types.OBJECT) { | |
|
ngeoffray
2012/01/19 08:56:12
Shouldn't that just be lookupTarget === Types.OBJE
karlklose
2012/01/19 13:51:24
Done.
| |
| 167 error(call, MessageKind.SUPER_INITIALIZER_IN_OBJECT); | |
|
ngeoffray
2012/01/19 08:56:12
Should you return here? Otherwise you would do a l
karlklose
2012/01/19 13:51:24
I skipped the lookup in this case but still resolv
ngeoffray
2012/01/19 14:36:33
Good point.
| |
| 168 } else { | |
| 169 lookupTarget = lookupTarget.supertype.element; | |
| 170 } | |
| 171 } else if (call.isConstructorRedirect) { | |
| 172 // Check that there are no other initializers. | |
| 173 if (initializerOrSuper !== null || next !== null) { | |
| 174 Node diagnosticNode = | |
| 175 initializerOrSuper !== null ? initializerOrSuper | |
| 176 : next; | |
| 177 error(diagnosticNode, | |
| 178 MessageKind.REDIRECTING_CTOR_HAS_INITIALIZER); | |
| 179 } | |
| 180 } else { | |
| 181 visitor.error(call, MessageKind.CONSTRUCTOR_CALL_EXPECTED); | |
| 182 } | |
| 183 | |
| 184 final SourceString name = getConstructorName(lookupTarget, call); | |
| 185 FunctionElement target = | |
| 186 lookupTarget.lookupConstructor(name, noConstructor); | |
| 187 if (target === null && call.arguments.isEmpty()) { | |
| 188 target = lookupTarget.getSynthesizedConstructor(); | |
| 189 } | |
| 190 if (target === null) { | |
| 191 error(call, MessageKind.CANNOT_RESOLVE, ["constructor $name"]); | |
|
ngeoffray
2012/01/19 08:56:12
Maybe add a CANNOT_RESOLVE_CONSTRUCTOR, to avoid h
karlklose
2012/01/19 13:51:24
Done.
| |
| 192 } else { | |
|
ngeoffray
2012/01/19 08:56:12
The parameters may already there, so I don't think
karlklose
2012/01/19 13:51:24
Done.
| |
| 193 final Compiler compiler = visitor.compiler; | |
| 194 final FunctionExpression targetNode = | |
| 195 target.parseNode(compiler, compiler); | |
| 196 // TODO(karlklose): support optional arguments. | |
| 197 if (targetNode.parameterCount() != call.argumentCount()) { | |
| 198 error(call, MessageKind.NO_MATCHING_CONSTRUCTOR); | |
| 199 } | |
| 200 } | |
| 201 visitor.compiler.enqueue(new WorkItem.toCompile(target)); | |
|
ngeoffray
2012/01/19 08:56:12
You should leave the codegen deciding if it should
karlklose
2012/01/19 13:51:24
Done.
| |
| 202 visitor.useElement(call, target); | |
| 203 // Resolve the arguments of the call. | |
| 204 for (Link<Node> arguments = call.arguments; | |
| 205 !arguments.isEmpty(); | |
| 206 arguments = arguments.tail) { | |
| 207 visitor.visitInStaticContext(arguments.head); | |
| 208 } | |
| 209 } | |
| 210 | |
| 211 void resolveInitializers(FunctionExpression node) { | |
| 212 if (node.initializers === null) return; | |
| 213 Compiler compiler = visitor.compiler; | |
| 214 // TODO(karlklose): implement initializer parameters. | |
|
ngeoffray
2012/01/19 08:56:12
Please add an unimplemented where this is not hand
karlklose
2012/01/19 13:51:24
This is not unimplemented here, it was only a note
ngeoffray
2012/01/19 14:36:33
I see. Thanks for the explanation.
| |
| 215 for (Link<Node> link = node.initializers.nodes; | |
| 216 !link.isEmpty(); | |
| 217 link = link.tail) { | |
| 218 if (link.head.asSendSet() != null) { | |
| 219 final SendSet init = link.head.asSendSet(); | |
| 220 resolveFieldInitializer(init); | |
| 221 } else if (link.head.asSend() !== null) { | |
| 222 final Send call = link.head.asSend(); | |
| 223 resolveSuperOrThis(call, link.tail.isEmpty() ? null : link.tail.head); | |
| 224 } else { | |
| 225 visitor.compiler.cancel('internal error: invalid initializer', | |
| 226 node: link.head); | |
| 227 } | |
| 228 } | |
| 229 } | |
| 230 } | |
| 231 | |
| 232 | |
| 137 // TODO(ahe): Frog cannot handle generic types. | 233 // TODO(ahe): Frog cannot handle generic types. |
| 138 class ResolverVisitor extends AbstractVisitor/*<Element>*/ { | 234 class ResolverVisitor extends AbstractVisitor/*<Element>*/ { |
| 139 final Compiler compiler; | 235 final Compiler compiler; |
| 140 final TreeElements mapping; | 236 final TreeElements mapping; |
| 141 final Element enclosingElement; | 237 final Element enclosingElement; |
| 142 bool inInstanceContext; | 238 bool inInstanceContext; |
| 143 Scope context; | 239 Scope context; |
| 144 ClassElement currentClass; | 240 ClassElement currentClass; |
| 145 bool typeRequired = false; | 241 bool typeRequired = false; |
| 146 | 242 |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 173 compiler.reportWarning(node, warning); | 269 compiler.reportWarning(node, warning); |
| 174 } | 270 } |
| 175 | 271 |
| 176 cancel(Node node, String message) { | 272 cancel(Node node, String message) { |
| 177 compiler.cancel(message, node: node); | 273 compiler.cancel(message, node: node); |
| 178 } | 274 } |
| 179 | 275 |
| 180 Element lookup(Node node, SourceString name) { | 276 Element lookup(Node node, SourceString name) { |
| 181 Element result = context.lookup(name); | 277 Element result = context.lookup(name); |
| 182 if (!inInstanceContext && result != null && result.isInstanceMember()) { | 278 if (!inInstanceContext && result != null && result.isInstanceMember()) { |
| 183 error(node, MessageKind.NOT_STATIC, [node]); | 279 error(node, MessageKind.NO_INSTANCE_AVAILABLE, [node]); |
| 184 } | 280 } |
| 185 return result; | 281 return result; |
| 186 } | 282 } |
| 187 | 283 |
| 188 visitInStaticContext(Node node) { | 284 visitInStaticContext(Node node) { |
| 189 bool wasInstanceContext = inInstanceContext; | 285 bool wasInstanceContext = inInstanceContext; |
| 190 inInstanceContext = false; | 286 inInstanceContext = false; |
| 191 visit(node); | 287 visit(node); |
| 192 inInstanceContext = wasInstanceContext; | 288 inInstanceContext = wasInstanceContext; |
| 193 } | 289 } |
| 194 | 290 |
| 195 visit(Node node) { | 291 visit(Node node) { |
| 196 if (node == null) return null; | 292 if (node == null) return null; |
| 197 return node.accept(this); | 293 return node.accept(this); |
| 198 } | 294 } |
| 199 | 295 |
| 200 visitIdentifier(Identifier node) { | 296 visitIdentifier(Identifier node) { |
| 201 if (node.isThis()) { | 297 if (node.isThis() || node.isSuper()) { |
|
ngeoffray
2012/01/19 08:56:12
This is already handled line 302.
karlklose
2012/01/19 13:51:24
Done.
| |
| 202 if (!inInstanceContext) error(node, MessageKind.NO_THIS_IN_STATIC); | 298 if (!inInstanceContext) { |
| 299 error(node, MessageKind.NO_INSTANCE_AVAILABLE, [node]); | |
| 300 } | |
| 203 return null; | 301 return null; |
| 204 } else if (node.isSuper()) { | 302 } else if (node.isSuper()) { |
| 205 if (!inInstanceContext) error(node, MessageKind.NO_SUPER_IN_STATIC); | 303 if (!inInstanceContext) error(node, MessageKind.NO_SUPER_IN_STATIC); |
| 206 return null; | 304 return null; |
| 207 } else { | 305 } else { |
| 208 Element element = lookup(node, node.source); | 306 Element element = lookup(node, node.source); |
| 209 if (element == null) { | 307 if (element == null) { |
| 210 error(node, MessageKind.CANNOT_RESOLVE, [node]); | 308 error(node, MessageKind.CANNOT_RESOLVE, [node]); |
| 211 } | 309 } |
| 212 return useElement(node, element); | 310 return useElement(node, element); |
| 213 } | 311 } |
| 214 } | 312 } |
| 215 | 313 |
| 216 visitTypeAnnotation(TypeAnnotation node) { | 314 visitTypeAnnotation(TypeAnnotation node) { |
| 217 Identifier name = node.typeName.asIdentifier(); | 315 SourceString className; |
| 218 if (name === null) { | 316 if (node.typeName.asSend() !== null) { |
| 219 // TODO(karlklose): In progress. | 317 // In new and const expressions, the type name can be a Send to |
| 220 cancel(node.typeName, "not implemented"); | 318 // denote named parameters or library prefixes. |
|
ngeoffray
2012/01/19 08:56:12
named parameters -> named constructor?
karlklose
2012/01/19 13:51:24
Done.
| |
| 319 Send send = node.typeName.asSend(); | |
| 320 className = send.receiver.asIdentifier().source; | |
| 321 } else { | |
| 322 className = node.typeName.asIdentifier().source; | |
| 221 } | 323 } |
| 222 if (name.source == const SourceString('var')) return null; | 324 if (className == const SourceString('var')) return null; |
| 223 if (name.source == const SourceString('void')) return null; | 325 if (className == const SourceString('void')) return null; |
| 224 Element element = context.lookup(name.source); | 326 Element element = context.lookup(className); |
| 225 if (element === null) { | 327 if (element === null) { |
| 226 if (typeRequired) { | 328 if (typeRequired) { |
| 227 error(node, MessageKind.CANNOT_RESOLVE_TYPE, [name]); | 329 error(node, MessageKind.CANNOT_RESOLVE_TYPE, [className]); |
| 228 } else { | 330 } else { |
| 229 warning(node, MessageKind.CANNOT_RESOLVE_TYPE, [name]); | 331 warning(node, MessageKind.CANNOT_RESOLVE_TYPE, [className]); |
| 230 } | 332 } |
| 231 } else if (element.kind !== ElementKind.CLASS) { | 333 } else if (element.kind !== ElementKind.CLASS) { |
| 232 if (typeRequired) { | 334 if (typeRequired) { |
| 233 error(node, MessageKind.NOT_A_TYPE, [name]); | 335 error(node, MessageKind.NOT_A_TYPE, [className]); |
| 234 } else { | 336 } else { |
| 235 warning(node, MessageKind.NOT_A_TYPE, [name]); | 337 warning(node, MessageKind.NOT_A_TYPE, [className]); |
| 236 } | 338 } |
| 237 } else { | 339 } else { |
| 238 ClassElement cls = element; | 340 ClassElement cls = element; |
| 239 compiler.resolver.toResolve.add(element); | 341 compiler.resolver.toResolve.add(element); |
| 240 // TODO(ahe): This should be a Type. | 342 // TODO(ahe): This should be a Type. |
| 241 useElement(node, element); | 343 useElement(node, element); |
| 242 } | 344 } |
| 243 return element; | 345 return element; |
| 244 } | 346 } |
| 245 | 347 |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 324 } | 426 } |
| 325 | 427 |
| 326 visitFor(For node) { | 428 visitFor(For node) { |
| 327 Scope scope = new BlockScope(context); | 429 Scope scope = new BlockScope(context); |
| 328 visitIn(node.initializer, scope); | 430 visitIn(node.initializer, scope); |
| 329 visitIn(node.condition, scope); | 431 visitIn(node.condition, scope); |
| 330 visitIn(node.update, scope); | 432 visitIn(node.update, scope); |
| 331 visitIn(node.body, scope); | 433 visitIn(node.body, scope); |
| 332 } | 434 } |
| 333 | 435 |
| 334 visitFunctionExpression(FunctionExpression node) { | 436 visitFunctionExpression(FunctionExpression node) { |
|
ngeoffray
2012/01/19 08:56:12
I don't think you can be here for a constructor. T
karlklose
2012/01/19 13:51:24
Done.
| |
| 335 visit(node.returnType); | 437 visit(node.returnType); |
| 438 SourceString name; | |
| 336 if (node.name === null) { | 439 if (node.name === null) { |
| 337 cancel(node, "anonymous functions are not implemented"); | 440 cancel(node, "anonymous functions are not implemented"); |
| 338 } | 441 } else if (node.name.asSend() != null) { |
| 339 if (node.name.asIdentifier() === null) { | 442 Identifier cls = node.asSend().receiver.asIdentifier(); |
| 340 cancel(node.name, "named constructors are not implemented"); | 443 Identifier constructor = node.asSend().selector.asIdentifier(); |
| 444 name = new SourceString('${cls.source}.${constructor.source}'); | |
| 445 } else { | |
| 446 name = node.name.asIdentifier().source; | |
| 341 } | 447 } |
| 342 FunctionElement enclosingElement = new FunctionElement.node( | 448 FunctionElement enclosingElement = new FunctionElement.node( |
| 343 node, ElementKind.FUNCTION, null, context.element); | 449 name, node, ElementKind.FUNCTION, null, context.element); |
| 344 defineElement(node, enclosingElement); | 450 defineElement(node, enclosingElement); |
| 345 context = new MethodScope(context, enclosingElement); | 451 context = new MethodScope(context, enclosingElement); |
| 346 | 452 |
| 347 // TODO(ahe): Can this be cleaned up to use resolveSignature? | 453 // TODO(ahe): Can this be cleaned up to use resolveSignature? |
| 348 ParametersVisitor visitor = new ParametersVisitor(this); | 454 ParametersVisitor visitor = new ParametersVisitor(this); |
| 349 visitor.visit(node.parameters); | 455 visitor.visit(node.parameters); |
| 350 enclosingElement.parameters = visitor.elements.toLink(); | 456 enclosingElement.parameters = visitor.elements.toLink(); |
| 351 | 457 |
| 352 visit(node.body); | 458 visit(node.body); |
| 353 context = context.parent; | 459 context = context.parent; |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 510 | 616 |
| 511 visitParenthesizedExpression(ParenthesizedExpression node) { | 617 visitParenthesizedExpression(ParenthesizedExpression node) { |
| 512 visit(node.expression); | 618 visit(node.expression); |
| 513 } | 619 } |
| 514 | 620 |
| 515 visitNewExpression(NewExpression node) { | 621 visitNewExpression(NewExpression node) { |
| 516 if (node.isConst()) cancel(node, 'const expressions are not implemented'); | 622 if (node.isConst()) cancel(node, 'const expressions are not implemented'); |
| 517 | 623 |
| 518 visit(node.send.argumentsNode); | 624 visit(node.send.argumentsNode); |
| 519 | 625 |
| 626 SourceString constructorName; | |
| 627 Node typeName = node.send.selector.asTypeAnnotation().typeName; | |
| 628 if (typeName.asSend() !== null) { | |
| 629 Identifier receiver = typeName.asSend().receiver.asIdentifier(); | |
| 630 Identifier selector = typeName.asSend().selector.asIdentifier(); | |
| 631 SourceString className = receiver.source; | |
| 632 SourceString name = selector.source; | |
| 633 constructorName = new SourceString('$className.$name'); | |
| 634 } else { | |
| 635 constructorName = typeName.asIdentifier().source; | |
| 636 } | |
| 520 ClassElement cls = resolveTypeRequired(node.send.selector); | 637 ClassElement cls = resolveTypeRequired(node.send.selector); |
| 521 Element constructor = null; | 638 Element constructor = null; |
| 522 if (cls !== null) { | 639 if (cls !== null) { |
| 523 // TODO(ngeoffray): set constructor-name correctly. | 640 constructor = cls.resolve(compiler).lookupConstructor(constructorName); |
| 524 SourceString name = cls.name; | 641 if (constructorName == cls.name |
| 525 constructor = cls.resolve(compiler).lookupConstructor(name); | |
| 526 if (name == cls.name | |
| 527 && constructor === null | 642 && constructor === null |
| 528 && node.send.argumentsNode.isEmpty()) { | 643 && node.send.argumentsNode.isEmpty()) { |
| 529 constructor = cls.getSynthesizedConstructor(); | 644 constructor = cls.getSynthesizedConstructor(); |
| 530 } | 645 } |
| 531 if (constructor === null) { | 646 if (constructor === null) { |
| 532 error(node, MessageKind.CANNOT_FIND_CONSTRUCTOR, [node]); | 647 error(node.send, MessageKind.CANNOT_FIND_CONSTRUCTOR, [node.send]); |
| 648 } else { | |
| 649 FunctionExpression fun = constructor.parseNode(compiler, compiler); | |
|
ngeoffray
2012/01/19 08:56:12
Same comment for resolveSignature.
karlklose
2012/01/19 13:51:24
Done.
| |
| 650 // TODO(karlklose): handle optional arguments. | |
| 651 if (node.send.argumentCount() != fun.parameterCount()) { | |
| 652 error(node.send, MessageKind.CANNOT_FIND_CONSTRUCTOR, [node.send]); | |
| 653 } | |
| 533 } | 654 } |
| 655 } else { | |
| 656 Node selector = node.send.selector; | |
| 657 error(selector, MessageKind.CANNOT_RESOLVE_TYPE, [selector]); | |
| 534 } | 658 } |
| 535 | |
| 536 useElement(node.send, constructor); | 659 useElement(node.send, constructor); |
| 537 return null; | 660 return null; |
| 538 } | 661 } |
| 539 | 662 |
| 540 ClassElement resolveTypeRequired(Node node) { | 663 ClassElement resolveTypeRequired(Node node) { |
| 541 bool old = typeRequired; | 664 bool old = typeRequired; |
| 542 typeRequired = true; | 665 typeRequired = true; |
| 543 ClassElement cls = visit(node); | 666 ClassElement cls = visit(node); |
| 544 typeRequired = old; | 667 typeRequired = old; |
| 545 return cls; | 668 return cls; |
| (...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 826 class TopScope extends Scope { | 949 class TopScope extends Scope { |
| 827 Universe universe; | 950 Universe universe; |
| 828 | 951 |
| 829 TopScope(Universe this.universe) : super(null, null); | 952 TopScope(Universe this.universe) : super(null, null); |
| 830 Element lookup(SourceString name) => universe.find(name); | 953 Element lookup(SourceString name) => universe.find(name); |
| 831 | 954 |
| 832 Element add(Element element) { | 955 Element add(Element element) { |
| 833 throw "Cannot add an element in the top scope"; | 956 throw "Cannot add an element in the top scope"; |
| 834 } | 957 } |
| 835 } | 958 } |
| OLD | NEW |