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

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

Issue 10628007: Resolve typedefs. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 6 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 3ab84c7dc809e0ce33018a5d292fe93d2917124b..ad889df3d89092460348897f4d5bac1731475508 100644
--- a/lib/compiler/implementation/resolver.dart
+++ b/lib/compiler/implementation/resolver.dart
@@ -212,8 +212,22 @@ class ResolverTask extends CompilerTask {
Type resolveTypeAnnotation(Element element, TypeAnnotation annotation) {
if (annotation === null) return compiler.types.dynamicType;
- ResolverVisitor visitor = new ResolverVisitor(compiler, element);
- Type result = visitor.resolveTypeAnnotation(annotation);
+ Scope context = new TopScope(element.getLibrary());
ahe 2012/06/22 08:59:11 Why are you calling a "scope" a "context"?
+ Type result;
+ Element contextElement = element.getEnclosingClassOrTypedef();
+ if (contextElement !== null &&
+ (contextElement.isTypedef() || contextElement.isClass())) {
+ var typeDefinition = contextElement;
+ context = new TypeVariablesScope(context, contextElement,
ahe 2012/06/22 08:59:11 Why is this not set up when resolving the type ali
+ typeDefinition.typeParameters);
+ TypeResolver typeResolver = new TypeResolver(compiler);
+ result = typeResolver.resolveTypeAnnotation(annotation,
+ inContext: context,
+ onFailure: warning);
+ } else {
+ ResolverVisitor visitor = new ResolverVisitor(compiler, element);
+ result = visitor.resolveTypeAnnotation(annotation);
+ }
if (result === null) {
// TODO(karklose): warning.
return compiler.types.dynamicType;
@@ -245,8 +259,9 @@ class ResolverTask extends CompilerTask {
return compiler.withCurrentElement(element, () {
Typedef node =
compiler.parser.measure(() => element.parseNode(compiler));
- return measure(() => SignatureResolver.analyze(
- compiler, node.formals, node.returnType, element));
+ TypedefResolverVisitor visitor =
+ new TypedefResolverVisitor(compiler, element.getLibrary(), element);
+ return measure(() => visitor.visit(node));
});
}
@@ -268,6 +283,11 @@ class ResolverTask extends CompilerTask {
ResolutionError message = new ResolutionError(kind, arguments);
compiler.reportError(node, message);
}
+
+ warning(Node node, MessageKind kind, [arguments = const []]) {
+ ResolutionWarning message = new ResolutionWarning(kind, arguments);
+ compiler.reportWarning(node, message);
+ }
}
class InitializerResolver {
@@ -1537,44 +1557,106 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
}
}
-class ClassResolverVisitor extends CommonResolverVisitor<Type> {
+class TypeDefinitionVisitor extends CommonResolverVisitor<Type> {
Scope context;
- ClassElement classElement;
+ LibraryElement library;
+ Element enclosing;
+ Function report;
+
+ visitTypeRequired(Node node) {
+ Function oldReport = report;
+ report = error;
+ Type result = super.visit(node);
+ report = oldReport;
+ return result;
+ }
- ClassResolverVisitor(Compiler compiler, LibraryElement library,
- ClassElement this.classElement)
- : context = new TopScope(library),
- super(compiler);
+ TypeDefinitionVisitor(Compiler compiler, LibraryElement library,
+ Element this.enclosing)
+ : this.library = library,
+ context = new TopScope(library),
+ super(compiler) {
+ report = warning;
+ }
- Type visitClassNode(ClassNode node) {
- compiler.ensure(classElement !== null);
- compiler.ensure(!classElement.isResolved);
- final Link<Node> parameters =
- node.typeParameters !== null ? node.typeParameters.nodes
- : const EmptyLink<TypeVariable>();
+ abstract Map<SourceString, Element> get typeParameters();
+
+ Type visitTypeAnnotation(TypeAnnotation node) {
+ return visit(node.typeName);
+ }
+
+ Type visitIdentifier(Identifier node) {
+ // TODO(karlklose): use a TypeResolver here.
+ if (node.source.stringValue === 'void') return compiler.types.voidType;
+ Element element = context.lookup(node.source);
+ if (element === null) {
+ report(node, MessageKind.CANNOT_RESOLVE_TYPE, [node]);
+ return null;
+ } else if (!element.impliesType() && !element.isTypeVariable()) {
+ report(node, MessageKind.NOT_A_TYPE, [node]);
+ return null;
+ } else {
+ if (element.isClass()) {
+ compiler.resolver.toResolve.add(element);
+ }
+ if (element.isTypeVariable()) {
+ TypeVariableElement variableElement = element;
+ return variableElement.type;
+ } else {
+ return element.computeType(compiler);
+ }
+ }
+ return null;
+ }
+
+ Type visitSend(Send node) {
+ Identifier prefix = node.receiver.asIdentifier();
+ if (prefix === null) {
+ report(node.receiver, MessageKind.NOT_A_PREFIX, [node.receiver]);
+ return null;
+ }
+ Element element = context.lookup(prefix.source);
+ if (element === null || element.kind !== ElementKind.PREFIX) {
+ report(node.receiver, MessageKind.NOT_A_PREFIX, [node.receiver]);
+ return null;
+ }
+ PrefixElement prefixElement = element;
+ Identifier selector = node.selector.asIdentifier();
+ var e = prefixElement.lookupLocalMember(selector.source);
+ if (e === null || !e.impliesType()) {
+ report(node.selector, MessageKind.CANNOT_RESOLVE_TYPE, [node.selector]);
+ return null;
+ }
+ return e.computeType(compiler);
+ }
+
+ createTypeVariables(NodeList node) {
+ if (node === null) return;
// Create types and elements for type variable.
- for (Link<Node> link = parameters; !link.isEmpty(); link = link.tail) {
+ for (Link<Node> link = node.nodes; !link.isEmpty(); link = link.tail) {
TypeVariable typeNode = link.head;
SourceString variableName = typeNode.name.source;
TypeVariableType variableType = new TypeVariableType(variableName);
TypeVariableElement variableElement =
- new TypeVariableElement(variableName, classElement, node,
+ new TypeVariableElement(variableName, enclosing, typeNode,
variableType);
variableType.element = variableElement;
- classElement.typeParameters[variableName] = variableElement;
- context = new TypeVariablesScope(context, classElement);
+ typeParameters[variableName] = variableElement;
}
+ }
+
+ visitNodeList(NodeList node) {
+ if (node === null) return;
// Resolve the bounds of type variables.
- for (Link<Node> link = parameters; !link.isEmpty(); link = link.tail) {
+ for (Link<Node> link = node.nodes; !link.isEmpty(); link = link.tail) {
TypeVariable typeNode = link.head;
SourceString variableName = typeNode.name.source;
- TypeVariableElement variableElement =
- classElement.typeParameters[variableName];
+ TypeVariableElement variableElement = typeParameters[variableName];
if (typeNode.bound !== null) {
Type boundType = visit(typeNode.bound);
if (boundType !== null && boundType.element == variableElement) {
- warning(node, MessageKind.CYCLIC_TYPE_VARIABLE,
- [variableElement.name]);
+ report(node, MessageKind.CYCLIC_TYPE_VARIABLE,
+ [variableElement.name]);
} else if (boundType !== null) {
variableElement.bound = boundType;
} else {
@@ -1582,8 +1664,80 @@ class ClassResolverVisitor extends CommonResolverVisitor<Type> {
}
}
}
+ }
+}
+
+class TypedefResolverVisitor extends TypeDefinitionVisitor {
+ TypedefElement get typedefElement() => enclosing;
+ get typeParameters() => typedefElement.typeParameters;
+
+ TypedefResolverVisitor(Compiler compiler, LibraryElement library,
+ TypedefElement typedefElement)
+ : super(compiler, library, typedefElement);
+
+ visitVariableDefinitions(VariableDefinitions variables) {
+ return visit(variables.type);
+ }
+
+ visitTypedef(Typedef node) {
+ createTypeVariables(node.typeParameters);
+ FunctionType type = new FunctionType(compiler.types.dynamicType,
+ null, typedefElement);
+ typedefElement.cachedType = type;
+ context = new TypeVariablesScope(context, enclosing, typeParameters);
+ Type returnType = visit(node.returnType);
+ if (returnType === null) {
+ returnType = compiler.types.dynamicType;
+ } else if (returnType.element === typedefElement) {
+ warning(node.returnType, MessageKind.CYCLIC_TYPEDEF);
+ returnType = compiler.types.dynamicType;
+ }
+ LinkBuilder<Type> formalsTypes = new LinkBuilder<Type>();
+ TypeResolver typeResolver = new TypeResolver(compiler);
+ for (Link<Node> formals = node.formals.nodes;
+ !formals.isEmpty();
+ formals = formals.tail) {
+ if (formals.head.asNodeList() !== null) {
+ // If there is a NodeList in the formal parameter list, it is the list
+ // of optional parameters.
+ // TODO(karlklose): support optional parameters.
+ break;
+ }
+ Type formalType = visit(formals.head);
+ if (formalType === null) {
+ formalType = compiler.types.dynamicType;
+ } else {
+ if (formalType.element === typedefElement) {
+ warning(formals.head, MessageKind.CYCLIC_TYPEDEF);
+ formalType = compiler.types.dynamicType;
+ }
+ }
+ formalsTypes.addLast(formalType);
+ }
+ type.parameterTypes = formalsTypes.toLink();
+ // Resolve type parameter bounds.
+ visit(node.typeParameters);
+ }
+}
+
+class ClassResolverVisitor extends TypeDefinitionVisitor {
+ ClassElement get classElement() => enclosing;
+
+ get typeParameters() => classElement.typeParameters;
+
+ ClassResolverVisitor(Compiler compiler, LibraryElement library,
+ ClassElement classElement)
+ : super(compiler, library, classElement);
+
+ Type visitClassNode(ClassNode node) {
+ compiler.ensure(classElement !== null);
+ compiler.ensure(!classElement.isResolved);
+ createTypeVariables(node.typeParameters);
+ // Resolve type paramters.
+ context = new TypeVariablesScope(context, enclosing, typeParameters);
+ visit(node.typeParameters);
// Find super type.
- Type supertype = visit(node.superclass);
+ Type supertype = visitTypeRequired(node.superclass);
if (supertype !== null && supertype.element.isExtendable()) {
classElement.supertype = supertype;
if (isBlackListed(supertype)) {
@@ -1603,12 +1757,12 @@ class ClassResolverVisitor extends CommonResolverVisitor<Type> {
classElement.supertype = new InterfaceType(objectElement);
}
if (node.defaultClause !== null) {
- classElement.defaultClass = visit(node.defaultClause);
+ classElement.defaultClass = visitTypeRequired(node.defaultClause);
}
for (Link<Node> link = node.interfaces.nodes;
!link.isEmpty();
link = link.tail) {
- Type interfaceType = visit(link.head);
+ Type interfaceType = visitTypeRequired(link.head);
if (interfaceType !== null && interfaceType.element.isExtendable()) {
classElement.interfaces =
classElement.interfaces.prepend(interfaceType);
@@ -1624,56 +1778,6 @@ class ClassResolverVisitor extends CommonResolverVisitor<Type> {
return classElement.computeType(compiler);
}
- Type visitTypeAnnotation(TypeAnnotation node) {
- return visit(node.typeName);
- }
-
- Type visitIdentifier(Identifier node) {
- Element element = context.lookup(node.source);
- if (element === null) {
- error(node, MessageKind.CANNOT_RESOLVE_TYPE, [node]);
- return null;
- } else if (!element.impliesType() && !element.isTypeVariable()) {
- error(node, MessageKind.NOT_A_TYPE, [node]);
- return null;
- } else {
- if (element.isClass()) {
- compiler.resolver.toResolve.add(element);
- }
- if (element.isTypeVariable()) {
- TypeVariableElement variableElement = element;
- return variableElement.type;
- } else if (element.isTypedef()) {
- compiler.unimplemented('visitIdentifier for typedefs', node: node);
- } else {
- // TODO(ngeoffray): Use type variables.
- return element.computeType(compiler);
- }
- }
- return null;
- }
-
- Type visitSend(Send node) {
- Identifier prefix = node.receiver.asIdentifier();
- if (prefix === null) {
- error(node.receiver, MessageKind.NOT_A_PREFIX, [node.receiver]);
- return null;
- }
- Element element = context.lookup(prefix.source);
- if (element === null || element.kind !== ElementKind.PREFIX) {
- error(node.receiver, MessageKind.NOT_A_PREFIX, [node.receiver]);
- return null;
- }
- PrefixElement prefixElement = element;
- Identifier selector = node.selector.asIdentifier();
- var e = prefixElement.lookupLocalMember(selector.source);
- if (e === null || !e.impliesType()) {
- error(node.selector, MessageKind.CANNOT_RESOLVE_TYPE, [node.selector]);
- return null;
- }
- return e.computeType(compiler);
- }
-
Link<Type> getOrCalculateAllSupertypes(ClassElement cls,
[Set<ClassElement> seen]) {
Link<Type> allSupertypes = cls.allSupertypes;
@@ -2031,13 +2135,16 @@ class Scope {
}
class TypeVariablesScope extends Scope {
- TypeVariablesScope(parent, ClassElement element) : super(parent, element);
+ final Map<SourceString, TypeVariableElement> variables;
+
+ TypeVariablesScope(parent, element, this.variables) : super(parent, element);
+
Element add(Element newElement) {
throw "Cannot add element to TypeVariableScope";
}
+
Element lookup(SourceString name) {
- ClassElement cls = element;
- Element result = cls.lookupTypeParameter(name);
+ Element result = variables[name];
if (result !== null) return result;
if (parent !== null) return parent.lookup(name);
}

Powered by Google App Engine
This is Rietveld 408576698