Chromium Code Reviews| 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 of [type] with the | |
|
Kevin Millikin (Google)
2016/11/01 13:03:01
The comment is wrong here.
asgerf
2016/11/01 13:59:36
Thanks. Fixed it.
| |
| 177 /// type arguments provided in [type]. | |
| 178 static Substitution bottomForClass(Class class_) { | |
| 179 if (class_.typeParameters.isEmpty) return _NullSubstitution.instance; | |
| 180 return new _ClassBottomSubstitution(class_); | |
| 181 } | |
| 182 | |
| 183 static Substitution combine(Substitution first, Substitution second) { | |
|
Kevin Millikin (Google)
2016/11/01 13:03:01
It subtle that the implementation prefers first.
asgerf
2016/11/01 13:59:36
Added some documentation.
| |
| 184 if (first == _NullSubstitution.instance) return second; | |
| 185 if (second == _NullSubstitution.instance) return first; | |
| 186 return new _CombinedSubstitution(first, second); | |
| 187 } | |
| 188 | |
| 172 DartType getSubstitute(TypeParameter parameter, bool upperBound); | 189 DartType getSubstitute(TypeParameter parameter, bool upperBound); |
| 173 | 190 |
| 174 DartType substituteType(DartType node) { | 191 DartType substituteType(DartType node, {bool contravariant: false}) { |
| 175 return new _TopSubstitutor(this).visit(node); | 192 return new _TopSubstitutor(this, contravariant).visit(node); |
| 176 } | 193 } |
| 177 | 194 |
| 178 Supertype substituteSupertype(Supertype node) { | 195 Supertype substituteSupertype(Supertype node) { |
| 179 return new _TopSubstitutor(this).visitSupertype(node); | 196 return new _TopSubstitutor(this, false).visitSupertype(node); |
| 180 } | 197 } |
| 181 } | 198 } |
| 182 | 199 |
| 183 class _NullSubstitution extends Substitution { | 200 class _NullSubstitution extends Substitution { |
| 184 static final _NullSubstitution instance = new _NullSubstitution(); | 201 static const _NullSubstitution instance = const _NullSubstitution(); |
| 202 | |
| 203 const _NullSubstitution(); | |
| 185 | 204 |
| 186 DartType getSubstitute(TypeParameter parameter, bool upperBound) { | 205 DartType getSubstitute(TypeParameter parameter, bool upperBound) { |
| 187 return new TypeParameterType(parameter); | 206 return new TypeParameterType(parameter); |
| 188 } | 207 } |
| 189 | 208 |
| 190 @override | 209 @override |
| 191 DartType substituteType(DartType node) => node; | 210 DartType substituteType(DartType node, {bool contravariant: false}) => node; |
| 192 | 211 |
| 193 @override | 212 @override |
| 194 Supertype substituteSupertype(Supertype node) => node; | 213 Supertype substituteSupertype(Supertype node) => node; |
| 195 } | 214 } |
| 196 | 215 |
| 197 class _MapSubstitution extends Substitution { | 216 class _MapSubstitution extends Substitution { |
| 198 final Map<TypeParameter, DartType> upper; | 217 final Map<TypeParameter, DartType> upper; |
| 199 final Map<TypeParameter, DartType> lower; | 218 final Map<TypeParameter, DartType> lower; |
| 200 | 219 |
| 201 _MapSubstitution(this.upper, this.lower); | 220 _MapSubstitution(this.upper, this.lower); |
| 202 | 221 |
| 203 DartType getSubstitute(TypeParameter parameter, bool upperBound) { | 222 DartType getSubstitute(TypeParameter parameter, bool upperBound) { |
| 204 return upperBound ? upper[parameter] : lower[parameter]; | 223 return upperBound ? upper[parameter] : lower[parameter]; |
| 205 } | 224 } |
| 206 } | 225 } |
| 207 | 226 |
| 208 class _TopSubstitutor extends _TypeSubstitutor { | 227 class _TopSubstitutor extends _TypeSubstitutor { |
| 209 final Substitution substitution; | 228 final Substitution substitution; |
| 210 | 229 |
| 211 _TopSubstitutor(this.substitution) : super(null); | 230 _TopSubstitutor(this.substitution, bool contravariant) : super(null) { |
| 231 if (contravariant) { | |
| 232 invertVariance(); | |
| 233 } | |
| 234 } | |
| 212 | 235 |
| 213 DartType lookup(TypeParameter parameter, bool upperBound) { | 236 DartType lookup(TypeParameter parameter, bool upperBound) { |
| 214 return substitution.getSubstitute(parameter, upperBound); | 237 return substitution.getSubstitute(parameter, upperBound); |
| 215 } | 238 } |
| 216 | 239 |
| 217 TypeParameter freshTypeParameter(TypeParameter node) { | 240 TypeParameter freshTypeParameter(TypeParameter node) { |
| 218 throw 'Create a fresh environment first'; | 241 throw 'Create a fresh environment first'; |
| 219 } | 242 } |
| 220 } | 243 } |
| 221 | 244 |
| 245 class _ClassBottomSubstitution extends Substitution { | |
| 246 final Class class_; | |
| 247 | |
| 248 _ClassBottomSubstitution(this.class_); | |
| 249 | |
| 250 DartType getSubstitute(TypeParameter parameter, bool upperBound) { | |
| 251 if (parameter.parent == class_) { | |
| 252 return upperBound ? const BottomType() : const DynamicType(); | |
| 253 } | |
| 254 return null; | |
| 255 } | |
| 256 } | |
| 257 | |
| 258 class _CombinedSubstitution extends Substitution { | |
| 259 final Substitution first, second; | |
| 260 | |
| 261 _CombinedSubstitution(this.first, this.second); | |
| 262 | |
| 263 DartType getSubstitute(TypeParameter parameter, bool upperBound) { | |
| 264 return first.getSubstitute(parameter, upperBound) ?? | |
| 265 second.getSubstitute(parameter, upperBound); | |
| 266 } | |
| 267 } | |
| 268 | |
| 222 class _InnerTypeSubstitutor extends _TypeSubstitutor { | 269 class _InnerTypeSubstitutor extends _TypeSubstitutor { |
| 223 final Map<TypeParameter, DartType> substitution = <TypeParameter, DartType>{}; | 270 final Map<TypeParameter, DartType> substitution = <TypeParameter, DartType>{}; |
| 224 | 271 |
| 225 _InnerTypeSubstitutor(_TypeSubstitutor outer) : super(outer); | 272 _InnerTypeSubstitutor(_TypeSubstitutor outer) : super(outer); |
| 226 | 273 |
| 227 DartType lookup(TypeParameter parameter, bool upperBound) { | 274 DartType lookup(TypeParameter parameter, bool upperBound) { |
| 228 return substitution[parameter]; | 275 return substitution[parameter]; |
| 229 } | 276 } |
| 230 | 277 |
| 231 TypeParameter freshTypeParameter(TypeParameter node) { | 278 TypeParameter freshTypeParameter(TypeParameter node) { |
| (...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 576 } | 623 } |
| 577 | 624 |
| 578 Map<dynamic/*=K*/, dynamic/*=W*/ > _mapValues/*<K,V,W>*/( | 625 Map<dynamic/*=K*/, dynamic/*=W*/ > _mapValues/*<K,V,W>*/( |
| 579 Map<dynamic/*=K*/, dynamic/*=V*/ > map, dynamic/*=W*/ fn(dynamic/*=V*/)) { | 626 Map<dynamic/*=K*/, dynamic/*=V*/ > map, dynamic/*=W*/ fn(dynamic/*=V*/)) { |
| 580 Map<dynamic/*=K*/, dynamic/*=W*/ > result = {}; | 627 Map<dynamic/*=K*/, dynamic/*=W*/ > result = {}; |
| 581 map.forEach((key, value) { | 628 map.forEach((key, value) { |
| 582 result[key] = fn(value); | 629 result[key] = fn(value); |
| 583 }); | 630 }); |
| 584 return result; | 631 return result; |
| 585 } | 632 } |
| OLD | NEW |