Chromium Code Reviews| Index: frog/leg/resolver.dart |
| diff --git a/frog/leg/resolver.dart b/frog/leg/resolver.dart |
| index 5385643239268eff3fc5a95883dbd50667327e3e..4b1fd25b426607ca805d104c01b3b9f5cd529cf7 100644 |
| --- a/frog/leg/resolver.dart |
| +++ b/frog/leg/resolver.dart |
| @@ -20,14 +20,13 @@ class ResolverTask extends CompilerTask { |
| TreeElements resolve(FunctionElement element) { |
| return measure(() { |
| FunctionExpression tree = element.parseNode(compiler, compiler); |
| - if (tree.initializers !== null) { |
| - compiler.cancel('initializers are not implemented', |
| - node: tree.initializers); |
| - } |
| ResolverVisitor visitor = new SignatureResolverVisitor(compiler, element); |
| visitor.visit(tree); |
| visitor = new FullResolverVisitor.from(visitor); |
| + if (tree.initializers != null) { |
| + resolveInitializers(element, tree, visitor); |
| + } |
| visitor.visit(tree.body); |
| // Resolve the type annotations encountered in the method. |
| @@ -38,6 +37,42 @@ class ResolverTask extends CompilerTask { |
| }); |
| } |
| + void resolveInitializers(element, node, visitor) { |
|
ngeoffray
2011/12/21 11:52:11
Types on parameters?
ahe
2011/12/21 12:01:58
I'd like a type on node.
karlklose
2011/12/21 16:33:46
Done.
karlklose
2011/12/21 16:33:46
Done.
|
| + Map<SourceString, Node> initialized = new Map<SourceString, Node>(); |
| + for (Link<Node> link = node.initializers.nodes; |
| + !link.isEmpty(); |
| + link = link.tail) { |
| + if (link.head.asSendSet() != null) { |
| + SendSet init = link.head; |
| + SourceString name = init.getInitializerFieldName( |
| + () => visitor.error(init, |
| + MessageKind.INVALID_RECEIVER_IN_INITIALIZER)); |
| + ClassElement classElement = element.enclosingElement; |
| + Element target = classElement.lookupLocalElement(name); |
| + Node selector = init.selector; |
| + if (target == null) { |
| + visitor.error(selector, MessageKind.CANNOT_RESOLVE, [name]); |
| + } else if (target.kind != ElementKind.FIELD) { |
| + visitor.error(selector, MessageKind.NOT_A_FIELD, [name]); |
| + } else if (!target.isInstanceMember()) { |
| + visitor.error(selector, MessageKind.INIT_STATIC_FIELD, [name]); |
| + } |
| + visitor.useElement(init, target); |
| + if (initialized.containsKey(name)) { |
| + visitor.warning(init, MessageKind.DUPLICATE_INITIALIZER, |
|
ngeoffray
2011/12/21 11:52:11
The spec says it's a compile time error, so should
karlklose
2011/12/21 16:33:46
Done.
|
| + [name, initialized[name]]); |
| + } |
| + initialized[name] = init; |
| + Node value = init.arguments.head; |
| + visitor.visitInStaticContext(value); |
| + } else { |
| + // TODO(karlklose): super(...), this(...). |
| + compiler.cancel('internal error: invalid initializer', |
|
ngeoffray
2011/12/21 11:52:11
invalid -> unimplemented
ahe
2011/12/21 12:01:58
This is not an internal error, and the initializer
karlklose
2011/12/21 16:33:46
Done.
karlklose
2011/12/21 16:33:46
Done.
|
| + node: link.head); |
| + } |
| + } |
| + } |
| + |
| void resolveType(ClassElement element) { |
| measure(() { |
| ClassNode tree = element.node; |
| @@ -61,6 +96,7 @@ class ResolverVisitor implements Visitor<Element> { |
| final TreeElements mapping; |
| final Element enclosingElement; |
| Scope context; |
| + bool isStaticContext; |
|
ngeoffray
2011/12/21 11:52:11
isStaticContext always looks weird to me (is it a
karlklose
2011/12/21 16:33:46
Done.
|
| ResolverVisitor(Compiler compiler, Element element) |
| : this.compiler = compiler, |
| @@ -68,7 +104,8 @@ class ResolverVisitor implements Visitor<Element> { |
| this.enclosingElement = element, |
| this.context = element.isMember() |
| ? new ClassScope(element.enclosingElement, compiler.universe) |
| - : new TopScope(compiler.universe); |
| + : new TopScope(compiler.universe), |
| + this.isStaticContext = false; |
| ResolverVisitor.from(ResolverVisitor other) |
| : compiler = other.compiler, |
| @@ -90,13 +127,28 @@ class ResolverVisitor implements Visitor<Element> { |
| compiler.cancel(message); |
| } |
| + Element lookup(Node node, SourceString name) { |
| + Element result = context.lookup(name); |
| + if (isStaticContext && result != null && result.isInstanceMember()) { |
| + error(node, MessageKind.NOT_STATIC, [node]); |
| + } |
| + return result; |
| + } |
| + |
| + visitInStaticContext(Node node) { |
| + bool wasStaticContext = isStaticContext; |
| + isStaticContext = true; |
| + visit(node); |
| + isStaticContext = wasStaticContext; |
| + } |
| + |
| visit(Node node) { |
| if (node == null) return null; |
| return node.accept(this); |
| } |
| visitIdentifier(Identifier node) { |
| - Element element = context.lookup(node.source); |
| + Element element = lookup(node, node.source); |
| if (element == null) { |
| error(node, MessageKind.CANNOT_RESOLVE, [node]); |
| } |
| @@ -146,7 +198,6 @@ class SignatureResolverVisitor extends ResolverVisitor { |
| visitFunctionExpression(FunctionExpression node) { |
| useElement(node, element); |
| context = new MethodScope(context, element); |
| - |
| if (element.parameters == null) { |
| ParametersVisitor visitor = new ParametersVisitor(this); |
| visitor.visit(node.parameters); |
| @@ -300,7 +351,7 @@ class FullResolverVisitor extends ResolverVisitor { |
| SourceString opName = mapOperatorToMethodName(name, node.isPrefix); |
| target = compiler.universe.find(opName); |
| } else if (node.receiver === null) { |
| - target = context.lookup(name); |
| + target = lookup(node, name); |
|
ngeoffray
2011/12/21 11:52:11
I think this should be changed to target = visit(n
karlklose
2011/12/21 16:33:46
Done.
|
| if (target == null && !enclosingElement.isInstanceMember()) { |
| error(node, MessageKind.CANNOT_RESOLVE, [name]); |
| } |
| @@ -344,7 +395,7 @@ class FullResolverVisitor extends ResolverVisitor { |
| if (node.isIndex) { |
| getter = target; |
| } else { |
| - getter = context.lookup(node.selector.asIdentifier().source); |
| + getter = lookup(node, node.selector.asIdentifier().source); |
|
ngeoffray
2011/12/21 11:52:11
ditto.
karlklose
2011/12/21 16:33:46
Done.
|
| } |
| useElement(node.selector, getter); |
| } |
| @@ -566,7 +617,7 @@ class Scope { |
| Scope(this.parent, this.element); |
| abstract Element add(Element element); |
| - abstract Element lookup(Element element); |
| + abstract Element lookup(SourceString name); |
| } |
| class MethodScope extends Scope { |