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

Unified Diff: lib/compiler/implementation/resolver.dart

Issue 10854158: Make selector registration in the resolver and code generator more explicit. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Merge from master. Created 8 years, 4 months 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: lib/compiler/implementation/resolver.dart
diff --git a/lib/compiler/implementation/resolver.dart b/lib/compiler/implementation/resolver.dart
index 8e7b7a3edb9f7fbcacd6d8e59598e88020f66081..ea8913a7c06491519fdbde5553ed98f71a71ac4f 100644
--- a/lib/compiler/implementation/resolver.dart
+++ b/lib/compiler/implementation/resolver.dart
@@ -449,6 +449,7 @@ class InitializerResolver {
error(init, MessageKind.INVALID_RECEIVER_IN_INITIALIZER);
}
visitor.useElement(init, target);
+ visitor.world.registerStaticUse(target);
// Check for duplicate initializers.
if (initialized.containsKey(name)) {
error(init, MessageKind.DUPLICATE_INITIALIZER, [name]);
@@ -466,7 +467,7 @@ class InitializerResolver {
ResolverTask resolver = visitor.compiler.resolver;
visitor.inStaticContext(() {
visitor.resolveSelector(call);
- visitor.visitArguments(call.argumentsNode);
+ visitor.resolveArguments(call.argumentsNode);
});
Selector selector = visitor.mapping.getSelector(call);
bool isSuperCall = Initializers.isSuperConstructorCall(call);
@@ -474,6 +475,7 @@ class InitializerResolver {
Element result = resolveSuperOrThis(
constructor, isSuperCall, false, constructorName, selector, call);
visitor.useElement(call, result);
+ visitor.world.registerStaticUse(result);
return result;
}
@@ -963,24 +965,6 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
Element useElement(Node node, Element element) {
if (element === null) return null;
mapping[node] = element;
- if (element.isTopLevel() || element.isMember()) {
- if (element.isInstanceMember()) {
- var send = node.asSend();
- if (send !== null) {
- Selector selector = mapping.getSelector(send);
- if (selector !== null) {
- world.registerDynamicInvocation(element.name, selector);
- }
- }
- } else {
- if (!element.isPrefix() &&
- !element.isClass() &&
- !element.isTypedef() &&
- !element.isTypeVariable()) {
- world.registerStaticUse(element);
- }
- }
- }
return element;
ahe 2012/08/15 14:32:21 These two lines can be merged. And yay!
kasperl 2012/08/16 10:35:47 Done.
}
@@ -1185,7 +1169,7 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
static Selector computeSendSelector(Send node, LibraryElement library) {
// First determine if this is part of an assignment.
- bool isSet = node is SendSet;
+ bool isSet = node.asSendSet() !== null;
if (node.isIndex) {
return isSet ? new Selector.indexSet() : new Selector.index();
@@ -1193,12 +1177,12 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
if (node.isOperator) {
SourceString source = node.selector.asOperator().source;
- switch (source.stringValue) {
- case '!' : case '&&' : case '||':
- case 'is' : case 'as' :
- case '===': case '!==':
- case '>>>':
- return null;
+ String string = source.stringValue;
+ if (string === '!' || string === '&&' || string == '||' ||
+ string === 'is' || string === 'as' ||
+ string === '===' || string === '!==' ||
+ string === '>>>') {
+ return null;
}
return node.arguments.isEmpty()
? new Selector.unaryOperator(source)
@@ -1220,17 +1204,16 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
!link.isEmpty();
link = link.tail) {
Expression argument = link.head;
- if (argument.asNamedArgument() != null) {
- named.add((argument as NamedArgument).name.source);
+ NamedArgument namedArgument = argument.asNamedArgument();
+ if (namedArgument !== null) {
+ named.add(namedArgument.name.source);
}
arity++;
}
- // If we're invoking a closure, we do not have an identifier. In
- // that case, we create a wildcard selector that can call any
- // method that may have been closurized.
- return (identifier == null)
- ? new Selector.callAny(arity, named)
+ // If we're invoking a closure, we do not have an identifier.
+ return (identifier === null)
+ ? new Selector.callClosure(arity, named)
: new Selector.call(identifier.source, library, arity, named);
}
@@ -1241,7 +1224,8 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
return selector;
}
- void visitArguments(NodeList list) {
+ void resolveArguments(NodeList list) {
+ if (list === null) return;
bool seenNamedArgument = false;
for (Link<Node> link = list.nodes; !link.isEmpty(); link = link.tail) {
Expression argument = link.head;
@@ -1256,42 +1240,41 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
visitSend(Send node) {
Element target = resolveSend(node);
+ if (target != null && target.kind == ElementKind.ABSTRACT_FIELD) {
+ AbstractFieldElement field = target;
+ target = field.getter;
+ }
+
+ bool resolvedArguments = false;
if (node.isOperator) {
- Operator op = node.selector.asOperator();
- if (op.source.stringValue === 'is' || op.source.stringValue === 'as') {
- resolveTypeTest(node.arguments.head);
+ String operatorString = node.selector.asOperator().source.stringValue;
+ if (operatorString === 'is' || operatorString === 'as') {
assert(node.arguments.tail.isEmpty());
- } else if (node.arguments.isEmpty()) {
- assert(op.token.kind !== PLUS_TOKEN);
- } else {
- visit(node.argumentsNode);
+ resolveTypeTest(node.arguments.head);
+ resolvedArguments = true;
}
- } else if (node.isIndex) {
- visit(node.argumentsNode);
- assert(node.arguments.tail.isEmpty());
- } else if (node.isPropertyAccess) {
- // Nothing to do here.
- } else {
- visitArguments(node.argumentsNode);
}
- if (target != null && target.kind == ElementKind.ABSTRACT_FIELD) {
- AbstractFieldElement field = target;
- target = field.getter;
+ if (!resolvedArguments) {
+ resolveArguments(node.argumentsNode);
}
+
+ // If the selector is null, it means that we will not be generating
+ // code for this as a send.
+ Selector selector = mapping.getSelector(node);
+ if (selector === null) return;
+
+ // If we don't know what we're calling or if we are calling a getter,
+ // we need to register that fact that we may be calling a closure
+ // with the same arguments.
if (node.isCall &&
(target === null ||
target.isGetter() ||
Elements.isClosureSend(node, target))) {
- Selector selector = mapping.getSelector(node);
- Selector call = new Selector.call(
- compiler.namer.CLOSURE_INVOCATION_NAME,
- selector.library,
- selector.argumentCount,
- selector.namedArguments);
- world.registerDynamicInvocation(compiler.namer.CLOSURE_INVOCATION_NAME,
- call);
+ Selector call = new Selector.callClosureFrom(selector);
+ world.registerDynamicInvocation(call.name, call);
}
+
// TODO(ngeoffray): We should do the check in
// visitExpressionStatement instead.
if (target === compiler.assertMethod && !node.isCall) {
@@ -1301,83 +1284,59 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
}
target = null;
}
+
// TODO(ngeoffray): Warn if target is null and the send is
// unqualified.
useElement(node, target);
- if (target === null) registerDynamicSend(node);
- if (node.isPropertyAccess) return target;
+ registerSend(node, selector, target);
+ return node.isPropertyAccess ? target : null;
}
visitSendSet(SendSet node) {
Element target = resolveSend(node);
- Element setter = null;
- Element getter = null;
+ Element setter = target;
+ Element getter = target;
if (target != null && target.kind == ElementKind.ABSTRACT_FIELD) {
AbstractFieldElement field = target;
setter = field.setter;
getter = field.getter;
- } else {
- setter = target;
- getter = target;
}
+
+ visit(node.argumentsNode);
+
// TODO(ngeoffray): Check if the target can be assigned.
+ // TODO(ngeoffray): Warn if target is null and the send is
+ // unqualified.
+
+ Selector selector = mapping.getSelector(node);
Identifier identifier = node.assignmentOperator;
- bool compoundAssignment = identifier.source.stringValue !== '=';
- if (compoundAssignment) {
+ bool isCompound = identifier.source.stringValue !== '=';
floitsch 2012/08/15 14:14:04 this should be a predicate on the SendSet node. No
+ if (isCompound) {
useElement(node.selector, getter);
+ registerSend(node, new Selector.getterFrom(selector), getter);
}
- visit(node.argumentsNode);
- // TODO(ngeoffray): Warn if target is null and the send is
- // unqualified.
- registerDynamicSend(node);
+
+ registerSend(node, selector, setter);
return useElement(node, setter);
}
- registerDynamicSend(Send node) {
- Identifier id = node.selector.asIdentifier();
- if (id === null) return;
- SourceString name = node.selector.asIdentifier().source;
- if (node.isIndex && node is SendSet) {
- name = Elements.constructOperatorName(
- const SourceString('operator'),
- const SourceString('[]='));
- } else if (node.selector.asOperator() != null) {
- switch (name.stringValue) {
- case '===':
- case '!==':
- case '!':
- case '&&':
- case '||':
- case 'is':
- case 'as':
- case '>>>':
- return null;
- }
- name = Elements.constructOperatorName(
- const SourceString('operator'),
- name,
- node.argumentsNode is Prefix);
- }
- Selector selector = mapping.getSelector(node);
- if (selector.isGetter()) {
- world.registerDynamicGetter(name, selector);
- } else if (selector.isSetter()) {
- world.registerDynamicSetter(name, selector);
- // Also register the getter for compound assignments.
- LibraryElement library = enclosingElement.getLibrary();
- Selector getter = new Selector.getter(name, library);
- world.registerDynamicGetter(name, getter);
- } else {
- if (selector.isIndexSet()) {
- // Also register the index selector for compound assignments.
- Selector index = new Selector.index();
- world.registerDynamicInvocation(index.name, index);
+ void registerSend(Node node, Selector selector, Element target) {
+ if (target === null || target.isInstanceMember()) {
+ if (selector.isGetter()) {
+ world.registerDynamicGetter(selector.name, selector);
+ } else if (selector.isSetter()) {
+ world.registerDynamicSetter(selector.name, selector);
+ } else {
+ world.registerDynamicInvocation(selector.name, selector);
}
- world.registerDynamicInvocation(name, selector);
+ } else if (Elements.isStaticOrTopLevel(target)) {
+ world.registerStaticUse(target);
}
+
+ // TODO(kasperl): Pass the selector directly.
var interceptor = new Interceptors(compiler).getStaticInterceptor(
- name,
- node.argumentCount());
+ selector.name,
+ selector.argumentCount);
if (interceptor !== null) {
world.registerStaticUse(interceptor);
}
@@ -1442,7 +1401,7 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
FunctionElement constructor = resolveConstructor(node);
resolveSelector(node.send);
- visitArguments(node.send.argumentsNode);
+ resolveArguments(node.send.argumentsNode);
if (constructor === null) return null;
// TODO(karlklose): handle optional arguments.
if (node.send.argumentCount() != constructor.parameterCount(compiler)) {
@@ -1451,6 +1410,7 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
// List constructor.
}
useElement(node.send, constructor);
+ world.registerStaticUse(constructor);
compiler.withCurrentElement(constructor, () {
FunctionExpression tree = constructor.parseNode(compiler);
compiler.resolver.resolveConstructorImplementation(constructor, tree);

Powered by Google App Engine
This is Rietveld 408576698