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

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

Issue 10834061: Resolve typedefs. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Updated scope handling and type resolution 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/elements/elements.dart
diff --git a/lib/compiler/implementation/elements/elements.dart b/lib/compiler/implementation/elements/elements.dart
index a104749521a57a0089f9f97975d1dc8d53b23074..dfe3f202266dade3983f0fcc65d99ef33d9aa2ab 100644
--- a/lib/compiler/implementation/elements/elements.dart
+++ b/lib/compiler/implementation/elements/elements.dart
@@ -38,7 +38,7 @@ class ElementCategory {
static final int IMPLIES_TYPE = CLASS | ALIAS | TYPE_VARIABLE;
- static final int IS_EXTENDABLE = CLASS | ALIAS;
+ static final int IS_EXTENDABLE = CLASS;
}
class ElementKind {
@@ -214,6 +214,18 @@ class Element implements Hashable {
return null;
}
+ /**
+ * Creates the scope for this element. The scope of the
+ * enclosing element will be the parent scope.
+ */
+ Scope buildScope() => buildEnclosingScope();
+
+ /**
+ * Creates the scope for the enclosing element. The scope of the
+ * enclosing element will be the parent scope.
ahe 2012/08/02 06:43:14 Could you explain what the difference between thes
+ */
+ Scope buildEnclosingScope() => enclosingElement.buildScope();
+
String toString() {
// TODO(johnniwinther): Test for nullness of name, or make non-nullness an
// invariant for all element types?
@@ -394,6 +406,8 @@ class LibraryElement extends CompilationUnitElement {
return path.substring(path.lastIndexOf('/') + 1);
}
}
+
+ Scope buildEnclosingScope() => new TopScope(this);
}
class PrefixElement extends Element {
@@ -418,19 +432,39 @@ class PrefixElement extends Element {
Token position() => firstPosition;
}
-class TypedefElement extends Element {
- Type cachedType;
+class TypedefElement extends Element implements TypeDeclarationElement {
+ TypedefElement(SourceString name, Element enclosing)
+ : super(name, ElementKind.TYPEDEF, enclosing);
+
+ TypedefType cachedType;
+ Type alias;
Typedef cachedNode;
- TypedefElement(SourceString name, Element enclosing)
- : super(name, ElementKind.TYPEDEF, enclosing);
+ /**
+ * Function signature for a typedef of a function type. The signature is
+ * kept to provide full information about parameter names through the mirror
+ * system.
+ *
+ * The [functionSignature] is not available until the typedef element has been
+ * resolved.
+ */
+ FunctionSignature functionSignature;
- Type computeType(Compiler compiler) {
- if (cachedType !== null) return cachedType;
- cachedType = compiler.computeFunctionType(
- this, compiler.resolveTypedef(this));
+ TypedefType computeType(Compiler compiler) {
+ if (cachedType == null) {
+ Typedef node = parseNode(compiler);
+ Link<TypeVariableType> parameters =
+ createTypeVariables(this, node.typeParameters);
ahe 2012/08/02 06:43:14 How about adding: assert(cachedType === null);
+ cachedType = new TypedefType(this, parameters);
+ }
return cachedType;
}
+
+
+ Link<TypeVariableType> get typeVariables() => cachedType.typeArguments;
+
+ Scope buildScope() =>
+ new TypeDeclarationScope(enclosingElement.buildScope(), this);
}
class VariableElement extends Element {
@@ -505,8 +539,8 @@ class VariableListElement extends Element {
/**
* Function signature for a variable with a function type. The signature is
- * kept to provide full information about parameter names through the the
- * mirror system.
+ * kept to provide full information about parameter names through the mirror
+ * system.
*/
FunctionSignature functionSignature;
@@ -613,6 +647,8 @@ class AbstractFieldElement extends Element {
}
}
+// TODO(johnniwinther): [FunctionSignature] should be merged with
+// [FunctionType].
class FunctionSignature {
Link<Element> requiredParameters;
Link<Element> optionalParameters;
@@ -811,30 +847,84 @@ class VoidElement extends Element {
bool impliesType() => true;
}
-class ClassElement extends ContainerElement {
+/**
+ * [TypeDeclarationElement] defines the common interface for class/interface
+ * declarations and typedefs.
+ */
+interface TypeDeclarationElement extends Element {
+ /**
+ * The type variables declared on this declaration. The type variables are not
+ * available until the type of the element has been computed through
+ * [computeType].
+ */
+ // TODO(johnniwinther): Find a (better) way to decouple [typeVariables] from
+ // [Compiler].
+ final Link<TypeVariableType> typeVariables;
+}
+
+/**
+ * Creates the type variables, their type and corresponding element, for the
+ * type variables declared in [parameter] on [element]. The bounds of the type
+ * variables are not set until [element] has been resolved.
+ */
+Link<TypeVariableType> createTypeVariables(TypeDeclarationElement element,
+ NodeList parameters) {
+ if (parameters === null) return const EmptyLink<TypeVariableType>();
+
+ // Create types and elements for type variable.
+ var arguments = new LinkBuilder<TypeVariableType>();
+ for (Link<Node> link = parameters.nodes; !link.isEmpty(); link = link.tail) {
+ TypeVariable typeNode = link.head;
+ SourceString variableName = typeNode.name.source;
+ TypeVariableType variableType = new TypeVariableType(variableName);
+ arguments.addLast(variableType);
+ TypeVariableElement variableElement =
+ new TypeVariableElement(variableName, element, typeNode, variableType);
+ variableType.element = variableElement;
+ }
+ return arguments.toLink();
+}
+
+/**
+ * Looks up [name] within the type variables declared in [element].
+ */
+Element lookupTypeVariable(TypeDeclarationElement element,
+ SourceString name) {
+ Link<TypeVariableType> typeVariableLink = element.typeVariables;
+ while (!typeVariableLink.isEmpty()) {
+ TypeVariableType typeVariable = typeVariableLink.head;
+ if (typeVariable.name == name) {
+ return typeVariable.element;
+ }
+ typeVariableLink = typeVariableLink.tail;
+ }
+ return null;
+}
+
ahe 2012/08/02 06:43:14 Extra line.
+
+class ClassElement extends ContainerElement
+ implements TypeDeclarationElement {
final int id;
- Type type;
- Type supertype;
- Type defaultClass;
+ InterfaceType type;
+ InterfaceType supertype;
ahe 2012/08/02 06:43:14 Eventually an interface may extend a typedef. So I
+ InterfaceType defaultClass;
Link<Element> members = const EmptyLink<Element>();
Map<SourceString, Element> localMembers;
Map<SourceString, Element> constructors;
- Link<Type> interfaces = const EmptyLink<Type>();
- LinkedHashMap<SourceString, TypeVariableElement> typeParameters;
+ Link<InterfaceType> interfaces = const EmptyLink<InterfaceType>();
bool isResolved = false;
bool isBeingResolved = false;
// backendMembers are members that have been added by the backend to simplify
// compilation. They don't have any user-side counter-part.
Link<Element> backendMembers = const EmptyLink<Element>();
- Link<Type> allSupertypes;
+ Link<InterfaceType> allSupertypes;
ClassElement patch = null;
Node defaultClause; // Only for interfaces.
ClassElement(SourceString name, CompilationUnitElement enclosing, this.id)
: localMembers = new Map<SourceString, Element>(),
constructors = new Map<SourceString, Element>(),
- typeParameters = new LinkedHashMap<SourceString, TypeVariableElement>(),
super(name, ElementKind.CLASS, enclosing);
void addMember(Element element, DiagnosticListener listener) {
@@ -850,23 +940,23 @@ class ClassElement extends ContainerElement {
}
}
- Type computeType(compiler) {
- if (type === null) {
- type = new InterfaceType(this);
+ InterfaceType computeType(compiler) {
+ if (type == null) {
+ ClassNode node = parseNode(compiler);
+ Link<TypeVariableType> parameters =
+ createTypeVariables(this, node.typeParameters);
+ type = new InterfaceType(this, parameters);
}
return type;
}
+ Link<TypeVariableType> get typeVariables() => type.typeArguments;
ahe 2012/08/02 06:43:14 Same applies here, so I would prefer Link<Type>.
+
ClassElement ensureResolved(Compiler compiler) {
compiler.resolveClass(this);
return this;
}
- Element lookupTypeParameter(SourceString parameterName) {
- Element result = typeParameters[parameterName];
- return result;
- }
-
Element lookupLocalMember(SourceString memberName) {
return localMembers[memberName];
}
@@ -1002,6 +1092,9 @@ class ClassElement extends ContainerElement {
bool isNative() => nativeName != null;
SourceString nativeName;
int hashCode() => id;
+
+ Scope buildScope() =>
+ new ClassScope(enclosingElement.buildScope(), this);
}
class Elements {
@@ -1180,13 +1273,17 @@ class TargetElement extends Element {
}
class TypeVariableElement extends Element {
- final Node node;
+ final Node cachedNode;
Type bound;
- Type type;
- TypeVariableElement(name, Element enclosing, this.node, this.type,
+ TypeVariableType type;
+
+ TypeVariableElement(name, Element enclosing, this.cachedNode, this.type,
[this.bound])
: super(name, ElementKind.TYPE_VARIABLE, enclosing);
- Type computeType(compiler) => type;
- Node parseNode(compiler) => node;
- toString() => "${enclosingElement.toString()}.${name.slowToString()}";
+
+ TypeVariableType computeType(compiler) => type;
+
+ Node parseNode(compiler) => cachedNode;
+
+ String toString() => "${enclosingElement.toString()}.${name.slowToString()}";
ahe 2012/08/02 06:43:14 This change is fine, but am I the only one thinkin
}

Powered by Google App Engine
This is Rietveld 408576698