Chromium Code Reviews| Index: dart/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart |
| diff --git a/dart/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart b/dart/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart |
| index c61db0c92dc74d31bc41cbc41db0a6383f410a24..104e4d87a4aff6f917bdf9d1cc44f7e832b4c051 100644 |
| --- a/dart/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart |
| +++ b/dart/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart |
| @@ -179,11 +179,11 @@ class SimpleTypesInferrer extends TypesInferrer { |
| * of a field, these [Node] are initially discarded, and once the |
| * type is computed, we make sure these constraints are satisfied |
| * for that type. For example: |
| - * |
| + * |
| * [: field++ ], or [: field += 42 :], the constraint is on the |
| * operator+, and we make sure that a typed selector with the found |
| * type returns that type. |
| - * |
| + * |
| * [: field = other.field :], the constraint in on the [:field] |
| * getter selector, and we make sure that the getter selector |
| * returns that type. |
| @@ -265,7 +265,8 @@ class SimpleTypesInferrer extends TypesInferrer { |
| recompiles++; |
| recomputeWatch.start(); |
| } |
| - bool changed = analyze(element); |
| + bool changed = |
| + compiler.withCurrentElement(element, () => analyze(element)); |
| analyzed++; |
| if (wasAnalyzed) { |
| recomputeWatch.stop(); |
| @@ -1199,7 +1200,7 @@ class SimpleTypeInferrerVisitor extends ResolvedVisitor<TypeMask> { |
| if (analyzedElement.isField()) { |
| return visit(node.asSendSet().arguments.head); |
| } |
| - |
| + |
| FunctionElement function = analyzedElement; |
| FunctionSignature signature = function.computeSignature(compiler); |
| signature.forEachOptionalParameter((element) { |
| @@ -1532,46 +1533,7 @@ class SimpleTypeInferrerVisitor extends ResolvedVisitor<TypeMask> { |
| } |
| } else if (op == '=') { |
| // [: foo = 42 :] or [: foo.bar = 42 :]. |
| - ArgumentsTypes arguments = new ArgumentsTypes([rhsType], null); |
| - if (Elements.isStaticOrTopLevelField(element)) { |
| - handleStaticSend(node, setterSelector, element, arguments); |
| - } else if (Elements.isUnresolved(element) || element.isSetter()) { |
| - handleDynamicSend(node, setterSelector, receiverType, arguments); |
| - } else if (element.isField()) { |
| - if (element.modifiers.isFinal()) { |
| - inferrer.recordFinalFieldType( |
| - node, outermostElement, element, rhsType); |
| - } else { |
| - locals.updateField(element, rhsType); |
| - if (visitingInitializers) { |
| - inferrer.recordNonFinalFieldElementType(node, element, rhsType); |
| - } else { |
| - handleDynamicSend(node, setterSelector, receiverType, arguments); |
| - } |
| - } |
| - } else if (Elements.isLocal(element)) { |
| - locals.update(element, rhsType); |
| - } |
| - |
| - if (!Elements.isLocal(element)) { |
| - // Recognize a constraint of the form [: field = other.field :]. |
| - // Note that we check if the right hand side is a local to |
| - // recognize the situation [: var a = 42; this.a = a; :]. Our |
| - // constraint mechanism only works with members or top level |
| - // elements. |
| - var rhs = node.arguments.head; |
| - if (rhs.asSend() != null |
| - && rhs.isPropertyAccess |
| - && !Elements.isLocal(elements[rhs]) |
| - && rhs.selector.source == node.selector.asIdentifier().source) { |
| - // TODO(ngeoffray): We should update selectors in the |
| - // element tree and find out if the typed selector still |
| - // applies to the receiver type. |
| - Selector constraint = elements.getSelector(rhs); |
| - inferrer.recordSetterConstraint(node, constraint); |
| - } |
| - } |
| - return rhsType; |
| + return handlePlainAssignment(node, element, setterSelector, receiverType, rhsType, node.arguments.head); |
|
Emily Fortuna
2013/04/09 16:48:21
80 char
ahe
2013/04/10 15:02:19
Done.
|
| } else { |
| // [: foo++ :] or [: foo += 1 :]. |
| TypeMask getterType; |
| @@ -1622,6 +1584,55 @@ class SimpleTypeInferrerVisitor extends ResolvedVisitor<TypeMask> { |
| } |
| } |
| + TypeMask handlePlainAssignment(Send node, |
|
kasperl
2013/04/10 08:34:54
Thank you for factoring this out!
|
| + Element element, |
| + Selector setterSelector, |
| + TypeMask receiverType, |
| + TypeMask rhsType, |
| + Node rhs) { |
| + ArgumentsTypes arguments = new ArgumentsTypes([rhsType], null); |
| + if (Elements.isStaticOrTopLevelField(element)) { |
| + handleStaticSend(node, setterSelector, element, arguments); |
| + } else if (Elements.isUnresolved(element) || element.isSetter()) { |
| + handleDynamicSend(node, setterSelector, receiverType, arguments); |
| + } else if (element.isField()) { |
|
Emily Fortuna
2013/04/09 16:48:21
not a show-stopper for this change, but it seems l
ahe
2013/04/10 15:02:19
It is true that we should clean this up. However,
|
| + if (element.modifiers.isFinal()) { |
| + inferrer.recordFinalFieldType( |
| + node, outermostElement, element, rhsType); |
| + } else { |
| + locals.updateField(element, rhsType); |
| + if (visitingInitializers) { |
| + inferrer.recordNonFinalFieldElementType(node, element, rhsType); |
| + } else { |
| + handleDynamicSend(node, setterSelector, receiverType, arguments); |
| + } |
| + } |
| + } else if (Elements.isLocal(element)) { |
| + locals.update(element, rhsType); |
| + } |
| + |
| + if (!Elements.isLocal(element)) { |
| + // Recognize a constraint of the form [: field = other.field :]. |
| + // Note that we check if the right hand side is a local to |
| + // recognize the situation [: var a = 42; this.a = a; :]. Our |
| + // constraint mechanism only works with members or top level |
| + // elements. |
| + Send send = rhs.asSend(); |
| + if (send != null |
| + && send.isPropertyAccess |
| + && !Elements.isLocal(elements[rhs]) |
| + && send.selector.asIdentifier().source |
| + == node.selector.asIdentifier().source) { |
| + // TODO(ngeoffray): We should update selectors in the |
| + // element tree and find out if the typed selector still |
| + // applies to the receiver type. |
| + Selector constraint = elements.getSelector(rhs); |
| + inferrer.recordSetterConstraint(node, constraint); |
| + } |
| + } |
| + return rhsType; |
| + } |
| + |
| TypeMask visitIdentifier(Identifier node) { |
| if (node.isThis()) { |
| return thisType; |
| @@ -2006,24 +2017,24 @@ class SimpleTypeInferrerVisitor extends ResolvedVisitor<TypeMask> { |
| bool changed = false; |
| visit(node.expression); |
| if (!isThisExposed && node.expression.isThis()) { |
| - Selector iteratorSelector = elements.getIteratorSelector(node); |
| + Selector iteratorSelector = compiler.iteratorSelector; |
| checkIfExposesThis(new TypedSelector(thisType, iteratorSelector)); |
| TypeMask iteratorType = inferrer.typeOfSelector(iteratorSelector); |
| checkIfExposesThis( |
| - new TypedSelector(iteratorType, elements.getMoveNextSelector(node))); |
| + new TypedSelector(iteratorType, compiler.moveNextSelector)); |
| checkIfExposesThis( |
| - new TypedSelector(iteratorType, elements.getCurrentSelector(node))); |
| + new TypedSelector(iteratorType, compiler.currentSelector)); |
| } |
| - Element variable; |
| - if (node.declaredIdentifier.asSend() != null) { |
| - variable = elements[node.declaredIdentifier]; |
| + Element variable = elements[node.declaredIdentifier]; |
| + Selector selector = elements.getSelector(node.declaredIdentifier); |
| + if (!Elements.isUnresolved(variable)) { |
| + locals.update(variable, inferrer.dynamicType); |
| } else { |
| - assert(node.declaredIdentifier.asVariableDefinitions() != null); |
| - VariableDefinitions variableDefinitions = node.declaredIdentifier; |
| - variable = elements[variableDefinitions.definitions.nodes.head]; |
| + handlePlainAssignment(new Send(), variable, selector, |
| + inferrer.dynamicType, inferrer.dynamicType, |
| + node.expression); |
| } |
| - locals.update(variable, inferrer.dynamicType); |
| loopLevel++; |
| do { |
| LocalsHandler saved = new LocalsHandler.from(locals); |