Chromium Code Reviews| 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); |
| } |