| 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 library kernel.type_algebra; | 4 library kernel.type_algebra; |
| 5 | 5 |
| 6 import 'ast.dart'; | 6 import 'ast.dart'; |
| 7 | 7 |
| 8 /// Returns a type where all occurrences of the given type parameters have been | 8 /// Returns a type where all occurrences of the given type parameters have been |
| 9 /// replaced with the corresponding types. | 9 /// replaced with the corresponding types. |
| 10 /// | 10 /// |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 112 Supertype substituteSuper(Supertype type) { | 112 Supertype substituteSuper(Supertype type) { |
| 113 return substitution.substituteSupertype(type); | 113 return substitution.substituteSupertype(type); |
| 114 } | 114 } |
| 115 } | 115 } |
| 116 | 116 |
| 117 // ------------------------------------------------------------------------ | 117 // ------------------------------------------------------------------------ |
| 118 // IMPLEMENTATION | 118 // IMPLEMENTATION |
| 119 // ------------------------------------------------------------------------ | 119 // ------------------------------------------------------------------------ |
| 120 | 120 |
| 121 abstract class Substitution { | 121 abstract class Substitution { |
| 122 const Substitution(); |
| 123 |
| 124 static const Substitution empty = _NullSubstitution.instance; |
| 125 |
| 122 /// Substitutes each parameter to the type it maps to in [map]. | 126 /// Substitutes each parameter to the type it maps to in [map]. |
| 123 static Substitution fromMap(Map<TypeParameter, DartType> map) { | 127 static Substitution fromMap(Map<TypeParameter, DartType> map) { |
| 124 if (map.isEmpty) return _NullSubstitution.instance; | 128 if (map.isEmpty) return _NullSubstitution.instance; |
| 125 return new _MapSubstitution(map, map); | 129 return new _MapSubstitution(map, map); |
| 126 } | 130 } |
| 127 | 131 |
| 128 /// Substitutes all occurrences of the given type parameters with the | 132 /// Substitutes all occurrences of the given type parameters with the |
| 129 /// corresponding upper or lower bound, depending on the variance of the | 133 /// corresponding upper or lower bound, depending on the variance of the |
| 130 /// context where it occurs. | 134 /// context where it occurs. |
| 131 /// | 135 /// |
| (...skipping 30 matching lines...) Expand all Loading... |
| 162 static Substitution fromPairs( | 166 static Substitution fromPairs( |
| 163 List<TypeParameter> parameters, List<DartType> types) { | 167 List<TypeParameter> parameters, List<DartType> types) { |
| 164 // TODO(asgerf): Investigate if it is more efficient to implement | 168 // TODO(asgerf): Investigate if it is more efficient to implement |
| 165 // substitution based on parallel pairwise lists instead of Maps. | 169 // substitution based on parallel pairwise lists instead of Maps. |
| 166 assert(parameters.length == types.length); | 170 assert(parameters.length == types.length); |
| 167 if (parameters.isEmpty) return _NullSubstitution.instance; | 171 if (parameters.isEmpty) return _NullSubstitution.instance; |
| 168 return fromMap( | 172 return fromMap( |
| 169 new Map<TypeParameter, DartType>.fromIterables(parameters, types)); | 173 new Map<TypeParameter, DartType>.fromIterables(parameters, types)); |
| 170 } | 174 } |
| 171 | 175 |
| 176 /// Substitutes the type parameters on the class with bottom or dynamic, |
| 177 /// depending on the covariance of its use. |
| 178 static Substitution bottomForClass(Class class_) { |
| 179 if (class_.typeParameters.isEmpty) return _NullSubstitution.instance; |
| 180 return new _ClassBottomSubstitution(class_); |
| 181 } |
| 182 |
| 183 /// Substitutes both variables from [first] and [second], favoring those from |
| 184 /// [first] if they overlap. |
| 185 /// |
| 186 /// Neither substitution is applied to the results of the other, so this does |
| 187 /// *not* correspond to a sequence of two subsitutions. For example, combining |
| 188 /// `{T -> List<G>}` with `{G -> String}` does not correspond to |
| 189 /// `{T -> List<String>}` because the result from substituting `T` is not |
| 190 /// searched for occurences of `G`. |
| 191 static Substitution combine(Substitution first, Substitution second) { |
| 192 if (first == _NullSubstitution.instance) return second; |
| 193 if (second == _NullSubstitution.instance) return first; |
| 194 return new _CombinedSubstitution(first, second); |
| 195 } |
| 196 |
| 172 DartType getSubstitute(TypeParameter parameter, bool upperBound); | 197 DartType getSubstitute(TypeParameter parameter, bool upperBound); |
| 173 | 198 |
| 174 DartType substituteType(DartType node) { | 199 DartType substituteType(DartType node, {bool contravariant: false}) { |
| 175 return new _TopSubstitutor(this).visit(node); | 200 return new _TopSubstitutor(this, contravariant).visit(node); |
| 176 } | 201 } |
| 177 | 202 |
| 178 Supertype substituteSupertype(Supertype node) { | 203 Supertype substituteSupertype(Supertype node) { |
| 179 return new _TopSubstitutor(this).visitSupertype(node); | 204 return new _TopSubstitutor(this, false).visitSupertype(node); |
| 180 } | 205 } |
| 181 } | 206 } |
| 182 | 207 |
| 183 class _NullSubstitution extends Substitution { | 208 class _NullSubstitution extends Substitution { |
| 184 static final _NullSubstitution instance = new _NullSubstitution(); | 209 static const _NullSubstitution instance = const _NullSubstitution(); |
| 210 |
| 211 const _NullSubstitution(); |
| 185 | 212 |
| 186 DartType getSubstitute(TypeParameter parameter, bool upperBound) { | 213 DartType getSubstitute(TypeParameter parameter, bool upperBound) { |
| 187 return new TypeParameterType(parameter); | 214 return new TypeParameterType(parameter); |
| 188 } | 215 } |
| 189 | 216 |
| 190 @override | 217 @override |
| 191 DartType substituteType(DartType node) => node; | 218 DartType substituteType(DartType node, {bool contravariant: false}) => node; |
| 192 | 219 |
| 193 @override | 220 @override |
| 194 Supertype substituteSupertype(Supertype node) => node; | 221 Supertype substituteSupertype(Supertype node) => node; |
| 195 } | 222 } |
| 196 | 223 |
| 197 class _MapSubstitution extends Substitution { | 224 class _MapSubstitution extends Substitution { |
| 198 final Map<TypeParameter, DartType> upper; | 225 final Map<TypeParameter, DartType> upper; |
| 199 final Map<TypeParameter, DartType> lower; | 226 final Map<TypeParameter, DartType> lower; |
| 200 | 227 |
| 201 _MapSubstitution(this.upper, this.lower); | 228 _MapSubstitution(this.upper, this.lower); |
| 202 | 229 |
| 203 DartType getSubstitute(TypeParameter parameter, bool upperBound) { | 230 DartType getSubstitute(TypeParameter parameter, bool upperBound) { |
| 204 return upperBound ? upper[parameter] : lower[parameter]; | 231 return upperBound ? upper[parameter] : lower[parameter]; |
| 205 } | 232 } |
| 206 } | 233 } |
| 207 | 234 |
| 208 class _TopSubstitutor extends _TypeSubstitutor { | 235 class _TopSubstitutor extends _TypeSubstitutor { |
| 209 final Substitution substitution; | 236 final Substitution substitution; |
| 210 | 237 |
| 211 _TopSubstitutor(this.substitution) : super(null); | 238 _TopSubstitutor(this.substitution, bool contravariant) : super(null) { |
| 239 if (contravariant) { |
| 240 invertVariance(); |
| 241 } |
| 242 } |
| 212 | 243 |
| 213 DartType lookup(TypeParameter parameter, bool upperBound) { | 244 DartType lookup(TypeParameter parameter, bool upperBound) { |
| 214 return substitution.getSubstitute(parameter, upperBound); | 245 return substitution.getSubstitute(parameter, upperBound); |
| 215 } | 246 } |
| 216 | 247 |
| 217 TypeParameter freshTypeParameter(TypeParameter node) { | 248 TypeParameter freshTypeParameter(TypeParameter node) { |
| 218 throw 'Create a fresh environment first'; | 249 throw 'Create a fresh environment first'; |
| 219 } | 250 } |
| 220 } | 251 } |
| 221 | 252 |
| 253 class _ClassBottomSubstitution extends Substitution { |
| 254 final Class class_; |
| 255 |
| 256 _ClassBottomSubstitution(this.class_); |
| 257 |
| 258 DartType getSubstitute(TypeParameter parameter, bool upperBound) { |
| 259 if (parameter.parent == class_) { |
| 260 return upperBound ? const BottomType() : const DynamicType(); |
| 261 } |
| 262 return null; |
| 263 } |
| 264 } |
| 265 |
| 266 class _CombinedSubstitution extends Substitution { |
| 267 final Substitution first, second; |
| 268 |
| 269 _CombinedSubstitution(this.first, this.second); |
| 270 |
| 271 DartType getSubstitute(TypeParameter parameter, bool upperBound) { |
| 272 return first.getSubstitute(parameter, upperBound) ?? |
| 273 second.getSubstitute(parameter, upperBound); |
| 274 } |
| 275 } |
| 276 |
| 222 class _InnerTypeSubstitutor extends _TypeSubstitutor { | 277 class _InnerTypeSubstitutor extends _TypeSubstitutor { |
| 223 final Map<TypeParameter, DartType> substitution = <TypeParameter, DartType>{}; | 278 final Map<TypeParameter, DartType> substitution = <TypeParameter, DartType>{}; |
| 224 | 279 |
| 225 _InnerTypeSubstitutor(_TypeSubstitutor outer) : super(outer); | 280 _InnerTypeSubstitutor(_TypeSubstitutor outer) : super(outer); |
| 226 | 281 |
| 227 DartType lookup(TypeParameter parameter, bool upperBound) { | 282 DartType lookup(TypeParameter parameter, bool upperBound) { |
| 228 return substitution[parameter]; | 283 return substitution[parameter]; |
| 229 } | 284 } |
| 230 | 285 |
| 231 TypeParameter freshTypeParameter(TypeParameter node) { | 286 TypeParameter freshTypeParameter(TypeParameter node) { |
| (...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 576 } | 631 } |
| 577 | 632 |
| 578 Map<dynamic/*=K*/, dynamic/*=W*/ > _mapValues/*<K,V,W>*/( | 633 Map<dynamic/*=K*/, dynamic/*=W*/ > _mapValues/*<K,V,W>*/( |
| 579 Map<dynamic/*=K*/, dynamic/*=V*/ > map, dynamic/*=W*/ fn(dynamic/*=V*/)) { | 634 Map<dynamic/*=K*/, dynamic/*=V*/ > map, dynamic/*=W*/ fn(dynamic/*=V*/)) { |
| 580 Map<dynamic/*=K*/, dynamic/*=W*/ > result = {}; | 635 Map<dynamic/*=K*/, dynamic/*=W*/ > result = {}; |
| 581 map.forEach((key, value) { | 636 map.forEach((key, value) { |
| 582 result[key] = fn(value); | 637 result[key] = fn(value); |
| 583 }); | 638 }); |
| 584 return result; | 639 return result; |
| 585 } | 640 } |
| OLD | NEW |