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

Unified Diff: sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart

Issue 12434002: Infer SendSet node correctly. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 10 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
« no previous file with comments | « no previous file | tests/compiler/dart2js/simple_inferrer_postfix_prefix_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart
===================================================================
--- sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart (revision 19455)
+++ sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart (working copy)
@@ -747,7 +747,7 @@
});
}
if (analyzedElement.isField()) {
- returnType = visit(node);
+ returnType = visit(node.asSendSet().arguments.head);
} else if (analyzedElement.isGenerativeConstructor()) {
FunctionElement function = analyzedElement;
FunctionSignature signature = function.computeSignature(compiler);
@@ -898,49 +898,102 @@
return compiler.dynamicClass;
}
- Operator op = node.assignmentOperator;
- if (node.isSuperCall) {
- // [: super.foo = 42 :] or [: super.foo++ :] or [: super.foo += 1 :].
- node.visitChildren(this);
- return compiler.dynamicClass;
- } else if (node.isIndex) {
- if (const SourceString("=") == op.source) {
+ Selector getterSelector =
+ elements.getGetterSelectorInComplexSendSet(node);
+ Selector operatorSelector =
+ elements.getOperatorSelectorInComplexSendSet(node);
+ Selector setterSelector = elements.getSelector(node);
+
+ String op = node.assignmentOperator.source.stringValue;
+ bool isIncrementOrDecrement = op == '++' || op == '--';
+
+ Element receiverType = element != null
+ ? compiler.dynamicClass
+ : visit(node.receiver);
+
+ Element rhsType = isIncrementOrDecrement
+ ? compiler.intClass
+ : node.isIndex
+ ? visit(node.arguments.tail.head)
+ : visit(node.arguments.head);
+
+ if (node.isIndex) {
+ Element index = visit(node.arguments.head);
+ if (op == '=') {
// [: foo[0] = 42 :]
- visit(node.receiver);
- Element returnType;
- for (Node argument in node.arguments) {
- returnType = argument.accept(this);
- }
- return returnType;
+ handleDynamicSend(
+ setterSelector,
+ receiverType,
+ new ArgumentsTypes([index, rhsType], null));
+ return rhsType;
} else {
// [: foo[0] += 42 :] or [: foo[0]++ :].
- node.visitChildren(this);
- return compiler.dynamicClass;
+ Element getterType = handleDynamicSend(
+ getterSelector,
+ receiverType,
+ new ArgumentsTypes([index], null));
+ Element returnType = handleDynamicSend(
+ operatorSelector,
+ getterType,
+ new ArgumentsTypes([rhsType], null));
+ handleDynamicSend(
+ setterSelector,
+ receiverType,
+ new ArgumentsTypes([index, returnType], null));
+
+ if (node.isPostfix) {
+ return getterType;
+ } else {
+ return returnType;
+ }
}
- } else if (const SourceString("=") == op.source) {
+ } else if (op == '=') {
// [: foo = 42 :] or [: foo.bar = 42 :].
- if (element == null) {
- visit(node.receiver);
- }
- Link<Node> link = node.arguments;
- assert(!link.isEmpty && link.tail.isEmpty);
- Element type = link.head.accept(this);
-
- if (!Elements.isUnresolved(element)) {
- if (element.isField() && element.modifiers.isFinal()) {
- inferrer.recordFinalFieldType(outermostElement, element, type);
- } else if (element.isVariable()) {
- locals.update(element, type);
+ if (Elements.isUnresolved(element) || element.isSetter()) {
+ handleDynamicSend(
+ setterSelector, receiverType, new ArgumentsTypes([rhsType], null));
+ } else if (element.isField()) {
+ if (element.modifiers.isFinal()) {
+ inferrer.recordFinalFieldType(outermostElement, element, rhsType);
}
+ } else if (Elements.isLocal(element)) {
+ locals.update(element, rhsType);
}
- return type;
+ return rhsType;
} else {
// [: foo++ :] or [: foo += 1 :].
- assert(const SourceString("++") == op.source ||
- const SourceString("--") == op.source ||
- node.assignmentOperator.source.stringValue.endsWith("="));
- node.visitChildren(this);
- return compiler.dynamicClass;
+ Element getterType;
+ Element newType;
+ ArgumentsTypes operatorArguments = new ArgumentsTypes([rhsType], null);
+ if (Elements.isUnresolved(element) || element.isSetter()) {
+ getterType = handleDynamicSend(
+ getterSelector, receiverType, null);
+ newType = handleDynamicSend(
+ operatorSelector, getterType, operatorArguments);
+ handleDynamicSend(
+ setterSelector, receiverType, new ArgumentsTypes([newType], null));
+ } else if (element.isField()) {
+ assert(!element.modifiers.isFinal());
+ getterType = compiler.dynamicClass; // The type of the field.
+ newType = handleDynamicSend(
+ operatorSelector, getterType, operatorArguments);
+ } else if (Elements.isLocal(element)) {
+ getterType = locals.use(element);
+ newType = handleDynamicSend(
+ operatorSelector, getterType, operatorArguments);
+ locals.update(element, newType);
+ } else {
+ // Bogus SendSet, for example [: myMethod += 42 :].
+ getterType = compiler.dynamicClass;
+ newType = handleDynamicSend(
+ operatorSelector, getterType, operatorArguments);
+ }
+
+ if (node.isPostfix) {
+ return getterType;
+ } else {
+ return newType;
+ }
}
}
@@ -1102,8 +1155,7 @@
receiverType = node.receiver.accept(this);
}
Selector selector = elements.getSelector(node);
- inferrer.registerGetterOnSelector(outermostElement, selector);
- return inferrer.returnTypeOfSelector(selector);
+ return handleDynamicSend(selector, receiverType, null);
} else if (Elements.isStaticOrTopLevelFunction(element)) {
inferrer.registerGetFunction(outermostElement, element);
return compiler.functionClass;
@@ -1131,6 +1183,20 @@
return compiler.dynamicClass;
}
+ handleDynamicSend(Selector selector,
+ Element receiver,
+ ArgumentsTypes arguments) {
+ if (selector.isGetter()) {
+ assert(arguments == null);
+ inferrer.registerGetterOnSelector(outermostElement, selector);
+ } else if (selector.isSetter()) {
+ // TODO(ngeoffray): Register called setter.
+ } else {
+ inferrer.registerCalledSelector(outermostElement, selector, arguments);
+ }
+ return inferrer.returnTypeOfSelector(selector);
+ }
+
visitDynamicSend(Send node) {
ClassElement receiverType;
if (node.receiver == null) {
@@ -1140,8 +1206,7 @@
}
ArgumentsTypes arguments = analyzeArguments(node.arguments);
Selector selector = elements.getSelector(node);
- inferrer.registerCalledSelector(outermostElement, selector, arguments);
- return inferrer.returnTypeOfSelector(selector);
+ return handleDynamicSend(selector, receiverType, arguments);
}
visitReturn(Return node) {
« no previous file with comments | « no previous file | tests/compiler/dart2js/simple_inferrer_postfix_prefix_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698