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

Unified Diff: lib/compiler/implementation/dart_backend/usager.dart

Issue 10836128: A visitor that builds a map from node to "Usage". (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 4 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: lib/compiler/implementation/dart_backend/usager.dart
diff --git a/lib/compiler/implementation/dart_backend/usager.dart b/lib/compiler/implementation/dart_backend/usager.dart
new file mode 100644
index 0000000000000000000000000000000000000000..bb2132480e0a881b0aff5c9086bf0dee18cf5229
--- /dev/null
+++ b/lib/compiler/implementation/dart_backend/usager.dart
@@ -0,0 +1,322 @@
+// 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.
+
+class SendVisitor extends ResolvedVisitor<String> {
+ final Usager usager;
+
+ SendVisitor(this.usager, TreeElements elements) : super(elements);
+
+ R visitSuperSend(Send node) => node.visitChildren(usager);
+ R visitOperatorSend(Send node) => node.visitChildren(usager);
+ R visitClosureSend(Send node) => node.visitChildren(usager);
+ R visitDynamicSend(Send node) => node.visitChildren(usager);
+ R visitForeignSend(Send node) => node.visitChildren(usager);
+
+ R visitGetterSend(Send node) {
+ final element = elements[node];
+ if (element !== null && element.isTopLevel()) {
Anton Muhin 2012/08/07 12:32:11 maybe use early return: if (element === null || el
Roman 2012/08/07 15:44:03 Done.
+ if (node.receiver !== null) {
+ // Library reference prefix. Omit it.
Anton Muhin 2012/08/07 12:32:11 please, add an assert, that receiver resolves to p
Roman 2012/08/07 15:44:03 Done.
+ usager.useNull(node.receiver);
+ }
+ usager.useElement(node.selector, element);
+ usager.visit(node.argumentsNode);
Anton Muhin 2012/08/07 12:32:11 I am not quite happy we duplicate visitChildren he
Roman 2012/08/07 15:44:03 Changed to visitChildren, it should not matter muc
+ } else {
+ node.visitChildren(usager);
+ }
+ }
+
+ R visitStaticSend(Send node) {
Anton Muhin 2012/08/07 12:32:11 isn't that too complicated? e.g. shouldn't we ren
Roman 2012/08/07 15:44:03 I will use magic from your CL to make it better.
+ final element = elements[node];
+ if (element.isTopLevel()) {
+ if (node.receiver !== null) {
+ // Library reference prefix. Omit it.
+ usager.useNull(node.receiver);
+ }
+ usager.useMethod(node.selector, element);
+ usager.visit(node.argumentsNode);
+ } else if (
+ (element.isGenerativeConstructor() || element.isFactoryConstructor())
+ // Don't want to rename redirects to :this(args) or super calls.
+ && !Initializers.isConstructorRedirect(node)
+ && !Initializers.isSuperConstructorCall(node)) {
+ final FunctionElement constructor = element.asFunctionElement();
+ final Send nameAsSend = constructor.cachedNode.name.asSend();
+ if (nameAsSend !== null) {
+ // Named constructor or factory call.
+ if (node.selector is TypeAnnotation) {
+ // Simple A.fromFoo();
+ assert(node.selector.typeName is Send);
+ assert(node.selector.typeName.receiver is Identifier);
+ assert(node.selector.typeName.selector is Identifier);
+ usager.useType(node.selector.typeName.receiver,
+ usager.resolveType(node.selector));
+ usager.useConstructorName(
+ node.selector.typeName.selector, constructor);
+ } else {
+ // lib.A.fromFoo() or A<T>.fromFoo()
+ // or lib.A.fromFoo() or lib.A<T>.fromFoo();
+ assert(node.selector is Send);
+ assert(node.selector.selector is Identifier);
+ assert(node.selector.receiver is TypeAnnotation);
+ usager.useType(node.selector.receiver.typeName,
+ usager.resolveType(node.selector.receiver));
+ usager.useConstructorName(node.selector.selector, constructor);
+ usager.visit(node.selector.receiver.typeArguments);
+ }
+ } else {
+ // Ordinary constructor call.
+ assert(node.selector is TypeAnnotation);
+ usager.useType(
+ node.selector.typeName, usager.resolveType(node.selector));
+ usager.visit(node.selector.typeArguments);
+ }
+ } else {
+ // Fallback to default processing.
+ node.visitChildren(usager);
+ }
+ }
+}
+
+class Usager implements Visitor {
+ final Compiler compiler;
+ final Map<Node, Usage> usages;
+ Element currentElement;
+ TreeElements treeElements;
+
+ Usager(this.compiler) : usages = new Map<Node, Usage>();
+
+ /**
+ * Checks if [:libraryElement:] is a core lib, that is a library
+ * provided by the implementation like dart:core, dart:coreimpl, etc.
+ */
+ bool isDartCoreLib(Compiler compiler, LibraryElement libraryElement) {
+ final libraries = compiler.libraries;
+ for (final uri in libraries.getKeys()) {
+ if (libraryElement === libraries[uri]) {
+ if (uri.startsWith('dart:')) return true;
+ }
+ }
+ return false;
+ }
+
+ void process(Element element, TreeElements elements) {
+ currentElement = element;
+ treeElements = elements;
+ Node elementNode = element.parseNode(compiler);
+ elementNode.accept(this);
+ }
+
+ Type resolveType(TypeAnnotation typeAnnotation) {
+ if (treeElements === null) return null;
+ var result = treeElements.getType(typeAnnotation);
+ if (result == null) {
Anton Muhin 2012/08/07 12:32:11 nit: === null
Roman 2012/08/07 15:44:03 Done.
+ result = compiler.resolveTypeAnnotation(currentElement, typeAnnotation);
+ }
+ return result;
+ }
+
+ void useType(Node node, Type type) {
+ assert(type !== null);
+ usages[node] = new TypeUsage(type);
+ }
+ void useConstructorName(Identifier node, FunctionElement constructor) {
+ assert(constructor !== null);
+ usages[node] = new ConstructorNameUsage(constructor);
+ }
+ void useMethod(Node node, Element method) {
+ assert(method !== null);
+ assert(method is FunctionElement || method is VariableElement);
+ usages[node] = new MethodUsage(method);
+ }
+ void useNull(Node node) {
+ usages[node] = new NullUsage();
+ }
+ void useElement(Node node, Element element) {
+ assert(element !== null);
+ usages[node] = new ElementUsage(element);
+ }
+
+ void internalError(String reason, [Node node]) {
+ compiler.cancel(reason: reason, node: node);
+ }
+
+ R visit(Node node) => (node == null) ? null : node.accept(this);
Anton Muhin 2012/08/07 12:32:11 nit: === null
Roman 2012/08/07 15:44:03 Done.
+
+ R visitBlock(Block node) {
Anton Muhin 2012/08/07 12:32:11 arrow syntax, your variant returns null.
Anton Muhin 2012/08/07 12:32:11 cannot you reuse AbstractVisitor?
+ node.visitChildren(this);
+ }
+ R visitBreakStatement(BreakStatement node) {
+ node.visitChildren(this);
+ }
+ R visitCascade(Cascade node) {
+ node.visitChildren(this);
+ }
+ R visitCascadeReceiver(CascadeReceiver node) {
+ node.visitChildren(this);
+ }
+ R visitCaseMatch(CaseMatch node) {
+ node.visitChildren(this);
+ }
+ R visitCatchBlock(CatchBlock node) {
+ node.visitChildren(this);
+ }
+ R visitClassNode(ClassNode node) {
+ internalError('Should never meet ClassNode', node);
+ }
+ R visitConditional(Conditional node) {
+ node.visitChildren(this);
+ }
+ R visitContinueStatement(ContinueStatement node) {
+ node.visitChildren(this);
+ }
+ R visitDoWhile(DoWhile node) {
+ node.visitChildren(this);
+ }
+ R visitEmptyStatement(EmptyStatement node) {
+ node.visitChildren(this);
+ }
+ R visitExpressionStatement(ExpressionStatement node) {
+ node.visitChildren(this);
+ }
+ R visitFor(For node) {
+ node.visitChildren(this);
+ }
+ R visitForIn(ForIn node) {
+ node.visitChildren(this);
+ }
+ R visitFunctionDeclaration(FunctionDeclaration node) {
+ node.visitChildren(this);
+ }
+ R visitFunctionExpression(FunctionExpression node) {
+ node.visitChildren(this);
+ }
+ R visitIdentifier(Identifier node) {
+ if (currentElement.isGenerativeConstructor()
+ || currentElement.isFactoryConstructor()) {
+ // Two complicated cases for class/interface renaming:
+ // 1) class which implements constructors of other interfaces, but not
+ // implements interfaces themselves:
+ // 0.dart: class C { I(); }
+ // 1.dart and 2.dart: interface I default C { I(); }
+ // now we have to duplicate our I() constructor in C class with
+ // proper names.
+ // 2) (even worse for us):
+ // 0.dart: class C { C(); }
+ // 1.dart: interface C default p0.C { C(); }
+ // the second case is just a bug now.
+ final ClassElement enclosingClass = currentElement.getEnclosingClass();
+ if (node.token.slowToString() == enclosingClass.name.slowToString()) {
+ // TODO: distinguish the case of constructor vs. nested named closure
+ // (see function_syntax_test).
+ // TODO: fix the bugs above and turn if into the assert.
+ useType(node, enclosingClass.type);
+ }
+ } else if (currentElement.isFunction()
+ && currentElement.cachedNode.name == node) {
+ useMethod(node, currentElement);
+ }
+ }
+ R visitIf(If node) {
+ node.visitChildren(this);
+ }
+ R visitLabel(Label node) {
+ node.visitChildren(this);
+ }
+ R visitLabeledStatement(LabeledStatement node) {
+ node.visitChildren(this);
+ }
+ R visitLiteralBool(LiteralBool node) {
+ node.visitChildren(this);
+ }
+ R visitLiteralDouble(LiteralDouble node) {
+ node.visitChildren(this);
+ }
+ R visitLiteralInt(LiteralInt node) {
+ node.visitChildren(this);
+ }
+ R visitLiteralList(LiteralList node) {
+ node.visitChildren(this);
+ }
+ R visitLiteralMap(LiteralMap node) {
+ node.visitChildren(this);
+ }
+ R visitLiteralMapEntry(LiteralMapEntry node) {
+ node.visitChildren(this);
+ }
+ R visitLiteralNull(LiteralNull node) {
+ node.visitChildren(this);
+ }
+ R visitLiteralString(LiteralString node) {
+ node.visitChildren(this);
+ }
+ R visitModifiers(Modifiers node) {
+ node.visitChildren(this);
+ }
+ R visitNamedArgument(NamedArgument node) {
+ node.visitChildren(this);
+ }
+ R visitNewExpression(NewExpression node) {
+ node.visitChildren(this);
+ }
+ R visitNodeList(NodeList node) {
+ node.visitChildren(this);
+ }
+ R visitOperator(Operator node) {
+ node.visitChildren(this);
+ }
+ R visitParenthesizedExpression(ParenthesizedExpression node) {
+ node.visitChildren(this);
+ }
+ R visitReturn(Return node) {
+ node.visitChildren(this);
+ }
+ R visitScriptTag(ScriptTag node) {
+ node.visitChildren(this);
+ }
+ R visitSend(Send send) => new SendVisitor(this, treeElements).visitSend(send);
+ R visitSendSet(SendSet node) {
+ node.visitChildren(this);
+ }
+ R visitStringInterpolation(StringInterpolation node) {
+ node.visitChildren(this);
+ }
+ R visitStringInterpolationPart(StringInterpolationPart node) {
+ node.visitChildren(this);
+ }
+ R visitStringJuxtaposition(StringJuxtaposition node) {
+ node.visitChildren(this);
+ }
+ R visitSwitchCase(SwitchCase node) {
+ node.visitChildren(this);
+ }
+ R visitSwitchStatement(SwitchStatement node) {
+ node.visitChildren(this);
+ }
+ R visitThrow(Throw node) {
+ node.visitChildren(this);
+ }
+ R visitTryStatement(TryStatement node) {
+ node.visitChildren(this);
+ }
+
+ R visitTypeAnnotation(TypeAnnotation node) {
+ Type type = resolveType(node);
+ useType(node.typeName, type);
+ visit(node.typeArguments);
+ }
+
+ R visitTypedef(Typedef node) {
+ node.visitChildren(this);
+ }
+ R visitTypeVariable(TypeVariable node) {
+ node.visitChildren(this);
+ }
+ R visitVariableDefinitions(VariableDefinitions node) {
+ node.visitChildren(this);
+ }
+ R visitWhile(While node) {
+ node.visitChildren(this);
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698