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

Unified Diff: lib/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: Created 8 years, 2 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/types/concrete_types_inferrer.dart
diff --git a/lib/compiler/implementation/types/concrete_types_inferrer.dart b/lib/compiler/implementation/types/concrete_types_inferrer.dart
index 2a3ad192b0468bfcd9027be8eac4349e57732963..abb1da9c26c23784e21ca8bbfa009487a2f24f95 100644
--- a/lib/compiler/implementation/types/concrete_types_inferrer.dart
+++ b/lib/compiler/implementation/types/concrete_types_inferrer.dart
@@ -988,55 +988,78 @@ class TypeInferrerVisitor extends ResolvedVisitor<ConcreteType> {
inferrer.fail(node, 'not yet implemented');
}
+ ConcreteType analyzeSetElement(Element receiver, ConcreteType argumentType) {
+ environment = environment.put(receiver, argumentType);
karlklose 2012/11/08 10:45:31 Do we keep track of the type of AbstractFields?
polux 2012/11/08 14:04:50 Good catch! Added a test. Discovered a similar iss
+ if (receiver.isField()) {
+ inferrer.augmentFieldType(receiver, argumentType);
+ }
+ 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 {
+ FunctionElement setter =
+ (fieldOrSetter as AbstractFieldElement).setter;
karlklose 2012/11/08 10:45:31 We usually assign to a variable instead of using a
polux 2012/11/08 14:04:50 Done.
+ // TODO: uncomment if we add an effect system
karlklose 2012/11/08 10:45:31 "TODO(polux)". Also, can you extend the comment to
polux 2012/11/08 14:04:50 Done.
+ //inferrer.addCaller(setter, currentMethod);
+ inferrer.getSendReturnType(setter, baseReceiverType,
+ new ArgumentsTypes([argumentType], new Map()));
+ }
+ }
+
+ if (receiverType.isUnkown()) {
+ for (final member in inferrer.getMembersByName(source)) {
karlklose 2012/11/08 10:45:31 Please type the loop variable.
polux 2012/11/08 14:04:50 Done.
+ Element classElem = member.enclosingElement;
karlklose 2012/11/08 10:45:31 Does this work for fields? Their enclosing member
polux 2012/11/08 14:04:50 Done.
+ 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());
karlklose 2012/11/08 10:45:31 How about using {} isntead of new Map()?
polux 2012/11/08 14:04:50 This would evaluate to <String,dynamic>{} and woul
+ 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) {
@@ -1338,18 +1361,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);
@@ -1361,8 +1381,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,
@@ -1374,6 +1394,18 @@ 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 canonicalizedMethodName =
karlklose 2012/11/08 10:45:31 Consider simply calling the variable 'name'. That
polux 2012/11/08 14:04:50 Done.
+ canonicalizeMethodName(node.selector.asIdentifier().source);
+ ArgumentsTypes argumentsTypes = analyzeArguments(node.arguments);
+ return analyzeDynamicSend(receiverType, canonicalizedMethodName,
+ 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') | tests/compiler/dart2js/cpa_inference_test.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698