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

Unified Diff: lib/compiler/implementation/resolver.dart

Issue 9431029: Implement interface types. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Add test. Created 8 years, 9 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/resolver.dart
diff --git a/lib/compiler/implementation/resolver.dart b/lib/compiler/implementation/resolver.dart
index 38909e31f51a14e1d32e72ff97a4216f3cc95f6b..f918f17a61e73ad6c3b72f71a2f6343239e5cd77 100644
--- a/lib/compiler/implementation/resolver.dart
+++ b/lib/compiler/implementation/resolver.dart
@@ -5,19 +5,29 @@
interface TreeElements {
Element operator[](Node node);
Selector getSelector(Send send);
+ Type getType(TypeAnnotation annotation);
}
class TreeElementMapping implements TreeElements {
Map<Node, Element> map;
Map<Send, Selector> selectors;
+ Map<TypeAnnotation, Type> types;
+
TreeElementMapping()
: map = new LinkedHashMap<Node, Element>(),
- selectors = new LinkedHashMap<Send, Selector>();
+ selectors = new LinkedHashMap<Send, Selector>(),
+ types = new LinkedHashMap<TypeAnnotation, Type>();
operator []=(Node node, Element element) => map[node] = element;
operator [](Node node) => map[node];
void remove(Node node) { map.remove(node); }
+ void setType(TypeAnnotation annotation, Type type) {
+ types[annotation] = type;
+ }
+
+ Type getType(TypeAnnotation annotation) => types[annotation];
+
void setSelector(Send send, Selector selector) {
selectors[send] = selector;
}
@@ -590,43 +600,10 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
}
}
- visitTypeAnnotation(TypeAnnotation node) {
- Send send = node.typeName.asSend();
- Element element;
- if (send !== null) {
- if (typeRequired) {
- element = resolveSend(send);
- } else {
- // Not calling resolveSend as it will emit an error instead of
- // a warning if the type is bogus.
- // TODO(ahe): Change resolveSend so it can emit a warning when needed.
- return null;
- }
- } else {
- element = context.lookup(node.typeName.asIdentifier().source);
- }
- if (element === null) {
- if (typeRequired) {
- error(node, MessageKind.CANNOT_RESOLVE_TYPE, [node.typeName]);
- } else {
- warning(node, MessageKind.CANNOT_RESOLVE_TYPE, [node.typeName]);
- }
- } else if (!element.impliesType()) {
- if (typeRequired) {
- error(node, MessageKind.NOT_A_TYPE, [node.typeName]);
- } else {
- warning(node, MessageKind.NOT_A_TYPE, [node.typeName]);
- }
- } else {
- if (element.isClass()) {
- // TODO(ngeoffray): Should we also resolve typedef?
- ClassElement cls = element;
- compiler.resolver.toResolve.add(element);
- }
- // TODO(ahe): This should be a Type.
- useElement(node, element);
- }
- return element;
+ ClassElement visitTypeAnnotation(TypeAnnotation node) {
+ Type type = resolveTypeAnnotation(node);
+ if (type !== null) return type.element;
+ return null;
}
Element defineElement(Node node, Element element,
@@ -647,6 +624,14 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
return mapping[node] = element;
}
+ Type useType(TypeAnnotation annotation, Type type) {
+ if (type !== null) {
+ mapping.setType(annotation, type);
+ useElement(annotation, type.element);
ahe 2012/04/12 15:05:23 Long term, could we avoid setting the element?
+ }
+ return type;
+ }
+
void setupFunction(FunctionExpression node, FunctionElement function) {
context = new MethodScope(context, function);
// Put the parameters in scope.
@@ -818,12 +803,14 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
return target;
}
- resolveTypeTest(Node argument) {
+ Type resolveTypeTest(Node argument) {
TypeAnnotation node = argument.asTypeAnnotation();
if (node == null) {
ahe 2012/04/12 15:05:23 ===
- node = argument.asSend().receiver;
+ // node is of the form !Type.
+ node = argument.asSend().receiver.asTypeAnnotation();
+ if (node === null) compiler.cancel("malformed send");
}
- resolveTypeRequired(node);
+ return resolveTypeRequired(node);
}
void handleArguments(Send node) {
@@ -986,27 +973,115 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
return null;
}
+ TypeAnnotation getTypeAnnotationFromSend(Send send) {
+ if (send.selector.asTypeAnnotation() !== null) {
+ return send.selector;
+ } else if (send.selector.asSend() !== null) {
+ Send selector = send.selector;
+ if (selector.receiver.asTypeAnnotation() !== null) {
+ return selector.receiver;
+ }
+ } else {
+ compiler.internalError("malformed send in new expression");
+ }
+ }
+
FunctionElement resolveConstructor(NewExpression node) {
FunctionElement constructor =
node.accept(new ConstructorResolver(compiler, this));
+ TypeAnnotation annotation = getTypeAnnotationFromSend(node.send);
+ Type type = resolveTypeRequired(annotation);
if (constructor === null) {
- Element resolved = resolveTypeRequired(node.send.selector);
+ Element resolved = (type != null) ? type.element : null;
if (resolved !== null && resolved.kind === ElementKind.TYPE_VARIABLE) {
- error(node, WarningKind.TYPE_VARIABLE_AS_CONSTRUCTOR);
+ error(node, MessageKind.TYPE_VARIABLE_AS_CONSTRUCTOR);
return null;
} else {
error(node.send, MessageKind.CANNOT_FIND_CONSTRUCTOR, [node.send]);
+ return null;
}
}
return constructor;
}
- Element resolveTypeRequired(Node node) {
+ Type resolveTypeRequired(TypeAnnotation node) {
bool old = typeRequired;
typeRequired = true;
- Element element = visit(node);
+ Type result = resolveTypeAnnotation(node);
typeRequired = old;
- return element;
+ return result;
+ }
+
+ Element resolveTypeName(node) {
+ Identifier typeName = node.typeName.asIdentifier();
+ Send send = node.typeName.asSend();
+ if (send !== null) {
+ typeName = send.selector;
+ }
+ if (typeName.source == Types.VOID) return compiler.types.voidType.element;
+ if (typeName.source == Types.DYNAMIC ||
+ typeName.source.stringValue == "var") {
ahe 2012/04/12 15:05:23 Is it necessary to test for "var"? Also, it should
+ return compiler.types.dynamicType.element;
+ }
+ if (send !== null) {
+ Element e = context.lookup(send.receiver.asIdentifier().source);
+ if (e !== null && e.kind === ElementKind.PREFIX) {
+ // The receiver is a prefix. Lookup in the imported members.
+ PrefixElement prefix = e;
+ return prefix.lookupLocalMember(typeName.source);
+ } else if (e !== null && e.kind === ElementKind.CLASS) {
+ // The receiver is the class part of a named constructor.
+ return e;
+ } else {
+ error(send.receiver, MessageKind.CANNOT_RESOLVE);
ahe 2012/04/12 15:05:23 Shouldn't this be a warning if typeRequired is fal
+ }
+ } else {
+ return context.lookup(typeName.source);
+ }
+ }
+
+ Type resolveTypeAnnotation(TypeAnnotation node) {
+ Element element = resolveTypeName(node);
+ Type type;
+ if (element === null) {
+ if (typeRequired) {
+ error(node, MessageKind.CANNOT_RESOLVE_TYPE, [node.typeName]);
+ } else {
+ warning(node, MessageKind.CANNOT_RESOLVE_TYPE, [node.typeName]);
+ }
+ } else if (!element.impliesType()) {
+ if (typeRequired) {
+ error(node, MessageKind.NOT_A_TYPE, [node.typeName]);
+ } else {
+ warning(node, MessageKind.NOT_A_TYPE, [node.typeName]);
+ }
+ } else {
+ if (element == compiler.types.voidType.element) {
ahe 2012/04/12 15:05:23 ===
+ type = compiler.types.voidType;
ahe 2012/04/12 15:05:23 Why not just: type = element.type;
+ } else if (element == compiler.types.dynamicType.element) {
ahe 2012/04/12 15:05:23 ===
+ type = compiler.types.dynamicType;
+ } else if (element.isClass()) {
+ // TODO(ngeoffray): Should we also resolve typedef?
ahe 2012/04/12 15:05:23 I think this TODO is obsolete.
+ ClassElement cls = element;
+ compiler.resolver.toResolve.add(cls);
+ LinkBuilder<Type> arguments = new LinkBuilder<Type>();
+ if (node.typeArguments !== null) {
+ for (Link<Node> typeArguments = node.typeArguments.nodes;
+ !typeArguments.isEmpty();
+ typeArguments = typeArguments.tail) {
+ arguments.addLast(resolveTypeAnnotation(typeArguments.head));
+ }
+ }
ahe 2012/04/12 15:05:23 I don't think you're validating that the number of
+ type = new InterfaceType(element.name, element, arguments.toLink());
ahe 2012/04/12 15:05:23 This means you create a new object every time you
+ } else if (element.isTypedef()) {
+ // TODO(karlklose): implement typedefs. We return a fake type that the
+ // code generator can use to detect typedefs in is-checks.
+ type = new SimpleType(element.name, element);
ahe 2012/04/12 15:05:23 Why not: type = element.type;
+ } else {
+ type = element.computeType(compiler);
ahe 2012/04/12 15:05:23 I'm not sure about this.
+ }
+ }
+ return useType(node, type);
}
visitModifiers(Modifiers node) {
@@ -1632,7 +1707,17 @@ class SignatureResolver extends CommonResolverVisitor<Element> {
// TODO(ahe): This is temporary.
void resolveType(Node node) {
if (node == null) return;
- node.accept(new ResolverVisitor(compiler, enclosingElement));
+ // Find the correct member context to perform the lookup in.
ahe 2012/04/12 15:05:23 This method was a temporary wrapper around calling
+ Element outer = enclosingElement;
+ Element context = outer;
+ while (outer !== null) {
+ if (outer.isMember()) {
+ context = outer;
+ break;
+ }
+ outer = outer.enclosingElement;
+ }
+ node.accept(new ResolverVisitor(compiler, context));
}
// TODO(ahe): This is temporary.

Powered by Google App Engine
This is Rietveld 408576698