| 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 c820a6c5eb6268c8c8e9d4bcca282b21f1fe4081..24948efa7901cd2791c0dba17c9699df025f3af3 100644
|
| --- a/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart
|
| +++ b/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart
|
| @@ -9,6 +9,7 @@ import '../constants/expressions.dart';
|
| import '../dart2jslib.dart' hide Selector, TypedSelector;
|
| import '../dart_types.dart';
|
| import '../elements/elements.dart';
|
| +import '../resolution/operators.dart';
|
| import '../tree/tree.dart';
|
| import '../universe/universe.dart';
|
| import '../util/util.dart';
|
| @@ -983,87 +984,114 @@ abstract class InferrerVisitor
|
| }
|
| }
|
|
|
| - T visitOperatorSend(Send node) {
|
| - Operator op = node.selector;
|
| - if ("[]" == op.source) {
|
| - return visitDynamicSend(node);
|
| - } else if ("&&" == op.source) {
|
| - conditionIsSimple = false;
|
| - bool oldAccumulateIsChecks = accumulateIsChecks;
|
| - List<Send> oldIsChecks = isChecks;
|
| - if (!accumulateIsChecks) {
|
| - accumulateIsChecks = true;
|
| - isChecks = <Send>[];
|
| - }
|
| - visit(node.receiver);
|
| - LocalsHandler<T> saved = locals;
|
| - locals = new LocalsHandler<T>.from(locals, node);
|
| - updateIsChecks(isChecks, usePositive: true);
|
| - LocalsHandler<T> narrowed;
|
| - if (oldAccumulateIsChecks) {
|
| - narrowed = new LocalsHandler<T>.topLevelCopyOf(locals);
|
| - } else {
|
| - accumulateIsChecks = false;
|
| - isChecks = oldIsChecks;
|
| - }
|
| - visit(node.arguments.head);
|
| - if (oldAccumulateIsChecks) {
|
| + @override
|
| + T visitIndex(Send node, Node receiver, Node index, _) {
|
| + return visitDynamicSend(node);
|
| + }
|
|
|
| - bool invalidatedInRightHandSide (Send test) {
|
| - Element receiver = elements[test.receiver];
|
| - if (receiver is LocalElement) {
|
| - return narrowed.locals[receiver] != locals.locals[receiver];
|
| - }
|
| - return false;
|
| - }
|
| + @override
|
| + T visitLogicalAnd(Send node, Node left, Node right, _) {
|
| + conditionIsSimple = false;
|
| + bool oldAccumulateIsChecks = accumulateIsChecks;
|
| + List<Send> oldIsChecks = isChecks;
|
| + if (!accumulateIsChecks) {
|
| + accumulateIsChecks = true;
|
| + isChecks = <Send>[];
|
| + }
|
| + visit(left);
|
| + LocalsHandler<T> saved = locals;
|
| + locals = new LocalsHandler<T>.from(locals, node);
|
| + updateIsChecks(isChecks, usePositive: true);
|
| + LocalsHandler<T> narrowed;
|
| + if (oldAccumulateIsChecks) {
|
| + narrowed = new LocalsHandler<T>.topLevelCopyOf(locals);
|
| + } else {
|
| + accumulateIsChecks = false;
|
| + isChecks = oldIsChecks;
|
| + }
|
| + visit(right);
|
| + if (oldAccumulateIsChecks) {
|
|
|
| - isChecks.removeWhere(invalidatedInRightHandSide);
|
| + bool invalidatedInRightHandSide (Send test) {
|
| + Element receiver = elements[test.receiver];
|
| + if (receiver is LocalElement) {
|
| + return narrowed.locals[receiver] != locals.locals[receiver];
|
| + }
|
| + return false;
|
| }
|
| - saved.mergeDiamondFlow(locals, null);
|
| - locals = saved;
|
| - return types.boolType;
|
| - } else if ("||" == op.source) {
|
| - conditionIsSimple = false;
|
| - List<Send> tests = <Send>[];
|
| - bool isSimple = handleCondition(node.receiver, tests);
|
| - LocalsHandler<T> saved = locals;
|
| - locals = new LocalsHandler<T>.from(locals, node);
|
| - if (isSimple) updateIsChecks(tests, usePositive: false);
|
| - bool oldAccumulateIsChecks = accumulateIsChecks;
|
| - accumulateIsChecks = false;
|
| - visit(node.arguments.head);
|
| - accumulateIsChecks = oldAccumulateIsChecks;
|
| - saved.mergeDiamondFlow(locals, null);
|
| - locals = saved;
|
| - return types.boolType;
|
| - } else if ("!" == op.source) {
|
| - bool oldAccumulateIsChecks = accumulateIsChecks;
|
| - accumulateIsChecks = false;
|
| - node.visitChildren(this);
|
| - accumulateIsChecks = oldAccumulateIsChecks;
|
| - return types.boolType;
|
| - } else if ("is" == op.source) {
|
| - potentiallyAddIsCheck(node);
|
| - node.visitChildren(this);
|
| - return types.boolType;
|
| - } else if ("as" == op.source) {
|
| - T receiverType = visit(node.receiver);
|
| - DartType type = elements.getType(node.arguments.head);
|
| - return types.narrowType(receiverType, type);
|
| - } else if (node.argumentsNode is Prefix) {
|
| - // Unary operator.
|
| - return visitDynamicSend(node);
|
| - } else if ('===' == op.source
|
| - || '!==' == op.source) {
|
| - node.visitChildren(this);
|
| - return types.boolType;
|
| - } else if ('!=' == op.source) {
|
| - visitDynamicSend(node);
|
| - return types.boolType;
|
| - } else {
|
| - // Binary operator.
|
| - return visitDynamicSend(node);
|
| +
|
| + isChecks.removeWhere(invalidatedInRightHandSide);
|
| }
|
| + saved.mergeDiamondFlow(locals, null);
|
| + locals = saved;
|
| + return types.boolType;
|
| + }
|
| +
|
| + @override
|
| + T visitLogicalOr(Send node, Node left, Node right, _) {
|
| + conditionIsSimple = false;
|
| + List<Send> tests = <Send>[];
|
| + bool isSimple = handleCondition(left, tests);
|
| + LocalsHandler<T> saved = locals;
|
| + locals = new LocalsHandler<T>.from(locals, node);
|
| + if (isSimple) updateIsChecks(tests, usePositive: false);
|
| + bool oldAccumulateIsChecks = accumulateIsChecks;
|
| + accumulateIsChecks = false;
|
| + visit(right);
|
| + accumulateIsChecks = oldAccumulateIsChecks;
|
| + saved.mergeDiamondFlow(locals, null);
|
| + locals = saved;
|
| + return types.boolType;
|
| + }
|
| +
|
| + @override
|
| + T visitNot(Send node, Node expression, _) {
|
| + bool oldAccumulateIsChecks = accumulateIsChecks;
|
| + accumulateIsChecks = false;
|
| + visit(expression);
|
| + accumulateIsChecks = oldAccumulateIsChecks;
|
| + return types.boolType;
|
| + }
|
| +
|
| + @override
|
| + T visitIs(Send node, Node expression, DartType type, _) {
|
| + potentiallyAddIsCheck(node);
|
| + visit(expression);
|
| + return types.boolType;
|
| + }
|
| +
|
| + @override
|
| + T visitIsNot(Send node, Node expression, DartType type, _) {
|
| + potentiallyAddIsCheck(node);
|
| + visit(expression);
|
| + return types.boolType;
|
| + }
|
| +
|
| + @override
|
| + T visitAs(Send node, Node expression, DartType type, _) {
|
| + T receiverType = visit(expression);
|
| + return types.narrowType(receiverType, type);
|
| + }
|
| +
|
| + @override
|
| + T visitUnary(Send node, UnaryOperator operator, Node expression, _) {
|
| + return visitDynamicSend(node);
|
| + }
|
| +
|
| + @override
|
| + T visitNotEquals(Send node, Node left, Node right, _) {
|
| + visitDynamicSend(node);
|
| + return types.boolType;
|
| + }
|
| +
|
| + @override
|
| + T visitEquals(Send node, Node left, Node right, _) {
|
| + return visitDynamicSend(node);
|
| + }
|
| +
|
| + @override
|
| + T visitBinary(Send node, Node left, BinaryOperator operator, Node right, _) {
|
| + return visitDynamicSend(node);
|
| }
|
|
|
| // Because some nodes just visit their children, we may end up
|
| @@ -1305,7 +1333,7 @@ abstract class InferrerVisitor
|
| return null;
|
| }
|
|
|
| - void internalError(Spannable node, String reason) {
|
| + internalError(Spannable node, String reason) {
|
| compiler.internalError(node, reason);
|
| }
|
|
|
|
|