This commit is contained in:
Mark Probst 2018-03-29 09:52:25 -07:00
Родитель 42787bbeb9
Коммит fe9f931ad6
1 изменённых файлов: 43 добавлений и 21 удалений

Просмотреть файл

@ -8,6 +8,36 @@ import { assert, defined } from "./Support";
import { TypeRef, GraphRewriteBuilder, StringTypeMapping } from "./TypeBuilder";
import { unifyTypes, UnifyUnionBuilder } from "./UnifyClasses";
function makeGroupsToFlatten(
unions: Set<UnionType>,
include: ((members: OrderedSet<Type>) => boolean) | undefined
): Type[][] {
let singleTypeGroups = Map<Type, OrderedSet<Type>>();
const groups: Type[][] = [];
unions.forEach(u => {
const members = setOperationMembersRecursively(u)[0];
if (include !== undefined) {
if (!include(members)) return;
}
if (members.size === 1) {
const t = defined(members.first());
let maybeSet = singleTypeGroups.get(t);
if (maybeSet === undefined) {
maybeSet = OrderedSet([t]);
}
maybeSet = maybeSet.add(u);
singleTypeGroups = singleTypeGroups.set(t, maybeSet);
} else {
groups.push([u]);
}
});
singleTypeGroups.forEach(ts => groups.push(ts.toArray()));
return groups;
}
export function flattenUnions(
graph: TypeGraph,
stringTypeMapping: StringTypeMapping,
@ -31,29 +61,21 @@ export function flattenUnions(
const allUnions = graph.allTypesUnordered().filter(t => t instanceof UnionType) as Set<UnionType>;
const nonCanonicalUnions = allUnions.filter(u => !u.isCanonical);
let singleTypeGroups = Map<Type, OrderedSet<Type>>();
const groups: Type[][] = [];
let foundIntersection: boolean = false;
nonCanonicalUnions.forEach(u => {
const members = setOperationMembersRecursively(u)[0];
let foundIntersection = false;
const groups = makeGroupsToFlatten(nonCanonicalUnions, members => {
assert(!members.isEmpty(), "We can't have an empty union");
if (members.some(m => m instanceof IntersectionType)) {
foundIntersection = true;
return;
}
if (members.size === 1) {
const t = defined(members.first());
let maybeSet = singleTypeGroups.get(t);
if (maybeSet === undefined) {
maybeSet = OrderedSet([t]);
}
maybeSet = maybeSet.add(u);
singleTypeGroups = singleTypeGroups.set(t, maybeSet);
} else {
groups.push([u]);
}
if (!members.some(m => m instanceof IntersectionType)) return true;
// FIXME: This is stupid. `flattenUnions` returns true when no more union
// flattening is necessary, but `resolveIntersections` can introduce new
// unions that might require flattening, so now `flattenUnions` needs to take
// that into account. Either change `resolveIntersections` such that it
// doesn't introduce non-canonical unions (by using `unifyTypes`), or have
// some other way to tell whether more work is needed that doesn't require
// the two passes to know about each other.
foundIntersection = true;
return false;
});
singleTypeGroups.forEach(ts => groups.push(ts.toArray()));
graph = graph.rewrite("flatten unions", stringTypeMapping, false, groups, replace);
// console.log(`flattened ${nonCanonicalUnions.size} of ${unions.size} unions`);