| Index: frog/leg/elements/elements.dart
|
| ===================================================================
|
| --- frog/leg/elements/elements.dart (revision 5925)
|
| +++ frog/leg/elements/elements.dart (working copy)
|
| @@ -1,969 +0,0 @@
|
| -// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
|
| -// for details. All rights reserved. Use of this source code is governed by a
|
| -// BSD-style license that can be found in the LICENSE file.
|
| -
|
| -#library('elements');
|
| -
|
| -#import('../tree/tree.dart');
|
| -#import('../scanner/scannerlib.dart');
|
| -#import('../leg.dart'); // TODO(karlklose): we only need type.
|
| -#import('../util/util.dart');
|
| -
|
| -class ElementCategory {
|
| - /**
|
| - * Represents things that we don't expect to find when looking in a
|
| - * scope.
|
| - */
|
| - static final int NONE = 0;
|
| -
|
| - /** Field, parameter, or variable. */
|
| - static final int VARIABLE = 1;
|
| -
|
| - /** Function, method, or foreign function. */
|
| - static final int FUNCTION = 2;
|
| -
|
| - static final int CLASS = 4;
|
| -
|
| - static final int PREFIX = 8;
|
| -
|
| - /** Constructor or factory. */
|
| - static final int FACTORY = 16;
|
| -
|
| - static final int ALIAS = 32;
|
| -
|
| - static final int SUPER = 64;
|
| -
|
| - /** Type variable */
|
| - static final int TYPE_VARIABLE = 128;
|
| -
|
| - static final int IMPLIES_TYPE = CLASS | ALIAS | TYPE_VARIABLE;
|
| -
|
| - static final int IS_EXTENDABLE = CLASS | ALIAS;
|
| -}
|
| -
|
| -class ElementKind {
|
| - final String id;
|
| - final int category;
|
| -
|
| - const ElementKind(String this.id, this.category);
|
| -
|
| - static final ElementKind VARIABLE =
|
| - const ElementKind('variable', ElementCategory.VARIABLE);
|
| - static final ElementKind PARAMETER =
|
| - const ElementKind('parameter', ElementCategory.VARIABLE);
|
| - // Parameters in constructors that directly initialize fields. For example:
|
| - // [:A(this.field):].
|
| - static final ElementKind FIELD_PARAMETER =
|
| - const ElementKind('field_parameter', ElementCategory.VARIABLE);
|
| - static final ElementKind FUNCTION =
|
| - const ElementKind('function', ElementCategory.FUNCTION);
|
| - static final ElementKind CLASS =
|
| - const ElementKind('class', ElementCategory.CLASS);
|
| - static final ElementKind FOREIGN =
|
| - const ElementKind('foreign', ElementCategory.FUNCTION);
|
| - static final ElementKind GENERATIVE_CONSTRUCTOR =
|
| - const ElementKind('generative_constructor', ElementCategory.FACTORY);
|
| - static final ElementKind FIELD =
|
| - const ElementKind('field', ElementCategory.VARIABLE);
|
| - static final ElementKind VARIABLE_LIST =
|
| - const ElementKind('variable_list', ElementCategory.NONE);
|
| - static final ElementKind FIELD_LIST =
|
| - const ElementKind('field_list', ElementCategory.NONE);
|
| - static final ElementKind GENERATIVE_CONSTRUCTOR_BODY =
|
| - const ElementKind('generative_constructor_body', ElementCategory.NONE);
|
| - static final ElementKind COMPILATION_UNIT =
|
| - const ElementKind('compilation_unit', ElementCategory.NONE);
|
| - static final ElementKind GETTER =
|
| - 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 =
|
| - const ElementKind('library', ElementCategory.NONE);
|
| - static final ElementKind PREFIX =
|
| - const ElementKind('prefix', ElementCategory.PREFIX);
|
| - static final ElementKind TYPEDEF =
|
| - const ElementKind('typedef', ElementCategory.ALIAS);
|
| -
|
| - static final ElementKind STATEMENT =
|
| - const ElementKind('statement', ElementCategory.NONE);
|
| - static final ElementKind LABEL =
|
| - const ElementKind('label', ElementCategory.NONE);
|
| -
|
| - toString() => id;
|
| -}
|
| -
|
| -class Element implements Hashable {
|
| - final SourceString name;
|
| - final ElementKind kind;
|
| - final Element enclosingElement;
|
| - Modifiers get modifiers() => null;
|
| -
|
| - Node parseNode(DiagnosticListener listener) {
|
| - listener.cancel("Internal Error: $this.parseNode", token: position());
|
| - }
|
| -
|
| - Type computeType(Compiler compiler) {
|
| - compiler.internalError("$this.computeType.", token: position());
|
| - }
|
| -
|
| - bool isFunction() => kind === ElementKind.FUNCTION;
|
| - bool isMember() =>
|
| - enclosingElement !== null && enclosingElement.kind === ElementKind.CLASS;
|
| - bool isInstanceMember() => false;
|
| - bool isFactoryConstructor() => modifiers !== null && modifiers.isFactory();
|
| - bool isGenerativeConstructor() => kind === ElementKind.GENERATIVE_CONSTRUCTOR;
|
| - bool isCompilationUnit() {
|
| - return kind === ElementKind.COMPILATION_UNIT ||
|
| - kind === ElementKind.LIBRARY;
|
| - }
|
| - bool isClass() => kind === ElementKind.CLASS;
|
| - bool isVariable() => kind === ElementKind.VARIABLE;
|
| - 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 isSetter() => kind === ElementKind.SETTER;
|
| - bool impliesType() => (kind.category & ElementCategory.IMPLIES_TYPE) != 0;
|
| - bool isExtendable() => (kind.category & ElementCategory.IS_EXTENDABLE) != 0;
|
| -
|
| - bool isAssignable() {
|
| - if (modifiers != null && modifiers.isFinal()) return false;
|
| - if (isFunction() || isGenerativeConstructor()) return false;
|
| - return true;
|
| - }
|
| -
|
| - Token position() => null;
|
| -
|
| - Token findMyName(Token token) {
|
| - for (Token t = token; t !== EOF_TOKEN; t = t.next) {
|
| - if (t.value == name) return t;
|
| - }
|
| - return token;
|
| - }
|
| -
|
| - Element(this.name, this.kind, this.enclosingElement) {
|
| - assert(getLibrary() !== null);
|
| - }
|
| -
|
| - // TODO(kasperl): This is a very bad hash code for the element and
|
| - // there's no reason why two elements with the same name should have
|
| - // the same hash code. Replace this with a simple id in the element?
|
| - int hashCode() => name.hashCode();
|
| -
|
| - CompilationUnitElement getCompilationUnit() {
|
| - Element element = this;
|
| - while (element !== null && !element.isCompilationUnit()) {
|
| - element = element.enclosingElement;
|
| - }
|
| - return element;
|
| - }
|
| -
|
| - LibraryElement getLibrary() {
|
| - Element element = this;
|
| - while (element.kind !== ElementKind.LIBRARY) {
|
| - element = element.enclosingElement;
|
| - }
|
| - return element;
|
| - }
|
| -
|
| - ClassElement getEnclosingClass() {
|
| - for (Element e = this; e !== null; e = e.enclosingElement) {
|
| - if (e.kind === ElementKind.CLASS) return e;
|
| - }
|
| - return null;
|
| - }
|
| -
|
| - toString() => '$kind(${name.slowToString()})';
|
| -
|
| - bool _isNative = false;
|
| - void setNative() => _isNative = true;
|
| - bool isNative() => _isNative;
|
| -}
|
| -
|
| -class ContainerElement extends Element {
|
| - ContainerElement(name, kind, enclosingElement) :
|
| - super(name, kind, enclosingElement);
|
| -
|
| - abstract void addMember(Element element, DiagnosticListener listener);
|
| -
|
| - void addGetterOrSetter(Element element,
|
| - Element existing,
|
| - DiagnosticListener listener) {
|
| - void reportError(Element other) {
|
| - listener.cancel('duplicate definition of ${element.name.slowToString()}',
|
| - element: element);
|
| - listener.cancel('existing definition', element: other);
|
| - }
|
| -
|
| - if (existing != null) {
|
| - if (existing.kind !== ElementKind.ABSTRACT_FIELD) {
|
| - reportError(existing);
|
| - } else {
|
| - AbstractFieldElement field = existing;
|
| - if (element.kind == ElementKind.GETTER) {
|
| - if (field.getter != null && field.getter != element) {
|
| - reportError(field.getter);
|
| - }
|
| - field.getter = element;
|
| - } else {
|
| - if (field.setter != null && field.setter != element) {
|
| - reportError(field.setter);
|
| - }
|
| - field.setter = element;
|
| - }
|
| - }
|
| - } else {
|
| - AbstractFieldElement field = new AbstractFieldElement(element.name, this);
|
| - addMember(field, listener);
|
| - if (element.kind == ElementKind.GETTER) {
|
| - field.getter = element;
|
| - } else {
|
| - field.setter = element;
|
| - }
|
| - }
|
| - }
|
| -}
|
| -
|
| -class CompilationUnitElement extends ContainerElement {
|
| - final Script script;
|
| - Link<Element> topLevelElements = const EmptyLink<Element>();
|
| -
|
| - CompilationUnitElement(Script script, Element enclosing)
|
| - : this.script = script,
|
| - super(new SourceString(script.name),
|
| - ElementKind.COMPILATION_UNIT,
|
| - enclosing);
|
| -
|
| - CompilationUnitElement.library(Script script)
|
| - : this.script = script,
|
| - super(new SourceString(script.name), ElementKind.LIBRARY, null);
|
| -
|
| - void addMember(Element element, DiagnosticListener listener) {
|
| - LibraryElement library = enclosingElement;
|
| - library.addMember(element, listener);
|
| - topLevelElements = topLevelElements.prepend(element);
|
| - }
|
| -
|
| - void define(Element element, DiagnosticListener listener) {
|
| - LibraryElement library = enclosingElement;
|
| - library.define(element, listener);
|
| - }
|
| -
|
| - void addTag(ScriptTag tag, DiagnosticListener listener) {
|
| - listener.cancel("script tags not allowed here", node: tag);
|
| - }
|
| -}
|
| -
|
| -class LibraryElement extends CompilationUnitElement {
|
| - // TODO(ahe): Library element should not be a subclass of
|
| - // CompilationUnitElement.
|
| -
|
| - Link<CompilationUnitElement> compilationUnits =
|
| - const EmptyLink<CompilationUnitElement>();
|
| - Link<ScriptTag> tags = const EmptyLink<ScriptTag>();
|
| - ScriptTag libraryTag;
|
| - Map<SourceString, Element> elements;
|
| - bool canUseNative = false;
|
| -
|
| - LibraryElement(Script script)
|
| - : elements = new Map<SourceString, Element>(),
|
| - super.library(script);
|
| -
|
| - void addCompilationUnit(CompilationUnitElement element) {
|
| - compilationUnits = compilationUnits.prepend(element);
|
| - }
|
| -
|
| - void addTag(ScriptTag tag, DiagnosticListener listener) {
|
| - tags = tags.prepend(tag);
|
| - }
|
| -
|
| - void addMember(Element element, DiagnosticListener listener) {
|
| - topLevelElements = topLevelElements.prepend(element);
|
| - define(element, listener);
|
| - }
|
| -
|
| - void define(Element element, DiagnosticListener listener) {
|
| - if (element.kind == ElementKind.GETTER
|
| - || element.kind == ElementKind.SETTER) {
|
| - addGetterOrSetter(element, elements[element.name], listener);
|
| - } else {
|
| - Element existing = elements.putIfAbsent(element.name, () => element);
|
| - if (existing !== element) {
|
| - listener.cancel('duplicate definition', token: element.position());
|
| - listener.cancel('existing definition', token: existing.position());
|
| - }
|
| - }
|
| - }
|
| -
|
| - Element find(SourceString elementName) {
|
| - return elements[elementName];
|
| - }
|
| -
|
| - void forEachExport(f(Element element)) {
|
| - elements.forEach((SourceString _, Element e) {
|
| - if (this === e.getLibrary()
|
| - && e.kind !== ElementKind.PREFIX
|
| - && e.kind !== ElementKind.FOREIGN) {
|
| - if (!e.name.isPrivate()) f(e);
|
| - }
|
| - });
|
| - }
|
| -
|
| - bool hasLibraryName() => libraryTag !== null;
|
| -}
|
| -
|
| -class PrefixElement extends Element {
|
| - Map<SourceString, Element> imported;
|
| - Token firstPosition;
|
| -
|
| - PrefixElement(SourceString prefix, Element enclosing, this.firstPosition)
|
| - : imported = new Map<SourceString, Element>(),
|
| - super(prefix, ElementKind.PREFIX, enclosing);
|
| -
|
| - lookupLocalMember(SourceString memberName) => imported[memberName];
|
| -
|
| - Type computeType(Compiler compiler) => compiler.types.dynamicType;
|
| -
|
| - Token position() => firstPosition;
|
| -}
|
| -
|
| -class TypedefElement extends Element {
|
| - Token token;
|
| - TypedefElement(SourceString name, Element enclosing, this.token)
|
| - : super(name, ElementKind.TYPEDEF, enclosing);
|
| -
|
| - position() => findMyName(token);
|
| -}
|
| -
|
| -class VariableElement extends Element {
|
| - final VariableListElement variables;
|
| - Expression cachedNode; // The send or the identifier in the variables list.
|
| -
|
| - Modifiers get modifiers() => variables.modifiers;
|
| -
|
| - VariableElement(SourceString name,
|
| - VariableListElement this.variables,
|
| - ElementKind kind,
|
| - Element enclosing,
|
| - [Node node])
|
| - : super(name, kind, enclosing), cachedNode = node;
|
| -
|
| - Node parseNode(DiagnosticListener listener) {
|
| - if (cachedNode !== null) return cachedNode;
|
| - VariableDefinitions definitions = variables.parseNode(listener);
|
| - for (Link<Node> link = definitions.definitions.nodes;
|
| - !link.isEmpty(); link = link.tail) {
|
| - Expression initializedIdentifier = link.head;
|
| - Identifier identifier = initializedIdentifier.asIdentifier();
|
| - if (identifier === null) {
|
| - identifier = initializedIdentifier.asSendSet().selector.asIdentifier();
|
| - }
|
| - if (name === identifier.source) {
|
| - cachedNode = initializedIdentifier;
|
| - return cachedNode;
|
| - }
|
| - }
|
| - listener.cancel('internal error: could not find $name', node: variables);
|
| - }
|
| -
|
| - Type computeType(Compiler compiler) {
|
| - return variables.computeType(compiler);
|
| - }
|
| -
|
| - Type get type() => variables.type;
|
| -
|
| - bool isInstanceMember() {
|
| - return isMember() && !modifiers.isStatic();
|
| - }
|
| -
|
| - // Note: cachedNode.getBeginToken() will not be correct in all
|
| - // cases, for example, for function typed parameters.
|
| - Token position() => findMyName(variables.position());
|
| -}
|
| -
|
| -/**
|
| - * Parameters in constructors that directly initialize fields. For example:
|
| - * [:A(this.field):].
|
| - */
|
| -class FieldParameterElement extends VariableElement {
|
| - VariableElement fieldElement;
|
| -
|
| - FieldParameterElement(SourceString name,
|
| - this.fieldElement,
|
| - VariableListElement variables,
|
| - Element enclosing,
|
| - Node node)
|
| - : super(name, variables, ElementKind.FIELD_PARAMETER, enclosing, node);
|
| -}
|
| -
|
| -// This element represents a list of variable or field declaration.
|
| -// It contains the node, and the type. A [VariableElement] always
|
| -// references its [VariableListElement]. It forwards its
|
| -// [computeType] and [parseNode] methods to this element.
|
| -class VariableListElement extends Element {
|
| - VariableDefinitions cachedNode;
|
| - Type type;
|
| - final Modifiers modifiers;
|
| -
|
| - VariableListElement(ElementKind kind,
|
| - Modifiers this.modifiers,
|
| - Element enclosing)
|
| - : super(null, kind, enclosing);
|
| -
|
| - VariableListElement.node(VariableDefinitions node,
|
| - ElementKind kind,
|
| - Element enclosing)
|
| - : super(null, kind, enclosing),
|
| - this.cachedNode = node,
|
| - this.modifiers = node.modifiers;
|
| -
|
| - VariableDefinitions parseNode(DiagnosticListener listener) {
|
| - return cachedNode;
|
| - }
|
| -
|
| - Type computeType(Compiler compiler) {
|
| - if (type != null) return type;
|
| - type = getType(parseNode(compiler).type, compiler, getLibrary());
|
| - return type;
|
| - }
|
| -
|
| - Token position() => cachedNode.getBeginToken();
|
| -}
|
| -
|
| -class ForeignElement extends Element {
|
| - ForeignElement(SourceString name, ContainerElement enclosingElement)
|
| - : super(name, ElementKind.FOREIGN, enclosingElement);
|
| -
|
| - Type computeType(Compiler compiler) {
|
| - return compiler.types.dynamicType;
|
| - }
|
| -
|
| - parseNode(DiagnosticListener listener) {
|
| - throw "internal error: ForeignElement has no node";
|
| - }
|
| -}
|
| -
|
| -class AbstractFieldElement extends Element {
|
| - FunctionElement getter;
|
| - FunctionElement setter;
|
| - Modifiers modifiers;
|
| -
|
| - AbstractFieldElement(SourceString name, Element enclosing)
|
| - : super(name, ElementKind.ABSTRACT_FIELD, enclosing),
|
| - modifiers = new Modifiers.empty();
|
| -
|
| - Type computeType(Compiler compiler) {
|
| - throw "internal error: AbstractFieldElement has no type";
|
| - }
|
| -
|
| - Node parseNode(DiagnosticListener listener) {
|
| - throw "internal error: AbstractFieldElement has no node";
|
| - }
|
| -
|
| - position() {
|
| - // The getter and setter may be defined in two different
|
| - // compilation units. However, we know that one of them is
|
| - // non-null and defined in the same compilation unit as the
|
| - // abstract element.
|
| - //
|
| - // We need to make sure that the position returned is relative to
|
| - // the compilation unit of the abstract element.
|
| - if (getter !== null && getter.enclosingElement === enclosingElement) {
|
| - return getter.position();
|
| - } else if (setter != null) {
|
| - // TODO(ahe): checking for null should not be necessary.
|
| - return setter.position();
|
| - }
|
| - }
|
| -}
|
| -
|
| -/** DEPRECATED. */
|
| -Type getType(TypeAnnotation typeAnnotation,
|
| - Compiler compiler,
|
| - LibraryElement library) {
|
| - // TODO(karlklose,ngeoffray): This method should be removed and the
|
| - // information should be computed by the resolver.
|
| -
|
| - if (typeAnnotation == null || typeAnnotation.typeName == null) {
|
| - return compiler.types.dynamicType;
|
| - }
|
| - Identifier identifier = typeAnnotation.typeName.asIdentifier();
|
| - if (identifier === null) {
|
| - compiler.reportWarning(typeAnnotation.typeName,
|
| - 'library prefixes not handled');
|
| - return compiler.types.dynamicType;
|
| - }
|
| - SourceString name = identifier.source;
|
| - Element element = library.find(name);
|
| - if (element !== null) {
|
| - if (element.isTypedef()) {
|
| - // TODO(ngeoffray): This is a hack to help us get support for the
|
| - // DOM library.
|
| - // TODO(ngeoffray): The list of types for the argument is wrong.
|
| - return new FunctionType(compiler.types.dynamicType,
|
| - const EmptyLink<Type>(),
|
| - element);
|
| - }
|
| - if (element.isClass()) {
|
| - // TODO(karlklose): substitute type parameters.
|
| - return element.computeType(compiler);
|
| - }
|
| - }
|
| - Type type = compiler.types.lookup(name);
|
| - if (type === null) {
|
| - type = compiler.types.dynamicType;
|
| - }
|
| - return type;
|
| -}
|
| -
|
| -class FunctionParameters {
|
| - Link<Element> requiredParameters;
|
| - Link<Element> optionalParameters;
|
| - int requiredParameterCount;
|
| - int optionalParameterCount;
|
| - FunctionParameters(this.requiredParameters,
|
| - this.optionalParameters,
|
| - this.requiredParameterCount,
|
| - this.optionalParameterCount);
|
| -
|
| - void forEachParameter(void function(Element parameter)) {
|
| - for (Link<Element> link = requiredParameters;
|
| - !link.isEmpty();
|
| - link = link.tail) {
|
| - function(link.head);
|
| - }
|
| - for (Link<Element> link = optionalParameters;
|
| - !link.isEmpty();
|
| - link = link.tail) {
|
| - function(link.head);
|
| - }
|
| - }
|
| -
|
| - int get parameterCount() => requiredParameterCount + optionalParameterCount;
|
| -}
|
| -
|
| -class FunctionElement extends Element {
|
| - FunctionExpression cachedNode;
|
| - Type type;
|
| - final Modifiers modifiers;
|
| -
|
| - FunctionParameters functionParameters;
|
| -
|
| - /**
|
| - * If this is an interface constructor, [defaultImplementation] will
|
| - * changed by the resolver to point to the default
|
| - * implementation. Otherwise, [:defaultImplementation === this:].
|
| - */
|
| - FunctionElement defaultImplementation;
|
| -
|
| - FunctionElement(SourceString name,
|
| - ElementKind kind,
|
| - Modifiers modifiers,
|
| - Element enclosing)
|
| - : this.tooMuchOverloading(name, null, kind, modifiers, enclosing, null);
|
| -
|
| - FunctionElement.node(SourceString name,
|
| - FunctionExpression node,
|
| - ElementKind kind,
|
| - Modifiers modifiers,
|
| - Element enclosing)
|
| - : this.tooMuchOverloading(name, node, kind, modifiers, enclosing, null);
|
| -
|
| - FunctionElement.from(SourceString name,
|
| - FunctionElement other,
|
| - Element enclosing)
|
| - : this.tooMuchOverloading(name, other.cachedNode, other.kind,
|
| - other.modifiers, enclosing,
|
| - other.functionParameters);
|
| -
|
| - FunctionElement.tooMuchOverloading(SourceString name,
|
| - FunctionExpression this.cachedNode,
|
| - ElementKind kind,
|
| - Modifiers this.modifiers,
|
| - Element enclosing,
|
| - FunctionParameters this.functionParameters)
|
| - : super(name, kind, enclosing)
|
| - {
|
| - defaultImplementation = this;
|
| - }
|
| -
|
| - bool isInstanceMember() {
|
| - return isMember()
|
| - && kind != ElementKind.GENERATIVE_CONSTRUCTOR
|
| - && !modifiers.isFactory()
|
| - && !modifiers.isStatic();
|
| - }
|
| -
|
| - FunctionParameters computeParameters(Compiler compiler) {
|
| - if (functionParameters !== null) return functionParameters;
|
| - functionParameters = compiler.resolveSignature(this);
|
| - return functionParameters;
|
| - }
|
| -
|
| - int requiredParameterCount(Compiler compiler) {
|
| - return computeParameters(compiler).requiredParameterCount;
|
| - }
|
| -
|
| - int optionalParameterCount(Compiler compiler) {
|
| - return computeParameters(compiler).optionalParameterCount;
|
| - }
|
| -
|
| - int parameterCount(Compiler compiler) {
|
| - return computeParameters(compiler).parameterCount;
|
| - }
|
| -
|
| - FunctionType computeType(Compiler compiler) {
|
| - if (type != null) return type;
|
| - FunctionParameters parameters = computeParameters(compiler);
|
| - Types types = compiler.types;
|
| - FunctionExpression node =
|
| - compiler.parser.measure(() => parseNode(compiler));
|
| - Type returnType = getType(node.returnType, compiler, getLibrary());
|
| - if (returnType === null) returnType = types.dynamicType;
|
| -
|
| - LinkBuilder<Type> parameterTypes = new LinkBuilder<Type>();
|
| - for (Link<Element> link = parameters.requiredParameters;
|
| - !link.isEmpty();
|
| - link = link.tail) {
|
| - parameterTypes.addLast(link.head.computeType(compiler));
|
| - }
|
| - type = new FunctionType(returnType, parameterTypes.toLink(), this);
|
| - return type;
|
| - }
|
| -
|
| - Node parseNode(DiagnosticListener listener) => cachedNode;
|
| -
|
| - Token position() => cachedNode.getBeginToken();
|
| -}
|
| -
|
| -class ConstructorBodyElement extends FunctionElement {
|
| - FunctionElement constructor;
|
| -
|
| - ConstructorBodyElement(FunctionElement constructor)
|
| - : this.constructor = constructor,
|
| - super(constructor.name,
|
| - ElementKind.GENERATIVE_CONSTRUCTOR_BODY,
|
| - null,
|
| - constructor.enclosingElement) {
|
| - functionParameters = constructor.functionParameters;
|
| - }
|
| -
|
| - bool isInstanceMember() => true;
|
| -
|
| - FunctionType computeType(Compiler compiler) { unreachable(); }
|
| -
|
| - Node parseNode(DiagnosticListener listener) {
|
| - if (cachedNode !== null) return cachedNode;
|
| - cachedNode = constructor.parseNode(listener);
|
| - assert(cachedNode !== null);
|
| - return cachedNode;
|
| - }
|
| -
|
| - Token position() => constructor.position();
|
| -}
|
| -
|
| -class SynthesizedConstructorElement extends FunctionElement {
|
| - SynthesizedConstructorElement(Element enclosing)
|
| - : super(enclosing.name, ElementKind.GENERATIVE_CONSTRUCTOR,
|
| - null, enclosing);
|
| -
|
| - Token position() => enclosingElement.position();
|
| -}
|
| -
|
| -class ClassElement extends ContainerElement {
|
| - Type type;
|
| - Type supertype;
|
| - Type defaultClass;
|
| - Link<Element> members = const EmptyLink<Element>();
|
| - 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
|
| - // compilation. They don't have any user-side counter-part.
|
| - Link<Element> backendMembers = const EmptyLink<Element>();
|
| -
|
| - Link<Type> allSupertypes;
|
| -
|
| - 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) {
|
| - members = members.prepend(element);
|
| - if (element.kind == ElementKind.GENERATIVE_CONSTRUCTOR ||
|
| - element.modifiers.isFactory()) {
|
| - constructors[element.name] = element;
|
| - } else if (element.kind == ElementKind.GETTER
|
| - || element.kind == ElementKind.SETTER) {
|
| - addGetterOrSetter(element, localMembers[element.name], listener);
|
| - } else {
|
| - localMembers[element.name] = element;
|
| - }
|
| - }
|
| -
|
| - Type computeType(compiler) {
|
| - if (type === null) {
|
| - type = new SimpleType(name, this);
|
| - }
|
| - return type;
|
| - }
|
| -
|
| - ClassElement ensureResolved(Compiler compiler) {
|
| - if (!isResolved && !isBeingResolved) {
|
| - isBeingResolved = true;
|
| - compiler.resolveType(this);
|
| - isBeingResolved = false;
|
| - isResolved = true;
|
| - }
|
| - return this;
|
| - }
|
| -
|
| - Element lookupTypeParameter(SourceString parameterName) {
|
| - Element result = typeParameters[parameterName];
|
| - return result;
|
| - }
|
| -
|
| - Element lookupLocalMember(SourceString memberName) {
|
| - return localMembers[memberName];
|
| - }
|
| -
|
| - Element lookupSuperMember(SourceString memberName) {
|
| - for (ClassElement s = superclass; s != null; s = s.superclass) {
|
| - Element e = s.lookupLocalMember(memberName);
|
| - if (e !== null) {
|
| - if (!memberName.isPrivate() || getLibrary() === e.getLibrary()) {
|
| - return e;
|
| - }
|
| - }
|
| - }
|
| - return null;
|
| - }
|
| -
|
| - Element lookupConstructor(SourceString className,
|
| - [SourceString constructorName =
|
| - const SourceString(''),
|
| - Element noMatch(Element)]) {
|
| - // TODO(karlklose): have a map from class names to a map of constructors
|
| - // instead of creating the name here?
|
| - SourceString normalizedName;
|
| - if (constructorName !== const SourceString('')) {
|
| - normalizedName = Elements.constructConstructorName(className,
|
| - constructorName);
|
| - } else {
|
| - normalizedName = className;
|
| - }
|
| - Element result = constructors[normalizedName];
|
| - if (result === null && noMatch !== null) {
|
| - result = noMatch(lookupLocalMember(constructorName));
|
| - }
|
| - return result;
|
| - }
|
| -
|
| - /**
|
| - * Returns the super class, if any.
|
| - *
|
| - * The returned element may not be resolved yet.
|
| - */
|
| - ClassElement get superclass() {
|
| - assert(isResolved);
|
| - return supertype === null ? null : supertype.element;
|
| - }
|
| -
|
| - bool isInterface() => false;
|
| - bool isNative() => nativeName != null;
|
| - SourceString nativeName;
|
| -}
|
| -
|
| -class Elements {
|
| - static bool isLocal(Element element) {
|
| - return ((element !== null)
|
| - && !element.isInstanceMember()
|
| - && !isStaticOrTopLevelField(element)
|
| - && !isStaticOrTopLevelFunction(element)
|
| - && (element.kind === ElementKind.VARIABLE ||
|
| - element.kind === ElementKind.PARAMETER ||
|
| - element.kind === ElementKind.FUNCTION));
|
| - }
|
| -
|
| - static bool isInstanceField(Element element) {
|
| - return (element !== null)
|
| - && element.isInstanceMember()
|
| - && (element.kind === ElementKind.FIELD
|
| - || element.kind === ElementKind.GETTER
|
| - || element.kind === ElementKind.SETTER);
|
| - }
|
| -
|
| - static bool isStaticOrTopLevel(Element element) {
|
| - return (element != null)
|
| - && !element.isInstanceMember()
|
| - && element.enclosingElement !== null
|
| - && (element.enclosingElement.kind == ElementKind.CLASS ||
|
| - element.enclosingElement.kind == ElementKind.COMPILATION_UNIT ||
|
| - element.enclosingElement.kind == ElementKind.LIBRARY);
|
| - }
|
| -
|
| - static bool isStaticOrTopLevelField(Element element) {
|
| - return isStaticOrTopLevel(element)
|
| - && (element.kind === ElementKind.FIELD
|
| - || element.kind === ElementKind.GETTER
|
| - || element.kind === ElementKind.SETTER);
|
| - }
|
| -
|
| - static bool isStaticOrTopLevelFunction(Element element) {
|
| - return isStaticOrTopLevel(element)
|
| - && (element.kind === ElementKind.FUNCTION);
|
| - }
|
| -
|
| - static bool isInstanceMethod(Element element) {
|
| - return (element != null)
|
| - && element.isInstanceMember()
|
| - && (element.kind === ElementKind.FUNCTION);
|
| - }
|
| -
|
| - static bool isInstanceSend(Send send, TreeElements elements) {
|
| - Element element = elements[send];
|
| - if (element === null) return !isClosureSend(send, elements);
|
| - return isInstanceMethod(element) || isInstanceField(element);
|
| - }
|
| -
|
| - static bool isClosureSend(Send send, TreeElements elements) {
|
| - if (send.isPropertyAccess) return false;
|
| - if (send.receiver !== null) return false;
|
| - Element element = elements[send];
|
| - // (o)() or foo()().
|
| - if (element === null && send.selector.asIdentifier() === null) return true;
|
| - if (element === null) return false;
|
| - // foo() with foo a local or a parameter.
|
| - return isLocal(element);
|
| - }
|
| -
|
| - static SourceString constructConstructorName(SourceString receiver,
|
| - SourceString selector) {
|
| - String r = receiver.slowToString();
|
| - String s = selector.slowToString();
|
| - return new SourceString('$r\$$s');
|
| - }
|
| -
|
| - static SourceString constructOperatorName(SourceString receiver,
|
| - SourceString selector,
|
| - [bool isPrefix = false]) {
|
| - String str = selector.stringValue;
|
| - if (str === '==' || str === '!=') return Namer.OPERATOR_EQUALS;
|
| -
|
| - if (str === '~') str = 'not';
|
| - else if (str === 'negate' || (str === '-' && isPrefix)) str = 'negate';
|
| - else if (str === '[]') str = 'index';
|
| - else if (str === '[]=') str = 'indexSet';
|
| - else if (str === '*' || str === '*=') str = 'mul';
|
| - else if (str === '/' || str === '/=') str = 'div';
|
| - else if (str === '%' || str === '%=') str = 'mod';
|
| - else if (str === '~/' || str === '~/=') str = 'tdiv';
|
| - else if (str === '+' || str === '+=') str = 'add';
|
| - else if (str === '-' || str === '-=') str = 'sub';
|
| - else if (str === '<<' || str === '<<=') str = 'shl';
|
| - else if (str === '>>' || str === '>>=') str = 'shr';
|
| - else if (str === '>=') str = 'ge';
|
| - else if (str === '>') str = 'gt';
|
| - else if (str === '<=') str = 'le';
|
| - else if (str === '<') str = 'lt';
|
| - else if (str === '&' || str === '&=') str = 'and';
|
| - else if (str === '^' || str === '^=') str = 'xor';
|
| - else if (str === '|' || str === '|=') str = 'or';
|
| - else {
|
| - throw new Exception('Unhandled selector: ${selector.slowToString()}');
|
| - }
|
| - return new SourceString('$receiver\$$str');
|
| - }
|
| -
|
| - static bool isStringSupertype(Element element, Compiler compiler) {
|
| - LibraryElement coreLibrary = compiler.coreLibrary;
|
| - return (element == coreLibrary.find(const SourceString('Comparable')))
|
| - || (element == coreLibrary.find(const SourceString('Hashable')))
|
| - || (element == coreLibrary.find(const SourceString('Pattern')));
|
| - }
|
| -
|
| - static bool isListSupertype(Element element, Compiler compiler) {
|
| - LibraryElement coreLibrary = compiler.coreLibrary;
|
| - return (element == coreLibrary.find(const SourceString('Collection')))
|
| - || (element == coreLibrary.find(const SourceString('Iterable')));
|
| - }
|
| -}
|
| -
|
| -
|
| -class LabelElement extends Element {
|
| - final Identifier label;
|
| - final String labelName;
|
| - final TargetElement target;
|
| - bool isBreakTarget = false;
|
| - bool isContinueTarget = false;
|
| - LabelElement(Identifier label, this.labelName, this.target,
|
| - Element enclosingElement)
|
| - : this.label = label,
|
| - super(label.source, ElementKind.LABEL, enclosingElement);
|
| -
|
| - void setBreakTarget() {
|
| - isBreakTarget = true;
|
| - target.isBreakTarget = true;
|
| - }
|
| - void setContinueTarget() {
|
| - isContinueTarget = true;
|
| - target.isContinueTarget = true;
|
| - }
|
| -
|
| - bool get isTarget() => isBreakTarget || isContinueTarget;
|
| - Node parseNode(DiagnosticListener l) => label;
|
| -
|
| - Token position() => label.token;
|
| - String toString() => "${labelName}:";
|
| -}
|
| -
|
| -// Represents a reference to a statement, either a label or the
|
| -// default target of a break or continue.
|
| -class TargetElement extends Element {
|
| - // TODO(lrn): StatementElement is not just referencing statements anymore.
|
| - final Node statement;
|
| - final int nestingLevel;
|
| - Link<LabelElement> labels = const EmptyLink<LabelElement>();
|
| - bool isBreakTarget = false;
|
| - bool isContinueTarget = false;
|
| -
|
| - TargetElement(this.statement, this.nestingLevel, Element enclosingElement)
|
| - : super(const SourceString(""), ElementKind.STATEMENT, enclosingElement);
|
| - bool get isTarget() => isBreakTarget || isContinueTarget;
|
| -
|
| - LabelElement addLabel(Identifier label, String labelName) {
|
| - LabelElement result = new LabelElement(label, labelName, this,
|
| - enclosingElement);
|
| - labels = labels.prepend(result);
|
| - return result;
|
| - }
|
| -
|
| - Node parseNode(DiagnosticListener l) => statement;
|
| -
|
| - bool get isSwitch() => statement is SwitchStatement;
|
| -
|
| - Token position() => statement.getBeginToken();
|
| - String toString() => statement.toString();
|
| -}
|
| -
|
| -class TypeVariableElement extends Element {
|
| - final Node node;
|
| - Type bound;
|
| - Type type;
|
| - TypeVariableElement(name, Element enclosing, this.node, this.type,
|
| - [this.bound])
|
| - : super(name, ElementKind.TYPE_VARIABLE, enclosing);
|
| - Type computeType(compiler) => type;
|
| - Node parseNode(compiler) => node;
|
| - toString() => "${enclosingElement.toString()}.${name.slowToString()}";
|
| -}
|
|
|