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

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: Don't call function that does not exist. 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
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 {

Powered by Google App Engine
This is Rietveld 408576698