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

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

Issue 929113002: Add SemanticVisitor to dart2js. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Updated and extended Created 5 years, 10 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/send_resolver.dart
diff --git a/pkg/compiler/lib/src/resolution/send_resolver.dart b/pkg/compiler/lib/src/resolution/send_resolver.dart
new file mode 100644
index 0000000000000000000000000000000000000000..4c5047312b08e89c59a1d50d31d49f00cde38f37
--- /dev/null
+++ b/pkg/compiler/lib/src/resolution/send_resolver.dart
@@ -0,0 +1,374 @@
+// Copyright (c) 2015, 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.semantics_visitor;
+
+enum SendStructureKind {
+ GET,
+ SET,
+ INVOKE,
+ UNARY,
+ NOT,
+ BINARY,
+ EQ,
+ NOT_EQ,
+ COMPOUND,
+ INDEX_SET,
+ COMPOUND_INDEX_SET,
+ PREFIX,
+ POSTFIX,
+}
+
+abstract class SendResolverMixin {
+ TreeElements get elements;
+
+ internalError(Spannable spannable, String message);
+
+ AccessSemantics handleStaticallyResolvedAccess(Send node,
+ Element element,
+ Element getter) {
+ if (element.isErroneous) {
+ return new StaticAccess.unresolved(element);
+ } else if (element.isParameter) {
+ return new StaticAccess.parameter(element);
+ } else if (element.isLocal) {
+ if (element.isFunction) {
+ return new StaticAccess.localFunction(element);
+ } else {
+ return new StaticAccess.localVariable(element);
+ }
+ } else if (element.isStatic) {
+ if (element.isField) {
+ return new StaticAccess.staticField(element);
+ } else if (element.isGetter) {
+ return new StaticAccess.staticGetter(element);
+ } else if (element.isSetter) {
+ if (getter != null) {
+ CompoundAccessKind accessKind;
+ if (getter.isGetter) {
+ accessKind = CompoundAccessKind.STATIC_GETTER_SETTER;
+ } else {
+ accessKind = CompoundAccessKind.STATIC_METHOD_SETTER;
+ }
+ return new CompoundAccessSemantics(
+ accessKind, getter, element);
+ } else {
+ return new StaticAccess.staticSetter(element);
+ }
+ } else {
+ return new StaticAccess.staticMethod(element);
+ }
+ } else if (element.isTopLevel) {
+ if (element.isField) {
+ return new StaticAccess.topLevelField(element);
+ } else if (element.isGetter) {
+ return new StaticAccess.topLevelGetter(element);
+ } else if (element.isSetter) {
+ if (getter != null) {
+ CompoundAccessKind accessKind;
+ if (getter.isGetter) {
+ accessKind = CompoundAccessKind.TOPLEVEL_GETTER_SETTER;
+ } else {
+ accessKind = CompoundAccessKind.TOPLEVEL_METHOD_SETTER;
+ }
+ return new CompoundAccessSemantics(
+ accessKind, getter, element);
+ } else {
+ return new StaticAccess.topLevelSetter(element);
+ }
+ } else {
+ return new StaticAccess.topLevelMethod(element);
+ }
+ } else {
+ return internalError(
+ node, "Unhandled resolved property access: $element");
+ }
+ }
+
+ SendStructure computeSendStructure(Send node) {
+ if (elements.isAssert(node)) {
+ if (!node.arguments.isEmpty && node.arguments.tail.isEmpty) {
+ return const AssertStructure();
+ } else {
+ return const InvalidAssertStructure();
+ }
+ }
+
+ AssignmentOperator assignmentOperator;
+ UnaryOperator unaryOperator;
+ BinaryOperator binaryOperator;
+ IncDecOperator incDecOperator;
+
+ if (node.isOperator) {
+ String operatorText = node.selector.asOperator().source;
+ if (operatorText == 'is') {
+ if (node.isIsNotCheck) {
+ return new IsNotStructure(
+ elements.getType(node.arguments.single.asSend().receiver));
+ } else {
+ return new IsStructure(elements.getType(node.arguments.single));
+ }
+ } else if (operatorText == 'as') {
+ return new AsStructure(elements.getType(node.arguments.single));
+ } else if (operatorText == '&&') {
+ return const LogicalAndStructure();
+ } else if (operatorText == '||') {
+ return const LogicalOrStructure();
+ }
+ }
+
+ SendStructureKind kind;
+
+ if (node.asSendSet() != null) {
+ SendSet sendSet = node.asSendSet();
+ String operatorText = sendSet.assignmentOperator.source;
+ if (sendSet.isPrefix || sendSet.isPostfix) {
+ kind = sendSet.isPrefix
+ ? SendStructureKind.PREFIX
+ : SendStructureKind.POSTFIX;
+ incDecOperator = IncDecOperator.parse(operatorText);
+ if (incDecOperator == null) {
+ return internalError(
+ node, "No inc/dec operator for '$operatorText'.");
+ }
+ } else {
+ assignmentOperator = AssignmentOperator.parse(operatorText);
+ if (assignmentOperator != null) {
+ switch (assignmentOperator.kind) {
+ case AssignmentOperatorKind.ASSIGN:
+ kind = SendStructureKind.SET;
+ break;
+ default:
+ kind = SendStructureKind.COMPOUND;
+ }
+ } else {
+ return internalError(
+ node, "No assignment operator for '$operatorText'.");
+ }
+ }
+ } else if (!node.isPropertyAccess) {
+ kind = SendStructureKind.INVOKE;
+ } else {
+ kind = SendStructureKind.GET;
+ }
+
+ if (node.isOperator) {
+ String operatorText = node.selector.asOperator().source;
+ if (node.arguments.isEmpty) {
+ unaryOperator = UnaryOperator.parse(operatorText);
+ if (unaryOperator != null) {
+ switch (unaryOperator.kind) {
+ case UnaryOperatorKind.NOT:
+ kind = SendStructureKind.NOT;
+ break;
+ default:
+ kind = SendStructureKind.UNARY;
+ break;
+ }
+ } else {
+ return const InvalidUnaryStructure();
+ }
+ } else {
+ binaryOperator = BinaryOperator.parse(operatorText);
+ if (binaryOperator != null) {
+ switch (binaryOperator.kind) {
+ case BinaryOperatorKind.EQ:
+ kind = SendStructureKind.EQ;
+ break;
+ case BinaryOperatorKind.NOT_EQ:
+ if (node.isSuperCall) {
+ // `super != foo` is a compile-time error.
+ return const InvalidBinaryStructure();
+ }
+ kind = SendStructureKind.NOT_EQ;
+ break;
+ case BinaryOperatorKind.INDEX:
+ if (node.arguments.tail.isEmpty) {
+ // a[b]
+ kind = SendStructureKind.BINARY;
+ } else {
+ if (kind == SendStructureKind.COMPOUND) {
+ // a[b] += c
+ kind = SendStructureKind.COMPOUND_INDEX_SET;
+ } else {
+ // a[b] = c
+ kind = SendStructureKind.INDEX_SET;
+ }
+ }
+ break;
+ default:
+ kind = SendStructureKind.BINARY;
+ break;
+ }
+ } else {
+ return const InvalidBinaryStructure();
+ }
+ }
+ }
+ AccessSemantics semantics = computeAccessSemantics(
+ node,
+ isGetOrSet: kind == SendStructureKind.GET ||
+ kind == SendStructureKind.SET,
+ isInvoke: kind == SendStructureKind.INVOKE,
+ isCompound: kind == SendStructureKind.COMPOUND ||
+ kind == SendStructureKind.COMPOUND_INDEX_SET ||
+ kind == SendStructureKind.PREFIX ||
+ kind == SendStructureKind.POSTFIX);
+ if (semantics == null) {
+ return internalError(node, 'No semantics for $node');
+ }
+ Selector selector = elements.getSelector(node);
+ switch (kind) {
+ case SendStructureKind.GET:
karlklose 2015/03/10 13:57:46 I think we use 2 space indentation for 'case'.
Johnni Winther 2015/03/11 09:14:47 Done.
+ return new GetStructure(semantics, selector);
+ case SendStructureKind.SET:
+ return new SetStructure(semantics, selector);
+ case SendStructureKind.INVOKE:
+ return new InvokeStructure(semantics, selector);
+ case SendStructureKind.UNARY:
+ return new UnaryStructure(semantics, unaryOperator, selector);
+ case SendStructureKind.NOT:
+ assert(selector == null);
+ return new NotStructure(semantics, selector);
+ case SendStructureKind.BINARY:
+ return new BinaryStructure(semantics, binaryOperator, selector);
+ case SendStructureKind.EQ:
+ return new EqualsStructure(semantics, selector);
+ case SendStructureKind.NOT_EQ:
+ return new NotEqualsStructure(semantics, selector);
+ case SendStructureKind.COMPOUND:
+ Selector getterSelector =
+ elements.getGetterSelectorInComplexSendSet(node);
+ return new CompoundStructure(
+ semantics,
+ assignmentOperator,
+ getterSelector,
+ selector);
+ case SendStructureKind.INDEX_SET:
+ return new IndexSetStructure(semantics, selector);
+ case SendStructureKind.COMPOUND_INDEX_SET:
+ Selector getterSelector =
+ elements.getGetterSelectorInComplexSendSet(node);
+ return new CompoundIndexSetStructure(
+ semantics,
+ assignmentOperator,
+ getterSelector,
+ selector);
+ case SendStructureKind.PREFIX:
+ Selector getterSelector =
+ elements.getGetterSelectorInComplexSendSet(node);
+ return new PrefixStructure(
+ semantics,
+ incDecOperator,
+ getterSelector,
+ selector);
+ case SendStructureKind.POSTFIX:
+ Selector getterSelector =
+ elements.getGetterSelectorInComplexSendSet(node);
+ return new PostfixStructure(
+ semantics,
+ incDecOperator,
+ getterSelector,
+ selector);
+ }
+ }
+
+ AccessSemantics computeAccessSemantics(Send node,
+ {bool isGetOrSet: false,
+ bool isInvoke: false,
+ bool isCompound: false}) {
+ Element element = elements[node];
+ Element getter = isCompound ? elements[node.selector] : null;
+ if (elements.isTypeLiteral(node)) {
+ DartType dartType = elements.getTypeLiteralType(node);
+ TypeConstantExpression constant = elements.getConstant(
+ isInvoke ? node.selector : node);
+ switch (dartType.kind) {
+ case TypeKind.INTERFACE:
+ return new ConstantAccess.classTypeLiteral(constant);
+ case TypeKind.TYPEDEF:
+ return new ConstantAccess.typedefTypeLiteral(constant);
+ case TypeKind.TYPE_VARIABLE:
+ return new StaticAccess.typeParameterTypeLiteral(dartType.element);
+ case TypeKind.DYNAMIC:
+ return new ConstantAccess.dynamicTypeLiteral(constant);
+ default:
+ return internalError(node, "Unexpected type literal type: $dartType");
+ }
+ } else if (node.isSuperCall) {
+ if (Elements.isUnresolved(element)) {
+ return new StaticAccess.unresolved(element);
+ } else if (isCompound && Elements.isUnresolved(getter)) {
+ // TODO(johnniwinther): Ensure that [getter] is not null. This happens
+ // in the case of missing super getter.
+ return new StaticAccess.unresolved(getter);
+ } else if (element.isField) {
+ if (getter != null && getter != element) {
+ CompoundAccessKind accessKind;
+ if (getter.isField) {
+ accessKind = CompoundAccessKind.SUPER_FIELD_FIELD;
+ } else if (getter.isGetter) {
+ accessKind = CompoundAccessKind.SUPER_GETTER_FIELD;
+ } else {
+ return internalError(node,
+ "Unsupported super call: $node : $element/$getter.");
+ }
+ return new CompoundAccessSemantics(accessKind, getter, element);
+ }
+ return new StaticAccess.superField(element);
+ } else if (element.isGetter) {
+ return new StaticAccess.superGetter(element);
+ } else if (element.isSetter) {
+ if (getter != null) {
+ CompoundAccessKind accessKind;
+ if (getter.isField) {
+ accessKind = CompoundAccessKind.SUPER_FIELD_SETTER;
+ } else if (getter.isGetter) {
+ accessKind = CompoundAccessKind.SUPER_GETTER_SETTER;
+ } else {
+ accessKind = CompoundAccessKind.SUPER_METHOD_SETTER;
+ }
+ return new CompoundAccessSemantics(accessKind, getter, element);
+ }
+ return new StaticAccess.superSetter(element);
+ } else if (isCompound) {
+ return new CompoundAccessSemantics(
+ CompoundAccessKind.SUPER_GETTER_SETTER, getter, element);
+ } else {
+ return new StaticAccess.superMethod(element);
+ }
+ } else if (node.isOperator) {
+ return new DynamicAccess.dynamicProperty(node.receiver);
+ } else if (Elements.isClosureSend(node, element)) {
+ if (element == null) {
+ if (node.selector.isThis()) {
+ return new AccessSemantics.thisAccess();
+ } else {
+ return new AccessSemantics.expression();
+ }
+ } else if (Elements.isErroneous(element)) {
+ return new StaticAccess.unresolved(element);
+ } else {
+ return handleStaticallyResolvedAccess(node, element, getter);
+ }
+ } else {
+ if (Elements.isErroneous(element)) {
+ return new StaticAccess.unresolved(element);
+ } else if (element == null || element.isInstanceMember) {
+ if (node.receiver == null || node.receiver.isThis()) {
+ return new AccessSemantics.thisProperty();
+ } else {
+ return new DynamicAccess.dynamicProperty(node.receiver);
+ }
+ } else if (element.impliesType) {
+ // TODO(johnniwinther): Provide an [ErroneousElement].
+ // This happens for code like `C.this`.
+ return new StaticAccess.unresolved(null);
+ } else {
+ return handleStaticallyResolvedAccess(node, element, getter);
+ }
+ }
+ }
+}
+

Powered by Google App Engine
This is Rietveld 408576698