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

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: Updated scope handling and type resolution 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 94808dc9e4b4d63e5c9a268f40e52da970dde9cf..27ad0c9551ceb6f02bd0241123f96c55907866bb 100644
--- a/lib/compiler/implementation/resolver.dart
+++ b/lib/compiler/implementation/resolver.dart
@@ -231,7 +231,7 @@ class ResolverTask extends CompilerTask {
measure(() {
ClassNode tree = element.parseNode(compiler);
ClassResolverVisitor visitor =
- new ClassResolverVisitor(compiler, element.getLibrary(), element);
+ new ClassResolverVisitor(compiler, element);
visitor.visit(tree);
element.isBeingResolved = false;
element.isResolved = true;
@@ -344,12 +344,15 @@ class ResolverTask extends CompilerTask {
compiler, node.parameters, node.returnType, element));
}
- FunctionSignature resolveTypedef(TypedefElement element) {
+ void resolveTypedef(TypedefElement element) {
return compiler.withCurrentElement(element, () {
- Typedef node =
+ measure(() {
+ Typedef node =
compiler.parser.measure(() => element.parseNode(compiler));
- return measure(() => SignatureResolver.analyze(
- compiler, node.formals, node.returnType, element));
+ TypedefResolverVisitor visitor =
+ new TypedefResolverVisitor(compiler, element);
+ visitor.visit(node);
+ });
});
}
@@ -371,6 +374,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 {
@@ -569,7 +577,8 @@ class CommonResolverVisitor<R> extends AbstractVisitor<R> {
CommonResolverVisitor(Compiler this.compiler);
R visitNode(Node node) {
- cancel(node, 'internal error');
+ cancel(node,
+ 'internal error: Unhandled node: ${node.getObjectDescription()}');
}
R visitEmptyStatement(Node node) => null;
@@ -653,6 +662,7 @@ class StatementScope {
LabelElement lookupLabel(String label) {
return labels.lookup(label);
}
+
TargetElement currentBreakTarget() =>
breakTargetStack.isEmpty() ? null : breakTargetStack.head;
@@ -697,18 +707,23 @@ class StatementScope {
class TypeResolver {
final Compiler compiler;
+
TypeResolver(this.compiler);
- Element resolveTypeName(Scope context, TypeAnnotation node) {
+ Element resolveTypeName(Scope scope, TypeAnnotation node) {
Identifier typeName = node.typeName.asIdentifier();
Send send = node.typeName.asSend();
+ return resolveTypeNameInternal(scope, typeName, send);
+ }
+
+ Element resolveTypeNameInternal(Scope scope, Identifier typeName, Send send) {
if (send !== null) {
typeName = send.selector;
}
if (typeName.source.stringValue === 'void') {
return compiler.types.voidType.element;
} else if (send !== null) {
- Element e = context.lookup(send.receiver.asIdentifier().source);
+ Element e = scope.lookup(send.receiver.asIdentifier().source);
if (e !== null && e.kind === ElementKind.PREFIX) {
// The receiver is a prefix. Lookup in the imported members.
PrefixElement prefix = e;
@@ -720,12 +735,14 @@ class TypeResolver {
return null;
}
} else {
- return context.lookup(typeName.source);
+ return scope.lookup(typeName.source);
}
}
+ // TODO(johnniwinther): Change [onFailure] and [whenResolved] to use boolean
+ // flags instead of closures.
Type resolveTypeAnnotation(TypeAnnotation node,
- [Scope inContext, ClassElement inClass,
+ [Scope inScope, ClassElement inClass,
onFailure(Node, MessageKind, [List arguments]),
whenResolved(Node, Type)]) {
if (onFailure === null) {
@@ -735,18 +752,18 @@ class TypeResolver {
whenResolved = (n, t) {};
}
if (inClass !== null) {
- inContext = new ClassScope(inClass, inClass.getLibrary());
+ inScope = inClass.buildScope();//new ClassScope(inClass, inClass.getLibrary());
ahe 2012/08/02 06:43:14 Remove comment.
}
- if (inContext === null) {
+ if (inScope === null) {
compiler.internalError('resolveTypeAnnotation: no scope specified');
}
- return resolveTypeAnnotationInContext(inContext, node, onFailure,
+ return resolveTypeAnnotationInContext(inScope, node, onFailure,
whenResolved);
}
- Type resolveTypeAnnotationInContext(Scope context, TypeAnnotation node,
+ Type resolveTypeAnnotationInContext(Scope scope, TypeAnnotation node,
onFailure, whenResolved) {
- Element element = resolveTypeName(context, node);
+ Element element = resolveTypeName(scope, node);
Type type;
if (element === null) {
onFailure(node, MessageKind.CANNOT_RESOLVE_TYPE, [node.typeName]);
@@ -758,35 +775,30 @@ class TypeResolver {
type = element.computeType(compiler);
} 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(context,
- typeArguments.head,
- onFailure,
- whenResolved);
- arguments.addLast(argType);
- }
- if (index < cls.typeParameters.length) {
- onFailure(node.typeArguments, MessageKind.MISSING_TYPE_ARGUMENT);
- }
- }
- if (cls.typeParameters.length == 0) {
+ compiler.resolver.toResolve.add(cls);
ahe 2012/08/02 06:43:14 Please add a comment to explain why it is safe to
+ cls.computeType(compiler);
+ Link<Type> typeArguments = resolveTypeArguments(
+ node, cls.typeVariables,
+ scope, onFailure, whenResolved);
+ if (cls.typeVariables.isEmpty()) {
// Return the canonical type if it has no type parameters.
type = cls.computeType(compiler);
} else {
- type = new InterfaceType(cls, arguments.toLink());
+ type = new InterfaceType(cls, typeArguments);
}
} else if (element.isTypedef()) {
- type = element.computeType(compiler);
+ TypedefElement typdef = element;
+ // TODO(johnniwinther): Do we need to resolve the typedef?
+ typdef.computeType(compiler);
+ Link<Type> typeArguments = resolveTypeArguments(
+ node, typdef.typeVariables,
+ scope, onFailure, whenResolved);
+ if (typdef.typeVariables.isEmpty()) {
+ // Return the canonical type if it has no type parameters.
+ type = typdef.computeType(compiler);
+ } else {
+ type = new TypedefType(typdef, typeArguments);
+ }
} else if (element.isTypeVariable()) {
type = element.computeType(compiler);
} else {
@@ -797,6 +809,53 @@ class TypeResolver {
whenResolved(node, type);
return type;
}
+
+ Link<Type> resolveTypeArguments(TypeAnnotation node,
+ Link<TypeVariableType> 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);
+ }
+ Node typeArgument = typeArguments.head;
+ Type argType;
+ if (typeArgument is TypeAnnotation) {
ahe 2012/08/02 06:43:14 typeArgument.asTypeAnnotation() !== null
+ argType = resolveTypeAnnotationInContext(scope,
+ typeArgument,
+ onFailure,
+ whenResolved);
+ } else if (typeArgument is TypeVariable) {
ahe 2012/08/02 06:43:14 asTypeVariable
+ // This happens in default clauses!
ahe 2012/08/02 06:43:14 This case is really not making any sense to me.
+ Element element = resolveTypeNameInternal(scope, typeArgument.name,
+ null);
+ if (element === null) {
+ onFailure(node, MessageKind.CANNOT_RESOLVE_TYPE, [typeArgument.name]);
ahe 2012/08/02 06:43:14 Doesn't the spec say that the type variables must
+ } else if (!element.impliesType()) {
+ onFailure(node, MessageKind.NOT_A_TYPE, [typeArgument.name]);
+ } else if (!element.isTypeVariable()) {
+ onFailure(node, MessageKind.GENERIC,
+ ["Default clauses can only contain type variables."]);
+ } else {
+ TypeVariableElement typeVariableElement = element;
+ argType = typeVariableElement.type;
+ }
+ }
+ 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> {
@@ -804,7 +863,7 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
final Element enclosingElement;
final TypeResolver typeResolver;
bool inInstanceContext;
- Scope context;
+ Scope scope;
ClassElement currentClass;
bool typeRequired = false;
StatementScope statementScope;
@@ -818,20 +877,17 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
this.currentClass = element.isMember() ? element.enclosingElement : null,
this.statementScope = new StatementScope(),
typeResolver = new TypeResolver(compiler),
+ scope = element.buildEnclosingScope(),
super(compiler) {
- LibraryElement library = element.getLibrary();
- element = element.getEnclosingMember();
- if (element !== null) {
- context = new ClassScope(element.enclosingElement, library);
- } else {
- this.context = new TopScope(library);
- }
+ if (element.enclosingElement == null) {
+ print(element);
+ }
}
Enqueuer get world() => compiler.enqueuer.resolution;
Element lookup(Node node, SourceString name) {
- Element result = context.lookup(name);
+ Element result = scope.lookup(name);
if (!inInstanceContext && result != null && result.isInstanceMember()) {
error(node, MessageKind.NO_INSTANCE_AVAILABLE, [node]);
}
@@ -877,7 +933,9 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
} else {
Element element = lookup(node, node.source);
if (element === null) {
- if (!inInstanceContext) error(node, MessageKind.CANNOT_RESOLVE, [node]);
+ if (!inInstanceContext) {
+ error(node, MessageKind.CANNOT_RESOLVE, [node]);
+ }
} else {
if ((element.kind.category & allowedCategory) == 0) {
// TODO(ahe): Improve error message. Need UX input.
@@ -899,7 +957,7 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
compiler.ensure(element !== null);
mapping[node] = element;
if (doAddToScope) {
- Element existing = context.add(element);
+ Element existing = scope.add(element);
if (existing != element) {
error(node, MessageKind.DUPLICATE_DEFINITION, [node]);
}
@@ -940,7 +998,7 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
}
void setupFunction(FunctionExpression node, FunctionElement function) {
- context = new MethodScope(context, function);
+ scope = new MethodScope(scope, function);
if (node.returnType !== null) resolveTypeAnnotation(node.returnType);
// Put the parameters in scope.
FunctionSignature functionParameters =
@@ -977,10 +1035,10 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
cancel(node, "shouldn't be called");
}
- visitIn(Node node, Scope scope) {
- context = scope;
+ visitIn(Node node, Scope nestedScope) {
+ scope = nestedScope;
Element element = visit(node);
- context = context.parent;
+ scope = scope.parent;
return element;
}
@@ -988,10 +1046,10 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
* Introduces new default targets for break and continue
* before visiting the body of the loop
*/
- visitLoopBodyIn(Node loop, Node body, Scope scope) {
+ visitLoopBodyIn(Node loop, Node body, Scope bodyScope) {
TargetElement element = getOrCreateTargetElement(loop);
statementScope.enterLoop(element);
- visitIn(body, scope);
+ visitIn(body, bodyScope);
statementScope.exitLoop();
if (!element.isTarget) {
mapping.remove(loop);
@@ -999,11 +1057,11 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
}
visitBlock(Block node) {
- visitIn(node.statements, new BlockScope(context));
+ visitIn(node.statements, new BlockScope(scope));
}
visitDoWhile(DoWhile node) {
- visitLoopBodyIn(node, node.body, new BlockScope(context));
+ visitLoopBodyIn(node, node.body, new BlockScope(scope));
visit(node.condition);
}
@@ -1014,11 +1072,11 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
}
visitFor(For node) {
- Scope scope = new BlockScope(context);
- visitIn(node.initializer, scope);
- visitIn(node.condition, scope);
- visitIn(node.update, scope);
- visitLoopBodyIn(node, node.body, scope);
+ Scope blockScope = new BlockScope(scope);
+ visitIn(node.initializer, blockScope);
+ visitIn(node.condition, blockScope);
+ visitIn(node.update, blockScope);
+ visitLoopBodyIn(node, node.body, blockScope);
}
visitFunctionDeclaration(FunctionDeclaration node) {
@@ -1040,7 +1098,7 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
}
FunctionElement enclosing = new FunctionElement.node(
name, node, ElementKind.FUNCTION, new Modifiers.empty(),
- context.element);
+ scope.element);
setupFunction(node, enclosing);
defineElement(node, enclosing, doAddToScope: node.name !== null);
@@ -1050,7 +1108,7 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
visit(node.body);
statementScope = oldScope;
- context = context.parent;
+ scope = scope.parent;
}
visitIf(If node) {
@@ -1320,7 +1378,7 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
visitWhile(While node) {
visit(node.condition);
- visitLoopBodyIn(node, node.body, new BlockScope(context));
+ visitLoopBodyIn(node, node.body, new BlockScope(scope));
}
visitParenthesizedExpression(ParenthesizedExpression node) {
@@ -1356,23 +1414,13 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
return null;
}
- TypeAnnotation getTypeAnnotationFromSend(Send send) {
- if (send.selector.asTypeAnnotation() !== null) {
- return send.selector;
- } else if (send.selector.asSend() !== null) {
- Send selector = send.selector;
- if (selector.receiver.asTypeAnnotation() !== null) {
- return selector.receiver;
- }
- } else {
- compiler.internalError("malformed send in new expression");
- }
- }
-
FunctionElement resolveConstructor(NewExpression node) {
FunctionElement constructor =
node.accept(new ConstructorResolver(compiler, this));
- TypeAnnotation annotation = getTypeAnnotationFromSend(node.send);
+ TypeAnnotation annotation = node.getTypeAnnotation();
+ if (annotation == null) {
+ compiler.internalError("malformed send in new expression");
+ }
Type type = resolveTypeRequired(annotation);
if (constructor === null) {
Element resolved = (type != null) ? type.element : null;
@@ -1383,6 +1431,8 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
error(node.send, MessageKind.CANNOT_FIND_CONSTRUCTOR, [node.send]);
return null;
}
+ } else {
+ useType(annotation, type);
}
return constructor;
}
@@ -1397,7 +1447,7 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
Type resolveTypeAnnotation(TypeAnnotation node) {
Function report = typeRequired ? error : warning;
- return typeResolver.resolveTypeAnnotation(node, inContext: context,
+ return typeResolver.resolveTypeAnnotation(node, inScope: scope,
onFailure: report,
whenResolved: useType);
}
@@ -1482,10 +1532,10 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
visitForIn(ForIn node) {
visit(node.expression);
- Scope scope = new BlockScope(context);
+ Scope blockScope = new BlockScope(scope);
Node declaration = node.declaredIdentifier;
- visitIn(declaration, scope);
- visitLoopBodyIn(node, node.body, scope);
+ visitIn(declaration, blockScope);
+ visitLoopBodyIn(node, node.body, blockScope);
// TODO(lrn): Also allow a single identifier.
if ((declaration is !Send || declaration.asSend().selector is !Identifier)
@@ -1605,7 +1655,7 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
visitSwitchCase(SwitchCase node) {
node.labelsAndCases.accept(this);
- visitIn(node.statements, new BlockScope(context));
+ visitIn(node.statements, new BlockScope(scope));
}
visitCaseMatch(CaseMatch node) {
@@ -1624,7 +1674,7 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
}
visitCatchBlock(CatchBlock node) {
- Scope scope = new BlockScope(context);
+ Scope blockScope = new BlockScope(scope);
if (node.formals.isEmpty()) {
error(node, MessageKind.EMPTY_CATCH_DECLARATION);
} else if (!node.formals.nodes.tail.isEmpty()
@@ -1633,8 +1683,8 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
error(extra, MessageKind.EXTRA_CATCH_DECLARATION);
}
}
- visitIn(node.formals, scope);
- visitIn(node.block, scope);
+ visitIn(node.formals, blockScope);
+ visitIn(node.block, blockScope);
}
visitTypedef(Typedef node) {
@@ -1642,55 +1692,99 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
}
}
-class ClassResolverVisitor 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);
- 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;
- context = new TypeVariablesScope(context, classElement);
- }
+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.
- for (Link<Node> link = parameters; !link.isEmpty(); link = link.tail) {
- TypeVariable typeNode = link.head;
- SourceString variableName = typeNode.name.source;
- TypeVariableElement variableElement =
- classElement.typeParameters[variableName];
+ Link<TypeVariableType> 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(typeVariable.name);
+
+ TypeVariableElement variableElement = typeVariable.element;
if (typeNode.bound !== null) {
- Type boundType = visit(typeNode.bound);
+ Type boundType = typeResolver.resolveTypeAnnotation(
+ typeNode.bound,
+ inScope: scope,
+ onFailure: warning);
if (boundType !== null && boundType.element == variableElement) {
warning(node, MessageKind.CYCLIC_TYPE_VARIABLE,
- [variableElement.name]);
+ [variableElement.name]);
} else if (boundType !== null) {
variableElement.bound = boundType;
} else {
variableElement.bound = compiler.objectClass.computeType(compiler);
}
}
+ nodeLink = nodeLink.tail;
+ typeLink = typeLink.tail;
}
+ }
+}
+
+class TypedefResolverVisitor extends TypeDefinitionVisitor {
+ TypedefElement get element() => super.element;
+
+ TypedefResolverVisitor(Compiler compiler, TypedefElement typedefElement)
+ : super(compiler, typedefElement);
+
+ visitTypedef(Typedef node) {
+ TypedefType type = element.computeType(compiler);
+ scope = new TypeDeclarationScope(scope, element);
+ resolveTypeVariableBounds(node.typeParameters);
+
+ element.functionSignature = SignatureResolver.analyze(
+ compiler, node.formals, node.returnType, element);
+
+ element.alias = compiler.computeFunctionType(
+ element, element.functionSignature);
+
+ // TODO(johnniwinther): Check for cyclic references in the typedef alias.
+ }
+}
+
+class ClassResolverVisitor extends TypeDefinitionVisitor {
+ ClassElement get element() => super.element;
+
+ ClassResolverVisitor(Compiler compiler, ClassElement classElement)
+ : super(compiler, classElement);
+
+ visitClassNode(ClassNode node) {
+ compiler.ensure(element !== null);
+ compiler.ensure(!element.isResolved);
+
+ InterfaceType type = element.computeType(compiler);
+ scope = new TypeDeclarationScope(scope, element);
+ resolveTypeVariableBounds(node.typeParameters);
+
// Find super type.
- Type supertype = visit(node.superclass);
+ Type supertype;
+ if (node.superclass != null) {
+ supertype = typeResolver.resolveTypeAnnotation(
+ node.superclass,
+ inScope: scope,
+ onFailure: error);
+ }
if (supertype !== null && supertype.element.isExtendable()) {
- classElement.supertype = supertype;
+ element.supertype = supertype;
if (isBlackListed(supertype)) {
error(node.superclass, MessageKind.CANNOT_EXTEND, [supertype]);
}
@@ -1698,25 +1792,25 @@ 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);
- }
- if (node.defaultClause !== null) {
- classElement.defaultClass = visit(node.defaultClause);
+ element.supertype = new InterfaceType(objectElement);
}
for (Link<Node> link = node.interfaces.nodes;
!link.isEmpty();
link = link.tail) {
- Type interfaceType = visit(link.head);
+ Type interfaceType = typeResolver.resolveTypeAnnotation(
+ link.head,
+ inScope: scope,
+ onFailure: error);
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]);
}
@@ -1724,64 +1818,21 @@ class ClassResolverVisitor extends CommonResolverVisitor<Type> {
error(link.head, MessageKind.TYPE_NAME_EXPECTED);
}
}
- calculateAllSupertypes(classElement, new Set<ClassElement>());
- addDefaultConstructorIfNeeded(classElement);
- 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;
+ calculateAllSupertypes(element, new Set<ClassElement>());
+ if (node.defaultClause !== null) {
+ // TODO(johnniwinther): Handle the variables in default clauses separately
ahe 2012/08/02 06:43:14 I don't think the code you have here is working at
+ // or encoded default clauses as something other than [TypeAnnotation].
+ element.defaultClass = typeResolver.resolveTypeAnnotation(
+ node.defaultClause,
+ inScope: scope,
+ onFailure: error);
}
- return e.computeType(compiler);
+ addDefaultConstructorIfNeeded(element);
}
- Link<Type> getOrCalculateAllSupertypes(ClassElement cls,
- [Set<ClassElement> seen]) {
- Link<Type> allSupertypes = cls.allSupertypes;
+ Link<InterfaceType> getOrCalculateAllSupertypes(ClassElement cls,
+ [Set<ClassElement> seen]) {
+ Link<InterfaceType> allSupertypes = cls.allSupertypes;
if (allSupertypes !== null) return allSupertypes;
if (seen === null) {
seen = new Set<ClassElement>();
@@ -1790,7 +1841,7 @@ class ClassResolverVisitor extends CommonResolverVisitor<Type> {
error(cls.parseNode(compiler),
MessageKind.CYCLIC_CLASS_HIERARCHY,
[cls.name]);
- cls.allSupertypes = const EmptyLink<Type>();
+ cls.allSupertypes = const EmptyLink<InterfaceType>();
} else {
cls.ensureResolved(compiler);
calculateAllSupertypes(cls, seen);
@@ -1799,26 +1850,36 @@ class ClassResolverVisitor extends CommonResolverVisitor<Type> {
}
void calculateAllSupertypes(ClassElement cls, Set<ClassElement> seen) {
- // TODO(karlklose): substitute type variables.
// TODO(karlklose): check if type arguments match, if a classelement occurs
// more than once in the supertypes.
if (cls.allSupertypes !== null) return;
- final Type supertype = cls.supertype;
+ final InterfaceType supertype = cls.supertype;
if (seen.contains(cls)) {
error(cls.parseNode(compiler),
MessageKind.CYCLIC_CLASS_HIERARCHY,
[cls.name]);
- cls.allSupertypes = const EmptyLink<Type>();
+ cls.allSupertypes = const EmptyLink<InterfaceType>();
} else if (supertype != null) {
seen.add(cls);
- Link<Type> superSupertypes =
- getOrCalculateAllSupertypes(supertype.element, seen);
- Link<Type> supertypes = new Link<Type>(supertype, superSupertypes);
- for (Link<Type> interfaces = cls.interfaces;
+ ClassElement supertypeElement = supertype.element;
+ Link<InterfaceType> superSupertypes =
+ getOrCalculateAllSupertypes(supertypeElement, seen);
+ var superTypesBuilder = new LinkBuilder<InterfaceType>();
+ superTypesBuilder.addLast(supertype);
+
+ // Substitute type variables in supertypes.
+ for (Type superSupertype in superSupertypes) {
+ superTypesBuilder.addLast(superSupertype.subst(compiler,
+ supertype.typeArguments,
+ supertypeElement.computeType(compiler).typeArguments));
+ }
+
+ Link<InterfaceType> supertypes = superTypesBuilder.toLink();
+ for (Link<InterfaceType> interfaces = cls.interfaces;
!interfaces.isEmpty();
interfaces = interfaces.tail) {
Element element = interfaces.head.element;
- Link<Type> interfaceSupertypes =
+ Link<InterfaceType> interfaceSupertypes =
getOrCalculateAllSupertypes(element, seen);
supertypes = supertypes.reversePrependAll(interfaceSupertypes);
supertypes = supertypes.prepend(interfaces.head);
@@ -1826,7 +1887,7 @@ class ClassResolverVisitor extends CommonResolverVisitor<Type> {
seen.remove(cls);
cls.allSupertypes = supertypes;
} else {
- cls.allSupertypes = const EmptyLink<Type>();
+ cls.allSupertypes = const EmptyLink<InterfaceType>();
}
}
@@ -1837,20 +1898,20 @@ class ClassResolverVisitor extends CommonResolverVisitor<Type> {
void addDefaultConstructorIfNeeded(ClassElement element) {
if (element.constructors.length != 0) return;
SynthesizedConstructorElement constructor =
- new SynthesizedConstructorElement(element);
+ new SynthesizedConstructorElement(element);
element.constructors[element.name] = constructor;
Type returnType = compiler.types.voidType;
constructor.type = new FunctionType(returnType, const EmptyLink<Type>(),
constructor);
constructor.cachedNode =
- new FunctionExpression(new Identifier(element.position()),
- new NodeList.empty(),
- new Block(new NodeList.empty()),
- null, null, null, null);
+ new FunctionExpression(new Identifier(element.position()),
+ new NodeList.empty(),
+ new Block(new NodeList.empty()),
+ null, null, null, null);
}
isBlackListed(Type type) {
- LibraryElement lib = classElement.getLibrary();
+ LibraryElement lib = element.getLibrary();
return
lib !== compiler.coreLibrary &&
lib !== compiler.coreImplLibrary &&
@@ -1877,7 +1938,7 @@ class VariableDefinitionsVisitor extends CommonResolverVisitor<SourceString> {
: super(compiler)
{
variables = new VariableListElement.node(
- definitions, ElementKind.VARIABLE_LIST, resolver.context.element);
+ definitions, ElementKind.VARIABLE_LIST, resolver.scope.element);
}
SourceString visitSendSet(SendSet node) {
@@ -1892,17 +1953,20 @@ class VariableDefinitionsVisitor extends CommonResolverVisitor<SourceString> {
for (Link<Node> link = node.nodes; !link.isEmpty(); link = link.tail) {
SourceString name = visit(link.head);
VariableElement element = new VariableElement(
- name, variables, kind, resolver.context.element, node: link.head);
+ name, variables, kind, resolver.scope.element, node: link.head);
resolver.defineElement(link.head, element);
}
}
}
+/**
+ * [SignatureResolver] resolves function signatures.
+ */
class SignatureResolver extends CommonResolverVisitor<Element> {
final Element enclosingElement;
Link<Element> optionalParameters = const EmptyLink<Element>();
int optionalParameterCount = 0;
- Node currentDefinitions;
+ VariableDefinitions currentDefinitions;
SignatureResolver(Compiler compiler, this.enclosingElement) : super(compiler);
@@ -2030,6 +2094,9 @@ class SignatureResolver extends CommonResolverVisitor<Element> {
return elements;
}
+ /**
+ * Resolves formal parameters and return type to a [FunctionSignature].
+ */
static FunctionSignature analyze(Compiler compiler,
NodeList formalParameters,
Node returnNode,
@@ -2149,17 +2216,45 @@ class Scope {
abstract Element lookup(SourceString name);
}
-class TypeVariablesScope extends Scope {
- TypeVariablesScope(parent, ClassElement element) : super(parent, element);
+class EmptyScope implements Scope {
+ const EmptyScope();
+
+ Element get element() => null;
+
+ Scope get parent() => null;
+
+ Element add(Element element) {
+ throw "Cannot add element to EmptyScope";
+ }
+
+ Element lookup(SourceString name) => null;
+}
+
+/**
+ * [TypeDeclarationScope] defines the outer scope of a type declaration in
+ * which the declared type variables and the entities in the enclosing scope are
+ * available but where declared and inherited members are not available. This
+ * scope is only used for class/interface declarations during resolution of the
+ * class hierarchy. In all other cases [ClassScope] is used.
+ */
+class TypeDeclarationScope extends Scope {
+ TypeDeclarationElement get element() => super.element;
+
+ TypeDeclarationScope(parent, TypeDeclarationElement element)
+ : super(parent, element);
+
Element add(Element newElement) {
- throw "Cannot add element to TypeVariableScope";
+ throw "Cannot add element to TypeDeclarationScope";
}
+
Element lookup(SourceString name) {
- ClassElement cls = element;
- Element result = cls.lookupTypeParameter(name);
+ Element result = lookupTypeVariable(element, name);
if (result !== null) return result;
if (parent !== null) return parent.lookup(name);
}
+
+ String toString() =>
+ '$element${element.typeVariables} > $parent';
}
class MethodScope extends Scope {
@@ -2181,23 +2276,30 @@ class MethodScope extends Scope {
elements[newElement.name] = newElement;
return newElement;
}
+
+ String toString() => '$element${elements.getKeys()} > $parent';
}
class BlockScope extends MethodScope {
BlockScope(Scope parent) : super(parent, parent.element);
+
+ String toString() => 'block${elements.getKeys()} > $parent';
}
-class ClassScope extends Scope {
- ClassScope(ClassElement element, LibraryElement library)
- : super(new TopScope(library), element);
+/**
+ * [ClassScope] defines the inner scope of a class/interface declaration in
+ * which declared members, declared type variables, entities in the enclosing
+ * scope and inherited members are available, in the given order.
+ */
+class ClassScope extends TypeDeclarationScope {
+ ClassScope(Scope parentScope, ClassElement element)
+ : super(parentScope, element);
Element lookup(SourceString name) {
ClassElement cls = element;
Element result = cls.lookupLocalMember(name);
if (result !== null) return result;
- result = cls.lookupTypeParameter(name);
- if (result !== null) return result;
- result = parent.lookup(name);
+ result = super.lookup(name);
if (result != null) return result;
return cls.lookupSuperMember(name);
}
@@ -2205,6 +2307,8 @@ class ClassScope extends Scope {
Element add(Element newElement) {
throw "Cannot add an element in a class scope";
}
+
+ String toString() => '$element > $parent';
}
class TopScope extends Scope {
@@ -2218,4 +2322,5 @@ class TopScope extends Scope {
Element add(Element newElement) {
throw "Cannot add an element in the top scope";
}
+ String toString() => '$element';
}

Powered by Google App Engine
This is Rietveld 408576698