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

Unified Diff: pkg/kernel/lib/ast.dart

Issue 2665723002: Implement canonical name scheme in kernel. (Closed)
Patch Set: Address Kevin's comments Created 3 years, 10 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
« no previous file with comments | « pkg/kernel/lib/analyzer/loader.dart ('k') | pkg/kernel/lib/binary/ast_from_binary.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/kernel/lib/ast.dart
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index 2f3cb111d74337e809f435bacbdfa2000ae8f9db..4bcc7f8e358581854631c9e2d8044e70962a41e9 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -56,6 +56,9 @@ export 'visitor.dart';
import 'type_propagation/type_propagation.dart';
export 'type_propagation/type_propagation.dart';
+import 'canonical_name.dart' show CanonicalName;
+export 'canonical_name.dart' show CanonicalName;
+
import 'transformations/flags.dart';
import 'text/ast_to_text.dart';
import 'type_algebra.dart';
@@ -152,11 +155,86 @@ abstract class TreeNode extends Node {
}
}
+/// An AST node that can be referenced by other nodes.
+///
+/// There is a single [reference] belonging to this node, providing a level of
+/// indirection that is needed during serialization.
+abstract class NamedNode extends TreeNode {
+ final Reference reference;
+
+ NamedNode(Reference reference)
+ : this.reference = reference ?? new Reference() {
+ this.reference.node = this;
+ }
+
+ CanonicalName get canonicalName => reference?.canonicalName;
+}
+
+/// Indirection between a reference and its definition.
+///
+/// There is only one reference object per [NamedNode].
+class Reference {
+ CanonicalName canonicalName;
+ NamedNode node;
+
+ String toString() {
+ if (canonicalName != null) {
+ return 'Reference to $canonicalName';
+ }
+ if (node != null) {
+ return 'Reference to $node';
+ }
+ return 'Unbound reference';
+ }
+
+ Library get asLibrary {
+ if (node == null) {
+ throw '$this is not bound to an AST node. A library was expected';
+ }
+ return node as Library;
+ }
+
+ Class get asClass {
+ if (node == null) {
+ throw '$this is not bound to an AST node. A class was expected';
+ }
+ return node as Class;
+ }
+
+ Member get asMember {
+ if (node == null) {
+ throw '$this is not bound to an AST node. A member was expected';
+ }
+ return node as Member;
+ }
+
+ Field get asField {
+ if (node == null) {
+ throw '$this is not bound to an AST node. A field was expected';
+ }
+ return node as Field;
+ }
+
+ Constructor get asConstructor {
+ if (node == null) {
+ throw '$this is not bound to an AST node. A constructor was expected';
+ }
+ return node as Constructor;
+ }
+
+ Procedure get asProcedure {
+ if (node == null) {
+ throw '$this is not bound to an AST node. A procedure was expected';
+ }
+ return node as Procedure;
+ }
+}
+
// ------------------------------------------------------------------------
// LIBRARIES and CLASSES
// ------------------------------------------------------------------------
-class Library extends TreeNode implements Comparable<Library> {
+class Library extends NamedNode implements Comparable<Library> {
/// An import path to this library.
///
/// The [Uri] should have the `dart`, `package`, `app`, or `file` scheme.
@@ -191,11 +269,13 @@ class Library extends TreeNode implements Comparable<Library> {
List<Class> classes,
List<Procedure> procedures,
List<Field> fields,
- this.fileUri})
+ this.fileUri,
+ Reference reference})
: this.deferredImports = imports ?? <DeferredImport>[],
this.classes = classes ?? <Class>[],
this.procedures = procedures ?? <Procedure>[],
- this.fields = fields ?? <Field>[] {
+ this.fields = fields ?? <Field>[],
+ super(reference) {
setParents(this.classes, this);
setParents(this.procedures, this);
setParents(this.fields, this);
@@ -224,6 +304,20 @@ class Library extends TreeNode implements Comparable<Library> {
classes.add(class_);
}
+ void computeCanonicalNames() {
+ assert(canonicalName != null);
+ for (var field in fields) {
+ canonicalName.getChildFromMember(field).bindTo(field.reference);
+ }
+ for (var member in procedures) {
+ canonicalName.getChildFromMember(member).bindTo(member.reference);
+ }
+ for (var class_ in classes) {
+ canonicalName.getChild(class_.name).bindTo(class_.reference);
+ class_.computeCanonicalNames();
+ }
+ }
+
accept(TreeVisitor v) => v.visitLibrary(this);
visitChildren(Visitor v) {
@@ -254,12 +348,16 @@ class Library extends TreeNode implements Comparable<Library> {
/// An import of form: `import <url> deferred as <name>;`.
class DeferredImport extends TreeNode {
- Library importedLibrary;
+ Reference importedLibraryReference;
String name;
- DeferredImport(this.importedLibrary, this.name);
+ DeferredImport(Library importedLibrary, String name)
+ : this.byReference(importedLibrary.reference, name);
+
+ DeferredImport.byReference(this.importedLibraryReference, this.name);
Library get enclosingLibrary => parent;
+ Library get importedLibrary => importedLibraryReference.asLibrary;
accept(TreeVisitor v) => v.visitDeferredImport(this);
@@ -321,7 +419,7 @@ enum ClassLevel {
/// use those from its mixed-in type. However, the IR does not enforce this
/// rule directly, as doing so can obstruct transformations. It is possible to
/// transform a mixin application to become a regular class, and vice versa.
-class Class extends TreeNode {
+class Class extends NamedNode {
/// The degree to which the contents of the class have been loaded.
ClassLevel level = ClassLevel.Body;
@@ -378,18 +476,33 @@ class Class extends TreeNode {
List<Constructor> constructors,
List<Procedure> procedures,
List<Field> fields,
- this.fileUri})
+ this.fileUri,
+ Reference reference})
: this.typeParameters = typeParameters ?? <TypeParameter>[],
this.implementedTypes = implementedTypes ?? <Supertype>[],
this.fields = fields ?? <Field>[],
this.constructors = constructors ?? <Constructor>[],
- this.procedures = procedures ?? <Procedure>[] {
+ this.procedures = procedures ?? <Procedure>[],
+ super(reference) {
setParents(this.typeParameters, this);
setParents(this.constructors, this);
setParents(this.procedures, this);
setParents(this.fields, this);
}
+ void computeCanonicalNames() {
+ assert(canonicalName != null);
+ for (var member in fields) {
+ canonicalName.getChildFromMember(member).bindTo(member.reference);
+ }
+ for (var member in procedures) {
+ canonicalName.getChildFromMember(member).bindTo(member.reference);
+ }
+ for (var member in constructors) {
+ canonicalName.getChildFromMember(member).bindTo(member.reference);
+ }
+ }
+
/// The immediate super class, or `null` if this is the root class.
Class get superclass => supertype?.classNode;
@@ -522,14 +635,7 @@ class Class extends TreeNode {
// MEMBERS
// ------------------------------------------------------------------------
-/// A indirect reference to a member, which can be updated to point at another
-/// member at a later time.
-class _MemberAccessor {
- Member target;
- _MemberAccessor(this.target);
-}
-
-abstract class Member extends TreeNode {
+abstract class Member extends NamedNode {
/// End offset in the source file it comes from. Valid values are from 0 and
/// up, or -1 ([TreeNode.noOffset]) if the file end offset is not available
/// (this is the default if none is specifically set).
@@ -559,7 +665,7 @@ abstract class Member extends TreeNode {
// TODO(asgerf): It might be worthwhile to put this on classes as well.
int transformerFlags = 0;
- Member(this.name);
+ Member(this.name, Reference reference) : super(reference);
Class get enclosingClass => parent is Class ? parent : null;
Library get enclosingLibrary => parent is Class ? parent.parent : parent;
@@ -617,9 +723,6 @@ abstract class Member extends TreeNode {
bool get containsSuperCalls {
return transformerFlags & TransformerFlag.superCalls != 0;
}
-
- _MemberAccessor get _getterInterface;
- _MemberAccessor get _setterInterface;
}
/// A field declaration.
@@ -627,8 +730,6 @@ abstract class Member extends TreeNode {
/// The implied getter and setter for the field are not represented explicitly,
/// but can be made explicit if needed.
class Field extends Member {
- _MemberAccessor _getterInterface, _setterInterface;
-
DartType type; // Not null. Defaults to DynamicType.
InferredValue inferredValue; // May be null.
int flags = 0;
@@ -647,10 +748,9 @@ class Field extends Member {
bool hasImplicitGetter,
bool hasImplicitSetter,
int transformerFlags: 0,
- this.fileUri})
- : super(name) {
- _getterInterface = new _MemberAccessor(this);
- _setterInterface = new _MemberAccessor(this);
+ this.fileUri,
+ Reference reference})
+ : super(name, reference) {
assert(type != null);
initializer?.parent = this;
this.isFinal = isFinal;
@@ -750,46 +850,6 @@ class Field extends Member {
DartType get getterType => type;
DartType get setterType => isMutable ? type : const BottomType();
- /// Makes all [PropertyGet]s that have this field as its interface target
- /// use [getter] as its interface target instead.
- ///
- /// That can be used to introduce an explicit getter for a field instead of
- /// its implicit getter.
- ///
- /// This method only updates the stored interface target -- the caller must
- /// ensure that [getter] actually becomes the target for dispatches that
- /// would previously hit the implicit field getter.
- ///
- /// [DirectPropertyGet]s are not affected, and will continue to access the
- /// field directly. [PropertyGet] nodes created after the call will not be
- /// affected until the method is called again.
- ///
- /// Existing [ClassHierarchy] instances are not affected by this call.
- void replaceGetterInterfaceWith(Procedure getter) {
- _getterInterface.target = getter;
- _getterInterface = new _MemberAccessor(this);
- }
-
- /// Makes all [PropertySet]s that have this field as its interface target
- /// use [setter] as its interface target instead.
- ///
- /// That can be used to introduce an explicit setter for a field instead of
- /// its implicit setter.
- ///
- /// This method only updates the stored interface target -- the caller must
- /// ensure that [setter] actually becomes the target for dispatches that
- /// would previously hit the implicit field setter.
- ///
- /// [DirectPropertySet] and [FieldInitializer]s are not affected, and will
- /// continue to access the field directly. [PropertySet] nodes created after
- /// the call will not be affected until the method is called again.
- ///
- /// Existing [ClassHierarchy] instances are not affected by this call.
- void replaceSetterInterfaceWith(Procedure setter) {
- _setterInterface.target = setter;
- _setterInterface = new _MemberAccessor(this);
- }
-
Location _getLocationInEnclosingFile(int offset) {
return enclosingProgram.getLocation(fileUri, offset);
}
@@ -813,9 +873,10 @@ class Constructor extends Member {
bool isConst: false,
bool isExternal: false,
List<Initializer> initializers,
- int transformerFlags: 0})
+ int transformerFlags: 0,
+ Reference reference})
: this.initializers = initializers ?? <Initializer>[],
- super(name) {
+ super(name, reference) {
function?.parent = this;
setParents(this.initializers, this);
this.isConst = isConst;
@@ -864,14 +925,6 @@ class Constructor extends Member {
DartType get getterType => const BottomType();
DartType get setterType => const BottomType();
-
- _MemberAccessor get _getterInterface {
- throw 'Constructors cannot be used as getters';
- }
-
- _MemberAccessor get _setterInterface {
- throw 'Constructors cannot be used as setters';
- }
}
/// A method, getter, setter, index-getter, index-setter, operator overloader,
@@ -890,7 +943,6 @@ class Constructor extends Member {
/// For operators, this is the token for the operator, e.g. `+` or `==`,
/// except for the unary minus operator, whose name is `unary-`.
class Procedure extends Member {
- _MemberAccessor _reference;
ProcedureKind kind;
int flags = 0;
FunctionNode function; // Body is null if and only if abstract or external.
@@ -904,9 +956,9 @@ class Procedure extends Member {
bool isExternal: false,
bool isConst: false,
int transformerFlags: 0,
- this.fileUri})
- : super(name) {
- _reference = new _MemberAccessor(this);
+ this.fileUri,
+ Reference reference})
+ : super(name, reference) {
function?.parent = this;
this.isAbstract = isAbstract;
this.isStatic = isStatic;
@@ -979,9 +1031,6 @@ class Procedure extends Member {
: const BottomType();
}
- _MemberAccessor get _getterInterface => _reference;
- _MemberAccessor get _setterInterface => _reference;
-
Location _getLocationInEnclosingFile(int offset) {
return enclosingProgram.getLocation(fileUri, offset);
}
@@ -1027,13 +1076,22 @@ class InvalidInitializer extends Initializer {
// exactly once, and that no fields are assigned twice in the initializer list.
class FieldInitializer extends Initializer {
/// Reference to the field being initialized. Not null.
- Field field;
+ Reference fieldReference;
Expression value;
- FieldInitializer(this.field, this.value) {
+ FieldInitializer(Field field, Expression value)
+ : this.byReference(field?.reference, value);
+
+ FieldInitializer.byReference(this.fieldReference, this.value) {
value?.parent = this;
}
+ Field get field => fieldReference?.node;
+
+ void set field(Field field) {
+ fieldReference = field?.reference;
+ }
+
accept(InitializerVisitor v) => v.visitFieldInitializer(this);
visitChildren(Visitor v) {
@@ -1060,13 +1118,22 @@ class FieldInitializer extends Initializer {
// from the extends clause.
class SuperInitializer extends Initializer {
/// Reference to the constructor being invoked in the super class. Not null.
- Constructor target;
+ Reference targetReference;
Arguments arguments;
- SuperInitializer(this.target, this.arguments) {
+ SuperInitializer(Constructor target, Arguments arguments)
+ : this.byReference(getMemberReference(target), arguments);
+
+ SuperInitializer.byReference(this.targetReference, this.arguments) {
arguments?.parent = this;
}
+ Constructor get target => targetReference?.asConstructor;
+
+ void set target(Constructor target) {
+ targetReference = getMemberReference(target);
+ }
+
accept(InitializerVisitor v) => v.visitSuperInitializer(this);
visitChildren(Visitor v) {
@@ -1089,13 +1156,22 @@ class SuperInitializer extends Initializer {
// constructor has a body or if there is a cycle in the initializer calls.
class RedirectingInitializer extends Initializer {
/// Reference to the constructor being invoked in the same class. Not null.
- Constructor target;
+ Reference targetReference;
Arguments arguments;
- RedirectingInitializer(this.target, this.arguments) {
+ RedirectingInitializer(Constructor target, Arguments arguments)
+ : this.byReference(getMemberReference(target), arguments);
+
+ RedirectingInitializer.byReference(this.targetReference, this.arguments) {
arguments?.parent = this;
}
+ Constructor get target => targetReference?.asConstructor;
+
+ void set target(Constructor target) {
+ targetReference = getMemberReference(target);
+ }
+
accept(InitializerVisitor v) => v.visitRedirectingInitializer(this);
visitChildren(Visitor v) {
@@ -1388,17 +1464,20 @@ class PropertyGet extends Expression {
Expression receiver;
Name name;
- _MemberAccessor _interfaceTargetReference;
+ Reference interfaceTargetReference;
+
+ PropertyGet(Expression receiver, Name name, [Member interfaceTarget])
+ : this.byReference(receiver, name, getMemberReference(interfaceTarget));
- PropertyGet(this.receiver, this.name, [Member interfaceTarget]) {
+ PropertyGet.byReference(
+ this.receiver, this.name, this.interfaceTargetReference) {
receiver?.parent = this;
- this.interfaceTarget = interfaceTarget;
}
- Member get interfaceTarget => _interfaceTargetReference?.target;
+ Member get interfaceTarget => interfaceTargetReference?.asMember;
- void set interfaceTarget(Member newTarget) {
- _interfaceTargetReference = newTarget?._getterInterface;
+ void set interfaceTarget(Member member) {
+ interfaceTargetReference = getMemberReference(member);
}
DartType getStaticType(TypeEnvironment types) {
@@ -1445,18 +1524,23 @@ class PropertySet extends Expression {
Name name;
Expression value;
- _MemberAccessor _interfaceTargetReference;
+ Reference interfaceTargetReference;
- PropertySet(this.receiver, this.name, this.value, [Member interfaceTarget]) {
+ PropertySet(Expression receiver, Name name, Expression value,
+ [Member interfaceTarget])
+ : this.byReference(
+ receiver, name, value, getMemberReference(interfaceTarget));
+
+ PropertySet.byReference(
+ this.receiver, this.name, this.value, this.interfaceTargetReference) {
receiver?.parent = this;
value?.parent = this;
- this.interfaceTarget = interfaceTarget;
}
- Member get interfaceTarget => _interfaceTargetReference?.target;
+ Member get interfaceTarget => interfaceTargetReference?.asMember;
- void set interfaceTarget(Member newTarget) {
- _interfaceTargetReference = newTarget?._setterInterface;
+ void set interfaceTarget(Member member) {
+ interfaceTargetReference = getMemberReference(member);
}
DartType getStaticType(TypeEnvironment types) => value.getStaticType(types);
@@ -1484,12 +1568,21 @@ class PropertySet extends Expression {
/// Directly read a field, call a getter, or tear off a method.
class DirectPropertyGet extends Expression {
Expression receiver;
- Member target;
+ Reference targetReference;
+
+ DirectPropertyGet(Expression receiver, Member target)
+ : this.byReference(receiver, getMemberReference(target));
- DirectPropertyGet(this.receiver, this.target) {
+ DirectPropertyGet.byReference(this.receiver, this.targetReference) {
receiver?.parent = this;
}
+ Member get target => targetReference?.asMember;
+
+ void set target(Member target) {
+ targetReference = getMemberReference(target);
+ }
+
visitChildren(Visitor v) {
receiver?.accept(v);
target?.acceptReference(v);
@@ -1518,14 +1611,24 @@ class DirectPropertyGet extends Expression {
/// Evaluates to the value of [value].
class DirectPropertySet extends Expression {
Expression receiver;
- Member target;
+ Reference targetReference;
Expression value;
- DirectPropertySet(this.receiver, this.target, this.value) {
+ DirectPropertySet(Expression receiver, Member target, Expression value)
+ : this.byReference(receiver, getMemberReference(target), value);
+
+ DirectPropertySet.byReference(
+ this.receiver, this.targetReference, this.value) {
receiver?.parent = this;
value?.parent = this;
}
+ Member get target => targetReference?.asMember;
+
+ void set target(Member target) {
+ targetReference = getMemberReference(target);
+ }
+
visitChildren(Visitor v) {
receiver?.accept(v);
target?.acceptReference(v);
@@ -1551,14 +1654,25 @@ class DirectPropertySet extends Expression {
/// Directly call an instance method, bypassing ordinary dispatch.
class DirectMethodInvocation extends InvocationExpression {
Expression receiver;
- Procedure target;
+ Reference targetReference;
Arguments arguments;
- DirectMethodInvocation(this.receiver, this.target, this.arguments) {
+ DirectMethodInvocation(
+ Expression receiver, Procedure target, Arguments arguments)
+ : this.byReference(receiver, getMemberReference(target), arguments);
+
+ DirectMethodInvocation.byReference(
+ this.receiver, this.targetReference, this.arguments) {
receiver?.parent = this;
arguments?.parent = this;
}
+ Procedure get target => targetReference?.asProcedure;
+
+ void set target(Procedure target) {
+ targetReference = getMemberReference(target);
+ }
+
Name get name => target?.name;
visitChildren(Visitor v) {
@@ -1601,16 +1715,17 @@ class DirectMethodInvocation extends InvocationExpression {
/// This may invoke a getter, read a field, or tear off a method.
class SuperPropertyGet extends Expression {
Name name;
- _MemberAccessor _interfaceTargetReference;
+ Reference interfaceTargetReference;
- SuperPropertyGet(this.name, [Member interfaceTarget]) {
- _interfaceTargetReference = interfaceTarget?._getterInterface;
- }
+ SuperPropertyGet(Name name, [Member interfaceTarget])
+ : this.byReference(name, getMemberReference(interfaceTarget));
- Member get interfaceTarget => _interfaceTargetReference?.target;
+ SuperPropertyGet.byReference(this.name, this.interfaceTargetReference);
- void set interfaceTarget(Member newTarget) {
- _interfaceTargetReference = newTarget?._getterInterface;
+ Member get interfaceTarget => interfaceTargetReference?.asMember;
+
+ void set interfaceTarget(Member member) {
+ interfaceTargetReference = getMemberReference(member);
}
DartType getStaticType(TypeEnvironment types) {
@@ -1642,17 +1757,20 @@ class SuperPropertyGet extends Expression {
class SuperPropertySet extends Expression {
Name name;
Expression value;
- _MemberAccessor _interfaceTargetReference;
+ Reference interfaceTargetReference;
+
+ SuperPropertySet(Name name, Expression value, Member interfaceTarget)
+ : this.byReference(name, value, getMemberReference(interfaceTarget));
- SuperPropertySet(this.name, this.value, [Member interfaceTarget]) {
+ SuperPropertySet.byReference(
+ this.name, this.value, this.interfaceTargetReference) {
value?.parent = this;
- _interfaceTargetReference = interfaceTarget?._setterInterface;
}
- Member get interfaceTarget => _interfaceTargetReference?.target;
+ Member get interfaceTarget => interfaceTargetReference?.asMember;
- void set interfaceTarget(Member newTarget) {
- _interfaceTargetReference = newTarget?._setterInterface;
+ void set interfaceTarget(Member member) {
+ interfaceTargetReference = getMemberReference(member);
}
DartType getStaticType(TypeEnvironment types) => value.getStaticType(types);
@@ -1675,9 +1793,17 @@ class SuperPropertySet extends Expression {
/// Read a static field, call a static getter, or tear off a static method.
class StaticGet extends Expression {
/// A static field, getter, or method (for tear-off).
- Member target;
+ Reference targetReference;
- StaticGet(this.target);
+ StaticGet(Member target) : this.byReference(getMemberReference(target));
+
+ StaticGet.byReference(this.targetReference);
+
+ Member get target => targetReference?.asMember;
+
+ void set target(Member target) {
+ targetReference = getMemberReference(target);
+ }
DartType getStaticType(TypeEnvironment types) => target.getterType;
@@ -1695,13 +1821,22 @@ class StaticGet extends Expression {
/// Evaluates to the value of [value].
class StaticSet extends Expression {
/// A mutable static field or a static setter.
- Member target;
+ Reference targetReference;
Expression value;
- StaticSet(this.target, this.value) {
+ StaticSet(Member target, Expression value)
+ : this.byReference(getMemberReference(target), value);
+
+ StaticSet.byReference(this.targetReference, this.value) {
value?.parent = this;
}
+ Member get target => targetReference?.asMember;
+
+ void set target(Member target) {
+ targetReference = getMemberReference(target);
+ }
+
DartType getStaticType(TypeEnvironment types) => value.getStaticType(types);
accept(ExpressionVisitor v) => v.visitStaticSet(this);
@@ -1795,14 +1930,25 @@ class MethodInvocation extends InvocationExpression {
Name name;
Arguments arguments;
- Procedure interfaceTarget;
+ Reference interfaceTargetReference;
- MethodInvocation(this.receiver, this.name, this.arguments,
- [this.interfaceTarget]) {
+ MethodInvocation(Expression receiver, Name name, Arguments arguments,
+ [Procedure interfaceTarget])
+ : this.byReference(
+ receiver, name, arguments, getMemberReference(interfaceTarget));
+
+ MethodInvocation.byReference(
+ this.receiver, this.name, this.arguments, this.interfaceTargetReference) {
receiver?.parent = this;
arguments?.parent = this;
}
+ Procedure get interfaceTarget => interfaceTargetReference?.asProcedure;
+
+ void set interfaceTarget(Member target) {
+ interfaceTargetReference = getMemberReference(target);
+ }
+
DartType getStaticType(TypeEnvironment types) {
if (interfaceTarget != null) {
if (types.isOverloadedArithmeticOperator(interfaceTarget)) {
@@ -1864,12 +2010,23 @@ class SuperMethodInvocation extends InvocationExpression {
Name name;
Arguments arguments;
- Procedure interfaceTarget;
+ Reference interfaceTargetReference;
+
+ SuperMethodInvocation(Name name, Arguments arguments,
+ [Procedure interfaceTarget])
+ : this.byReference(name, arguments, getMemberReference(interfaceTarget));
- SuperMethodInvocation(this.name, this.arguments, this.interfaceTarget) {
+ SuperMethodInvocation.byReference(
+ this.name, this.arguments, this.interfaceTargetReference) {
arguments?.parent = this;
}
+ Procedure get interfaceTarget => interfaceTargetReference?.asProcedure;
+
+ void set interfaceTarget(Procedure target) {
+ interfaceTargetReference = getMemberReference(target);
+ }
+
DartType getStaticType(TypeEnvironment types) {
if (interfaceTarget == null) return const DynamicType();
Class superclass = interfaceTarget.enclosingClass;
@@ -1903,7 +2060,7 @@ class SuperMethodInvocation extends InvocationExpression {
///
/// The provided arguments might not match the parameters of the target.
class StaticInvocation extends InvocationExpression {
- Procedure target;
+ Reference targetReference;
Arguments arguments;
/// True if this is a constant call to an external constant factory.
@@ -1911,10 +2068,21 @@ class StaticInvocation extends InvocationExpression {
Name get name => target?.name;
- StaticInvocation(this.target, this.arguments, {this.isConst: false}) {
+ StaticInvocation(Procedure target, Arguments arguments, {bool isConst: false})
+ : this.byReference(getMemberReference(target), arguments,
+ isConst: isConst);
+
+ StaticInvocation.byReference(this.targetReference, this.arguments,
+ {this.isConst: false}) {
arguments?.parent = this;
}
+ Procedure get target => targetReference?.asProcedure;
+
+ void set target(Procedure target) {
+ targetReference = getMemberReference(target);
+ }
+
DartType getStaticType(TypeEnvironment types) {
return Substitution
.fromPairs(target.function.typeParameters, arguments.types)
@@ -1944,16 +2112,28 @@ class StaticInvocation extends InvocationExpression {
// `classTypeArguments`? They are quite different from type arguments to
// generic functions.
class ConstructorInvocation extends InvocationExpression {
- Constructor target;
+ Reference targetReference;
Arguments arguments;
bool isConst;
Name get name => target?.name;
- ConstructorInvocation(this.target, this.arguments, {this.isConst: false}) {
+ ConstructorInvocation(Constructor target, Arguments arguments,
+ {bool isConst: false})
+ : this.byReference(getMemberReference(target), arguments,
+ isConst: isConst);
+
+ ConstructorInvocation.byReference(this.targetReference, this.arguments,
+ {this.isConst: false}) {
arguments?.parent = this;
}
+ Constructor get target => targetReference?.asConstructor;
+
+ void set target(Constructor target) {
+ targetReference = getMemberReference(target);
+ }
+
DartType getStaticType(TypeEnvironment types) {
return arguments.types.isEmpty
? target.enclosingClass.rawType
@@ -3200,17 +3380,21 @@ class FunctionDeclaration extends Statement {
abstract class Name implements Node {
final int hashCode;
final String name;
+ Reference get libraryName;
Library get library;
bool get isPrivate;
Name._internal(this.hashCode, this.name);
- factory Name(String name, [Library library]) {
+ factory Name(String name, [Library library]) =>
+ new Name.byReference(name, library?.reference);
+
+ factory Name.byReference(String name, Reference libraryName) {
/// Use separate subclasses for the public and private case to save memory
/// for public names.
if (name.startsWith('_')) {
- assert(library != null);
- return new _PrivateName(name, library);
+ assert(libraryName != null);
+ return new _PrivateName(name, libraryName);
} else {
return new _PublicName(name);
}
@@ -3228,21 +3412,24 @@ abstract class Name implements Node {
}
class _PrivateName extends Name {
- final Library library;
+ final Reference libraryName;
bool get isPrivate => true;
- _PrivateName(String name, Library library)
- : this.library = library,
- super._internal(_computeHashCode(name, library), name);
+ _PrivateName(String name, Reference libraryName)
+ : this.libraryName = libraryName,
+ super._internal(_computeHashCode(name, libraryName), name);
String toString() => library != null ? '$library::$name' : name;
- static int _computeHashCode(String name, Library library) {
- return 131 * name.hashCode + 17 * library.hashCode;
+ Library get library => libraryName.asLibrary;
+
+ static int _computeHashCode(String name, Reference libraryName) {
+ return 131 * name.hashCode + 17 * libraryName.hashCode;
}
}
class _PublicName extends Name {
+ Reference get libraryName => null;
Library get library => null;
bool get isPrivate => false;
@@ -3322,14 +3509,18 @@ class BottomType extends DartType {
}
class InterfaceType extends DartType {
- final Class classNode;
+ final Reference className;
final List<DartType> typeArguments;
/// The [typeArguments] list must not be modified after this call. If the
/// list is omitted, 'dynamic' type arguments are filled in.
InterfaceType(Class classNode, [List<DartType> typeArguments])
- : this.classNode = classNode,
- this.typeArguments = typeArguments ?? _defaultTypeArguments(classNode);
+ : this.byReference(getClassReference(classNode),
+ typeArguments ?? _defaultTypeArguments(classNode));
+
+ InterfaceType.byReference(this.className, this.typeArguments);
+
+ Class get classNode => className.asClass;
static List<DartType> _defaultTypeArguments(Class classNode) {
if (classNode.typeParameters.length == 0) {
@@ -3351,7 +3542,7 @@ class InterfaceType extends DartType {
bool operator ==(Object other) {
if (identical(this, other)) return true;
if (other is InterfaceType) {
- if (classNode != other.classNode) return false;
+ if (className != other.className) return false;
if (typeArguments.length != other.typeArguments.length) return false;
for (int i = 0; i < typeArguments.length; ++i) {
if (typeArguments[i] != other.typeArguments[i]) return false;
@@ -3363,7 +3554,7 @@ class InterfaceType extends DartType {
}
int get hashCode {
- int hash = 0x3fffffff & classNode.hashCode;
+ int hash = 0x3fffffff & className.hashCode;
for (int i = 0; i < typeArguments.length; ++i) {
hash = 0x3fffffff & (hash * 31 + (hash ^ typeArguments[i].hashCode));
}
@@ -3551,10 +3742,15 @@ class TypeParameter extends TreeNode {
}
class Supertype extends Node {
- final Class classNode;
+ final Reference className;
final List<DartType> typeArguments;
- Supertype(this.classNode, this.typeArguments);
+ Supertype(Class classNode, List<DartType> typeArguments)
+ : this.byReference(getClassReference(classNode), typeArguments);
+
+ Supertype.byReference(this.className, this.typeArguments);
+
+ Class get classNode => className.asClass;
accept(Visitor v) => v.visitSupertype(this);
@@ -3570,7 +3766,7 @@ class Supertype extends Node {
bool operator ==(Object other) {
if (identical(this, other)) return true;
if (other is Supertype) {
- if (classNode != other.classNode) return false;
+ if (className != other.className) return false;
if (typeArguments.length != other.typeArguments.length) return false;
for (int i = 0; i < typeArguments.length; ++i) {
if (typeArguments[i] != other.typeArguments[i]) return false;
@@ -3582,7 +3778,7 @@ class Supertype extends Node {
}
int get hashCode {
- int hash = 0x3fffffff & classNode.hashCode;
+ int hash = 0x3fffffff & className.hashCode;
for (int i = 0; i < typeArguments.length; ++i) {
hash = 0x3fffffff & (hash * 31 + (hash ^ typeArguments[i].hashCode));
}
@@ -3596,6 +3792,8 @@ class Supertype extends Node {
/// A way to bundle up all the libraries in a program.
class Program extends TreeNode {
+ final CanonicalName root = new CanonicalName.root();
+
final List<Library> libraries;
/// Map from a source file uri to a line-starts table and source code.
@@ -3604,12 +3802,29 @@ class Program extends TreeNode {
final Map<String, Source> uriToSource;
/// Reference to the main method in one of the libraries.
- Procedure mainMethod;
+ Reference mainMethodName;
Program([List<Library> libraries, Map<String, Source> uriToSource])
: libraries = libraries ?? <Library>[],
uriToSource = uriToSource ?? <String, Source>{} {
- setParents(libraries, this);
+ setParents(this.libraries, this);
+ }
+
+ void computeCanonicalNames() {
+ for (var library in libraries) {
+ root.getChildFromUri(library.importUri).bindTo(library.reference);
+ library.computeCanonicalNames();
+ }
+ }
+
+ void unbindCanonicalNames() {
+ root.unbindAll();
+ }
+
+ Procedure get mainMethod => mainMethodName?.asProcedure;
+
+ void set mainMethod(Procedure main) {
+ mainMethodName = getMemberReference(main);
}
accept(TreeVisitor v) => v.visitProgram(this);
@@ -3752,3 +3967,53 @@ class Source {
Source(this.lineStarts, this.source);
}
+
+/// Returns the [Reference] object for the given member.
+///
+/// Returns `null` if the member is `null`.
+Reference getMemberReference(Member member) {
+ return member?.reference;
+}
+
+/// Returns the [Reference] object for the given class.
+///
+/// Returns `null` if the class is `null`.
+Reference getClassReference(Class class_) {
+ return class_?.reference;
+}
+
+/// Returns the canonical name of [member], or throws an exception if the
+/// member has not been assigned a canonical name yet.
+///
+/// Returns `null` if the member is `null`.
+CanonicalName getCanonicalNameOfMember(Member member) {
+ if (member == null) return null;
+ if (member.canonicalName == null) {
+ throw '$member has no canonical name';
+ }
+ return member.canonicalName;
+}
+
+/// Returns the canonical name of [class_], or throws an exception if the
+/// class has not been assigned a canonical name yet.
+///
+/// Returns `null` if the class is `null`.
+CanonicalName getCanonicalNameOfClass(Class class_) {
+ if (class_ == null) return null;
+ if (class_.canonicalName == null) {
+ throw '$class_ has no canonical name';
+ }
+ return class_.canonicalName;
+}
+
+/// Returns the canonical name of [library], or throws an exception if the
+/// library has not been assigned a canonical name yet.
+///
+/// Returns `null` if the library is `null`.
+CanonicalName getCanonicalNameOfLibrary(Library library) {
+ if (library == null) return null;
+ if (library.canonicalName == null) {
+ throw '$library has no canonical name';
+ }
+ return library.canonicalName;
+}
« no previous file with comments | « pkg/kernel/lib/analyzer/loader.dart ('k') | pkg/kernel/lib/binary/ast_from_binary.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698