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

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

Issue 10825177: Unify ClassElement and TypedefElement. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 4 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
« no previous file with comments | « lib/compiler/implementation/elements/elements.dart ('k') | lib/compiler/implementation/ssa/codegen.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/compiler/implementation/resolver.dart
diff --git a/lib/compiler/implementation/resolver.dart b/lib/compiler/implementation/resolver.dart
index f7929f2178c1414385a24ae573fc4ea00766ce23..8f6842d9a23809f18a08023a9ddf36b7931f1ca4 100644
--- a/lib/compiler/implementation/resolver.dart
+++ b/lib/compiler/implementation/resolver.dart
@@ -733,6 +733,8 @@ class TypeResolver {
// TODO(johnniwinther): Change [onFailure] and [whenResolved] to use boolean
// flags instead of closures.
+ // TODO(johnniwinther): Should never return [null] but instead an erroneous
+ // type.
Type resolveTypeAnnotation(TypeAnnotation node,
[Scope inScope, ClassElement inClass,
onFailure(Node, MessageKind, [List arguments]),
@@ -768,31 +770,14 @@ class TypeResolver {
} else if (element.isClass()) {
ClassElement cls = element;
if (!cls.isResolved) compiler.resolveClass(cls);
- LinkBuilder<Type> arguments = new LinkBuilder<Type>();
- if (node.typeArguments !== null) {
- int index = 0;
- for (Link<Node> typeArguments = node.typeArguments.nodes;
- !typeArguments.isEmpty();
- typeArguments = typeArguments.tail) {
- if (++index > cls.typeParameters.length) {
- onFailure(typeArguments.head,
- MessageKind.ADDITIONAL_TYPE_ARGUMENT);
- }
- Type argType = resolveTypeAnnotationInContext(scope,
- typeArguments.head,
- onFailure,
- whenResolved);
- arguments.addLast(argType);
- }
- if (index < cls.typeParameters.length) {
- onFailure(node.typeArguments, MessageKind.MISSING_TYPE_ARGUMENT);
- }
- }
- if (cls.typeParameters.length == 0) {
- // Return the canonical type if it has no type parameters.
+ Link<Type> arguments =
+ resolveTypeArguments(node, cls.typeVariables, scope,
+ onFailure, whenResolved);
+ if (cls.typeVariables.isEmpty() && arguments.isEmpty()) {
+ // Use the canonical type if it has no type parameters.
type = cls.computeType(compiler);
} else {
- type = new InterfaceType(cls, arguments.toLink());
+ type = new InterfaceType(cls, arguments);
}
} else if (element.isTypedef()) {
type = element.computeType(compiler);
@@ -806,6 +791,34 @@ class TypeResolver {
whenResolved(node, type);
return type;
}
+
+ Link<Type> resolveTypeArguments(TypeAnnotation node,
+ Link<Type> typeVariables,
+ Scope scope, onFailure, whenResolved) {
+ if (node.typeArguments == null) {
+ return const EmptyLink<Type>();
+ }
+ var arguments = new LinkBuilder<Type>();
+ for (Link<Node> typeArguments = node.typeArguments.nodes;
+ !typeArguments.isEmpty();
+ typeArguments = typeArguments.tail) {
+ if (typeVariables.isEmpty()) {
+ onFailure(typeArguments.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT);
+ }
+ Type argType = resolveTypeAnnotationInContext(scope,
+ typeArguments.head,
+ onFailure,
+ whenResolved);
+ arguments.addLast(argType);
+ if (!typeVariables.isEmpty()) {
+ typeVariables = typeVariables.tail;
+ }
+ }
+ if (!typeVariables.isEmpty()) {
+ onFailure(node.typeArguments, MessageKind.MISSING_TYPE_ARGUMENT);
+ }
+ return arguments.toLink();
+ }
}
class ResolverVisitor extends CommonResolverVisitor<Element> {
@@ -1644,56 +1657,27 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
}
}
-class ClassResolverVisitor extends CommonResolverVisitor<Type> {
- Scope scope;
- ClassElement classElement;
+class ClassResolverVisitor extends TypeDefinitionVisitor {
+ ClassElement get element() => super.element;
- ClassResolverVisitor(Compiler compiler,
- ClassElement classElement)
- : this.classElement = classElement,
- scope = classElement.buildEnclosingScope(),
- super(compiler);
+ ClassResolverVisitor(Compiler compiler, ClassElement classElement)
+ : super(compiler, classElement);
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>();
- // Create types and elements for type variable.
- for (Link<Node> link = parameters; !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,
- variableType);
- variableType.element = variableElement;
- classElement.typeParameters[variableName] = variableElement;
- scope = new TypeDeclarationScope(scope, classElement);
- }
- // Resolve the bounds of type variables.
- 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);
- }
- }
- }
+ compiler.ensure(element !== null);
+ compiler.ensure(!element.isResolved);
+
+ InterfaceType type = element.computeType(compiler);
+ scope = new TypeDeclarationScope(scope, element);
+ // TODO(ahe): It is not safe to call resolveTypeVariableBounds yet.
+ // As a side-effect, this may get us back here trying to
+ // resolve this class again.
+ resolveTypeVariableBounds(node.typeParameters);
+
// Find super type.
Type supertype = visit(node.superclass);
if (supertype !== null && supertype.element.isExtendable()) {
- classElement.supertype = supertype;
+ element.supertype = supertype;
if (isBlackListed(supertype)) {
error(node.superclass, MessageKind.CANNOT_EXTEND, [supertype]);
}
@@ -1701,25 +1685,26 @@ class ClassResolverVisitor extends CommonResolverVisitor<Type> {
error(node.superclass, MessageKind.TYPE_NAME_EXPECTED);
}
final objectElement = compiler.objectClass;
- if (classElement !== objectElement && classElement.supertype === null) {
+ if (element !== objectElement && element.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);
+ // TODO(ahe): This should be objectElement.computeType(...).
+ element.supertype = new InterfaceType(objectElement);
}
if (node.defaultClause !== null) {
- classElement.defaultClass = visit(node.defaultClause);
+ element.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);
+ element.interfaces =
+ element.interfaces.prepend(interfaceType);
if (isBlackListed(interfaceType)) {
error(link.head, MessageKind.CANNOT_IMPLEMENT, [interfaceType]);
}
@@ -1727,9 +1712,9 @@ class ClassResolverVisitor extends CommonResolverVisitor<Type> {
error(link.head, MessageKind.TYPE_NAME_EXPECTED);
}
}
- calculateAllSupertypes(classElement, new Set<ClassElement>());
- addDefaultConstructorIfNeeded(classElement);
- return classElement.computeType(compiler);
+ calculateAllSupertypes(element, new Set<ClassElement>());
+ addDefaultConstructorIfNeeded(element);
+ return element.computeType(compiler);
}
Type visitTypeAnnotation(TypeAnnotation node) {
@@ -1853,7 +1838,7 @@ class ClassResolverVisitor extends CommonResolverVisitor<Type> {
}
isBlackListed(Type type) {
- LibraryElement lib = classElement.getLibrary();
+ LibraryElement lib = element.getLibrary();
return
lib !== compiler.coreLibrary &&
lib !== compiler.coreImplLibrary &&
@@ -1869,6 +1854,58 @@ class ClassResolverVisitor extends CommonResolverVisitor<Type> {
}
}
+class TypeDefinitionVisitor extends CommonResolverVisitor<Type> {
+ Scope scope;
+ TypeDeclarationElement element;
+ TypeResolver typeResolver;
+
+ TypeDefinitionVisitor(Compiler compiler, TypeDeclarationElement element)
+ : this.element = element,
+ scope = element.enclosingElement.buildScope(),
+ typeResolver = new TypeResolver(compiler),
+ super(compiler);
+
+ void resolveTypeVariableBounds(NodeList node) {
+ if (node === null) return;
+
+ var nameSet = new Set<SourceString>();
+ // Resolve the bounds of type variables.
+ Link<Type> typeLink = element.typeVariables;
+ Link<Node> nodeLink = node.nodes;
+ while (!nodeLink.isEmpty()) {
+ TypeVariableType typeVariable = typeLink.head;
+ SourceString typeName = typeVariable.name;
+ TypeVariable typeNode = nodeLink.head;
+ if (nameSet.contains(typeName)) {
+ error(typeNode, MessageKind.DUPLICATE_TYPE_VARIABLE_NAME, [typeName]);
+ }
+ nameSet.add(typeName);
+
+ TypeVariableElement variableElement = typeVariable.element;
+ if (typeNode.bound !== null) {
+ Type boundType = typeResolver.resolveTypeAnnotation(
+ typeNode.bound, inScope: scope, onFailure: warning);
+ if (boundType !== null && boundType.element == variableElement) {
+ // TODO(johnniwinther): Check for more general cycles, like
+ // [: <A extends B, B extends C, C extends B> :].
+ warning(node, MessageKind.CYCLIC_TYPE_VARIABLE,
+ [variableElement.name]);
+ } else if (boundType !== null) {
+ variableElement.bound = boundType;
+ } else {
+ // TODO(johnniwinther): Should be an erroneous type.
+ variableElement.bound = compiler.objectClass.computeType(compiler);
+ }
+ } else {
+ variableElement.bound = compiler.objectClass.computeType(compiler);
+ }
+ nodeLink = nodeLink.tail;
+ typeLink = typeLink.tail;
+ }
+ assert(typeLink.isEmpty());
+ }
+}
+
class VariableDefinitionsVisitor extends CommonResolverVisitor<SourceString> {
VariableDefinitions definitions;
ResolverVisitor resolver;
@@ -2166,30 +2203,49 @@ class Scope {
* class hierarchy. In all other cases [ClassScope] is used.
*/
class TypeDeclarationScope extends Scope {
- ClassElement get element() => super.element;
+ TypeDeclarationElement get element() => super.element;
- TypeDeclarationScope(Scope parent, ClassElement element)
- : super(parent, element);
+ TypeDeclarationScope(parent, TypeDeclarationElement element)
+ : super(parent, element) {
+ assert(parent !== null);
+ }
Element add(Element newElement) {
throw "Cannot add element to TypeDeclarationScope";
}
+ /**
+ * Looks up [name] within the type variables declared in [element].
+ */
+ Element lookupTypeVariable(SourceString name) {
+ return null;
+ }
+
Element lookup(SourceString name) {
- Element result = element.lookupTypeParameter(name);
- if (result !== null) return result;
- if (parent !== null) return parent.lookup(name);
+ Link<Type> typeVariableLink = element.typeVariables;
+ while (!typeVariableLink.isEmpty()) {
+ TypeVariableType typeVariable = typeVariableLink.head;
+ if (typeVariable.name == name) {
+ return typeVariable.element;
+ }
+ typeVariableLink = typeVariableLink.tail;
+ }
+
+ return parent.lookup(name);
}
String toString() =>
- '$element${element.typeParameters.getKeys()} > $parent';
+ '$element${element.typeVariables} > $parent';
}
class MethodScope extends Scope {
final Map<SourceString, Element> elements;
MethodScope(Scope parent, Element element)
- : super(parent, element), this.elements = new Map<SourceString, Element>();
+ : super(parent, element),
+ this.elements = new Map<SourceString, Element>() {
+ assert(parent !== null);
+ }
Element lookup(SourceString name) {
Element found = elements[name];
« no previous file with comments | « lib/compiler/implementation/elements/elements.dart ('k') | lib/compiler/implementation/ssa/codegen.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698