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'); |
} |