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/resolver.dart

Issue 10834061: Resolve typedefs. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 5 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 e6f318669266e92f4079050283c060538e33ecf9..24aeb049ff63c347fc423daa0e63dfa823e83fb9 100644
--- a/lib/compiler/implementation/resolver.dart
+++ b/lib/compiler/implementation/resolver.dart
@@ -216,8 +216,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/07/30 10:30:05 It seems ad hoc how we build the scope here. I wou
Johnni Winther 2012/08/01 10:12:28 Done.
+ Type result;
+ Element contextElement = element.getEnclosingClassOrTypedef();
+ if (contextElement !== null &&
+ (contextElement.isTypedef() || contextElement.isClass())) {
+ var typeDefinition = contextElement;
+ context = new TypeVariablesScope(context, contextElement,
+ 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;
@@ -348,8 +362,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);
ahe 2012/07/30 10:30:05 Construction of the visitor should also be measure
Johnni Winther 2012/08/01 10:12:29 Done.
+ return measure(() => visitor.visit(node));
});
}
@@ -371,6 +386,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 {
@@ -1635,86 +1655,30 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
}
}
-class ClassResolverVisitor extends CommonResolverVisitor<Type> {
+class TypeDefinitionVisitor extends CommonResolverVisitor<Type> {
Scope context;
- ClassElement classElement;
-
- ClassResolverVisitor(Compiler compiler, LibraryElement library,
- ClassElement this.classElement)
- : context = new TopScope(library),
- super(compiler);
-
- Type visitClassNode(ClassNode node) {
- compiler.ensure(classElement !== null);
- compiler.ensure(!classElement.isResolved);
-
- classElement.ensureParametersAndType(compiler);
- context = new TypeVariablesScope(context, classElement);
-
- // Resolve the bounds of type variables.
- Link<Node> parameters =
- node.typeParameters !== null ? node.typeParameters.nodes
- : const EmptyLink<TypeVariable>();
- for (Link<Node> link = parameters; !link.isEmpty(); link = link.tail) {
- TypeVariable typeNode = link.head;
- SourceString variableName = typeNode.name.source;
- TypeVariableElement variableElement =
- classElement.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]);
- } else if (boundType !== null) {
- variableElement.bound = boundType;
- } else {
- variableElement.bound = compiler.objectClass.computeType(compiler);
- }
- }
- }
+ LibraryElement library;
+ Element enclosing;
+ Function report;
+
+ visitTypeRequired(Node node) {
+ Function oldReport = report;
+ report = error;
+ Type result = super.visit(node);
+ report = oldReport;
+ return result;
+ }
- // Find super type.
- Type supertype = visit(node.superclass);
- if (supertype !== null && supertype.element.isExtendable()) {
- classElement.supertype = supertype;
- if (isBlackListed(supertype)) {
- error(node.superclass, MessageKind.CANNOT_EXTEND, [supertype]);
- }
- } else if (supertype !== null) {
- error(node.superclass, MessageKind.TYPE_NAME_EXPECTED);
- }
- final objectElement = compiler.objectClass;
- if (classElement !== objectElement && classElement.supertype === null) {
- if (objectElement === null) {
- compiler.internalError("Internal error: cannot resolve Object",
- node: node);
- } else if (!objectElement.isResolved) {
- compiler.resolver.toResolve.add(objectElement);
- }
- classElement.supertype = new InterfaceType(objectElement);
- }
- if (node.defaultClause !== null) {
- classElement.defaultClass = visit(node.defaultClause);
- }
- for (Link<Node> link = node.interfaces.nodes;
- !link.isEmpty();
- link = link.tail) {
- Type interfaceType = visit(link.head);
- if (interfaceType !== null && interfaceType.element.isExtendable()) {
- classElement.interfaces =
- classElement.interfaces.prepend(interfaceType);
- if (isBlackListed(interfaceType)) {
- error(link.head, MessageKind.CANNOT_IMPLEMENT, [interfaceType]);
- }
- } else {
- error(link.head, MessageKind.TYPE_NAME_EXPECTED);
- }
- }
- calculateAllSupertypes(classElement, new Set<ClassElement>());
- addDefaultConstructorIfNeeded(classElement);
- return classElement.computeType(compiler);
+ TypeDefinitionVisitor(Compiler compiler, LibraryElement library,
+ Element this.enclosing)
+ : this.library = library,
+ context = new TopScope(library),
+ super(compiler) {
+ report = warning;
ahe 2012/07/30 10:30:05 This creates a new function closure object on each
Johnni Winther 2012/08/01 10:12:29 TODO
}
+ abstract Map<SourceString, Element> get typeParameters();
ahe 2012/07/30 10:30:05 What is this for?
Johnni Winther 2012/08/01 10:12:29 Removed.
+
Type visitTypeAnnotation(TypeAnnotation node) {
Type type = visit(node.typeName);
if (type is! InterfaceType) {
@@ -1750,6 +1714,8 @@ class ClassResolverVisitor extends CommonResolverVisitor<Type> {
}
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) {
error(node, MessageKind.CANNOT_RESOLVE_TYPE, [node]);
@@ -1764,8 +1730,6 @@ class ClassResolverVisitor extends CommonResolverVisitor<Type> {
if (element.isTypeVariable()) {
TypeVariableElement variableElement = element;
return variableElement.type;
- } else if (element.isTypedef()) {
- compiler.unimplemented('visitIdentifier for typedefs', node: node);
} else {
// Type variables are handled in [visitTypeAnnotation].
return element.computeType(compiler);
@@ -1777,24 +1741,177 @@ class ClassResolverVisitor extends CommonResolverVisitor<Type> {
Type visitSend(Send node) {
Identifier prefix = node.receiver.asIdentifier();
if (prefix === null) {
- error(node.receiver, MessageKind.NOT_A_PREFIX, [node.receiver]);
+ report(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]);
+ 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()) {
- error(node.selector, MessageKind.CANNOT_RESOLVE_TYPE, [node.selector]);
+ 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 = 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, enclosing, typeNode,
+ variableType);
+ variableType.element = variableElement;
+ typeParameters[variableName] = variableElement;
+ }
+ }
+
+ visitNodeList(NodeList node) {
+ if (node === null) return;
+ // Resolve the bounds of type variables.
+ for (Link<Node> link = node.nodes; !link.isEmpty(); link = link.tail) {
+ TypeVariable typeNode = link.head;
+ SourceString variableName = typeNode.name.source;
+ TypeVariableElement variableElement = typeParameters[variableName];
+ if (typeNode.bound !== null) {
+ Type boundType = visit(typeNode.bound);
+ if (boundType !== null && boundType.element == variableElement) {
+ report(node, MessageKind.CYCLIC_TYPE_VARIABLE,
+ [variableElement.name]);
+ } else if (boundType !== null) {
+ variableElement.bound = boundType;
+ } else {
+ variableElement.bound = compiler.objectClass.computeType(compiler);
+ }
+ }
+ }
+ }
+}
+
+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);
+
+ // TODO(johnniwinther): Unify [ClassElement.ensureParametersAndType] and
+ // [TypeDefinitionVisitor.createTypeVariables]
+ classElement.ensureParametersAndType(compiler);
+
+ // Resolve type paramters.
+ context = new TypeVariablesScope(context, enclosing, typeParameters);
+ visit(node.typeParameters);
+
+ // Find super type.
+ Type supertype = visitTypeRequired(node.superclass);
+ if (supertype !== null && supertype.element.isExtendable()) {
+ classElement.supertype = supertype;
+ if (isBlackListed(supertype)) {
+ error(node.superclass, MessageKind.CANNOT_EXTEND, [supertype]);
+ }
+ } else if (supertype !== null) {
+ error(node.superclass, MessageKind.TYPE_NAME_EXPECTED);
+ }
+ final objectElement = compiler.objectClass;
+ if (classElement !== objectElement && classElement.supertype === null) {
+ if (objectElement === null) {
+ compiler.internalError("Internal error: cannot resolve Object",
+ node: node);
+ } else if (!objectElement.isResolved) {
+ compiler.resolver.toResolve.add(objectElement);
+ }
+ classElement.supertype = new InterfaceType(objectElement);
+ }
+ if (node.defaultClause !== null) {
+ classElement.defaultClass = visitTypeRequired(node.defaultClause);
+ }
+ for (Link<Node> link = node.interfaces.nodes;
+ !link.isEmpty();
+ link = link.tail) {
+ Type interfaceType = visitTypeRequired(link.head);
+ if (interfaceType !== null && interfaceType.element.isExtendable()) {
+ classElement.interfaces =
+ classElement.interfaces.prepend(interfaceType);
+ if (isBlackListed(interfaceType)) {
+ error(link.head, MessageKind.CANNOT_IMPLEMENT, [interfaceType]);
+ }
+ } else {
+ error(link.head, MessageKind.TYPE_NAME_EXPECTED);
+ }
+ }
+ calculateAllSupertypes(classElement, new Set<ClassElement>());
+ addDefaultConstructorIfNeeded(classElement);
+ return classElement.computeType(compiler);
+ }
+
Link<InterfaceType> getOrCalculateAllSupertypes(ClassElement cls,
[Set<ClassElement> seen]) {
Link<InterfaceType> allSupertypes = cls.allSupertypes;
@@ -2175,13 +2292,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