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