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); |
} |