Chromium Code Reviews| Index: sdk/lib/_internal/compiler/implementation/dart_types.dart |
| diff --git a/sdk/lib/_internal/compiler/implementation/dart_types.dart b/sdk/lib/_internal/compiler/implementation/dart_types.dart |
| index 04aceea1cfeadb864cb89e6b63dcaf83a3843f01..6b69c3905058d425cc5daae8b980ed1b76186dd2 100644 |
| --- a/sdk/lib/_internal/compiler/implementation/dart_types.dart |
| +++ b/sdk/lib/_internal/compiler/implementation/dart_types.dart |
| @@ -11,7 +11,17 @@ import 'elements/modelx.dart' |
| show VoidElementX, LibraryElementX, BaseClassElementX; |
| import 'elements/elements.dart'; |
| import 'ordered_typeset.dart' show OrderedTypeSet; |
| -import 'util/util.dart' show Link, LinkBuilder, CURRENT_ELEMENT_SPANNABLE; |
| +import 'util/util.dart' show CURRENT_ELEMENT_SPANNABLE; |
| + |
| +bool _isSameList(List a, List b) { |
| + if (a.length != b.length) return false; |
| + for (int index = 0; index < a.length; index++) { |
| + if (a[index] != b[index]) { |
| + return false; |
| + } |
| + } |
| + return true; |
| +} |
| class TypeKind { |
| final String id; |
| @@ -58,12 +68,13 @@ abstract class DartType { |
| * |
| * Invariant: There must be the same number of [arguments] and [parameters]. |
| */ |
| - DartType subst(Link<DartType> arguments, Link<DartType> parameters); |
| + DartType subst(List<DartType> arguments, List<DartType> parameters); |
| /// Performs the substitution of the type arguments of [type] for their |
| /// corresponding type variables in this type. |
| - DartType substByContext(GenericType type) => |
| - subst(type.typeArguments, type.element.typeVariables); |
| + DartType substByContext(GenericType type) { |
| + return subst(type.typeArguments, type.element.typeVariables.toList()); |
|
Johnni Winther
2014/02/26 14:01:54
`toList()` not needed.
karlklose
2014/02/27 09:31:41
Done.
|
| + } |
| /** |
| * Returns the unaliased type of this type. |
| @@ -108,9 +119,9 @@ abstract class DartType { |
| /// Applies [f] to each occurence of a [TypeVariableType] within this type. |
| void forEachTypeVariable(f(TypeVariableType variable)) {} |
| - TypeVariableType _findTypeVariableOccurrence(Link<DartType> types) { |
| - for (Link<DartType> link = types; !link.isEmpty ; link = link.tail) { |
| - TypeVariableType typeVariable = link.head.typeVariableOccurrence; |
| + TypeVariableType _findTypeVariableOccurrence(List<DartType> types) { |
| + for (DartType type in types) { |
| + TypeVariableType typeVariable = type.typeVariableOccurrence; |
| if (typeVariable != null) { |
| return typeVariable; |
| } |
| @@ -131,10 +142,10 @@ abstract class DartType { |
| void visitChildren(DartTypeVisitor visitor, var argument) {} |
| - static void visitList(Link<DartType> types, |
| + static void visitList(List<DartType> types, |
| DartTypeVisitor visitor, var argument) { |
| - for (Link<DartType> link = types; !link.isEmpty ; link = link.tail) { |
| - link.head.accept(visitor, argument); |
| + for (DartType type in types) { |
| + type.accept(visitor, argument); |
| } |
| } |
| } |
| @@ -170,25 +181,19 @@ class TypeVariableType extends DartType { |
| String get name => element.name; |
| - DartType subst(Link<DartType> arguments, Link<DartType> parameters) { |
| + DartType subst(List<DartType> arguments, List<DartType> parameters) { |
| + assert(arguments.length == parameters.length); |
| if (parameters.isEmpty) { |
| - assert(arguments.isEmpty); |
| // Return fast on empty substitutions. |
| return this; |
| } |
| - Link<DartType> parameterLink = parameters; |
| - Link<DartType> argumentLink = arguments; |
| - while (!argumentLink.isEmpty && !parameterLink.isEmpty) { |
| - TypeVariableType parameter = parameterLink.head; |
| - DartType argument = argumentLink.head; |
| + for (int index = 0; index < arguments.length; index++) { |
| + TypeVariableType parameter = parameters[index]; |
| + DartType argument = arguments[index]; |
| if (parameter == this) { |
| - assert(argumentLink.tail.isEmpty == parameterLink.tail.isEmpty); |
| return argument; |
| } |
| - parameterLink = parameterLink.tail; |
| - argumentLink = argumentLink.tail; |
| } |
| - assert(argumentLink.isEmpty && parameterLink.isEmpty); |
| // The type variable was not substituted. |
| return this; |
| } |
| @@ -238,7 +243,7 @@ class StatementType extends DartType { |
| return (identical(this, other)) ? this : MAYBE_RETURNING; |
| } |
| - DartType subst(Link<DartType> arguments, Link<DartType> parameters) { |
| + DartType subst(List<DartType> arguments, List<DartType> parameters) { |
| // Statement types are not substitutable. |
| return this; |
| } |
| @@ -268,7 +273,7 @@ class VoidType extends DartType { |
| final Element element; |
| - DartType subst(Link<DartType> arguments, Link<DartType> parameters) { |
| + DartType subst(List<DartType> arguments, List<DartType> parameters) { |
| // Void cannot be substituted. |
| return this; |
| } |
| @@ -309,7 +314,7 @@ class MalformedType extends DartType { |
| * [: dynamic :] and [: T :], respectively, or for [: X<int> :] where [: X :] |
| * is not resolved or does not imply a type. |
| */ |
| - final Link<DartType> typeArguments; |
| + final List<DartType> typeArguments; |
| final int hashCode = (nextHash++) & 0x3fffffff; |
| static int nextHash = 43765; |
| @@ -321,7 +326,7 @@ class MalformedType extends DartType { |
| String get name => element.name; |
| - DartType subst(Link<DartType> arguments, Link<DartType> parameters) { |
| + DartType subst(List<DartType> arguments, List<DartType> parameters) { |
| // Malformed types are not substitutable. |
| return this; |
| } |
| @@ -345,7 +350,7 @@ class MalformedType extends DartType { |
| } |
| if (!typeArguments.isEmpty) { |
| sb.write('<'); |
| - typeArguments.printOn(sb, ', '); |
| + sb.write(typeArguments.join(', ')); |
| sb.write('>'); |
| } |
| } else { |
| @@ -356,16 +361,16 @@ class MalformedType extends DartType { |
| } |
| abstract class GenericType extends DartType { |
| - final Link<DartType> typeArguments; |
| + final List<DartType> typeArguments; |
| - GenericType(Link<DartType> this.typeArguments); |
| + GenericType(List<DartType> this.typeArguments); |
| TypeDeclarationElement get element; |
| /// Creates a new instance of this type using the provided type arguments. |
| - GenericType createInstantiation(Link<DartType> newTypeArguments); |
| + GenericType createInstantiation(List<DartType> newTypeArguments); |
| - DartType subst(Link<DartType> arguments, Link<DartType> parameters) { |
| + DartType subst(List<DartType> arguments, List<DartType> parameters) { |
| if (typeArguments.isEmpty) { |
| // Return fast on non-generic types. |
| return this; |
| @@ -375,7 +380,7 @@ abstract class GenericType extends DartType { |
| // Return fast on empty substitutions. |
| return this; |
| } |
| - Link<DartType> newTypeArguments = |
| + List<DartType> newTypeArguments = |
| Types.substTypes(typeArguments, arguments, parameters); |
| if (!identical(typeArguments, newTypeArguments)) { |
| // Create a new type only if necessary. |
| @@ -389,8 +394,8 @@ abstract class GenericType extends DartType { |
| } |
| void forEachTypeVariable(f(TypeVariableType variable)) { |
| - for (Link<DartType> link = typeArguments; !link.isEmpty; link = link.tail) { |
| - link.head.forEachTypeVariable(f); |
| + for (DartType type in typeArguments) { |
| + type.forEachTypeVariable(f); |
| } |
| } |
| @@ -403,7 +408,7 @@ abstract class GenericType extends DartType { |
| sb.write(name); |
| if (!isRaw) { |
| sb.write('<'); |
| - typeArguments.printOn(sb, ', '); |
| + sb.write(typeArguments.join(', ')); |
| sb.write('>'); |
| } |
| return sb.toString(); |
| @@ -411,10 +416,8 @@ abstract class GenericType extends DartType { |
| int get hashCode { |
| int hash = element.hashCode; |
| - for (Link<DartType> arguments = this.typeArguments; |
| - !arguments.isEmpty; |
| - arguments = arguments.tail) { |
| - int argumentHash = arguments.head != null ? arguments.head.hashCode : 0; |
| + for (DartType argument in typeArguments) { |
| + int argumentHash = argument != null ? argument.hashCode : 0; |
| hash = 17 * hash + 3 * argumentHash; |
| } |
| return hash; |
| @@ -424,7 +427,7 @@ abstract class GenericType extends DartType { |
| if (other is !GenericType) return false; |
| return kind == other.kind |
| && element == other.element |
| - && typeArguments == other.typeArguments; |
| + && _isSameList(typeArguments, other.typeArguments); |
| } |
| /// Returns `true` if the declaration of this type has type variables. |
| @@ -436,8 +439,8 @@ abstract class GenericType extends DartType { |
| bool get treatAsRaw { |
| if (isRaw) return true; |
| - for (Link<DartType> link = typeArguments; !link.isEmpty; link = link.tail) { |
| - if (!link.head.treatAsDynamic) return false; |
| + for (DartType type in typeArguments) { |
| + if (!type.treatAsDynamic) return false; |
| } |
| return true; |
| } |
| @@ -447,25 +450,25 @@ class InterfaceType extends GenericType { |
| final ClassElement element; |
| InterfaceType(this.element, |
| - [Link<DartType> typeArguments = const Link<DartType>()]) |
| + [List<DartType> typeArguments = const <DartType>[]]) |
| : super(typeArguments) { |
| assert(invariant(element, element.isDeclaration)); |
| assert(invariant(element, element.thisType == null || |
| - typeArguments.slowLength() == element.typeVariables.slowLength(), |
| + typeArguments.length == element.typeVariables.length, |
| message: () => 'Invalid type argument count on ${element.thisType}. ' |
| 'Provided type arguments: $typeArguments.')); |
| } |
| InterfaceType.forUserProvidedBadType(this.element, |
| - [Link<DartType> typeArguments = |
| - const Link<DartType>()]) |
| + [List<DartType> typeArguments = |
| + const <DartType>[]]) |
| : super(typeArguments); |
| TypeKind get kind => TypeKind.INTERFACE; |
| String get name => element.name; |
| - InterfaceType createInstantiation(Link<DartType> newTypeArguments) { |
| + InterfaceType createInstantiation(List<DartType> newTypeArguments) { |
| return new InterfaceType(element, newTypeArguments); |
| } |
| @@ -479,7 +482,7 @@ class InterfaceType extends GenericType { |
| for (InterfaceType supertype in element.allSupertypes) { |
| ClassElement superclass = supertype.element; |
| if (superclass == other) { |
| - Link<DartType> arguments = Types.substTypes(supertype.typeArguments, |
| + List<DartType> arguments = Types.substTypes(supertype.typeArguments, |
| typeArguments, |
| element.typeVariables); |
| return new InterfaceType(superclass, arguments); |
| @@ -562,60 +565,56 @@ class BadTypedefType extends TypedefType { |
| class FunctionType extends DartType { |
| final Element element; |
| final DartType returnType; |
| - final Link<DartType> parameterTypes; |
| - final Link<DartType> optionalParameterTypes; |
| + final List<DartType> parameterTypes; |
| + final List<DartType> optionalParameterTypes; |
| /** |
| * The names of the named parameters ordered lexicographically. |
| */ |
| - final Link<String> namedParameters; |
| + final List<String> namedParameters; |
| /** |
| * The types of the named parameters in the order corresponding to the |
| * [namedParameters]. |
| */ |
| - final Link<DartType> namedParameterTypes; |
| + final List<DartType> namedParameterTypes; |
| FunctionType(Element this.element, |
| DartType this.returnType, |
| - [this.parameterTypes = const Link<DartType>(), |
| - this.optionalParameterTypes = const Link<DartType>(), |
| - this.namedParameters = const Link<String>(), |
| - this.namedParameterTypes = const Link<DartType>()]) { |
| + [this.parameterTypes = const <DartType>[], |
| + this.optionalParameterTypes = const <DartType>[], |
| + this.namedParameters = const <String>[], |
| + this.namedParameterTypes = const <DartType>[]]) { |
| assert(invariant(element, element.isDeclaration)); |
| // Assert that optional and named parameters are not used at the same time. |
| assert(optionalParameterTypes.isEmpty || namedParameterTypes.isEmpty); |
| - assert(namedParameters.slowLength() == namedParameterTypes.slowLength()); |
| + assert(namedParameters.length == namedParameterTypes.length); |
| } |
| TypeKind get kind => TypeKind.FUNCTION; |
| DartType getNamedParameterType(String name) { |
| - Link<String> namedParameter = namedParameters; |
| - Link<DartType> namedParameterType = namedParameterTypes; |
| - while (!namedParameter.isEmpty && !namedParameterType.isEmpty) { |
| - if (namedParameter.head == name) { |
| - return namedParameterType.head; |
| + for (int i = 0; i < namedParameters.length; i++) { |
| + if (namedParameters[i] == name) { |
| + return namedParameterTypes[i]; |
| } |
| - namedParameter = namedParameter.tail; |
| - namedParameterType = namedParameterType.tail; |
| } |
| return null; |
| } |
| - DartType subst(Link<DartType> arguments, Link<DartType> parameters) { |
| + DartType subst(List<DartType> arguments, List<DartType> parameters) { |
| if (parameters.isEmpty) { |
| assert(arguments.isEmpty); |
| // Return fast on empty substitutions. |
| return this; |
| } |
| - var newReturnType = returnType.subst(arguments, parameters); |
| + DartType newReturnType = returnType.subst(arguments, parameters); |
| bool changed = !identical(newReturnType, returnType); |
| - var newParameterTypes = |
| + List<DartType> newParameterTypes = |
| Types.substTypes(parameterTypes, arguments, parameters); |
| - var newOptionalParameterTypes = |
| + List<DartType> newOptionalParameterTypes = |
| Types.substTypes(optionalParameterTypes, arguments, parameters); |
| - var newNamedParameterTypes = |
| + List<DartType> newNamedParameterTypes = |
| Types.substTypes(namedParameterTypes, arguments, parameters); |
| if (!changed && |
| (!identical(parameterTypes, newParameterTypes) || |
| @@ -677,14 +676,14 @@ class FunctionType extends DartType { |
| String toString() { |
| StringBuffer sb = new StringBuffer(); |
| sb.write('('); |
| - parameterTypes.printOn(sb, ', '); |
| + sb.write(parameterTypes.join(', ')); |
| bool first = parameterTypes.isEmpty; |
| if (!optionalParameterTypes.isEmpty) { |
| if (!first) { |
| sb.write(', '); |
| } |
| sb.write('['); |
| - optionalParameterTypes.printOn(sb, ', '); |
| + sb.write(optionalParameterTypes.join(', ')); |
| sb.write(']'); |
| first = false; |
| } |
| @@ -693,18 +692,14 @@ class FunctionType extends DartType { |
| sb.write(', '); |
| } |
| sb.write('{'); |
| - Link<String> namedParameter = namedParameters; |
| - Link<DartType> namedParameterType = namedParameterTypes; |
| first = true; |
| - while (!namedParameter.isEmpty && !namedParameterType.isEmpty) { |
| + for (int i = 0; i < namedParameters.length; i++) { |
| if (!first) { |
| sb.write(', '); |
| } |
| - sb.write(namedParameterType.head); |
| + sb.write(namedParameterTypes[i]); |
| sb.write(' '); |
| - sb.write(namedParameter.head); |
| - namedParameter = namedParameter.tail; |
| - namedParameterType = namedParameterType.tail; |
| + sb.write(namedParameters[i]); |
| first = false; |
| } |
| sb.write('}'); |
| @@ -741,10 +736,10 @@ class FunctionType extends DartType { |
| bool operator ==(other) { |
| if (other is !FunctionType) return false; |
| return returnType == other.returnType |
| - && parameterTypes == other.parameterTypes |
| - && optionalParameterTypes == other.optionalParameterTypes |
| - && namedParameters == other.namedParameters |
| - && namedParameterTypes == other.namedParameterTypes; |
| + && _isSameList(parameterTypes, other.parameterTypes) |
| + && _isSameList(optionalParameterTypes, other.optionalParameterTypes) |
| + && _isSameList(namedParameters, other.namedParameters) |
| + && _isSameList(namedParameterTypes, other.namedParameterTypes); |
| } |
| } |
| @@ -754,16 +749,16 @@ class TypedefType extends GenericType { |
| // TODO(johnniwinther): Assert that the number of arguments and parameters |
| // match, like for [InterfaceType]. |
| TypedefType(this.element, |
| - [Link<DartType> typeArguments = const Link<DartType>()]) |
| + [List<DartType> typeArguments = const <DartType>[]]) |
| : super(typeArguments); |
| - TypedefType createInstantiation(Link<DartType> newTypeArguments) { |
| + TypedefType createInstantiation(List<DartType> newTypeArguments) { |
| return new TypedefType(element, newTypeArguments); |
| } |
| TypedefType.forUserProvidedBadType(this.element, |
| - [Link<DartType> typeArguments = |
| - const Link<DartType>()]) |
| + [List<DartType> typeArguments = |
| + const <DartType>[]]) |
| : super(typeArguments); |
| TypeKind get kind => TypeKind.TYPEDEF; |
| @@ -918,17 +913,14 @@ abstract class AbstractTypeRelation extends DartTypeVisitor<bool, DartType> { |
| t.element.ensureResolved(compiler); |
| bool checkTypeArguments(InterfaceType instance, InterfaceType other) { |
| - Link<DartType> tTypeArgs = instance.typeArguments; |
| - Link<DartType> sTypeArgs = other.typeArguments; |
| - while (!tTypeArgs.isEmpty) { |
| - assert(!sTypeArgs.isEmpty); |
| - if (invalidTypeArguments(tTypeArgs.head, sTypeArgs.head)) { |
| + List<DartType> tTypeArgs = instance.typeArguments; |
| + List<DartType> sTypeArgs = other.typeArguments; |
| + assert(tTypeArgs.length == sTypeArgs.length); |
| + for (int i = 0; i < tTypeArgs.length; i++) { |
| + if (invalidTypeArguments(tTypeArgs[i], sTypeArgs[i])) { |
| return false; |
| } |
| - tTypeArgs = tTypeArgs.tail; |
| - sTypeArgs = sTypeArgs.tail; |
| } |
| - assert(sTypeArgs.isEmpty); |
| return true; |
| } |
| @@ -940,7 +932,7 @@ abstract class AbstractTypeRelation extends DartTypeVisitor<bool, DartType> { |
| } |
| } |
| - bool visitFunctionType(FunctionType t, DartType s) { |
| + bool visitFunctionType(FunctionType t, DartType s) { |
| if (s is InterfaceType && identical(s.element, compiler.functionClass)) { |
| return true; |
| } |
| @@ -959,72 +951,76 @@ abstract class AbstractTypeRelation extends DartTypeVisitor<bool, DartType> { |
| // x.o : optionalParameterTypes on [:x:], and |
| // len(xs) : length of list [:xs:]. |
| - Link<DartType> tps = tf.parameterTypes; |
| - Link<DartType> sps = sf.parameterTypes; |
| - while (!tps.isEmpty && !sps.isEmpty) { |
| - if (invalidFunctionParameterTypes(tps.head, sps.head)) return false; |
| - tps = tps.tail; |
| - sps = sps.tail; |
| + Iterator<DartType> tps = tf.parameterTypes.iterator; |
| + Iterator<DartType> sps = sf.parameterTypes.iterator; |
| + bool sNotEmpty = sps.moveNext(); |
| + bool tNotEmpty = tps.moveNext(); |
| + tNext() => (tNotEmpty = tps.moveNext()); |
| + sNext() => (sNotEmpty = sps.moveNext()); |
| + |
| + bool incompatibleParameters() { |
| + while (tNotEmpty && sNotEmpty) { |
| + if (invalidFunctionParameterTypes(tps.current, sps.current)) { |
| + return true; |
| + } |
| + tNext(); |
| + sNext(); |
| + } |
| + return false; |
| } |
| - if (!tps.isEmpty) { |
| + |
| + if (incompatibleParameters()) return false; |
| + if (tNotEmpty) { |
| // We must have [: len(t.p) <= len(s.p) :]. |
| return false; |
| } |
| if (!sf.namedParameters.isEmpty) { |
| - if (!sps.isEmpty) { |
| // We must have [: len(t.p) == len(s.p) :]. |
| + if (sNotEmpty) { |
| return false; |
| } |
| // Since named parameters are globally ordered we can determine the |
| // subset relation with a linear search for [:sf.namedParameters:] |
| // within [:tf.namedParameters:]. |
| - Link<String> tNames = tf.namedParameters; |
| - Link<DartType> tTypes = tf.namedParameterTypes; |
| - Link<String> sNames = sf.namedParameters; |
| - Link<DartType> sTypes = sf.namedParameterTypes; |
| - while (!tNames.isEmpty && !sNames.isEmpty) { |
| - if (sNames.head == tNames.head) { |
| - if (invalidFunctionParameterTypes(tTypes.head, sTypes.head)) { |
| + List<String> tNames = tf.namedParameters; |
| + List<DartType> tTypes = tf.namedParameterTypes; |
| + List<String> sNames = sf.namedParameters; |
| + List<DartType> sTypes = sf.namedParameterTypes; |
| + int tIndex = 0; |
| + int sIndex = 0; |
| + while (tIndex < tNames.length && sIndex < sNames.length) { |
| + if (tNames[tIndex] == sNames[sIndex]) { |
| + if (invalidFunctionParameterTypes(tTypes[tIndex], sTypes[sIndex])) { |
| return false; |
| } |
| - |
| - sNames = sNames.tail; |
| - sTypes = sTypes.tail; |
| + sIndex++; |
| } |
| - tNames = tNames.tail; |
| - tTypes = tTypes.tail; |
| + tIndex++; |
| } |
| - if (!sNames.isEmpty) { |
| + if (sIndex < sNames.length) { |
| // We didn't find all names. |
| return false; |
| } |
| } else { |
| + |
| // Check the remaining [: s.p :] against [: t.o :]. |
| - tps = tf.optionalParameterTypes; |
| - while (!tps.isEmpty && !sps.isEmpty) { |
| - if (invalidFunctionParameterTypes(tps.head, sps.head)) return false; |
| - tps = tps.tail; |
| - sps = sps.tail; |
| - } |
| - if (!sps.isEmpty) { |
| + tps = tf.optionalParameterTypes.iterator; |
| + if (incompatibleParameters()) return false; |
| + if (sNotEmpty) { |
| // We must have [: len(t.p) + len(t.o) >= len(s.p) :]. |
| return false; |
| } |
| if (!sf.optionalParameterTypes.isEmpty) { |
| // Check the remaining [: s.o :] against the remaining [: t.o :]. |
| - sps = sf.optionalParameterTypes; |
| - while (!tps.isEmpty && !sps.isEmpty) { |
| - if (invalidFunctionParameterTypes(tps.head, sps.head)) return false; |
| - tps = tps.tail; |
| - sps = sps.tail; |
| - } |
| - if (!sps.isEmpty) { |
| + sps = sf.optionalParameterTypes.iterator; |
| + if (incompatibleParameters()) return false; |
| + if (sNotEmpty) { |
| // We didn't find enough parameters: |
| // We must have [: len(t.p) + len(t.o) <= len(s.p) + len(s.o) :]. |
| return false; |
| } |
| } else { |
| - if (!sps.isEmpty) { |
| + if (sNotEmpty) { |
| // We must have [: len(t.p) + len(t.o) >= len(s.p) :]. |
| return false; |
| } |
| @@ -1038,9 +1034,9 @@ abstract class AbstractTypeRelation extends DartTypeVisitor<bool, DartType> { |
| DartType bound = t.element.bound; |
| if (bound.element.isTypeVariable()) { |
| // The bound is potentially cyclic so we need to be extra careful. |
| - Link<TypeVariableElement> seenTypeVariables = |
| - const Link<TypeVariableElement>(); |
| - seenTypeVariables = seenTypeVariables.prepend(t.element); |
| + Set<TypeVariableElement> seenTypeVariables = |
| + new Set<TypeVariableElement>(); |
| + seenTypeVariables.add(t.element); |
| while (bound.element.isTypeVariable()) { |
| TypeVariableElement element = bound.element; |
| if (identical(bound.element, s.element)) { |
| @@ -1053,7 +1049,7 @@ abstract class AbstractTypeRelation extends DartTypeVisitor<bool, DartType> { |
| // of [s]. |
| return false; |
| } |
| - seenTypeVariables = seenTypeVariables.prepend(element); |
| + seenTypeVariables.add(element); |
| bound = element.bound; |
| } |
| } |
| @@ -1246,44 +1242,37 @@ class Types { |
| void checkTypeVariableBounds(GenericType type, |
| CheckTypeVariableBound checkTypeVariableBound) { |
| TypeDeclarationElement element = type.element; |
| - Link<DartType> typeArguments = type.typeArguments; |
| - Link<DartType> typeVariables = element.typeVariables; |
| - while (!typeVariables.isEmpty && !typeArguments.isEmpty) { |
| - TypeVariableType typeVariable = typeVariables.head; |
| + List<DartType> typeArguments = type.typeArguments; |
| + List<DartType> typeVariables = element.typeVariables.toList(); |
|
Johnni Winther
2014/02/26 14:01:54
`toList()` not needed.
karlklose
2014/02/27 09:31:41
Done.
|
| + assert(typeVariables.length == typeArguments.length); |
| + for (int index = 0; index < typeArguments.length; index++) { |
| + TypeVariableType typeVariable = typeVariables[index]; |
| DartType bound = typeVariable.element.bound.substByContext(type); |
| - DartType typeArgument = typeArguments.head; |
| + DartType typeArgument = typeArguments[index]; |
| checkTypeVariableBound(type, typeArgument, typeVariable, bound); |
| - typeVariables = typeVariables.tail; |
| - typeArguments = typeArguments.tail; |
| } |
| - assert(typeVariables.isEmpty && typeArguments.isEmpty); |
| } |
| /** |
| - * Helper method for performing substitution of a linked list of types. |
| + * Helper method for performing substitution of a Listed list of types. |
|
Johnni Winther
2014/02/26 14:01:54
Remove `Listed`.
karlklose
2014/02/27 09:31:41
Done.
|
| * |
| * If no types are changed by the substitution, the [types] is returned |
| - * instead of a newly created linked list. |
| + * instead of a newly created Listed list. |
|
Johnni Winther
2014/02/26 14:01:54
Ditto.
karlklose
2014/02/27 09:31:41
Done.
|
| */ |
| - static Link<DartType> substTypes(Link<DartType> types, |
| - Link<DartType> arguments, |
| - Link<DartType> parameters) { |
| + static List<DartType> substTypes(List<DartType> types, |
| + List<DartType> arguments, |
| + List<DartType> parameters) { |
| bool changed = false; |
| - var builder = new LinkBuilder<DartType>(); |
| - Link<DartType> typeLink = types; |
| - while (!typeLink.isEmpty) { |
| - var argument = typeLink.head.subst(arguments, parameters); |
| - if (!changed && !identical(argument, typeLink.head)) { |
| + List<DartType> result = <DartType>[]; |
|
Johnni Winther
2014/02/26 14:01:54
Use index and make [result] a fixed-length list?
karlklose
2014/02/27 09:31:41
Done.
|
| + for (DartType type in types) { |
| + DartType argument = type.subst(arguments, parameters); |
| + if (!changed && !identical(argument, type)) { |
| changed = true; |
| } |
| - builder.addLast(argument); |
| - typeLink = typeLink.tail; |
| + result.add(argument); |
| } |
| - if (changed) { |
| - // Create a new link only if necessary. |
| - return builder.toLink(); |
| - } |
| - return types; |
| + // Use the new List only if necessary. |
| + return changed ? result : types; |
| } |
| /** |
| @@ -1375,18 +1364,17 @@ class Types { |
| result = compareList(aFunc.optionalParameterTypes, |
| bFunc.optionalParameterTypes); |
| if (result != 0) return result; |
| - Link<String> aNames = aFunc.namedParameters; |
| - Link<String> bNames = bFunc.namedParameters; |
| - while (!aNames.isEmpty && !bNames.isEmpty) { |
| - int result = aNames.head.compareTo(bNames.head); |
| + // TODO(karlklose): reuse [compareList]. |
| + Iterator<String> aNames = aFunc.namedParameters.iterator; |
| + Iterator<String> bNames = bFunc.namedParameters.iterator; |
| + while (aNames.moveNext() && bNames.moveNext()) { |
| + int result = aNames.current.compareTo(bNames.current); |
| if (result != 0) return result; |
| - aNames = aNames.tail; |
| - bNames = bNames.tail; |
| } |
| - if (!aNames.isEmpty) { |
| + if (aNames.moveNext()) { |
| // [aNames] is longer that [bNames] => a > b. |
| return 1; |
| - } else if (!bNames.isEmpty) { |
| + } else if (bNames.moveNext()) { |
| // [bNames] is longer that [aNames] => a < b. |
| return -1; |
| } |
| @@ -1418,18 +1406,14 @@ class Types { |
| return Elements.compareByPosition(a.element, b.element); |
| } |
| - static int compareList(Link<DartType> a, Link<DartType> b) { |
| - while (!a.isEmpty && !b.isEmpty) { |
| - int result = compare(a.head, b.head); |
| + static int compareList(List<DartType> a, List<DartType> b) { |
| + for (int index = 0; index < min(a.length, b.length); index++) { |
| + int result = compare(a[index], b[index]); |
| if (result != 0) return result; |
| - a = a.tail; |
| - b = b.tail; |
| } |
| - if (!a.isEmpty) { |
| - // [a] is longer than [b] => a > b. |
| + if (a.length > b.length) { |
| return 1; |
| - } else if (!b.isEmpty) { |
| - // [b] is longer than [a] => a < b. |
| + } else if (a.length < b.length) { |
| return -1; |
| } |
| return 0; |
| @@ -1471,16 +1455,15 @@ class Types { |
| /// Computes the least upper bound of the types in the longest prefix of [a] |
| /// and [b]. |
| - Link<DartType> computeLeastUpperBoundsTypes(Link<DartType> a, |
| - Link<DartType> b) { |
| - if (a.isEmpty || b.isEmpty) return const Link<DartType>(); |
| - LinkBuilder<DartType> types = new LinkBuilder<DartType>(); |
| - while (!a.isEmpty && !b.isEmpty) { |
| - types.addLast(computeLeastUpperBound(a.head, b.head)); |
| - a = a.tail; |
| - b = b.tail; |
| + List<DartType> computeLeastUpperBoundsTypes(List<DartType> a, |
| + List<DartType> b) { |
| + if (a.isEmpty || b.isEmpty) return const <DartType>[]; |
| + int prefixLength = min(a.length, b.length); |
| + List<DartType> types = new List(prefixLength); |
|
Johnni Winther
2014/02/26 14:01:54
Add type argument to the new list.
karlklose
2014/02/27 09:31:41
Done.
|
| + for (int index = 0; index < prefixLength; index++) { |
| + types[index] = computeLeastUpperBound(a[index], b[index]); |
| } |
| - return types.toLink(); |
| + return types; |
| } |
| /// Computes the least upper bound of two function types [a] and [b]. |
| @@ -1496,43 +1479,46 @@ class Types { |
| /// [a] and [b]. |
| DartType computeLeastUpperBoundFunctionTypes(FunctionType a, |
| FunctionType b) { |
| - if (a.parameterTypes.slowLength() != b.parameterTypes.slowLength()) { |
| + if (a.parameterTypes.length != b.parameterTypes.length) { |
| return compiler.functionClass.rawType; |
| } |
| DartType returnType = computeLeastUpperBound(a.returnType, b.returnType); |
| - Link<DartType> parameterTypes = |
| + List<DartType> parameterTypes = |
| computeLeastUpperBoundsTypes(a.parameterTypes, b.parameterTypes); |
| - Link<DartType> optionalParameterTypes = |
| + List<DartType> optionalParameterTypes = |
| computeLeastUpperBoundsTypes(a.optionalParameterTypes, |
| b.optionalParameterTypes); |
| - LinkBuilder<String> namedParameters = new LinkBuilder<String>(); |
| - Link<String> aNamedParameters = a.namedParameters; |
| - Link<String> bNamedParameters = b.namedParameters; |
| - LinkBuilder<DartType> namedParameterTypes = new LinkBuilder<DartType>(); |
| - Link<DartType> aNamedParameterTypes = a.namedParameterTypes; |
| - Link<DartType> bNamedParameterTypes = b.namedParameterTypes; |
| - while (!aNamedParameters.isEmpty && !bNamedParameters.isEmpty) { |
| - String aNamedParameter = aNamedParameters.head; |
| - String bNamedParameter = bNamedParameters.head; |
| + List<String> namedParameters = <String>[]; |
| + List<String> aNamedParameters = a.namedParameters; |
| + List<String> bNamedParameters = b.namedParameters; |
| + List<DartType> namedParameterTypes = <DartType>[]; |
| + List<DartType> aNamedParameterTypes = a.namedParameterTypes; |
| + List<DartType> bNamedParameterTypes = b.namedParameterTypes; |
| + int aIndex = 0; |
| + int bIndex = 0; |
| + int prefixLength = |
| + min(aNamedParameterTypes.length, bNamedParameterTypes.length); |
| + while (aIndex < aNamedParameters.length && |
| + bIndex < bNamedParameters.length) { |
| + String aNamedParameter = aNamedParameters[aIndex]; |
| + String bNamedParameter = bNamedParameters[bIndex]; |
| int result = aNamedParameter.compareTo(bNamedParameter); |
| if (result == 0) { |
| - namedParameters.addLast(aNamedParameter); |
| - namedParameterTypes.addLast(computeLeastUpperBound( |
| - aNamedParameterTypes.head, bNamedParameterTypes.head)); |
| + namedParameters.add(aNamedParameter); |
| + namedParameterTypes.add(computeLeastUpperBound( |
| + aNamedParameterTypes[aIndex], bNamedParameterTypes[bIndex])); |
| } |
| if (result <= 0) { |
| - aNamedParameters = aNamedParameters.tail; |
| - aNamedParameterTypes = aNamedParameterTypes.tail; |
| + aIndex++; |
| } |
| if (result >= 0) { |
| - bNamedParameters = bNamedParameters.tail; |
| - bNamedParameterTypes = bNamedParameterTypes.tail; |
| + bIndex++; |
| } |
| } |
| return new FunctionType(compiler.functionClass, |
| returnType, |
| parameterTypes, optionalParameterTypes, |
| - namedParameters.toLink(), namedParameterTypes.toLink()); |
| + namedParameters, namedParameterTypes); |
| } |
| /// Computes the least upper bound of two types of which at least one is a |
| @@ -1638,11 +1624,11 @@ class MoreSpecificSubtypeVisitor extends DartTypeVisitor<bool, DartType> { |
| constraintMap[typeVariable] = compiler.types.dynamicType; |
| }); |
| if (supertypeInstance.accept(this, supertype)) { |
| - LinkBuilder<DartType> typeArguments = new LinkBuilder<DartType>(); |
| + List<DartType> typeArguments = <DartType>[]; |
|
Johnni Winther
2014/02/26 14:01:54
Use index and make [typeArguments] a fixed-length
karlklose
2014/02/27 09:31:41
Done.
|
| element.typeVariables.forEach((TypeVariableType typeVariable) { |
| - typeArguments.addLast(constraintMap[typeVariable]); |
| + typeArguments.add(constraintMap[typeVariable]); |
| }); |
| - return element.thisType.createInstantiation(typeArguments.toLink()); |
| + return element.thisType.createInstantiation(typeArguments.toList()); |
|
Johnni Winther
2014/02/26 14:01:54
Not needed.
karlklose
2014/02/27 09:31:41
Done.
|
| } |
| return null; |
| } |
| @@ -1651,13 +1637,12 @@ class MoreSpecificSubtypeVisitor extends DartTypeVisitor<bool, DartType> { |
| return compiler.types.isMoreSpecific(type, argument); |
| } |
| - bool visitTypes(Link<DartType> a, Link<DartType> b) { |
| - while (!a.isEmpty && !b.isEmpty) { |
| - if (!a.head.accept(this, b.head)) return false; |
| - a = a.tail; |
| - b = b.tail; |
| + bool visitTypes(List<DartType> a, List<DartType> b) { |
| + int prefixLength = min(a.length, b.length); |
| + for (int index = 0; index < prefixLength; index++) { |
| + if (!a[index].accept(this, b[index])) return false; |
| } |
| - return a.isEmpty && b.isEmpty; |
| + return prefixLength == a.length && a == b; |
| } |
| bool visitTypeVariableType(TypeVariableType type, DartType argument) { |
| @@ -1669,12 +1654,12 @@ class MoreSpecificSubtypeVisitor extends DartTypeVisitor<bool, DartType> { |
| bool visitFunctionType(FunctionType type, DartType argument) { |
| if (argument is FunctionType) { |
| - if (type.parameterTypes.slowLength() != |
| - argument.parameterTypes.slowLength()) { |
| + if (type.parameterTypes.length != |
| + argument.parameterTypes.length) { |
| return false; |
| } |
| - if (type.optionalParameterTypes.slowLength() != |
| - argument.optionalParameterTypes.slowLength()) { |
| + if (type.optionalParameterTypes.length != |
| + argument.optionalParameterTypes.length) { |
| return false; |
| } |
| if (type.namedParameters != argument.namedParameters) { |
| @@ -1738,17 +1723,16 @@ class TypeDeclarationFormatter extends DartTypeVisitor<dynamic, String> { |
| type.accept(this, null); |
| } |
| - void visitTypes(Link<DartType> types, String prefix) { |
| + void visitTypes(List<DartType> types, String prefix) { |
| bool needsComma = false; |
| - for (Link<DartType> link = types; |
| - !link.isEmpty; |
| - link = link.tail) { |
| + for (DartType type in types) { |
| if (needsComma) { |
| sb.write(', '); |
| } |
| - link.head.accept(this, prefix); |
| + type.accept(this, prefix); |
| needsComma = true; |
| - } } |
| + } |
| + } |
| void visitType(DartType type, String name) { |
| if (name == null) { |
| @@ -1796,16 +1780,14 @@ class TypeDeclarationFormatter extends DartTypeVisitor<dynamic, String> { |
| sb.write(', '); |
| } |
| sb.write('{'); |
| - Link<String> namedParameter = type.namedParameters; |
| - Link<DartType> namedParameterType = type.namedParameterTypes; |
| + List<String> namedParameters = type.namedParameters; |
| + List<DartType> namedParameterTypes = type.namedParameterTypes; |
| needsComma = false; |
| - while (!namedParameter.isEmpty && !namedParameterType.isEmpty) { |
| + for (int index = 0; index < namedParameters.length; index++) { |
| if (needsComma) { |
| sb.write(', '); |
| } |
| - namedParameterType.head.accept(this, namedParameter.head); |
| - namedParameter = namedParameter.tail; |
| - namedParameterType = namedParameterType.tail; |
| + namedParameterTypes[index].accept(this, namedParameters[index]); |
| needsComma = true; |
| } |
| sb.write('}'); |