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

Unified Diff: sdk/lib/_internal/compiler/implementation/typechecker.dart

Issue 11418113: Substitution added to DartType (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Updated cf. comments Created 8 years, 1 month 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: sdk/lib/_internal/compiler/implementation/typechecker.dart
diff --git a/sdk/lib/_internal/compiler/implementation/typechecker.dart b/sdk/lib/_internal/compiler/implementation/typechecker.dart
index 9572643066b468c27a90d0a62e17b7200f0a6716..7a8e0c3a2a74a2db4016ff1f76a15572950fd0f9 100644
--- a/sdk/lib/_internal/compiler/implementation/typechecker.dart
+++ b/sdk/lib/_internal/compiler/implementation/typechecker.dart
@@ -60,6 +60,19 @@ abstract class DartType {
Element get element;
/**
+ * Performs the substitution [: [arguments[i]/parameters[i]]this :].
+ *
+ * The notation is known from this lambda calculus rule:
+ *
+ * (lambda x.e0)e1 -> [e1/x]e0.
+ *
+ * See [TypeVariableType] for a motivation for this method.
+ *
+ * Invariant: There must be the same number of [arguments] and [parameters].
+ */
+ DartType subst(Link<DartType> arguments, Link<DartType> parameters);
+
+ /**
* Returns the unaliased type of this type.
*
* The unaliased type of a typedef'd type is the unaliased type to which its
@@ -76,6 +89,28 @@ abstract class DartType {
DartType asRaw() => this;
}
+/**
+ * Represents a type variable, that is the type parameters of a class type.
+ *
+ * For example, in [: class Array<E> { ... } :], E is a type variable.
+ *
+ * Each class should have its own unique type variables, one for each type
+ * parameter. A class with type parameters is said to be parameterized or
+ * generic.
+ *
+ * Non-static members, constructors, and factories of generic
+ * class/interface can refer to type variables of the current class
+ * (not of supertypes).
+ *
+ * When using a generic type, also known as an application or
+ * instantiation of the type, the actual type arguments should be
+ * substituted for the type variables in the class declaration.
+ *
+ * For example, given a box, [: class Box<T> { T value; } :], the
+ * type of the expression [: new Box<String>().value :] is
+ * [: String :] because we must substitute [: String :] for the
+ * the type variable [: T :].
+ */
class TypeVariableType extends DartType {
final TypeVariableElement element;
@@ -85,6 +120,29 @@ class TypeVariableType extends DartType {
SourceString get name => element.name;
+ DartType subst(Link<DartType> arguments, Link<DartType> parameters) {
+ 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;
+ 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;
+ }
+
DartType unalias(Compiler compiler) => this;
int get hashCode => 17 * element.hashCode;
@@ -120,6 +178,11 @@ class StatementType extends DartType {
return (identical(this, other)) ? this : MAYBE_RETURNING;
}
+ DartType subst(Link<DartType> arguments, Link<DartType> parameters) {
+ // Statement types are not substitutable.
+ return this;
+ }
+
DartType unalias(Compiler compiler) => this;
int get hashCode => 17 * stringName.hashCode;
@@ -141,6 +204,11 @@ class VoidType extends DartType {
final VoidElement element;
+ DartType subst(Link<DartType> arguments, Link<DartType> parameters) {
+ // Void cannot be substituted.
+ return this;
+ }
+
DartType unalias(Compiler compiler) => this;
int get hashCode => 1729;
@@ -150,12 +218,38 @@ class VoidType extends DartType {
String toString() => name.slowToString();
}
+/**
+ * Helper method for performing substitution of a linked list of types.
+ *
+ * If no types are changed by the substitution, the [types] is returned instead
+ * of a newly created linked list.
+ */
+Link<DartType> substTypes(Link<DartType> types,
+ Link<DartType> arguments, Link<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)) {
+ changed = true;
+ }
+ builder.addLast(argument);
+ typeLink = typeLink.tail;
+ }
+ if (changed) {
+ // Create a new link only if necessary.
+ return builder.toLink();
+ }
+ return types;
+}
+
class InterfaceType extends DartType {
final Element element;
- final Link<DartType> arguments;
+ final Link<DartType> typeArguments;
InterfaceType(this.element,
- [this.arguments = const Link<DartType>()]) {
+ [this.typeArguments = const Link<DartType>()]) {
assert(invariant(element, element.isDeclaration));
}
@@ -163,14 +257,33 @@ class InterfaceType extends DartType {
SourceString get name => element.name;
+ DartType subst(Link<DartType> arguments, Link<DartType> parameters) {
+ if (typeArguments.isEmpty) {
+ // Return fast on non-generic types.
+ return this;
+ }
+ if (parameters.isEmpty) {
+ assert(arguments.isEmpty);
+ // Return fast on empty substitutions.
+ return this;
+ }
+ Link<DartType> newTypeArguments =
+ substTypes(typeArguments, arguments, parameters);
+ if (!identical(typeArguments, newTypeArguments)) {
+ // Create a new type only if necessary.
+ return new InterfaceType(element, newTypeArguments);
+ }
+ return this;
+ }
+
DartType unalias(Compiler compiler) => this;
String toString() {
StringBuffer sb = new StringBuffer();
sb.add(name.slowToString());
- if (!arguments.isEmpty) {
+ if (!typeArguments.isEmpty) {
sb.add('<');
- arguments.printOn(sb, ', ');
+ typeArguments.printOn(sb, ', ');
sb.add('>');
}
return sb.toString();
@@ -178,7 +291,7 @@ class InterfaceType extends DartType {
int get hashCode {
int hash = element.hashCode;
- for (Link<DartType> arguments = this.arguments;
+ for (Link<DartType> arguments = this.typeArguments;
!arguments.isEmpty;
arguments = arguments.tail) {
int argumentHash = arguments.head != null ? arguments.head.hashCode : 0;
@@ -190,11 +303,11 @@ class InterfaceType extends DartType {
bool operator ==(other) {
if (other is !InterfaceType) return false;
if (!identical(element, other.element)) return false;
- return arguments == other.arguments;
+ return typeArguments == other.typeArguments;
}
InterfaceType asRaw() {
- if (arguments.isEmpty) return this;
+ if (typeArguments.isEmpty) return this;
return new InterfaceType(element);
}
}
@@ -211,6 +324,25 @@ class FunctionType extends DartType {
TypeKind get kind => TypeKind.FUNCTION;
+ DartType subst(Link<DartType> arguments, Link<DartType> parameters) {
+ if (parameters.isEmpty) {
+ assert(arguments.isEmpty);
+ // Return fast on empty substitutions.
+ return this;
+ }
+ var newReturnType = returnType.subst(arguments, parameters);
+ bool changed = !identical(newReturnType, returnType);
+ var newParameterTypes = substTypes(parameterTypes, arguments, parameters);
+ if (!changed && !identical(parameterTypes, newParameterTypes)) {
+ changed = true;
+ }
+ if (changed) {
+ // Create a new type only if necessary.
+ return new FunctionType(newReturnType, newParameterTypes, element);
+ }
+ return this;
+ }
+
DartType unalias(Compiler compiler) => this;
String toString() {
@@ -259,15 +391,35 @@ class TypedefType extends DartType {
final Link<DartType> typeArguments;
const TypedefType(this.element,
- [this.typeArguments = const Link<DartType>()]);
+ [this.typeArguments = const Link<DartType>()]);
TypeKind get kind => TypeKind.TYPEDEF;
SourceString get name => element.name;
+ DartType subst(Link<DartType> arguments, Link<DartType> parameters) {
+ if (typeArguments.isEmpty) {
+ // Return fast on non-generic typedefs.
+ return this;
+ }
+ if (parameters.isEmpty) {
+ assert(arguments.isEmpty);
+ // Return fast on empty substitutions.
+ return this;
+ }
+ Link<DartType> newTypeArguments =
+ substTypes(typeArguments, arguments, parameters);
+ if (!identical(typeArguments, newTypeArguments)) {
+ // Create a new type only if necessary.
+ return new TypedefType(element, newTypeArguments);
+ }
+ return this;
+ }
+
DartType unalias(Compiler compiler) {
// TODO(ahe): This should be [ensureResolved].
compiler.resolveTypedef(element);
+ // TODO(johnniwinther): Perform substitution on the unaliased type.
return element.alias.unalias(compiler);
}
@@ -291,21 +443,34 @@ class TypedefType extends DartType {
}
}
+/**
+ * Special type to hold the [dynamic] type. Used for correctly returning
+ * 'dynamic' on [toString].
+ */
+class DynamicType extends InterfaceType {
+ DynamicType(ClassElement element) : super(element);
+
+ String toString() => 'dynamic';
+}
+
+
class Types {
final Compiler compiler;
// TODO(karlklose): should we have a class Void?
final VoidType voidType;
final InterfaceType dynamicType;
- Types(Compiler compiler, Element dynamicElement)
+ Types(Compiler compiler, ClassElement dynamicElement)
: this.with(compiler, dynamicElement,
new LibraryElement(new Script(null, null)));
Types.with(Compiler this.compiler,
- Element dynamicElement,
+ ClassElement dynamicElement,
LibraryElement library)
: voidType = new VoidType(new VoidElement(library)),
- dynamicType = new InterfaceType(dynamicElement);
+ dynamicType = new DynamicType(dynamicElement) {
+ dynamicElement.type = dynamicType;
+ }
/** Returns true if t is a subtype of s */
bool isSubtype(DartType t, DartType s) {
« no previous file with comments | « sdk/lib/_internal/compiler/implementation/ssa/codegen.dart ('k') | sdk/lib/_internal/compiler/implementation/world.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698