OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 /// ----------------------------------------------------------------------- | 5 /// ----------------------------------------------------------------------- |
6 /// ERROR HANDLING | 6 /// ERROR HANDLING |
7 /// ----------------------------------------------------------------------- | 7 /// ----------------------------------------------------------------------- |
8 /// | 8 /// |
9 /// As a rule of thumb, errors that can be detected statically are handled by | 9 /// As a rule of thumb, errors that can be detected statically are handled by |
10 /// the frontend, typically by translating the erroneous code into a 'throw' or | 10 /// the frontend, typically by translating the erroneous code into a 'throw' or |
(...skipping 926 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
937 DartType get setterType { | 937 DartType get setterType { |
938 return isSetter | 938 return isSetter |
939 ? function.positionalParameters[0].type | 939 ? function.positionalParameters[0].type |
940 : const BottomType(); | 940 : const BottomType(); |
941 } | 941 } |
942 | 942 |
943 _MemberAccessor get _getterInterface => _reference; | 943 _MemberAccessor get _getterInterface => _reference; |
944 _MemberAccessor get _setterInterface => _reference; | 944 _MemberAccessor get _setterInterface => _reference; |
945 } | 945 } |
946 | 946 |
947 enum ProcedureKind { Method, Getter, Setter, Operator, Factory, } | 947 enum ProcedureKind { |
| 948 Method, |
| 949 Getter, |
| 950 Setter, |
| 951 Operator, |
| 952 Factory, |
| 953 } |
948 | 954 |
949 // ------------------------------------------------------------------------ | 955 // ------------------------------------------------------------------------ |
950 // CONSTRUCTOR INITIALIZERS | 956 // CONSTRUCTOR INITIALIZERS |
951 // ------------------------------------------------------------------------ | 957 // ------------------------------------------------------------------------ |
952 | 958 |
953 /// Part of an initializer list in a constructor. | 959 /// Part of an initializer list in a constructor. |
954 abstract class Initializer extends TreeNode { | 960 abstract class Initializer extends TreeNode { |
955 accept(InitializerVisitor v); | 961 accept(InitializerVisitor v); |
956 } | 962 } |
957 | 963 |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1093 | 1099 |
1094 /// A function declares parameters and has a body. | 1100 /// A function declares parameters and has a body. |
1095 /// | 1101 /// |
1096 /// This may occur in a procedure, constructor, function expression, or local | 1102 /// This may occur in a procedure, constructor, function expression, or local |
1097 /// function declaration. | 1103 /// function declaration. |
1098 class FunctionNode extends TreeNode { | 1104 class FunctionNode extends TreeNode { |
1099 AsyncMarker asyncMarker; | 1105 AsyncMarker asyncMarker; |
1100 List<TypeParameter> typeParameters; | 1106 List<TypeParameter> typeParameters; |
1101 int requiredParameterCount; | 1107 int requiredParameterCount; |
1102 List<VariableDeclaration> positionalParameters; | 1108 List<VariableDeclaration> positionalParameters; |
1103 List<VariableDeclaration> namedParameters; | 1109 List<VariableDeclaration> namedParameters; // Must be sorted. |
1104 InferredValue inferredReturnValue; // May be null. | 1110 InferredValue inferredReturnValue; // May be null. |
1105 DartType returnType; // Not null. | 1111 DartType returnType; // Not null. |
1106 Statement body; | 1112 Statement body; |
1107 | 1113 |
1108 FunctionNode(this.body, | 1114 FunctionNode(this.body, |
1109 {List<TypeParameter> typeParameters, | 1115 {List<TypeParameter> typeParameters, |
1110 List<VariableDeclaration> positionalParameters, | 1116 List<VariableDeclaration> positionalParameters, |
1111 List<VariableDeclaration> namedParameters, | 1117 List<VariableDeclaration> namedParameters, |
1112 int requiredParameterCount, | 1118 int requiredParameterCount, |
1113 this.returnType: const DynamicType(), | 1119 this.returnType: const DynamicType(), |
1114 this.inferredReturnValue, | 1120 this.inferredReturnValue, |
1115 this.asyncMarker: AsyncMarker.Sync}) | 1121 this.asyncMarker: AsyncMarker.Sync}) |
1116 : this.positionalParameters = | 1122 : this.positionalParameters = |
1117 positionalParameters ?? <VariableDeclaration>[], | 1123 positionalParameters ?? <VariableDeclaration>[], |
1118 this.requiredParameterCount = | 1124 this.requiredParameterCount = |
1119 requiredParameterCount ?? positionalParameters?.length ?? 0, | 1125 requiredParameterCount ?? positionalParameters?.length ?? 0, |
1120 this.namedParameters = namedParameters ?? <VariableDeclaration>[], | 1126 this.namedParameters = namedParameters ?? <VariableDeclaration>[], |
1121 this.typeParameters = typeParameters ?? <TypeParameter>[] { | 1127 this.typeParameters = typeParameters ?? <TypeParameter>[] { |
1122 assert(returnType != null); | 1128 assert(returnType != null); |
1123 setParents(this.typeParameters, this); | 1129 setParents(this.typeParameters, this); |
1124 setParents(this.positionalParameters, this); | 1130 setParents(this.positionalParameters, this); |
1125 setParents(this.namedParameters, this); | 1131 setParents(this.namedParameters, this); |
1126 body?.parent = this; | 1132 body?.parent = this; |
1127 } | 1133 } |
1128 | 1134 |
1129 static DartType _getTypeOfVariable(VariableDeclaration node) => node.type; | 1135 static DartType _getTypeOfVariable(VariableDeclaration node) => node.type; |
1130 | 1136 |
| 1137 static NamedType _getNamedTypeOfVariable(VariableDeclaration node) { |
| 1138 return new NamedType(node.name, node.type); |
| 1139 } |
| 1140 |
1131 FunctionType get functionType { | 1141 FunctionType get functionType { |
1132 Map<String, DartType> named = const <String, DartType>{}; | 1142 Map<String, DartType> named = const <String, DartType>{}; |
1133 if (namedParameters.isNotEmpty) { | 1143 if (namedParameters.isNotEmpty) { |
1134 named = <String, DartType>{}; | 1144 named = <String, DartType>{}; |
1135 for (var node in namedParameters) { | 1145 for (var node in namedParameters) { |
1136 named[node.name] = node.type; | 1146 named[node.name] = node.type; |
1137 } | 1147 } |
1138 } | 1148 } |
1139 TreeNode parent = this.parent; | 1149 TreeNode parent = this.parent; |
1140 return new FunctionType( | 1150 return new FunctionType( |
1141 positionalParameters.map(_getTypeOfVariable).toList(), returnType, | 1151 positionalParameters.map(_getTypeOfVariable).toList(), returnType, |
1142 namedParameters: named, | 1152 namedParameters: namedParameters.map(_getNamedTypeOfVariable).toList(), |
1143 typeParameters: parent is Constructor | 1153 typeParameters: parent is Constructor |
1144 ? parent.enclosingClass.typeParameters | 1154 ? parent.enclosingClass.typeParameters |
1145 : typeParameters, | 1155 : typeParameters, |
1146 requiredParameterCount: requiredParameterCount); | 1156 requiredParameterCount: requiredParameterCount); |
1147 } | 1157 } |
1148 | 1158 |
1149 accept(TreeVisitor v) => v.visitFunctionNode(this); | 1159 accept(TreeVisitor v) => v.visitFunctionNode(this); |
1150 | 1160 |
1151 visitChildren(Visitor v) { | 1161 visitChildren(Visitor v) { |
1152 visitList(typeParameters, v); | 1162 visitList(typeParameters, v); |
(...skipping 821 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1974 | 1984 |
1975 /// Expression of form `x ? y : z`. | 1985 /// Expression of form `x ? y : z`. |
1976 class ConditionalExpression extends Expression { | 1986 class ConditionalExpression extends Expression { |
1977 Expression condition; | 1987 Expression condition; |
1978 Expression then; | 1988 Expression then; |
1979 Expression otherwise; | 1989 Expression otherwise; |
1980 | 1990 |
1981 /// The static type of the expression. Should not be `null`. | 1991 /// The static type of the expression. Should not be `null`. |
1982 DartType staticType; | 1992 DartType staticType; |
1983 | 1993 |
1984 ConditionalExpression(this.condition, this.then, this.otherwise, | 1994 ConditionalExpression( |
1985 this.staticType) { | 1995 this.condition, this.then, this.otherwise, this.staticType) { |
1986 condition?.parent = this; | 1996 condition?.parent = this; |
1987 then?.parent = this; | 1997 then?.parent = this; |
1988 otherwise?.parent = this; | 1998 otherwise?.parent = this; |
1989 } | 1999 } |
1990 | 2000 |
1991 DartType getStaticType(TypeEnvironment types) => staticType; | 2001 DartType getStaticType(TypeEnvironment types) => staticType; |
1992 | 2002 |
1993 accept(ExpressionVisitor v) => v.visitConditionalExpression(this); | 2003 accept(ExpressionVisitor v) => v.visitConditionalExpression(this); |
1994 | 2004 |
1995 visitChildren(Visitor v) { | 2005 visitChildren(Visitor v) { |
(...skipping 960 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2956 } | 2966 } |
2957 | 2967 |
2958 /// Declaration of a local variable. | 2968 /// Declaration of a local variable. |
2959 /// | 2969 /// |
2960 /// This may occur as a statement, but is also used in several non-statement | 2970 /// This may occur as a statement, but is also used in several non-statement |
2961 /// contexts, such as in [ForStatement], [Catch], and [FunctionNode]. | 2971 /// contexts, such as in [ForStatement], [Catch], and [FunctionNode]. |
2962 /// | 2972 /// |
2963 /// When this occurs as a statement, it must be a direct child of a [Block]. | 2973 /// When this occurs as a statement, it must be a direct child of a [Block]. |
2964 // | 2974 // |
2965 // DESIGN TODO: Should we remove the 'final' modifier from variables? | 2975 // DESIGN TODO: Should we remove the 'final' modifier from variables? |
2966 class VariableDeclaration extends Statement { | 2976 class VariableDeclaration extends Statement |
| 2977 implements Comparable<VariableDeclaration> { |
2967 /// For named parameters, this is the name of the parameter. No two named | 2978 /// For named parameters, this is the name of the parameter. No two named |
2968 /// parameters (in the same parameter list) can have the same name. | 2979 /// parameters (in the same parameter list) can have the same name. |
2969 /// | 2980 /// |
2970 /// In all other cases, the name is cosmetic, may be empty or null, | 2981 /// In all other cases, the name is cosmetic, may be empty or null, |
2971 /// and is not necessarily unique. | 2982 /// and is not necessarily unique. |
2972 String name; | 2983 String name; |
2973 int flags = 0; | 2984 int flags = 0; |
2974 DartType type; // Not null, defaults to dynamic. | 2985 DartType type; // Not null, defaults to dynamic. |
2975 InferredValue inferredValue; // May be null. | 2986 InferredValue inferredValue; // May be null. |
2976 | 2987 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3029 type = v.visitDartType(type); | 3040 type = v.visitDartType(type); |
3030 if (initializer != null) { | 3041 if (initializer != null) { |
3031 initializer = initializer.accept(v); | 3042 initializer = initializer.accept(v); |
3032 initializer?.parent = this; | 3043 initializer?.parent = this; |
3033 } | 3044 } |
3034 } | 3045 } |
3035 | 3046 |
3036 /// Returns a possibly synthesized name for this variable, consistent with | 3047 /// Returns a possibly synthesized name for this variable, consistent with |
3037 /// the names used across all [toString] calls. | 3048 /// the names used across all [toString] calls. |
3038 String toString() => debugVariableDeclarationName(this); | 3049 String toString() => debugVariableDeclarationName(this); |
| 3050 |
| 3051 int compareTo(VariableDeclaration other) { |
| 3052 return name.compareTo(other.name); |
| 3053 } |
3039 } | 3054 } |
3040 | 3055 |
3041 /// Declaration a local function. | 3056 /// Declaration a local function. |
3042 /// | 3057 /// |
3043 /// The body of the function may use [variable] as its self-reference. | 3058 /// The body of the function may use [variable] as its self-reference. |
3044 class FunctionDeclaration extends Statement { | 3059 class FunctionDeclaration extends Statement { |
3045 VariableDeclaration variable; // Is final and has no initializer. | 3060 VariableDeclaration variable; // Is final and has no initializer. |
3046 FunctionNode function; | 3061 FunctionNode function; |
3047 | 3062 |
3048 FunctionDeclaration(this.variable, this.function) { | 3063 FunctionDeclaration(this.variable, this.function) { |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3255 } | 3270 } |
3256 return hash; | 3271 return hash; |
3257 } | 3272 } |
3258 } | 3273 } |
3259 | 3274 |
3260 /// A possibly generic function type. | 3275 /// A possibly generic function type. |
3261 class FunctionType extends DartType { | 3276 class FunctionType extends DartType { |
3262 final List<TypeParameter> typeParameters; | 3277 final List<TypeParameter> typeParameters; |
3263 final int requiredParameterCount; | 3278 final int requiredParameterCount; |
3264 final List<DartType> positionalParameters; | 3279 final List<DartType> positionalParameters; |
3265 final Map<String, DartType> namedParameters; | 3280 final List<NamedType> namedParameters; // Must be sorted. |
3266 final DartType returnType; | 3281 final DartType returnType; |
3267 int _hashCode; | 3282 int _hashCode; |
3268 | 3283 |
3269 FunctionType(List<DartType> positionalParameters, this.returnType, | 3284 FunctionType(List<DartType> positionalParameters, this.returnType, |
3270 {this.namedParameters: const <String, DartType>{}, | 3285 {this.namedParameters: const <NamedType>[], |
3271 this.typeParameters: const <TypeParameter>[], | 3286 this.typeParameters: const <TypeParameter>[], |
3272 int requiredParameterCount}) | 3287 int requiredParameterCount}) |
3273 : this.positionalParameters = positionalParameters, | 3288 : this.positionalParameters = positionalParameters, |
3274 this.requiredParameterCount = | 3289 this.requiredParameterCount = |
3275 requiredParameterCount ?? positionalParameters.length; | 3290 requiredParameterCount ?? positionalParameters.length; |
3276 | 3291 |
3277 accept(DartTypeVisitor v) => v.visitFunctionType(this); | 3292 accept(DartTypeVisitor v) => v.visitFunctionType(this); |
3278 | 3293 |
3279 visitChildren(Visitor v) { | 3294 visitChildren(Visitor v) { |
3280 visitList(typeParameters, v); | 3295 visitList(typeParameters, v); |
3281 visitList(positionalParameters, v); | 3296 visitList(positionalParameters, v); |
3282 visitIterable(namedParameters.values, v); | 3297 visitList(namedParameters, v); |
3283 returnType.accept(v); | 3298 returnType.accept(v); |
3284 } | 3299 } |
3285 | 3300 |
3286 bool operator ==(Object other) { | 3301 bool operator ==(Object other) { |
3287 if (identical(this, other)) return true; | 3302 if (identical(this, other)) return true; |
3288 if (other is FunctionType) { | 3303 if (other is FunctionType) { |
3289 if (typeParameters.length != other.typeParameters.length || | 3304 if (typeParameters.length != other.typeParameters.length || |
3290 requiredParameterCount != other.requiredParameterCount || | 3305 requiredParameterCount != other.requiredParameterCount || |
3291 positionalParameters.length != other.positionalParameters.length || | 3306 positionalParameters.length != other.positionalParameters.length || |
3292 namedParameters.length != other.namedParameters.length) { | 3307 namedParameters.length != other.namedParameters.length) { |
3293 return false; | 3308 return false; |
3294 } | 3309 } |
3295 if (typeParameters.isEmpty) { | 3310 if (typeParameters.isEmpty) { |
3296 for (int i = 0; i < positionalParameters.length; ++i) { | 3311 for (int i = 0; i < positionalParameters.length; ++i) { |
3297 if (positionalParameters[i] != other.positionalParameters[i]) { | 3312 if (positionalParameters[i] != other.positionalParameters[i]) { |
3298 return false; | 3313 return false; |
3299 } | 3314 } |
3300 } | 3315 } |
3301 for (var name in namedParameters.keys) { | 3316 for (int i = 0; i < namedParameters.length; ++i) { |
3302 // If the other function type declared differently named parameters, | 3317 if (namedParameters[i] != other.namedParameters[i]) { |
3303 // one side of this equality will be null and we're good. | |
3304 if (namedParameters[name] != other.namedParameters[name]) { | |
3305 return false; | 3318 return false; |
3306 } | 3319 } |
3307 } | 3320 } |
3308 return returnType == other.returnType; | 3321 return returnType == other.returnType; |
3309 } else { | 3322 } else { |
3310 // Structural equality does not tell us if two generic function types | 3323 // Structural equality does not tell us if two generic function types |
3311 // are the same type. If they are unifiable without substituting any | 3324 // are the same type. If they are unifiable without substituting any |
3312 // type variables, they are equal. | 3325 // type variables, they are equal. |
3313 return unifyTypes(this, other, new Set<TypeParameter>()) != null; | 3326 return unifyTypes(this, other, new Set<TypeParameter>()) != null; |
3314 } | 3327 } |
(...skipping 20 matching lines...) Expand all Loading... |
3335 int hash = 1237; | 3348 int hash = 1237; |
3336 hash = 0x3fffffff & (hash * 31 + requiredParameterCount); | 3349 hash = 0x3fffffff & (hash * 31 + requiredParameterCount); |
3337 for (int i = 0; i < typeParameters.length; ++i) { | 3350 for (int i = 0; i < typeParameters.length; ++i) { |
3338 TypeParameter parameter = typeParameters[i]; | 3351 TypeParameter parameter = typeParameters[i]; |
3339 _temporaryHashCodeTable[parameter] = _temporaryHashCodeTable.length; | 3352 _temporaryHashCodeTable[parameter] = _temporaryHashCodeTable.length; |
3340 hash = 0x3fffffff & (hash * 31 + parameter.bound.hashCode); | 3353 hash = 0x3fffffff & (hash * 31 + parameter.bound.hashCode); |
3341 } | 3354 } |
3342 for (int i = 0; i < positionalParameters.length; ++i) { | 3355 for (int i = 0; i < positionalParameters.length; ++i) { |
3343 hash = 0x3fffffff & (hash * 31 + positionalParameters[i].hashCode); | 3356 hash = 0x3fffffff & (hash * 31 + positionalParameters[i].hashCode); |
3344 } | 3357 } |
3345 // TODO: Using a sorted list of names would be better than a map here. | 3358 for (int i = 0; i < namedParameters.length; ++i) { |
3346 namedParameters.forEach((String name, DartType type) { | 3359 hash = 0x3fffffff & (hash * 31 + namedParameters[i].hashCode); |
3347 // Note that we use only addition and truncation here, so that we do not | 3360 } |
3348 // rely on the iteration of the of the map. | |
3349 hash = 0x3fffffff & (hash + name.hashCode); | |
3350 hash = 0x3fffffff & (hash + type.hashCode); | |
3351 }); | |
3352 hash = 0x3fffffff & (hash * 31 + returnType.hashCode); | 3361 hash = 0x3fffffff & (hash * 31 + returnType.hashCode); |
3353 for (int i = 0; i < typeParameters.length; ++i) { | 3362 for (int i = 0; i < typeParameters.length; ++i) { |
3354 // Remove the type parameters from the scope again. | 3363 // Remove the type parameters from the scope again. |
3355 _temporaryHashCodeTable.remove(typeParameters[i]); | 3364 _temporaryHashCodeTable.remove(typeParameters[i]); |
3356 } | 3365 } |
3357 return hash; | 3366 return hash; |
3358 } | 3367 } |
3359 } | 3368 } |
3360 | 3369 |
| 3370 /// A named parameter in [FunctionType]. |
| 3371 class NamedType extends Node implements Comparable<NamedType> { |
| 3372 final String name; |
| 3373 final DartType type; |
| 3374 |
| 3375 NamedType(this.name, this.type); |
| 3376 |
| 3377 bool operator ==(Object other) { |
| 3378 return other is NamedType && name == other.name && type == other.type; |
| 3379 } |
| 3380 |
| 3381 int get hashCode { |
| 3382 return name.hashCode * 31 + type.hashCode * 37; |
| 3383 } |
| 3384 |
| 3385 int compareTo(NamedType other) => name.compareTo(other.name); |
| 3386 |
| 3387 accept(Visitor v) => v.visitNamedType(this); |
| 3388 |
| 3389 void visitChildren(Visitor v) { |
| 3390 type.accept(v); |
| 3391 } |
| 3392 } |
| 3393 |
3361 /// Stores the hash code of function type parameters while computing the hash | 3394 /// Stores the hash code of function type parameters while computing the hash |
3362 /// code of a [FunctionType] object. | 3395 /// code of a [FunctionType] object. |
3363 /// | 3396 /// |
3364 /// This ensures that distinct [FunctionType] objects get the same hash code | 3397 /// This ensures that distinct [FunctionType] objects get the same hash code |
3365 /// if they represent the same type, even though their type parameters are | 3398 /// if they represent the same type, even though their type parameters are |
3366 /// represented by different objects. | 3399 /// represented by different objects. |
3367 final Map<TypeParameter, int> _temporaryHashCodeTable = <TypeParameter, int>{}; | 3400 final Map<TypeParameter, int> _temporaryHashCodeTable = <TypeParameter, int>{}; |
3368 | 3401 |
3369 /// Reference to a type variable. | 3402 /// Reference to a type variable. |
3370 class TypeParameterType extends DartType { | 3403 class TypeParameterType extends DartType { |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3606 | 3639 |
3607 @override | 3640 @override |
3608 defaultTreeNode(TreeNode node) { | 3641 defaultTreeNode(TreeNode node) { |
3609 if (node == child) { | 3642 if (node == child) { |
3610 return replacement; | 3643 return replacement; |
3611 } else { | 3644 } else { |
3612 return node; | 3645 return node; |
3613 } | 3646 } |
3614 } | 3647 } |
3615 } | 3648 } |
OLD | NEW |