Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(19)

Unified Diff: frog/leg/resolver.dart

Issue 8974014: Resolve initializers in constructors. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address 2nd round of comments. Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « frog/leg/elements/elements.dart ('k') | frog/leg/warnings.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: frog/leg/resolver.dart
diff --git a/frog/leg/resolver.dart b/frog/leg/resolver.dart
index 53de406c79b9ef8f1c2cad1509a379b28d940dc8..8d2a9d4ceac62f617c52b840eec7140394b5378c 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,59 @@ class ResolverTask extends CompilerTask {
});
}
+ bool isInitializer(SendSet node) {
+ if (node.selector.asIdentifier() == null) return false;
+ if (node.receiver == null) return true;
+ if (node.receiver.asIdentifier() == null) return false;
+ return node.receiver.asIdentifier().isThis();
+ }
+
+ SourceString getInitializerFieldName(SendSet node, onError(node)) {
+ if (!isInitializer(node)) onError(node);
+ return node.selector.asIdentifier().source;
+ }
+
+ void resolveInitializers(Element element, FunctionExpression node,
+ ResolverVisitor visitor) {
+ void onError(node) {
+ visitor.error(node, MessageKind.INVALID_RECEIVER_IN_INITIALIZER);
+ }
+ 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 = getInitializerFieldName(init, onError);
ngeoffray 2011/12/21 16:44:08 If it's not an identifier, what do you get as a na
+ ClassElement classElement = element.enclosingElement;
+ Element target = classElement.lookupLocalElement(name);
ngeoffray 2011/12/21 16:44:08 lookupLocalElement -> lookupLocalMember (after mer
+ 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.error(init, MessageKind.DUPLICATE_INITIALIZER, [name]);
+ visitor.warning(initialized[name], MessageKind.ALREADY_INITIALIZED,
+ [name]);
ngeoffray 2011/12/21 16:44:08 @ahe: not sure, but splitting the warning in two,
+ }
+ initialized[name] = init;
+ Node value = init.arguments.head;
+ visitor.visitInStaticContext(value);
+ } else if (link.head.asSend() !== null) {
+ // TODO(karlklose): super(...), this(...).
+ compiler.cancel('uniplemented', node:link.head);
ngeoffray 2011/12/21 16:44:08 uniMplemented
+ } else {
+ compiler.cancel('internal error: invalid initializer',
+ node: link.head);
+ }
+ }
+ }
+
void resolveType(ClassElement element) {
measure(() {
ClassNode tree = element.node;
@@ -92,6 +144,21 @@ class ResolverVisitor implements Visitor<Element> {
compiler.cancel(message);
}
+ Element lookup(Node node, SourceString name) {
+ Element result = context.lookup(name);
+ if (!inInstanceContext && result != null && result.isInstanceMember()) {
+ error(node, MessageKind.NOT_STATIC, [node]);
+ }
+ return result;
+ }
+
+ visitInStaticContext(Node node) {
+ bool wasInstanceContext = inInstanceContext;
+ inInstanceContext = false;
+ visit(node);
+ inInstanceContext = wasInstanceContext;
+ }
+
visit(Node node) {
if (node == null) return null;
return node.accept(this);
@@ -102,7 +169,7 @@ class ResolverVisitor implements Visitor<Element> {
if (!inInstanceContext) error(node, MessageKind.NO_THIS_IN_STATIC);
return null;
} else {
- Element element = context.lookup(node.source);
+ Element element = lookup(node, node.source);
if (element == null) {
error(node, MessageKind.CANNOT_RESOLVE, [node]);
}
@@ -153,7 +220,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);
@@ -308,7 +374,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 = visit(node);
if (target == null && !enclosingElement.isInstanceMember()) {
error(node, MessageKind.CANNOT_RESOLVE, [name]);
}
@@ -352,7 +418,7 @@ class FullResolverVisitor extends ResolverVisitor {
if (node.isIndex) {
getter = target;
} else {
- getter = context.lookup(node.selector.asIdentifier().source);
+ getter = visit(node);
}
useElement(node.selector, getter);
}
@@ -569,7 +635,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 {
« no previous file with comments | « frog/leg/elements/elements.dart ('k') | frog/leg/warnings.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698