Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(17)

Unified Diff: pkg/compiler/lib/src/resolution/members.dart

Issue 1152903003: Create SendStructure for unary and binary in resolution. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: pkg/compiler/lib/src/resolution/members.dart
diff --git a/pkg/compiler/lib/src/resolution/members.dart b/pkg/compiler/lib/src/resolution/members.dart
index 57004c3d40b5c159744798daaf3cdb2ef44d82e2..12468031a68e31a34a407504cfe0c39da812d6c7 100644
--- a/pkg/compiler/lib/src/resolution/members.dart
+++ b/pkg/compiler/lib/src/resolution/members.dart
@@ -2648,13 +2648,13 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
}
// TODO(johnniwinther): Ensure correct behavior if currentClass is a
// patch.
- target = currentClass.lookupSuperSelector(selector);
+ target = currentClass.lookupSuperByName(selector.memberName);
// [target] may be null which means invoking noSuchMethod on
// super.
if (target == null) {
target = reportAndCreateErroneousElement(
node, name, MessageKind.NO_SUCH_SUPER_MEMBER,
- {'className': currentClass, 'memberName': name});
+ {'className': currentClass.name, 'memberName': name});
// We still need to register the invocation, because we might
// call [:super.noSuchMethod:] which calls
// [JSInvocationMirror._invokeOn].
@@ -2859,15 +2859,342 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
}
}
- ResolutionResult visitSend(Send node) {
+ /// Check that access to `super` is currently allowed.
+ bool checkSuperAccess(Node node) {
+ registry.registerSuperUse(node);
karlklose 2015/05/26 08:23:32 Move this to after the checks?
Johnni Winther 2015/05/26 08:53:11 Done.
+ if (!inInstanceContext) {
+ compiler.reportError(node, MessageKind.NO_SUPER_AVAILABLE);
+ return false;
+ }
+ if (currentClass.supertype == null) {
+ // This is just to guard against internal errors, so no need
+ // for a real error message.
+ compiler.reportError(node, MessageKind.GENERIC,
+ {'text': "Object has no superclass"});
+ return false;
+ }
+ return true;
+ }
+
+ /// Compute the [AccessSemantics] corresponding to a super access of [target].
+ AccessSemantics computeSuperAccess(Spannable node, Element target) {
+ if (target.isErroneous) {
+ return new StaticAccess.unresolvedSuper(target);
+ } else if (target.isGetter) {
+ return new StaticAccess.superGetter(target);
+ } else if (target.isSetter) {
+ return new StaticAccess.superSetter(target);
+ } else if (target.isField) {
+ return new StaticAccess.superField(target);
+ } else {
+ assert(invariant(node, target.isFunction,
+ message: "Unexpected super target '$target'."));
+ return new StaticAccess.superMethod(target);
+ }
+ }
+
+ AccessSemantics computeSuperSemantics(Spannable node,
+ Selector selector,
+ {Name alternateName}) {
+ Name name = selector.memberName;
+ // TODO(johnniwinther): Ensure correct behavior if currentClass is a
+ // patch.
+ Element target = currentClass.lookupSuperByName(name);
+ // [target] may be null which means invoking noSuchMethod on super.
+ if (target == null) {
+ Element error = reportAndCreateErroneousElement(
+ node, name.text, MessageKind.NO_SUCH_SUPER_MEMBER,
+ {'className': currentClass.name, 'memberName': name});
+ if (alternateName != null) {
+ target = currentClass.lookupSuperByName(alternateName);
+ }
+ if (target == null) {
+ // If a setter wasn't resolved, use the [ErroneousElement].
+ target = error;
+ }
+ // We still need to register the invocation, because we might
+ // call [:super.noSuchMethod:] which calls [JSInvocationMirror._invokeOn].
+ registry.registerDynamicInvocation(selector);
+ registry.registerSuperNoSuchMethod();
+ }
+ return computeSuperAccess(node, target);
+ }
+
+ ResolutionResult visitExpression(Node node) {
bool oldSendIsMemberAccess = sendIsMemberAccess;
- sendIsMemberAccess = node.isPropertyAccess || node.isCall;
- ResolutionResult result;
- if (node.isLogicalAnd) {
- result = doInPromotionScope(node.receiver, () => resolveSend(node));
+ sendIsMemberAccess = false;
+ ResolutionResult result = visit(node);
+ sendIsMemberAccess = oldSendIsMemberAccess;
+ return result;
+ }
+
+ ResolutionResult handleIs(Send node) {
+ Node expression = node.receiver;
+ visitExpression(expression);
+
+ // TODO(johnniwinther): Use seen type tests to avoid registration of
+ // mutation/access to unpromoted variables.
+
+ Send notTypeNode = node.arguments.head.asSend();
+ DartType type;
+ SendStructure sendStructure;
+ if (notTypeNode != null) {
+ // `e is! T`.
+ Node typeNode = notTypeNode.receiver;
+ type = resolveTypeAnnotation(typeNode);
+ sendStructure = new IsNotStructure(type);
} else {
- result = resolveSend(node);
+ // `e is T`.
+ Node typeNode = node.arguments.head;
+ type = resolveTypeAnnotation(typeNode);
+ sendStructure = new IsStructure(type);
}
+ registry.registerIsCheck(type);
+ registry.registerSendStructure(node, sendStructure);
+ return null;
karlklose 2015/05/26 08:23:32 Not this change, but: I really do not like to retu
Johnni Winther 2015/05/26 08:53:11 Acknowledged.
+ }
+
+ ResolutionResult handleAs(Send node) {
+ Node expression = node.receiver;
+ visitExpression(expression);
+
+ Node typeNode = node.arguments.head;
+ DartType type = resolveTypeAnnotation(typeNode);
+ registry.registerAsCheck(type);
+ registry.registerSendStructure(node, new AsStructure(type));
+ return null;
+ }
+
+ ResolutionResult handleUnresolvedUnary(Send node, String text) {
+ Node expression = node.receiver;
+ if (node.isSuperCall) {
+ checkSuperAccess(node);
+ } else {
+ visitExpression(expression);
+ }
+
+ registry.registerSendStructure(node, const InvalidUnaryStructure());
+ return null;
+ }
+
+ ResolutionResult handleUserDefinableUnary(Send node, UnaryOperator operator) {
+ Node expression = node.receiver;
+ Selector selector = operator.selector;
+ // TODO(johnniwinther): Remove this when all information goes through the
+ // [SendStructure].
+ registry.setSelector(node, selector);
+
+ AccessSemantics semantics;
+ if (node.isSuperCall) {
+ if (checkSuperAccess(node)) {
+ semantics = computeSuperSemantics(node, selector);
+ // TODO(johnniwinther): Add information to [AccessSemantics] about
+ // whether it is erroneous.
+ switch (semantics.kind) {
karlklose 2015/05/26 08:23:32 How about if (semantics.kind == AccessKind.SUPER_
Johnni Winther 2015/05/26 08:53:11 Done.
+ case AccessKind.SUPER_METHOD:
+ registry.registerStaticUse(semantics.element.declaration);
+ break;
+ default:
+ }
+ // TODO(johnniwinther): Remove this when all information goes through
+ // the [SendStructure].
+ registry.useElement(node, semantics.element);
+ }
+ } else {
+ visitExpression(expression);
+ semantics = new DynamicAccess.dynamicProperty(expression);
+ registry.registerDynamicInvocation(selector);
+ }
+ if (semantics != null) {
+ // TODO(johnniwinther): Support invalid super access as an
+ // [AccessSemantics].
+ registry.registerSendStructure(node,
+ new UnaryStructure(semantics, operator));
+ }
+ return null;
+ }
+
+ ResolutionResult handleNot(Send node, UnaryOperator operator) {
+ assert(invariant(node, operator.kind == UnaryOperatorKind.NOT));
+
+ Node expression = node.receiver;
+ visitExpression(expression);
+ registry.registerSendStructure(node,
+ new NotStructure(new DynamicAccess.dynamicProperty(expression)));
+ return null;
+ }
+
+ ResolutionResult handleLogicalAnd(Send node) {
+ Node left = node.receiver;
+ Node right = node.arguments.head;
+ doInPromotionScope(left, () => visitExpression(left));
+ doInPromotionScope(right, () => visitExpression(right));
+ registry.registerSendStructure(node, const LogicalAndStructure());
+ return null;
+ }
+
+ ResolutionResult handleLogicalOr(Send node) {
+ Node left = node.receiver;
+ Node right = node.arguments.head;
+ visitExpression(left);
+ visitExpression(right);
+ registry.registerSendStructure(node, const LogicalOrStructure());
+ return null;
+ }
+
+ ResolutionResult handleUnresolvedBinary(Send node, String text) {
+ Node left = node.receiver;
+ Node right = node.arguments.head;
+ if (node.isSuperCall) {
+ checkSuperAccess(node);
+ } else {
+ visitExpression(left);
+ }
+ visitExpression(right);
+ registry.registerSendStructure(node, const InvalidBinaryStructure());
+ return null;
+ }
+
+ ResolutionResult handleUserDefinableBinary(Send node,
+ BinaryOperator operator) {
+ Node left = node.receiver;
+ Node right = node.arguments.head;
+ AccessSemantics semantics;
+ Selector selector;
+ if (operator.kind == BinaryOperatorKind.INDEX) {
+ selector = new Selector.index();
+ } else {
+ selector = new Selector.binaryOperator(operator.selectorName);
+ }
+ // TODO(johnniwinther): Remove this when all information goes through the
+ // [SendStructure].
+ registry.setSelector(node, selector);
+
+ if (node.isSuperCall) {
+ if (checkSuperAccess(node)) {
+ semantics = computeSuperSemantics(node, selector);
+ // TODO(johnniwinther): Add information to [AccessSemantics] about
+ // whether it is erroneous.
+ switch (semantics.kind) {
karlklose 2015/05/26 08:23:33 See comment for l. 2993.
Johnni Winther 2015/05/26 08:53:11 Done.
+ case AccessKind.SUPER_METHOD:
+ registry.registerStaticUse(semantics.element.declaration);
+ break;
+ default:
+ }
+ // TODO(johnniwinther): Remove this when all information goes through
+ // the [SendStructure].
+ registry.useElement(node, semantics.element);
+
+ }
+ } else {
+ visitExpression(left);
+ registry.registerDynamicInvocation(selector);
+ semantics = new DynamicAccess.dynamicProperty(left);
+ }
+ visitExpression(right);
+
+ if (semantics != null) {
+ // TODO(johnniwinther): Support invalid super access as an
+ // [AccessSemantics].
+ SendStructure sendStructure;
+ switch (operator.kind) {
+ case BinaryOperatorKind.EQ:
+ sendStructure = new EqualsStructure(semantics);
+ break;
+ case BinaryOperatorKind.NOT_EQ:
+ sendStructure = new NotEqualsStructure(semantics);
+ break;
+ case BinaryOperatorKind.INDEX:
+ sendStructure = new IndexStructure(semantics);
+ break;
+ case BinaryOperatorKind.ADD:
+ case BinaryOperatorKind.SUB:
+ case BinaryOperatorKind.MUL:
+ case BinaryOperatorKind.DIV:
+ case BinaryOperatorKind.IDIV:
+ case BinaryOperatorKind.MOD:
+ case BinaryOperatorKind.SHL:
+ case BinaryOperatorKind.SHR:
+ case BinaryOperatorKind.GTEQ:
+ case BinaryOperatorKind.GT:
+ case BinaryOperatorKind.LTEQ:
+ case BinaryOperatorKind.LT:
+ case BinaryOperatorKind.AND:
+ case BinaryOperatorKind.OR:
+ case BinaryOperatorKind.XOR:
+ sendStructure = new BinaryStructure(semantics, operator);
+ break;
+ case BinaryOperatorKind.LOGICAL_AND:
+ case BinaryOperatorKind.LOGICAL_OR:
+ internalError(node, "Unexpected binary operator '${operator}'.");
+ break;
+ }
+ registry.registerSendStructure(node, sendStructure);
+ }
+ return null;
+ }
+
+ ResolutionResult visitSend(Send node) {
+ if (node.isOperator) {
+ String operatorText = node.selector.asOperator().source;
+ if (operatorText == 'is') {
+ return handleIs(node);
+ } else if (operatorText == 'as') {
+ return handleAs(node);
+ } else if (node.arguments.isEmpty) {
+ UnaryOperator operator = UnaryOperator.parse(operatorText);
+ if (operator == null) {
+ return handleUnresolvedUnary(node, operatorText);
+ } else {
+ switch (operator.kind) {
+ case UnaryOperatorKind.NOT:
+ return handleNot(node, operator);
+ case UnaryOperatorKind.COMPLEMENT:
+ case UnaryOperatorKind.NEGATE:
+ assert(invariant(node, operator.isUserDefinable,
+ message: "Unexpected unary operator '${operator}'."));
+ return handleUserDefinableUnary(node, operator);
+ }
+ return handleUserDefinableUnary(node, operator);
+ }
+ } else {
+ BinaryOperator operator = BinaryOperator.parse(operatorText);
+ if (operator == null) {
+ return handleUnresolvedBinary(node, operatorText);
+ } else {
+ switch (operator.kind) {
+ case BinaryOperatorKind.LOGICAL_AND:
+ return handleLogicalAnd(node);
+ case BinaryOperatorKind.LOGICAL_OR:
+ return handleLogicalOr(node);
+ case BinaryOperatorKind.EQ:
+ case BinaryOperatorKind.NOT_EQ:
+ case BinaryOperatorKind.INDEX:
+ case BinaryOperatorKind.ADD:
+ case BinaryOperatorKind.SUB:
+ case BinaryOperatorKind.MUL:
+ case BinaryOperatorKind.DIV:
+ case BinaryOperatorKind.IDIV:
+ case BinaryOperatorKind.MOD:
+ case BinaryOperatorKind.SHL:
+ case BinaryOperatorKind.SHR:
+ case BinaryOperatorKind.GTEQ:
+ case BinaryOperatorKind.GT:
+ case BinaryOperatorKind.LTEQ:
+ case BinaryOperatorKind.LT:
+ case BinaryOperatorKind.AND:
+ case BinaryOperatorKind.OR:
+ case BinaryOperatorKind.XOR:
+ return handleUserDefinableBinary(node, operator);
+ }
+ }
+ }
+ }
+
+ bool oldSendIsMemberAccess = sendIsMemberAccess;
+ sendIsMemberAccess = node.isPropertyAccess || node.isCall;
+
+ ResolutionResult result = resolveSend(node);
sendIsMemberAccess = oldSendIsMemberAccess;
Element target = result != null ? result.element : null;
@@ -2918,43 +3245,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
}
bool resolvedArguments = false;
- if (node.isOperator) {
- String operatorString = node.selector.asOperator().source;
- SendStructure sendStructure;
- if (operatorString == 'is') {
- // TODO(johnniwinther): Use seen type tests to avoid registration of
- // mutation/access to unpromoted variables.
- DartType type =
- resolveTypeAnnotation(node.typeAnnotationFromIsCheckOrCast);
- if (type != null) {
- sendStructure = node.isIsNotCheck
- ? new IsNotStructure(type) : new IsStructure(type);
- registry.registerIsCheck(type);
- }
- resolvedArguments = true;
- } else if (identical(operatorString, 'as')) {
- DartType type = resolveTypeAnnotation(node.arguments.head);
- if (type != null) {
- sendStructure = new AsStructure(type);
- registry.registerAsCheck(type);
- }
- resolvedArguments = true;
- } else if (identical(operatorString, '&&')) {
- doInPromotionScope(node.arguments.head,
- () => resolveArguments(node.argumentsNode));
- sendStructure = const LogicalAndStructure();
- resolvedArguments = true;
- } else if (operatorString == '||') {
- sendStructure = const LogicalOrStructure();
- }
- if (sendStructure != null) {
- registry.registerSendStructure(node, sendStructure);
- }
- }
-
- if (!resolvedArguments) {
- resolveArguments(node.argumentsNode);
- }
+ resolveArguments(node.argumentsNode);
// If the selector is null, it means that we will not be generating
// code for this as a send.
@@ -3124,11 +3415,11 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
registerSend(getterSelector, getter);
registry.setGetterSelectorInComplexSendSet(node, getterSelector);
if (node.isSuperCall) {
- getter = currentClass.lookupSuperSelector(getterSelector);
+ getter = currentClass.lookupSuperByName(getterSelector.memberName);
if (getter == null) {
target = reportAndCreateErroneousElement(
node, selector.name, MessageKind.NO_SUCH_SUPER_MEMBER,
- {'className': currentClass, 'memberName': selector.name});
+ {'className': currentClass.name, 'memberName': selector.name});
registry.registerSuperNoSuchMethod();
}
}

Powered by Google App Engine
This is Rietveld 408576698