blob: 3a1ccb2415616ad6c52e00ef3e60010466f15bea [file] [log] [blame]
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE.md file.
import 'kernel_builder.dart'
show
TypeVariableBuilder,
KernelTypeBuilder,
KernelNamedTypeBuilder,
KernelTypeVariableBuilder,
KernelClassBuilder,
KernelFunctionTypeAliasBuilder;
KernelTypeBuilder substituteRec(
KernelTypeBuilder type,
Map<TypeVariableBuilder, KernelTypeBuilder> substitution,
KernelTypeBuilder dynamicType,
int depth) {
if (type is KernelNamedTypeBuilder) {
if (type.builder is KernelTypeVariableBuilder &&
substitution.containsKey(type.builder)) {
if (depth > 0) {
return substituteRec(
substitution[type.builder], substitution, dynamicType, depth - 1);
}
return dynamicType;
} else if (type.builder is KernelClassBuilder ||
type.builder is KernelFunctionTypeAliasBuilder) {
if (type.arguments == null || type.arguments.length == 0) {
return type;
}
List<KernelTypeBuilder> typeArguments =
new List<KernelTypeBuilder>(type.arguments.length);
for (int i = 0; i < typeArguments.length; i++) {
typeArguments[i] =
substituteRec(type.arguments[i], substitution, dynamicType, depth);
}
return new KernelNamedTypeBuilder(type.name, typeArguments)
..bind(type.builder);
}
}
return type;
}
List<KernelTypeBuilder> calculateBounds(
List<TypeVariableBuilder> typeParameters,
KernelTypeBuilder dynamicType,
KernelClassBuilder objectClass) {
var refinedBounds = new List<KernelTypeBuilder>(typeParameters.length);
var substitution = new Map<TypeVariableBuilder, KernelTypeBuilder>();
for (int i = 0; i < typeParameters.length; i++) {
KernelTypeBuilder type = typeParameters[i].bound;
if (type == null ||
type is KernelNamedTypeBuilder &&
type.builder is KernelClassBuilder &&
(type.builder as KernelClassBuilder).cls == objectClass?.cls) {
type = dynamicType;
}
refinedBounds[i] = type;
substitution[typeParameters[i]] = type;
}
// TODO(dmitryas): Replace the call to [substituteRec] with actual
// instantiate-to-bounds algorithm.
List<KernelTypeBuilder> result =
new List<KernelTypeBuilder>(typeParameters.length);
for (int i = 0; i < result.length; i++) {
// The current bound `refinedBounds[i]` is used as a starting point for
// [substituteRec], that is, the first substitution of a type parameter with
// its bound is already performed, so the depth parameter is lessened by 1.
result[i] = substituteRec(
refinedBounds[i], substitution, dynamicType, typeParameters.length - 1);
}
return result;
}