| Index: lib/compiler/implementation/typechecker.dart
|
| diff --git a/lib/compiler/implementation/typechecker.dart b/lib/compiler/implementation/typechecker.dart
|
| index aa6891976f43dcf3c4b610b6a68172a6a3a6b6b5..8c36f1f797c130ca126d8835e49d6f1753b77471 100644
|
| --- a/lib/compiler/implementation/typechecker.dart
|
| +++ b/lib/compiler/implementation/typechecker.dart
|
| @@ -27,6 +27,18 @@ class TypeCheckerTask extends CompilerTask {
|
| interface Type {
|
| SourceString get name();
|
| Element get element();
|
| +
|
| + /**
|
| + * Returns the unaliased type of this type.
|
| + *
|
| + * The unaliased type of a typedef'd type is the unaliased type to which its
|
| + * name is bound. The unaliased version of any other type is the type itself.
|
| + *
|
| + * For example, the unaliased type of [: typedef A Func<A,B>(B b) :] is the
|
| + * function type [: (B) -> A :] and the unaliased type of
|
| + * [: Func<int,String> :] is the function type [: (String) -> int :].
|
| + */
|
| + Type unalias(Compiler compiler);
|
| }
|
|
|
| class TypeVariableType implements Type {
|
| @@ -36,7 +48,9 @@ class TypeVariableType implements Type {
|
|
|
| SourceString get name() => element.name;
|
|
|
| - toString() => name.slowToString();
|
| + Type unalias(Compiler compiler) => this;
|
| +
|
| + String toString() => name.slowToString();
|
| }
|
|
|
| /**
|
| @@ -59,6 +73,8 @@ class StatementType implements Type {
|
| return (this === other) ? this : MAYBE_RETURNING;
|
| }
|
|
|
| + Type unalias(Compiler compiler) => this;
|
| +
|
| String toString() => stringName;
|
| }
|
|
|
| @@ -67,7 +83,9 @@ class VoidType implements Type {
|
| SourceString get name() => element.name;
|
| final VoidElement element;
|
|
|
| - toString() => name.slowToString();
|
| + Type unalias(Compiler compiler) => this;
|
| +
|
| + String toString() => name.slowToString();
|
| }
|
|
|
| class InterfaceType implements Type {
|
| @@ -79,7 +97,9 @@ class InterfaceType implements Type {
|
|
|
| SourceString get name() => element.name;
|
|
|
| - toString() {
|
| + Type unalias(Compiler compiler) => this;
|
| +
|
| + String toString() {
|
| StringBuffer sb = new StringBuffer();
|
| sb.add(name.slowToString());
|
| if (!arguments.isEmpty()) {
|
| @@ -99,7 +119,9 @@ class FunctionType implements Type {
|
| FunctionType(Type this.returnType, Link<Type> this.parameterTypes,
|
| Element this.element);
|
|
|
| - toString() {
|
| + Type unalias(Compiler compiler) => this;
|
| +
|
| + String toString() {
|
| StringBuffer sb = new StringBuffer();
|
| bool first = true;
|
| sb.add('(');
|
| @@ -124,23 +146,60 @@ class FunctionType implements Type {
|
| }
|
| }
|
|
|
| +class TypedefType implements Type {
|
| + final TypedefElement element;
|
| + final Link<Type> typeArguments;
|
| +
|
| + const TypedefType(this.element,
|
| + [this.typeArguments = const EmptyLink<Type>()]);
|
| +
|
| + SourceString get name() => element.name;
|
| +
|
| + Type unalias(Compiler compiler) {
|
| + // TODO(ahe): This should be [ensureResolved].
|
| + compiler.resolveTypedef(element);
|
| + return element.alias.unalias(compiler);
|
| + }
|
| +
|
| + String toString() {
|
| + StringBuffer sb = new StringBuffer();
|
| + sb.add(name.slowToString());
|
| + if (!typeArguments.isEmpty()) {
|
| + sb.add('<');
|
| + typeArguments.printOn(sb, ', ');
|
| + sb.add('>');
|
| + }
|
| + return sb.toString();
|
| + }
|
| +}
|
| +
|
| class Types {
|
| + final Compiler compiler;
|
| + // TODO(karlklose): should we have a class Void?
|
| final VoidType voidType;
|
| final InterfaceType dynamicType;
|
|
|
| - Types(Element dynamicElement)
|
| - : this.with(dynamicElement, new LibraryElement(new Script(null, null)));
|
| + Types(Compiler compiler, Element dynamicElement)
|
| + : this.with(compiler, dynamicElement,
|
| + new LibraryElement(new Script(null, null)));
|
|
|
| - // TODO(karlklose): should we have a class Void?
|
| - Types.with(Element dynamicElement, LibraryElement library)
|
| - : voidType = new VoidType(new VoidElement(library.entryCompilationUnit)),
|
| + Types.with(Compiler this.compiler,
|
| + Element dynamicElement,
|
| + LibraryElement library)
|
| + : voidType = new VoidType(new VoidElement(library)),
|
| dynamicType = new InterfaceType(dynamicElement);
|
|
|
| /** Returns true if t is a subtype of s */
|
| bool isSubtype(Type t, Type s) {
|
| - if (t === s || t === dynamicType || s === dynamicType ||
|
| - // TODO(karlklose): Test for s.element === compiler.objectClass.
|
| - s.name == const SourceString('Object')) return true;
|
| + if (t === s ||
|
| + t === dynamicType ||
|
| + s === dynamicType ||
|
| + s.element === compiler.objectClass) {
|
| + return true;
|
| + }
|
| + t = t.unalias(compiler);
|
| + s = s.unalias(compiler);
|
| +
|
| if (t is VoidType) {
|
| return false;
|
| } else if (t is InterfaceType) {
|
| @@ -155,6 +214,7 @@ class Types {
|
| }
|
| return false;
|
| } else if (t is FunctionType) {
|
| + if (s.element === compiler.functionClass) return true;
|
| if (s is !FunctionType) return false;
|
| FunctionType tf = t;
|
| FunctionType sf = s;
|
|
|