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