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

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

Issue 10832029: Substitution implemented for the class hierarchy. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: 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/typechecker.dart
diff --git a/lib/compiler/implementation/typechecker.dart b/lib/compiler/implementation/typechecker.dart
index f5a600fa3e08f04b40f497efe977c7630b43dbe0..440c60b7f974d75817b8d7a0a1af6f96da027bef 100644
--- a/lib/compiler/implementation/typechecker.dart
+++ b/lib/compiler/implementation/typechecker.dart
@@ -27,14 +27,64 @@ class TypeCheckerTask extends CompilerTask {
interface Type {
SourceString get name();
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.
+ */
+ Type subst(Link<Type> arguments, List<Type> parameters);
}
+/**
+ * Represents a type variable, that is the type parameters of a class
+ * or interface type. For example, in class Array<E> { ... }`,
+ * E is a type variable.
+ *
+ * Each class/interface should have its own unique type variables,
+ * one for each type parameter. A class/interface 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 implements Type {
final SourceString name;
TypeVariableElement element;
TypeVariableType(this.name, [this.element]);
- toString() => name.slowToString();
+ Type subst(Link<Type> arguments, List<Type> parameters) {
+ if (arguments.isEmpty()) {
+ // Return fast on empty substitutions.
+ return this;
+ }
+ Link<Type> argumentLink = arguments;
+ Iterator<Type> parameterIterator = parameters.iterator();
+ while (!argumentLink.isEmpty() && parameterIterator.hasNext()) {
+ Type parameter = parameterIterator.next();
+ Type argument = argumentLink.head;
+ if (parameter === this) {
+ return argument;
+ }
+ argumentLink = argumentLink.tail;
+ }
+ // The type variable was not substituted.
+ return this;
+ }
+
+ String toString() => name.slowToString();
}
/**
@@ -57,6 +107,11 @@ class StatementType implements Type {
return (this === other) ? this : MAYBE_RETURNING;
}
+ Type subst(Link<Type> arguments, List<Type> parameters) {
+ // Statement types are not substitutable.
+ return this;
+ }
+
String toString() => stringName;
}
@@ -65,7 +120,12 @@ class VoidType implements Type {
SourceString get name() => element.name;
final VoidElement element;
- toString() => name.slowToString();
+ Type subst(Link<Type> arguments, List<Type> parameters) {
+ // Void cannot be substituted.
+ return this;
+ }
+
+ String toString() => name.slowToString();
}
class InterfaceType implements Type {
@@ -77,7 +137,34 @@ class InterfaceType implements Type {
SourceString get name() => element.name;
- toString() {
+ Type subst(Link<Type> replacements, List<Type> parameters) {
+ if (arguments.isEmpty()) {
+ // Return fast on non-generic types.
+ return this;
+ }
+ if (replacements.isEmpty()) {
+ // Return fast on empty substitutions.
+ return this;
+ }
+ bool changed = false;
+ var argumentsBuilder = new LinkBuilder<Type>();
+ Link<Type> argument = arguments;
+ while (!argument.isEmpty()) {
+ var replacement = argument.head.subst(replacements, parameters);
+ if (!changed && replacement !== argument.head) {
+ changed = true;
+ }
+ argumentsBuilder.addLast(replacement);
+ argument = argument.tail;
+ }
+ if (changed) {
+ // Create a new type only if necessary.
+ return new InterfaceType(element, argumentsBuilder.toLink());
+ }
+ return this;
+ }
+
+ String toString() {
StringBuffer sb = new StringBuffer();
sb.add(name.slowToString());
if (!arguments.isEmpty()) {
@@ -97,7 +184,32 @@ class FunctionType implements Type {
const FunctionType(Type this.returnType, Link<Type> this.parameterTypes,
Element this.element);
- toString() {
+ Type subst(Link<Type> arguments, List<Type> parameters) {
+ if (arguments.isEmpty()) {
+ // Return fast on empty substitutions.
+ return this;
+ }
+ var newReturnType = returnType.subst(arguments, parameters);
+ bool changed = newReturnType !== returnType;
+ var parameterBuilder = new LinkBuilder<Type>();
+ Link<Type> parameterType = parameterTypes;
+ while (!parameterType.isEmpty()) {
+ var replacement = parameterType.head.subst(arguments, parameters);
+ if (!changed && replacement !== parameterType.head) {
+ changed = true;
+ }
+ parameterBuilder.addLast(replacement);
+ parameterType = parameterType.tail;
+ }
+ if (changed) {
+ // Create a new type only if necessary.
+ return new FunctionType(newReturnType, parameterBuilder.toLink(),
+ element);
+ }
+ return this;
+ }
+
+ String toString() {
StringBuffer sb = new StringBuffer();
bool first = true;
sb.add('(');

Powered by Google App Engine
This is Rietveld 408576698