blob: 6828a795257b606adf83058b87bbb004050abf9b [file] [log] [blame]
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
part of dart2js;
/// Enum for the visit methods added in [ResolvedVisitor].
// TODO(johnniwinther): Remove this.
enum ResolvedKind {
ASSERT,
TYPE_LITERAL,
SUPER,
OPERATOR,
TYPE_PREFIX,
GETTER,
STATIC,
CLOSURE,
DYNAMIC,
ERROR,
SEND_SET,
NEW,
SUPER_CONSTRUCTOR,
}
/// Abstract interface for a [ResolvedVisitor].
// TODO(johnniwinther): Remove this.
abstract class ResolvedKindVisitor<R> {
@deprecated
R visitSuperSend(Send node);
@deprecated
R visitOperatorSend(Send node);
R visitGetterSend(Send node);
@deprecated
R visitClosureSend(Send node);
@deprecated
R visitDynamicSend(Send node);
R visitStaticSend(Send node);
R handleSuperConstructorInvoke(Send node);
R handleSendSet(SendSet node);
R handleNewExpression(NewExpression node);
/// Visitor callback for a type literal.
@deprecated
R visitTypeLiteralSend(Send node);
/// Visitor callback for the class prefix of a static access, like `Foo` in
/// `Foo.staticField`.
// TODO(johnniwinther): Remove this when not needed by the inferrer.
@deprecated
R visitTypePrefixSend(Send node);
@deprecated
R visitAssertSend(Send node);
internalError(Spannable node, String reason);
}
/// Visitor that returns the [ResolvedKind] corresponding to the called visitor
/// method.
class ResolvedKindComputer implements ResolvedKindVisitor {
const ResolvedKindComputer();
ResolvedKind visitSuperSend(Send node) => ResolvedKind.SUPER;
ResolvedKind visitOperatorSend(Send node) => ResolvedKind.OPERATOR;
ResolvedKind visitGetterSend(Send node) => ResolvedKind.GETTER;
ResolvedKind visitClosureSend(Send node) => ResolvedKind.CLOSURE;
ResolvedKind visitDynamicSend(Send node) => ResolvedKind.DYNAMIC;
ResolvedKind visitStaticSend(Send node) => ResolvedKind.STATIC;
ResolvedKind visitTypeLiteralSend(Send node) => ResolvedKind.TYPE_LITERAL;
ResolvedKind visitTypePrefixSend(Send node) => ResolvedKind.TYPE_PREFIX;
ResolvedKind visitAssertSend(Send node) => ResolvedKind.ASSERT;
ResolvedKind handleSuperConstructorInvoke(Send node) {
return ResolvedKind.SUPER_CONSTRUCTOR;
}
ResolvedKind handleSendSet(SendSet node) => ResolvedKind.SEND_SET;
ResolvedKind handleNewExpression(NewExpression node) => ResolvedKind.NEW;
internalError(Spannable node, String reason) => ResolvedKind.ERROR;
}
abstract class ResolvedVisitor<R>
implements Visitor<R>, ResolvedKindVisitor<R> {}
abstract class BaseResolvedVisitor<R> extends Visitor<R>
implements ResolvedVisitor<R> {
TreeElements elements;
BaseResolvedVisitor(this.elements);
/// Dispatch using the old [ResolvedVisitor] logic.
// TODO(johnniwinther): Remove this.
_oldDispatch(Send node, ResolvedKindVisitor visitor) {
Element element = elements[node];
if (elements.isAssert(node)) {
return visitor.visitAssertSend(node);
} else if (elements.isTypeLiteral(node)) {
return visitor.visitTypeLiteralSend(node);
} else if (node.isSuperCall) {
if (element != null && element.isConstructor) {
return visitor.handleSuperConstructorInvoke(node);
}
return visitor.visitSuperSend(node);
} else if (node.isOperator) {
return visitor.visitOperatorSend(node);
} else if (node.isPropertyAccess) {
if (!Elements.isUnresolved(element) && element.impliesType) {
return visitor.visitTypePrefixSend(node);
} else {
return visitor.visitGetterSend(node);
}
} else if (element != null && Initializers.isConstructorRedirect(node)) {
return visitor.visitStaticSend(node);
} else if (Elements.isClosureSend(node, element)) {
return visitor.visitClosureSend(node);
} else {
if (node.isConditional) {
return visitor.visitDynamicSend(node);
} else if (Elements.isUnresolved(element)) {
if (element == null) {
// Example: f() with 'f' unbound.
// This can only happen inside an instance method.
return visitor.visitDynamicSend(node);
} else {
return visitor.visitStaticSend(node);
}
} else if (element.isInstanceMember) {
// Example: f() with 'f' bound to instance method.
return visitor.visitDynamicSend(node);
} else if (!element.isInstanceMember) {
// Example: A.f() or f() with 'f' bound to a static function.
// Also includes new A() or new A.named() which is treated like a
// static call to a factory.
return visitor.visitStaticSend(node);
} else {
return visitor.internalError(node, "Cannot generate code for send");
}
}
}
internalError(Spannable node, String reason);
R visitNode(Node node) {
internalError(node, "Unhandled node");
return null;
}
}
abstract class NewResolvedVisitor<R> extends BaseResolvedVisitor<R>
with SendResolverMixin,
GetBulkMixin<R, dynamic>,
SetBulkMixin<R, dynamic>,
ErrorBulkMixin<R, dynamic>,
InvokeBulkMixin<R, dynamic>,
IndexSetBulkMixin<R, dynamic>,
CompoundBulkMixin<R, dynamic>,
UnaryBulkMixin<R, dynamic>,
BaseBulkMixin<R, dynamic>,
BinaryBulkMixin<R, dynamic>,
PrefixBulkMixin<R, dynamic>,
PostfixBulkMixin<R, dynamic>,
NewBulkMixin<R, dynamic> {
final ResolvedSemanticDispatcher<R> _semanticDispatcher =
new ResolvedSemanticDispatcher<R>();
final ResolvedSemanticDispatcher<ResolvedKind> _resolvedKindDispatcher =
new ResolvedSemanticDispatcher<ResolvedKind>();
NewResolvedVisitor(TreeElements elements) : super(elements);
/// Dispatch using the new [SemanticSendVisitor] logic.
_newDispatch(Send node,
ResolvedKindVisitor kindVisitor,
SemanticSendVisitor sendVisitor) {
Element element = elements[node];
if (element != null && element.isConstructor) {
if (node.isSuperCall) {
return kindVisitor.handleSuperConstructorInvoke(node);
} else {
return kindVisitor.visitStaticSend(node);
}
} else if (element != null && element.isPrefix) {
return kindVisitor.visitGetterSend(node);
} else if (!elements.isTypeLiteral(node) &&
node.isPropertyAccess &&
!Elements.isUnresolved(element) &&
element.impliesType) {
return kindVisitor.visitTypePrefixSend(node);
} else {
SendStructure sendStructure = computeSendStructure(node);
if (sendStructure != null) {
var arg = sendVisitor == _resolvedKindDispatcher
? kindVisitor : sendStructure;
return sendStructure.dispatch(sendVisitor, node, arg);
} else {
return kindVisitor.visitStaticSend(node);
}
}
}
@override
R visitDynamicSend(Send node) {
return internalError(node, "visitDynamicSend is deprecated");
}
@override
R visitSuperSend(Send node) {
return internalError(node, "visitSuperSend is deprecated");
}
@override
R visitOperatorSend(Send node) {
return internalError(node, "visitOperaterSend is deprecated");
}
@override
R visitClosureSend(Send node) {
return internalError(node, "visitClosureSend is deprecated");
}
@override
R visitTypeLiteralSend(Send node) {
return internalError(node, "visitTypeLiteralSend is deprecated");
}
@override
R visitTypePrefixSend(Send node) {
return internalError(node, "visitTypePrefixSend is deprecated");
}
@override
R visitAssertSend(Send node) {
return internalError(node, "visitAssertSend is deprecated");
}
bool checkResolvedKind(Node node,
ResolvedKind oldKind,
ResolvedKind newKind) {
return invariant(node, oldKind == newKind,
message: 'old=$oldKind != new=$newKind');
}
ResolvedKind computeResolvedKindFromStructure(
Node node, SemanticSendStructure structure) {
return structure.dispatch(
_resolvedKindDispatcher, node, const ResolvedKindComputer());
}
@override
R visitSend(Send node) {
assert(checkResolvedKind(
node,
_oldDispatch(node, const ResolvedKindComputer()),
_newDispatch(node, const ResolvedKindComputer(),
_resolvedKindDispatcher)));
return _newDispatch(node, this, this);
}
@override
R visitSendSet(Send node) {
SendStructure structure = computeSendStructure(node);
if (structure == null) {
return internalError(node, 'No structure for $node');
} else {
assert(checkResolvedKind(node,
ResolvedKind.SEND_SET,
computeResolvedKindFromStructure(node, structure)));
return structure.dispatch(this, node, structure);
}
}
@override
R visitNewExpression(NewExpression node) {
NewStructure structure = computeNewStructure(node);
if (structure == null) {
return internalError(node, 'No structure for $node');
} else {
assert(checkResolvedKind(node,
ResolvedKind.NEW,
computeResolvedKindFromStructure(node, structure)));
return structure.dispatch(this, node, structure);
}
}
@override
R apply(Node node, arg) {
return visitNode(node);
}
@override
R bulkHandleNode(
Node node,
String message,
SemanticSendStructure structure) {
return structure.dispatch(_semanticDispatcher, node, this);
}
}
/// Visitor that dispatches [SemanticSendVisitor] calls to the corresponding
/// visit methods in [ResolvedVisitor].
class ResolvedSemanticDispatcher<R> extends Object
with GetBulkMixin<R, ResolvedKindVisitor<R>>,
SetBulkMixin<R, ResolvedKindVisitor<R>>,
InvokeBulkMixin<R, ResolvedKindVisitor<R>>,
PrefixBulkMixin<R, ResolvedKindVisitor<R>>,
PostfixBulkMixin<R, ResolvedKindVisitor<R>>,
SuperBulkMixin<R, ResolvedKindVisitor<R>>,
CompoundBulkMixin<R, ResolvedKindVisitor<R>>,
IndexSetBulkMixin<R, ResolvedKindVisitor<R>>,
NewBulkMixin<R, ResolvedKindVisitor<R>>,
ErrorBulkMixin<R, ResolvedKindVisitor<R>>
implements SemanticSendVisitor<R, ResolvedKindVisitor<R>> {
ResolvedSemanticDispatcher();
@override
R apply(Node node, ResolvedKindVisitor<R> visitor) {
return visitor.internalError(
node, "ResolvedSemanticDispatcher.apply unsupported.");
}
@override
R bulkHandleNode(
Node node,
String message,
ResolvedKindVisitor<R> visitor) {
return bulkHandleError(node, visitor);
}
R bulkHandleError(Node node, ResolvedKindVisitor<R> visitor) {
if (node.asSendSet() != null) {
return visitor.handleSendSet(node);
} else if (node.asNewExpression() != null) {
return visitor.handleNewExpression(node);
}
return visitor.internalError(node, "No resolved kind for $node.");
}
@override
R bulkHandleGet(Node node, ResolvedKindVisitor<R> visitor) {
return visitor.visitGetterSend(node);
}
@override
R bulkHandleInvoke(Node node, ResolvedKindVisitor<R> visitor) {
// Most invokes are static.
return visitor.visitStaticSend(node);
}
@override
R bulkHandlePrefix(Node node, ResolvedKindVisitor<R> visitor) {
return visitor.handleSendSet(node);
}
@override
R bulkHandlePostfix(Node node, ResolvedKindVisitor<R> visitor) {
return visitor.handleSendSet(node);
}
@override
R bulkHandleSuper(Node node, ResolvedKindVisitor<R> visitor) {
if (node.asSendSet() != null) {
return visitor.handleSendSet(node);
}
return visitor.visitSuperSend(node);
}
@override
R bulkHandleSet(SendSet node, ResolvedKindVisitor<R> visitor) {
return visitor.handleSendSet(node);
}
@override
R bulkHandleCompound(SendSet node, ResolvedKindVisitor<R> visitor) {
return visitor.handleSendSet(node);
}
@override
R bulkHandleIndexSet(SendSet node, ResolvedKindVisitor<R> visitor) {
return visitor.handleSendSet(node);
}
@override
R bulkHandleNew(NewExpression node, ResolvedKindVisitor<R> visitor) {
return visitor.handleNewExpression(node);
}
@override
R errorInvalidAssert(
Send node,
NodeList arguments,
ResolvedKindVisitor<R> visitor) {
return visitor.visitAssertSend(node);
}
@override
R visitLocalFunctionPostfix(
Send node,
LocalFunctionElement function,
op.IncDecOperator operator,
ResolvedKindVisitor<R> visitor) {
return visitor.handleSendSet(node);
}
@override
R visitLocalFunctionPrefix(
Send node,
LocalFunctionElement function,
op.IncDecOperator operator,
ResolvedKindVisitor<R> visitor) {
return visitor.handleSendSet(node);
}
@override
R visitStaticSetterGet(
Send node,
FunctionElement setter,
ResolvedKindVisitor<R> visitor) {
return visitor.visitGetterSend(node);
}
@override
R visitStaticSetterInvoke(
Send node,
FunctionElement setter,
NodeList arguments,
CallStructure callStructure,
ResolvedKindVisitor<R> visitor) {
return visitor.visitStaticSend(node);
}
@override
R visitSuperSetterGet(
Send node,
FunctionElement setter,
ResolvedKindVisitor<R> visitor) {
return visitor.visitSuperSend(node);
}
@override
R visitSuperSetterInvoke(
Send node,
FunctionElement setter,
NodeList arguments,
CallStructure callStructure,
ResolvedKindVisitor<R> visitor) {
return visitor.visitSuperSend(node);
}
@override
R visitTopLevelSetterGet(
Send node,
FunctionElement setter,
ResolvedKindVisitor<R> visitor) {
return visitor.visitGetterSend(node);
}
@override
R visitTopLevelSetterInvoke(
Send node,
FunctionElement setter,
NodeList arguments,
CallStructure callStructure,
ResolvedKindVisitor<R> visitor) {
return visitor.visitStaticSend(node);
}
@override
R errorUndefinedBinaryExpression(
Send node,
Node left,
Operator operator,
Node right,
ResolvedKindVisitor<R> visitor) {
return visitor.visitOperatorSend(node);
}
@override
R errorUndefinedUnaryExpression(
Send node,
Operator operator,
Node expression,
ResolvedKindVisitor<R> visitor) {
return visitor.visitOperatorSend(node);
}
@override
R visitUnresolvedGet(
Send node,
Element element,
ResolvedKindVisitor<R> visitor) {
return visitor.visitGetterSend(node);
}
@override
R visitUnresolvedSuperGet(
Send node,
Element element,
ResolvedKindVisitor<R> visitor) {
return visitor.visitSuperSend(node);
}
@override
R visitUnresolvedInvoke(
Send node,
Element element,
NodeList arguments,
Selector selector,
ResolvedKindVisitor<R> visitor) {
return visitor.visitStaticSend(node);
}
@override
R visitUnresolvedPostfix(
Send node,
Element element,
op.IncDecOperator operator,
ResolvedKindVisitor<R> visitor) {
return visitor.handleSendSet(node);
}
@override
R visitUnresolvedPrefix(
Send node,
Element element,
op.IncDecOperator operator,
ResolvedKindVisitor<R> visitor) {
return visitor.handleSendSet(node);
}
@override
R visitAs(
Send node,
Node expression,
DartType type,
ResolvedKindVisitor<R> visitor) {
return visitor.visitOperatorSend(node);
}
@override
R visitAssert(
Send node,
Node expression,
ResolvedKindVisitor<R> visitor) {
return visitor.visitAssertSend(node);
}
@override
R visitBinary(
Send node,
Node left,
op.BinaryOperator operator,
Node right,
ResolvedKindVisitor<R> visitor) {
return visitor.visitOperatorSend(node);
}
@override
R visitEquals(
Send node,
Node left,
Node right,
ResolvedKindVisitor<R> visitor) {
return visitor.visitOperatorSend(node);
}
@override
R visitIs(
Send node,
Node expression,
DartType type,
ResolvedKindVisitor<R> visitor) {
return visitor.visitOperatorSend(node);
}
@override
R visitIsNot(
Send node,
Node expression,
DartType type,
ResolvedKindVisitor<R> visitor) {
return visitor.visitOperatorSend(node);
}
@override
R visitIfNull(
Send node,
Node left,
Node right,
ResolvedKindVisitor<R> visitor) {
return visitor.visitOperatorSend(node);
}
@override
R visitLogicalAnd(
Send node,
Node left,
Node right,
ResolvedKindVisitor<R> visitor) {
return visitor.visitOperatorSend(node);
}
@override
R visitLogicalOr(
Send node,
Node left,
Node right,
ResolvedKindVisitor<R> visitor) {
return visitor.visitOperatorSend(node);
}
@override
R visitNot(
Send node,
Node expression,
ResolvedKindVisitor<R> visitor) {
return visitor.visitOperatorSend(node);
}
@override
R visitNotEquals(
Send node,
Node left,
Node right,
ResolvedKindVisitor<R> visitor) {
return visitor.visitOperatorSend(node);
}
@override
R visitUnary(
Send node,
op.UnaryOperator operator,
Node expression,
ResolvedKindVisitor<R> visitor) {
return visitor.visitOperatorSend(node);
}
@override
R visitDynamicPropertyInvoke(
Send node,
Node receiver,
NodeList arguments,
Selector selector,
ResolvedKindVisitor<R> visitor) {
return visitor.visitDynamicSend(node);
}
@override
R visitIfNotNullDynamicPropertyInvoke(
Send node,
Node receiver,
NodeList arguments,
Selector selector,
ResolvedKindVisitor<R> visitor) {
return visitor.visitDynamicSend(node);
}
@override
R visitThisPropertyInvoke(
Send node,
NodeList arguments,
Selector selector,
ResolvedKindVisitor<R> visitor) {
return visitor.visitDynamicSend(node);
}
@override
R visitExpressionInvoke(
Send node,
Node receiver,
NodeList arguments,
Selector selector,
ResolvedKindVisitor<R> visitor) {
return visitor.visitClosureSend(node);
}
@override
R visitParameterInvoke(
Send node,
ParameterElement parameter,
NodeList arguments,
CallStructure callStructure,
ResolvedKindVisitor<R> visitor) {
return visitor.visitClosureSend(node);
}
@override
R visitLocalVariableInvoke(
Send node,
LocalVariableElement variable,
NodeList arguments,
CallStructure callStructure,
ResolvedKindVisitor<R> visitor) {
return visitor.visitClosureSend(node);
}
@override
R visitLocalFunctionInvoke(
Send node,
LocalFunctionElement function,
NodeList arguments,
CallStructure callStructure,
ResolvedKindVisitor<R> visitor) {
return visitor.visitClosureSend(node);
}
@override
R visitThisInvoke(
Send node,
NodeList arguments,
CallStructure callStructure,
ResolvedKindVisitor<R> visitor) {
return visitor.visitClosureSend(node);
}
@override
R visitClassTypeLiteralGet(
Send node,
ConstantExpression constant,
ResolvedKindVisitor<R> visitor) {
return visitor.visitTypeLiteralSend(node);
}
@override
R visitTypedefTypeLiteralGet(
Send node,
ConstantExpression constant,
ResolvedKindVisitor<R> visitor) {
return visitor.visitTypeLiteralSend(node);
}
@override
R visitDynamicTypeLiteralGet(
Send node,
ConstantExpression constant,
ResolvedKindVisitor<R> visitor) {
return visitor.visitTypeLiteralSend(node);
}
@override
R visitTypeVariableTypeLiteralGet(
Send node,
TypeVariableElement element,
ResolvedKindVisitor<R> visitor) {
return visitor.visitTypeLiteralSend(node);
}
@override
R visitClassTypeLiteralInvoke(
Send node,
ConstantExpression constant,
NodeList arguments,
CallStructure callStructure,
ResolvedKindVisitor<R> visitor) {
return visitor.visitTypeLiteralSend(node);
}
@override
R visitTypedefTypeLiteralInvoke(
Send node,
ConstantExpression constant,
NodeList arguments,
CallStructure callStructure,
ResolvedKindVisitor<R> visitor) {
return visitor.visitTypeLiteralSend(node);
}
@override
R visitDynamicTypeLiteralInvoke(
Send node,
ConstantExpression constant,
NodeList arguments,
CallStructure callStructure,
ResolvedKindVisitor<R> visitor) {
return visitor.visitTypeLiteralSend(node);
}
@override
R visitTypeVariableTypeLiteralInvoke(
Send node,
TypeVariableElement element,
NodeList arguments,
CallStructure callStructure,
ResolvedKindVisitor<R> visitor) {
return visitor.visitTypeLiteralSend(node);
}
@override
R visitIndex(
Send node,
Node receiver,
Node index,
ResolvedKindVisitor<R> visitor) {
return visitor.visitOperatorSend(node);
}
@override
R visitSuperIndex(
Send node,
FunctionElement function,
Node index,
ResolvedKindVisitor<R> visitor) {
return visitor.visitSuperSend(node);
}
}