Index: pkg/compiler/lib/src/inferrer/inferrer_visitor.dart |
diff --git a/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart b/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart |
index 85a81bc4627716b7481657c35f67b0d075e20801..5d4623a7b337c2868e58bb6f4819d2d059c74f58 100644 |
--- a/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart |
+++ b/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart |
@@ -4,32 +4,24 @@ |
library inferrer_visitor; |
-import 'dart:collection' show |
- IterableMixin; |
+import 'dart:collection' show IterableMixin; |
import '../common.dart'; |
-import '../compiler.dart' show |
- Compiler; |
+import '../compiler.dart' show Compiler; |
import '../constants/constant_system.dart'; |
import '../constants/expressions.dart'; |
import '../dart_types.dart'; |
import '../elements/elements.dart'; |
import '../resolution/operators.dart'; |
import '../resolution/semantic_visitor.dart'; |
-import '../resolution/tree_elements.dart' show |
- TreeElements; |
+import '../resolution/tree_elements.dart' show TreeElements; |
import '../tree/tree.dart'; |
-import '../types/types.dart' show |
- TypeMask; |
-import '../types/constants.dart' show |
- computeTypeMask; |
-import '../universe/call_structure.dart' show |
- CallStructure; |
-import '../universe/selector.dart' show |
- Selector; |
+import '../types/types.dart' show TypeMask; |
+import '../types/constants.dart' show computeTypeMask; |
+import '../universe/call_structure.dart' show CallStructure; |
+import '../universe/selector.dart' show Selector; |
import '../util/util.dart'; |
-import '../world.dart' show |
- ClassWorld; |
+import '../world.dart' show ClassWorld; |
/** |
* The interface [InferrerVisitor] will use when working on types. |
@@ -67,13 +59,11 @@ abstract class TypeSystem<T> { |
bool isNull(T type); |
TypeMask newTypedSelector(T receiver, TypeMask mask); |
- T allocateList(T type, |
- Node node, |
- Element enclosing, |
- [T elementType, int length]); |
+ T allocateList(T type, Node node, Element enclosing, |
+ [T elementType, int length]); |
- T allocateMap(T type, Node node, Element element, [List<T> keyType, |
- List<T> valueType]); |
+ T allocateMap(T type, Node node, Element element, |
+ [List<T> keyType, List<T> valueType]); |
T allocateClosure(Node node, Element element); |
@@ -106,7 +96,6 @@ abstract class TypeSystem<T> { |
*/ |
T allocatePhi(Node node, Local variable, T inputType); |
- |
/** |
* Returns a new type for holding the potential types of [element]. |
* [inputType] is the first incoming type of the phi. [allocateLoopPhi] |
@@ -143,10 +132,8 @@ abstract class TypeSystem<T> { |
* conditional send (e.g. `a?.selector`), in which case the returned type may |
* be null. |
*/ |
- T refineReceiver(Selector selector, |
- TypeMask mask, |
- T receiverType, |
- bool isConditional); |
+ T refineReceiver( |
+ Selector selector, TypeMask mask, T receiverType, bool isConditional); |
/** |
* Returns the internal inferrer representation for [mask]. |
@@ -211,9 +198,8 @@ class VariableScope<T> { |
variables.forEach(f); |
} |
- void forEachLocalUntilNode(Node node, |
- void f(Local variable, T type), |
- [Setlet<Local> seenLocals]) { |
+ void forEachLocalUntilNode(Node node, void f(Local variable, T type), |
+ [Setlet<Local> seenLocals]) { |
if (seenLocals == null) seenLocals = new Setlet<Local>(); |
if (variables != null) { |
variables.forEach((variable, type) { |
@@ -273,7 +259,7 @@ class FieldInitializationScope<T> { |
} |
void mergeDiamondFlow(FieldInitializationScope<T> thenScope, |
- FieldInitializationScope<T> elseScope) { |
+ FieldInitializationScope<T> elseScope) { |
// Quick bailout check. If [isThisExposed] is true, we know the |
// code following won't do anything. |
if (isThisExposed) return; |
@@ -297,12 +283,14 @@ class ArgumentsTypes<T> extends IterableMixin<T> { |
final List<T> positional; |
final Map<String, T> named; |
ArgumentsTypes(this.positional, named) |
- : this.named = (named == null || named.isEmpty) ? const {} : named { |
+ : this.named = (named == null || named.isEmpty) ? const {} : named { |
assert(this.positional.every((T type) => type != null)); |
assert(this.named.values.every((T type) => type != null)); |
} |
- ArgumentsTypes.empty() : positional = const [], named = const {}; |
+ ArgumentsTypes.empty() |
+ : positional = const [], |
+ named = const {}; |
int get length => positional.length + named.length; |
@@ -310,7 +298,7 @@ class ArgumentsTypes<T> extends IterableMixin<T> { |
String toString() => "{ positional = $positional, named = $named }"; |
- bool operator==(other) { |
+ bool operator ==(other) { |
if (positional.length != other.positional.length) return false; |
if (named.length != other.named.length) return false; |
for (int i = 0; i < positional.length; i++) { |
@@ -366,7 +354,6 @@ class ArgumentsTypesIterator<T> implements Iterator<T> { |
} |
} |
- |
abstract class MinimalInferrerEngine<T> { |
/** |
* Returns the type of [element]. |
@@ -408,21 +395,18 @@ class LocalsHandler<T> { |
bool get aborts { |
return seenReturnOrThrow || seenBreakOrContinue; |
} |
+ |
bool get inTryBlock => tryBlock != null; |
- LocalsHandler(this.inferrer, |
- this.types, |
- this.compiler, |
- Node block, |
- [this.fieldScope]) |
+ LocalsHandler(this.inferrer, this.types, this.compiler, Node block, |
+ [this.fieldScope]) |
: locals = new VariableScope<T>(block), |
captured = new Map<Local, Element>(), |
capturedAndBoxed = new Map<Local, Element>(), |
tryBlock = null; |
- LocalsHandler.from(LocalsHandler<T> other, |
- Node block, |
- {bool useOtherTryBlock: true}) |
+ LocalsHandler.from(LocalsHandler<T> other, Node block, |
+ {bool useOtherTryBlock: true}) |
: locals = new VariableScope<T>(block, other.locals), |
fieldScope = new FieldInitializationScope<T>.from(other.fieldScope), |
captured = other.captured, |
@@ -479,8 +463,8 @@ class LocalsHandler<T> { |
// narrowed to non-null. |
type = types.addPhiInput( |
local, |
- types.allocatePhi(locals.block, local, |
- types.narrowNotNull(currentType)), |
+ types.allocatePhi( |
+ locals.block, local, types.narrowNotNull(currentType)), |
type); |
} |
locals[local] = type; |
@@ -489,8 +473,7 @@ class LocalsHandler<T> { |
} |
} |
if (capturedAndBoxed.containsKey(local)) { |
- inferrer.recordTypeOfNonFinalField( |
- node, capturedAndBoxed[local], type); |
+ inferrer.recordTypeOfNonFinalField(node, capturedAndBoxed[local], type); |
} else if (inTryBlock) { |
// We don't know if an assignment in a try block |
// will be executed, so all assigments in that block are |
@@ -519,17 +502,17 @@ class LocalsHandler<T> { |
capturedAndBoxed[local] = field; |
} |
- void mergeDiamondFlow(LocalsHandler<T> thenBranch, |
- LocalsHandler<T> elseBranch) { |
+ void mergeDiamondFlow( |
+ LocalsHandler<T> thenBranch, LocalsHandler<T> elseBranch) { |
if (fieldScope != null && elseBranch != null) { |
fieldScope.mergeDiamondFlow(thenBranch.fieldScope, elseBranch.fieldScope); |
} |
- seenReturnOrThrow = thenBranch.seenReturnOrThrow |
- && elseBranch != null |
- && elseBranch.seenReturnOrThrow; |
- seenBreakOrContinue = thenBranch.seenBreakOrContinue |
- && elseBranch != null |
- && elseBranch.seenBreakOrContinue; |
+ seenReturnOrThrow = thenBranch.seenReturnOrThrow && |
+ elseBranch != null && |
+ elseBranch.seenReturnOrThrow; |
+ seenBreakOrContinue = thenBranch.seenBreakOrContinue && |
+ elseBranch != null && |
+ elseBranch.seenBreakOrContinue; |
if (aborts) return; |
void mergeOneBranch(LocalsHandler<T> other) { |
@@ -612,7 +595,7 @@ class LocalsHandler<T> { |
* labeled statement that do not break out. |
*/ |
void mergeAfterBreaks(List<LocalsHandler<T>> handlers, |
- {bool keepOwnLocals: true}) { |
+ {bool keepOwnLocals: true}) { |
Node level = locals.block; |
// Use a separate locals handler to perform the merge in, so that Phi |
// creation does not invalidate previous type knowledge while we might |
@@ -631,9 +614,8 @@ class LocalsHandler<T> { |
for (Local variable in seenLocals) { |
T originalType = locals[variable]; |
if (originalType != null) { |
- merged.locals[variable] = types.addPhiInput(variable, |
- merged.locals[variable], |
- originalType); |
+ merged.locals[variable] = types.addPhiInput( |
+ variable, merged.locals[variable], originalType); |
} |
} |
} |
@@ -642,8 +624,8 @@ class LocalsHandler<T> { |
merged.locals.forEachOwnLocal((Local variable, T type) { |
locals[variable] = types.simplifyPhi(level, variable, type); |
}); |
- seenReturnOrThrow = allBranchesAbort && |
- (!keepOwnLocals || seenReturnOrThrow); |
+ seenReturnOrThrow = |
+ allBranchesAbort && (!keepOwnLocals || seenReturnOrThrow); |
} |
/** |
@@ -711,14 +693,15 @@ class LocalsHandler<T> { |
abstract class InferrerVisitor<T, E extends MinimalInferrerEngine<T>> |
extends Visitor<T> |
- with SemanticSendResolvedMixin<T, dynamic>, |
- CompoundBulkMixin<T, dynamic>, |
- SetIfNullBulkMixin<T, dynamic>, |
- PrefixBulkMixin<T, dynamic>, |
- PostfixBulkMixin<T, dynamic>, |
- ErrorBulkMixin<T, dynamic>, |
- NewBulkMixin<T, dynamic>, |
- SetBulkMixin<T, dynamic> |
+ with |
+ SemanticSendResolvedMixin<T, dynamic>, |
+ CompoundBulkMixin<T, dynamic>, |
+ SetIfNullBulkMixin<T, dynamic>, |
+ PrefixBulkMixin<T, dynamic>, |
+ PostfixBulkMixin<T, dynamic>, |
+ ErrorBulkMixin<T, dynamic>, |
+ NewBulkMixin<T, dynamic>, |
+ SetBulkMixin<T, dynamic> |
implements SemanticSendVisitor<T, dynamic> { |
final Compiler compiler; |
final AstElement analyzedElement; |
@@ -743,20 +726,19 @@ abstract class InferrerVisitor<T, E extends MinimalInferrerEngine<T>> |
? locals.fieldScope.isThisExposed |
: true; |
} |
+ |
void set isThisExposed(value) { |
if (analyzedElement.isGenerativeConstructor) { |
locals.fieldScope.isThisExposed = value; |
} |
} |
- InferrerVisitor(AstElement analyzedElement, |
- this.inferrer, |
- this.types, |
- this.compiler, |
- [LocalsHandler<T> handler]) |
- : this.analyzedElement = analyzedElement, |
- this.locals = handler, |
- this.elements = analyzedElement.resolvedAst.elements { |
+ InferrerVisitor( |
+ AstElement analyzedElement, this.inferrer, this.types, this.compiler, |
+ [LocalsHandler<T> handler]) |
+ : this.analyzedElement = analyzedElement, |
+ this.locals = handler, |
+ this.elements = analyzedElement.resolvedAst.elements { |
if (handler != null) return; |
Node node = analyzedElement.node; |
FieldInitializationScope<T> fieldScope = |
@@ -905,91 +887,55 @@ abstract class InferrerVisitor<T, E extends MinimalInferrerEngine<T>> |
return types.dynamicType; |
} |
- |
@override |
T bulkHandleNode(Node node, String message, _) { |
return internalError(node, message.replaceAll('#', '$node')); |
} |
@override |
- T visitConstantGet( |
- Send node, |
- ConstantExpression constant, |
- _) { |
+ T visitConstantGet(Send node, ConstantExpression constant, _) { |
return bulkHandleNode(node, "Constant read `#` unhandled.", _); |
} |
@override |
- T visitConstantInvoke( |
- Send node, |
- ConstantExpression constant, |
- NodeList arguments, |
- CallStructure callStructure, |
- _) { |
+ T visitConstantInvoke(Send node, ConstantExpression constant, |
+ NodeList arguments, CallStructure callStructure, _) { |
return bulkHandleNode(node, "Constant invoke `#` unhandled.", _); |
} |
- T visitClassTypeLiteralGet( |
- Send node, |
- ConstantExpression constant, |
- _) { |
+ T visitClassTypeLiteralGet(Send node, ConstantExpression constant, _) { |
return handleTypeLiteralGet(); |
} |
- T visitClassTypeLiteralInvoke( |
- Send node, |
- ConstantExpression constant, |
- NodeList arguments, |
- CallStructure callStructure, |
- _) { |
+ T visitClassTypeLiteralInvoke(Send node, ConstantExpression constant, |
+ NodeList arguments, CallStructure callStructure, _) { |
return handleTypeLiteralInvoke(arguments); |
} |
- T visitTypedefTypeLiteralGet( |
- Send node, |
- ConstantExpression constant, |
- _) { |
+ T visitTypedefTypeLiteralGet(Send node, ConstantExpression constant, _) { |
return handleTypeLiteralGet(); |
} |
- T visitTypedefTypeLiteralInvoke( |
- Send node, |
- ConstantExpression constant, |
- NodeList arguments, |
- CallStructure callStructure, |
- _) { |
+ T visitTypedefTypeLiteralInvoke(Send node, ConstantExpression constant, |
+ NodeList arguments, CallStructure callStructure, _) { |
return handleTypeLiteralInvoke(arguments); |
} |
- T visitTypeVariableTypeLiteralGet( |
- Send node, |
- TypeVariableElement element, |
- _) { |
+ T visitTypeVariableTypeLiteralGet(Send node, TypeVariableElement element, _) { |
return handleTypeLiteralGet(); |
} |
- T visitTypeVariableTypeLiteralInvoke( |
- Send node, |
- TypeVariableElement element, |
- NodeList arguments, |
- CallStructure callStructure, |
- _) { |
+ T visitTypeVariableTypeLiteralInvoke(Send node, TypeVariableElement element, |
+ NodeList arguments, CallStructure callStructure, _) { |
return handleTypeLiteralInvoke(arguments); |
} |
- T visitDynamicTypeLiteralGet( |
- Send node, |
- ConstantExpression constant, |
- _) { |
+ T visitDynamicTypeLiteralGet(Send node, ConstantExpression constant, _) { |
return handleTypeLiteralGet(); |
} |
- T visitDynamicTypeLiteralInvoke( |
- Send node, |
- ConstantExpression constant, |
- NodeList arguments, |
- CallStructure callStructure, |
- _) { |
+ T visitDynamicTypeLiteralInvoke(Send node, ConstantExpression constant, |
+ NodeList arguments, CallStructure callStructure, _) { |
return handleTypeLiteralInvoke(arguments); |
} |
@@ -1014,8 +960,8 @@ abstract class InferrerVisitor<T, E extends MinimalInferrerEngine<T>> |
T _superType; |
T get superType { |
if (_superType != null) return _superType; |
- return _superType = types.nonNullExact( |
- outermostElement.enclosingClass.superclass); |
+ return _superType = |
+ types.nonNullExact(outermostElement.enclosingClass.superclass); |
} |
@override |
@@ -1073,8 +1019,8 @@ abstract class InferrerVisitor<T, E extends MinimalInferrerEngine<T>> |
Element receiverElement = elements[node.receiver]; |
Element argumentElement = elements[node.arguments.first]; |
String operator = node.selector.asOperator().source; |
- if ((operator == '==' && usePositive) |
- || (operator == '!=' && !usePositive)) { |
+ if ((operator == '==' && usePositive) || |
+ (operator == '!=' && !usePositive)) { |
// Type the elements as null. |
if (Elements.isLocal(receiverElement)) { |
locals.update(receiverElement, types.nullType, node); |
@@ -1103,30 +1049,19 @@ abstract class InferrerVisitor<T, E extends MinimalInferrerEngine<T>> |
@override |
T visitDynamicPropertyInvoke( |
- Send node, |
- Node receiver, |
- NodeList arguments, |
- Selector selector, |
- _) { |
+ Send node, Node receiver, NodeList arguments, Selector selector, _) { |
return handleDynamicInvoke(node); |
} |
@override |
T visitIfNotNullDynamicPropertyInvoke( |
- Send node, |
- Node receiver, |
- NodeList arguments, |
- Selector selector, |
- _) { |
+ Send node, Node receiver, NodeList arguments, Selector selector, _) { |
return handleDynamicInvoke(node); |
} |
@override |
T visitThisPropertyInvoke( |
- Send node, |
- NodeList arguments, |
- Selector selector, |
- _) { |
+ Send node, NodeList arguments, Selector selector, _) { |
return handleDynamicInvoke(node); |
} |
@@ -1159,8 +1094,7 @@ abstract class InferrerVisitor<T, E extends MinimalInferrerEngine<T>> |
} |
visit(right); |
if (oldAccumulateIsChecks) { |
- |
- bool invalidatedInRightHandSide (Send test) { |
+ bool invalidatedInRightHandSide(Send test) { |
Element receiver = elements[test.receiver]; |
if (receiver is LocalElement) { |
return narrowed.locals[receiver] != locals.locals[receiver]; |
@@ -1267,8 +1201,8 @@ abstract class InferrerVisitor<T, E extends MinimalInferrerEngine<T>> |
T visitVariableDefinitions(VariableDefinitions node) { |
for (Link<Node> link = node.definitions.nodes; |
- !link.isEmpty; |
- link = link.tail) { |
+ !link.isEmpty; |
+ link = link.tail) { |
Node definition = link.head; |
if (definition is Identifier) { |
locals.update(elements[definition], types.nullType, node); |
@@ -1353,8 +1287,7 @@ abstract class InferrerVisitor<T, E extends MinimalInferrerEngine<T>> |
loopLevel--; |
saved.endLoop(node); |
bool keepOwnLocals = node.asDoWhile() == null; |
- saved.mergeAfterBreaks( |
- getBreaks(target), keepOwnLocals: keepOwnLocals); |
+ saved.mergeAfterBreaks(getBreaks(target), keepOwnLocals: keepOwnLocals); |
locals = saved; |
clearBreaksAndContinues(target); |
return null; |
@@ -1391,8 +1324,7 @@ abstract class InferrerVisitor<T, E extends MinimalInferrerEngine<T>> |
T visitTryStatement(TryStatement node) { |
LocalsHandler<T> saved = locals; |
- locals = new LocalsHandler<T>.from( |
- locals, node, useOtherTryBlock: false); |
+ locals = new LocalsHandler<T>.from(locals, node, useOtherTryBlock: false); |
visit(node.tryBlock); |
saved.mergeDiamondFlow(locals, null); |
locals = saved; |
@@ -1417,9 +1349,7 @@ abstract class InferrerVisitor<T, E extends MinimalInferrerEngine<T>> |
Node exception = node.exception; |
if (exception != null) { |
DartType type = elements.getType(node.type); |
- T mask = type == null || |
- type.treatAsDynamic || |
- type.isTypeVariable |
+ T mask = type == null || type.treatAsDynamic || type.isTypeVariable |
? types.dynamicType |
: types.nonNullSubtype(type.element); |
locals.update(elements[exception], mask, node); |
@@ -1448,9 +1378,9 @@ abstract class InferrerVisitor<T, E extends MinimalInferrerEngine<T>> |
T visitLabeledStatement(LabeledStatement node) { |
Statement body = node.statement; |
- if (body is Loop |
- || body is SwitchStatement |
- || Elements.isUnusedLabel(node, elements)) { |
+ if (body is Loop || |
+ body is SwitchStatement || |
+ Elements.isUnusedLabel(node, elements)) { |
// Loops and switches handle their own labels. |
visit(body); |
} else { |