Chromium Code Reviews| Index: lib/ast.dart |
| diff --git a/lib/ast.dart b/lib/ast.dart |
| index b8f08976ecb666e2f0f822969922e2133ff45f14..69eb1be823d984682982f037126d09ea127ec130 100644 |
| --- a/lib/ast.dart |
| +++ b/lib/ast.dart |
| @@ -944,7 +944,13 @@ class Procedure extends Member { |
| _MemberAccessor get _setterInterface => _reference; |
| } |
| -enum ProcedureKind { Method, Getter, Setter, Operator, Factory, } |
| +enum ProcedureKind { |
| + Method, |
| + Getter, |
| + Setter, |
| + Operator, |
| + Factory, |
| +} |
| // ------------------------------------------------------------------------ |
| // CONSTRUCTOR INITIALIZERS |
| @@ -1100,7 +1106,7 @@ class FunctionNode extends TreeNode { |
| List<TypeParameter> typeParameters; |
| int requiredParameterCount; |
| List<VariableDeclaration> positionalParameters; |
| - List<VariableDeclaration> namedParameters; |
| + List<VariableDeclaration> namedParameters; // Must be sorted. |
| InferredValue inferredReturnValue; // May be null. |
| DartType returnType; // Not null. |
| Statement body; |
| @@ -1128,6 +1134,10 @@ class FunctionNode extends TreeNode { |
| static DartType _getTypeOfVariable(VariableDeclaration node) => node.type; |
| + static NamedType _getNamedTypeOfVariable(VariableDeclaration node) { |
| + return new NamedType(node.name, node.type); |
| + } |
| + |
| FunctionType get functionType { |
| Map<String, DartType> named = const <String, DartType>{}; |
| if (namedParameters.isNotEmpty) { |
| @@ -1139,7 +1149,7 @@ class FunctionNode extends TreeNode { |
| TreeNode parent = this.parent; |
| return new FunctionType( |
| positionalParameters.map(_getTypeOfVariable).toList(), returnType, |
| - namedParameters: named, |
| + namedParameters: namedParameters.map(_getNamedTypeOfVariable).toList(), |
| typeParameters: parent is Constructor |
| ? parent.enclosingClass.typeParameters |
| : typeParameters, |
| @@ -1981,8 +1991,8 @@ class ConditionalExpression extends Expression { |
| /// The static type of the expression. Should not be `null`. |
| DartType staticType; |
| - ConditionalExpression(this.condition, this.then, this.otherwise, |
| - this.staticType) { |
| + ConditionalExpression( |
| + this.condition, this.then, this.otherwise, this.staticType) { |
| condition?.parent = this; |
| then?.parent = this; |
| otherwise?.parent = this; |
| @@ -2963,7 +2973,8 @@ class YieldStatement extends Statement { |
| /// When this occurs as a statement, it must be a direct child of a [Block]. |
| // |
| // DESIGN TODO: Should we remove the 'final' modifier from variables? |
| -class VariableDeclaration extends Statement { |
| +class VariableDeclaration extends Statement |
| + implements Comparable<VariableDeclaration> { |
| /// For named parameters, this is the name of the parameter. No two named |
| /// parameters (in the same parameter list) can have the same name. |
| /// |
| @@ -3036,6 +3047,10 @@ class VariableDeclaration extends Statement { |
| /// Returns a possibly synthesized name for this variable, consistent with |
| /// the names used across all [toString] calls. |
| String toString() => debugVariableDeclarationName(this); |
| + |
| + int compareTo(VariableDeclaration other) { |
| + return name.compareTo(other.name); |
| + } |
| } |
| /// Declaration a local function. |
| @@ -3262,12 +3277,12 @@ class FunctionType extends DartType { |
| final List<TypeParameter> typeParameters; |
| final int requiredParameterCount; |
| final List<DartType> positionalParameters; |
| - final Map<String, DartType> namedParameters; |
| + final List<NamedType> namedParameters; // Must be sorted. |
| final DartType returnType; |
| int _hashCode; |
| FunctionType(List<DartType> positionalParameters, this.returnType, |
| - {this.namedParameters: const <String, DartType>{}, |
| + {this.namedParameters: const <NamedType>[], |
| this.typeParameters: const <TypeParameter>[], |
| int requiredParameterCount}) |
| : this.positionalParameters = positionalParameters, |
| @@ -3279,7 +3294,7 @@ class FunctionType extends DartType { |
| visitChildren(Visitor v) { |
| visitList(typeParameters, v); |
| visitList(positionalParameters, v); |
| - visitIterable(namedParameters.values, v); |
| + visitList(namedParameters, v); |
| returnType.accept(v); |
| } |
| @@ -3298,10 +3313,8 @@ class FunctionType extends DartType { |
| return false; |
| } |
| } |
| - for (var name in namedParameters.keys) { |
| - // If the other function type declared differently named parameters, |
| - // one side of this equality will be null and we're good. |
| - if (namedParameters[name] != other.namedParameters[name]) { |
| + for (int i = 0; i < namedParameters.length; ++i) { |
| + if (namedParameters[i] != other.namedParameters[i]) { |
| return false; |
| } |
| } |
| @@ -3342,13 +3355,9 @@ class FunctionType extends DartType { |
| for (int i = 0; i < positionalParameters.length; ++i) { |
| hash = 0x3fffffff & (hash * 31 + positionalParameters[i].hashCode); |
| } |
| - // TODO: Using a sorted list of names would be better than a map here. |
| - namedParameters.forEach((String name, DartType type) { |
| - // Note that we use only addition and truncation here, so that we do not |
| - // rely on the iteration of the of the map. |
| - hash = 0x3fffffff & (hash + name.hashCode); |
| - hash = 0x3fffffff & (hash + type.hashCode); |
| - }); |
| + for (int i = 0; i < namedParameters.length; ++i) { |
| + hash = 0x3fffffff & (hash * 31 + namedParameters[i].hashCode); |
| + } |
| hash = 0x3fffffff & (hash * 31 + returnType.hashCode); |
| for (int i = 0; i < typeParameters.length; ++i) { |
| // Remove the type parameters from the scope again. |
| @@ -3358,6 +3367,30 @@ class FunctionType extends DartType { |
| } |
| } |
| +/// A named parameter in [FunctionType]. |
| +class NamedType extends Node implements Comparable<NamedType> { |
| + final String name; |
| + final DartType type; |
| + |
| + NamedType(this.name, this.type); |
| + |
| + bool operator ==(Object other) { |
| + return other is NamedType && name == other.name && type == other.type; |
| + } |
| + |
| + int get hashCode { |
| + return name.hashCode * 31 + type.hashCode * 37; |
|
ahe
2016/11/16 13:21:03
Compute this in constructor?
asgerf
2016/11/16 13:38:20
The FunctionType caches its hash code, so there is
ahe
2016/11/16 13:41:56
Good point.
|
| + } |
| + |
| + int compareTo(NamedType other) => name.compareTo(other.name); |
| + |
| + accept(Visitor v) => v.visitNamedType(this); |
| + |
| + void visitChildren(Visitor v) { |
| + type.accept(v); |
| + } |
| +} |
| + |
| /// Stores the hash code of function type parameters while computing the hash |
| /// code of a [FunctionType] object. |
| /// |