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

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

Issue 11272032: Handle compound operators. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Add name in TODO Created 8 years, 1 month 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/cpa_inference_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/concrete_types_inferrer.dart
diff --git a/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart b/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
index ec025ead89457d24c056e80241745435acd017dd..88d9fea4177f1d773af631b0f4c864a10ba34500 100644
--- a/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
@@ -484,7 +484,7 @@ class ConcreteTypesInferrer {
List<FunctionElement> getMembersByName(SourceString methodName) {
// TODO(polux): make this faster!
var result = new List<FunctionElement>();
- for (final cls in compiler.enqueuer.resolution.seenClasses) {
+ for (ClassElement cls in compiler.enqueuer.resolution.seenClasses) {
Element elem = cls.lookupLocalMember(methodName);
if (elem != null) {
result.add(elem);
@@ -992,55 +992,93 @@ class TypeInferrerVisitor extends ResolvedVisitor<ConcreteType> {
inferrer.fail(node, 'not yet implemented');
}
+ ConcreteType analyzeSetElement(Element receiver, ConcreteType argumentType) {
+ environment = environment.put(receiver, argumentType);
+ if (receiver.isField()) {
+ inferrer.augmentFieldType(receiver, argumentType);
+ } else if (receiver.isSetter()){
+ FunctionElement setter = receiver;
+ // TODO(polux): A setter always returns void so there's no need to
+ // invalidate its callers even if it is called with new arguments.
+ // However, if we start to record more than returned types, like
+ // exceptions for instance, we need to do it by uncommenting the following
+ // line.
+ // inferrer.addCaller(setter, currentMethod);
+ BaseType baseReceiverType = new ClassBaseType(receiver.enclosingElement);
+ inferrer.getSendReturnType(setter, baseReceiverType,
+ new ArgumentsTypes([argumentType], new Map()));
+ }
+ return argumentType;
+ }
+
+ ConcreteType analyzeSetNode(Node receiver, ConcreteType argumentType,
+ SourceString source) {
+ ConcreteType receiverType = analyze(receiver);
+
+ void augmentField(BaseType baseReceiverType, Element fieldOrSetter) {
+ if (fieldOrSetter.isField()) {
+ inferrer.augmentFieldType(fieldOrSetter, argumentType);
+ } else {
+ AbstractFieldElement abstractField = fieldOrSetter;
+ FunctionElement setter = abstractField.setter;
+ // TODO(polux): A setter always returns void so there's no need to
+ // invalidate its callers even if it is called with new arguments.
+ // However, if we start to record more than returned types, like
+ // exceptions for instance, we need to do it by uncommenting the
+ // following line.
+ // inferrer.addCaller(setter, currentMethod);
+ inferrer.getSendReturnType(setter, baseReceiverType,
+ new ArgumentsTypes([argumentType], new Map()));
+ }
+ }
+
+ if (receiverType.isUnkown()) {
+ for (FunctionElement member in inferrer.getMembersByName(source)) {
+ Element classElem = member.getEnclosingClass();
+ BaseType baseReceiverType = new ClassBaseType(classElem);
+ augmentField(baseReceiverType, member);
+ }
+ } else {
+ for (ClassBaseType baseReceiverType in receiverType.baseTypes) {
+ Element member = baseReceiverType.element.lookupMember(source);
+ if (member != null) {
+ augmentField(baseReceiverType, member);
+ }
+ }
+ }
+ return argumentType;
+ }
+
+ SourceString canonicalizeCompoundOperator(String op) {
+ if (op == '++') return const SourceString(r'operator$add');
+ else return const SourceString(r'operator$sub');
+ }
+
// TODO(polux): handle sendset as expression
ConcreteType visitSendSet(SendSet node) {
Identifier selector = node.selector;
final name = node.assignmentOperator.source.stringValue;
- if (identical(name, '++') || identical(name, '--')) {
- inferrer.fail(node, 'not yet implemented');
+ ConcreteType argumentType;
+ if (name == '++' || name == '--') {
+ ConcreteType receiverType = visitGetterSend(node);
+ SourceString canonicalizedMethodName = canonicalizeCompoundOperator(name);
+ List<ConcreteType> positionalArguments = <ConcreteType>[
+ new ConcreteType.singleton(inferrer.baseTypes.intBaseType)];
+ ArgumentsTypes argumentsTypes =
+ new ArgumentsTypes(positionalArguments, new Map());
+ argumentType = analyzeDynamicSend(receiverType, canonicalizedMethodName,
+ argumentsTypes);
} else {
- Element element = elements[node];
- if (element != null) {
- ConcreteType type = analyze(node.argumentsNode);
- environment = environment.put(elements[node], type);
- if (element.isField()) {
- inferrer.augmentFieldType(element, type);
- }
- } else {
- ConcreteType receiverType = analyze(node.receiver);
- ConcreteType type = analyze(node.argumentsNode);
- SourceString source = node.selector.asIdentifier().source;
-
- void augmentField(BaseType baseReceiverType, Element fieldOrSetter) {
- if (fieldOrSetter.isField()) {
- inferrer.augmentFieldType(fieldOrSetter, type);
- } else {
- FunctionElement setter =
- (fieldOrSetter as AbstractFieldElement).setter;
- // TODO: uncomment if we add an effect system
- //inferrer.addCaller(setter, currentMethod);
- inferrer.getSendReturnType(setter, baseReceiverType,
- new ArgumentsTypes([type], new Map()));
- }
- }
+ argumentType = analyze(node.argumentsNode);
+ }
- if (receiverType.isUnkown()) {
- for (final member in inferrer.getMembersByName(source)) {
- Element classElem = member.enclosingElement;
- BaseType baseReceiverType = new ClassBaseType(classElem);
- augmentField(baseReceiverType, member);
- }
- } else {
- for (ClassBaseType baseReceiverType in receiverType.baseTypes) {
- Element member = baseReceiverType.element.lookupMember(source);
- if (member != null) {
- augmentField(baseReceiverType, member);
- }
- }
- }
- }
+ Element element = elements[node];
+ if (element != null) {
+ return analyzeSetElement(element, argumentType);
+ } else {
+ return analyzeSetNode(node.receiver, argumentType,
+ node.selector.asIdentifier().source);
}
- return new ConcreteType.empty();
}
ConcreteType visitLiteralInt(LiteralInt node) {
@@ -1237,6 +1275,19 @@ class TypeInferrerVisitor extends ResolvedVisitor<ConcreteType> {
return visitDynamicSend(node);
}
+ ConcreteType analyzeFieldRead(Element field) {
+ inferrer.addReader(field, currentMethod);
+ return inferrer.getFieldType(field);
+ }
+
+ ConcreteType analyzeGetterSend(BaseType baseReceiverType,
+ FunctionElement getter) {
+ inferrer.addCaller(getter, currentMethod);
+ return inferrer.getSendReturnType(getter,
+ baseReceiverType,
+ new ArgumentsTypes([], new Map()));
+ }
+
ConcreteType visitGetterSend(Send node) {
Element element = elements[node];
if (element != null) {
@@ -1246,9 +1297,15 @@ class TypeInferrerVisitor extends ResolvedVisitor<ConcreteType> {
// node is a local variable
return result;
} else {
- // node is a field of this
- inferrer.addReader(element, currentMethod);
- return inferrer.getFieldType(element);
+ // node is a field or a getter of this
+ if (element.isField()) {
+ return analyzeFieldRead(element);
+ } else {
+ assert(element.isGetter());
+ ClassBaseType baseReceiverType =
+ new ClassBaseType(element.enclosingElement);
+ return analyzeGetterSend(baseReceiverType, element);
+ }
}
} else {
// node is a field of not(this)
@@ -1257,18 +1314,12 @@ class TypeInferrerVisitor extends ResolvedVisitor<ConcreteType> {
ConcreteType result = new ConcreteType.empty();
void augmentResult(BaseType baseReceiverType, Element getterOrField) {
if (getterOrField.isField()) {
- inferrer.addReader(getterOrField, currentMethod);
- result = result.union(inferrer.getFieldType(getterOrField));
+ result = result.union(analyzeFieldRead(getterOrField));
} else {
// call to a getter
- FunctionElement getter =
- (getterOrField as AbstractFieldElement).getter;
- inferrer.addCaller(getter, currentMethod);
- ConcreteType returnType =
- inferrer.getSendReturnType(getter,
- baseReceiverType,
- new ArgumentsTypes([], new Map()));
- result = result.union(returnType);
+ AbstractFieldElement abstractField = getterOrField;
+ result = result.union(analyzeGetterSend(baseReceiverType,
+ abstractField.getter));
}
}
@@ -1277,7 +1328,7 @@ class TypeInferrerVisitor extends ResolvedVisitor<ConcreteType> {
List<Element> members =
inferrer.getMembersByName(node.selector.asIdentifier().source);
for (final member in members) {
- Element classElement = member.enclosingElement;
+ Element classElement = member.getEnclosingClass();
ClassBaseType baseReceiverType = new ClassBaseType(classElement);
augmentResult(baseReceiverType, member);
}
@@ -1342,18 +1393,15 @@ class TypeInferrerVisitor extends ResolvedVisitor<ConcreteType> {
: s;
}
- ConcreteType visitDynamicSend(Send node) {
- ConcreteType receiverType = (node.receiver != null)
- ? analyze(node.receiver)
- : new ConcreteType.singleton(
- new ClassBaseType(currentMethod.getEnclosingClass()));
+ ConcreteType analyzeDynamicSend(ConcreteType receiverType,
+ SourceString canonicalizedMethodName,
+ ArgumentsTypes argumentsTypes) {
ConcreteType result = new ConcreteType.empty();
- final argumentsTypes = analyzeArguments(node.arguments);
if (receiverType.isUnkown()) {
- List<FunctionElement> methods = inferrer.getMembersByName(
- canonicalizeMethodName(node.selector.asIdentifier().source));
- for (final method in methods) {
+ List<FunctionElement> methods =
+ inferrer.getMembersByName(canonicalizedMethodName);
+ for (FunctionElement method in methods) {
inferrer.addCaller(method, currentMethod);
Element classElem = method.enclosingElement;
ClassBaseType baseReceiverType = new ClassBaseType(classElem);
@@ -1365,8 +1413,8 @@ class TypeInferrerVisitor extends ResolvedVisitor<ConcreteType> {
for (BaseType baseReceiverType in receiverType.baseTypes) {
if (!baseReceiverType.isNull()) {
ClassBaseType classBaseReceiverType = baseReceiverType;
- FunctionElement method = classBaseReceiverType.element
- .lookupMember(canonicalizeMethodName(node.selector.asIdentifier().source));
+ FunctionElement method = classBaseReceiverType.element.lookupMember(
+ canonicalizedMethodName);
if (method != null) {
inferrer.addCaller(method, currentMethod);
result = result.union(inferrer.getSendReturnType(method,
@@ -1378,6 +1426,17 @@ class TypeInferrerVisitor extends ResolvedVisitor<ConcreteType> {
return result;
}
+ ConcreteType visitDynamicSend(Send node) {
+ ConcreteType receiverType = (node.receiver != null)
+ ? analyze(node.receiver)
+ : new ConcreteType.singleton(
+ new ClassBaseType(currentMethod.getEnclosingClass()));
+ SourceString name =
+ canonicalizeMethodName(node.selector.asIdentifier().source);
+ ArgumentsTypes argumentsTypes = analyzeArguments(node.arguments);
+ return analyzeDynamicSend(receiverType, name, argumentsTypes);
+ }
+
ConcreteType visitForeignSend(Send node) {
inferrer.fail(node, 'not implemented');
}
« no previous file with comments | « no previous file | tests/compiler/dart2js/cpa_inference_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698