Chromium Code Reviews| Index: frog/leg/elements/elements.dart |
| diff --git a/frog/leg/elements/elements.dart b/frog/leg/elements/elements.dart |
| index c7d7d39ccda1ab5b580b83ecbab20afb20eff82c..85d71bcc86ce4ef03b8f643f803cce7768415184 100644 |
| --- a/frog/leg/elements/elements.dart |
| +++ b/frog/leg/elements/elements.dart |
| @@ -33,6 +33,9 @@ class ElementCategory { |
| static final int SUPER = 64; |
| + /** Type variable */ |
| + static final int TYPE_VARIABLE = 128; |
| + |
| static final int IMPLIES_TYPE = CLASS | ALIAS; |
| } |
| @@ -68,6 +71,8 @@ class ElementKind { |
| const ElementKind('getter', ElementCategory.NONE); |
| static final ElementKind SETTER = |
| const ElementKind('setter', ElementCategory.NONE); |
| + static final ElementKind TYPE_VARIABLE = |
| + const ElementKind('type_variable', ElementCategory.TYPE_VARIABLE); |
| static final ElementKind ABSTRACT_FIELD = |
| const ElementKind('abstract_field', ElementCategory.VARIABLE); |
| static final ElementKind LIBRARY = |
| @@ -114,6 +119,7 @@ class Element implements Hashable { |
| bool isParameter() => kind === ElementKind.PARAMETER; |
| bool isStatement() => kind === ElementKind.STATEMENT; |
| bool isTypedef() => kind === ElementKind.TYPEDEF; |
| + bool isTypeVariable() => kind === ElementKind.TYPE_VARIABLE; |
| bool isGetter() => kind === ElementKind.GETTER; |
| bool impliesType() => (kind.category & ElementCategory.IMPLIES_TYPE) != 0; |
| @@ -633,6 +639,7 @@ class ClassElement extends ContainerElement { |
| Map<SourceString, Element> localMembers; |
| Map<SourceString, Element> constructors; |
| Link<Type> interfaces = const EmptyLink<Type>(); |
| + Map<SourceString, TypeVariableElement> typeParameters; |
| bool isResolved = false; |
| bool isBeingResolved = false; |
| // backendMembers are members that have been added by the backend to simplify |
| @@ -644,6 +651,7 @@ class ClassElement extends ContainerElement { |
| ClassElement(SourceString name, CompilationUnitElement enclosing) |
| : localMembers = new Map<SourceString, Element>(), |
| constructors = new Map<SourceString, Element>(), |
| + typeParameters = new Map<SourceString, TypeVariableElement>(), |
| super(name, ElementKind.CLASS, enclosing); |
| void addMember(Element element, DiagnosticListener listener) { |
| @@ -676,6 +684,11 @@ class ClassElement extends ContainerElement { |
| return this; |
| } |
| + Element lookupTypeParameter(SourceString parameterName) { |
|
ahe
2012/03/15 11:17:33
As far as I can tell, this creates a separate scop
karlklose
2012/03/16 14:58:47
Yes, but the resolver will try to look names up us
|
| + Element result = typeParameters[parameterName]; |
| + return result; |
| + } |
| + |
| Element lookupLocalMember(SourceString memberName) { |
| return localMembers[memberName]; |
| } |
| @@ -881,3 +894,14 @@ class TargetElement extends Element { |
| Token position() => statement.getBeginToken(); |
| String toString() => statement.toString(); |
| } |
| + |
| +class TypeVariableElement extends Element { |
|
ahe
2012/03/15 11:17:33
Please override toString to include the name of th
karlklose
2012/03/16 14:58:47
Done.
|
| + final Node node; |
| + Type bound; |
| + Type type; |
| + TypeVariableElement(name, Element enclosing, this.node, this.type, |
|
ngeoffray
2012/03/15 11:47:40
I prefer having enclosing at the end.
|
| + [this.bound]) |
|
ngeoffray
2012/03/15 11:47:40
should that default to Object to avoid null checks
karlklose
2012/03/16 14:58:47
The bound is set when resolving the class containi
|
| + : super(name, ElementKind.TYPE_VARIABLE, enclosing); |
| + Type computeType(compiler) => type; |
| + Node parseNode(compiler) => node; |
| +} |