big part of the code base still needs to be 'ported' to the updated type constructors.
38 lines
1.5 KiB
JavaScript
38 lines
1.5 KiB
JavaScript
import { getParams, getSymbol } from "../type_constructor.js";
|
|
import { compareBools, compareSymbols } from "./primitives.js";
|
|
import { compareLists } from "./structures.js";
|
|
|
|
const __compareTypes = state => typeX => typeY => {
|
|
// tagX and tagY: just something unique & deterministic that can serve as JS map key
|
|
const tagX = state.nextTag++;
|
|
const tagY = state.nextTag++;
|
|
state.tagsX.add(tagX);
|
|
state.tagsY.add(tagY);
|
|
state.comparing.set(tagX, tagY);
|
|
return compareSymbols(getSymbol(typeX))(getSymbol(typeY))
|
|
|| compareLists
|
|
(paramOfX => paramOfY => {
|
|
const pX = paramOfX(tagX);
|
|
const pY = paramOfY(tagY);
|
|
return compareBools(state.tagsX.has(pX))(state.tagsY.has(pY))
|
|
|| (() => {
|
|
if (state.tagsX.has(pX)) {
|
|
// both sub-types have been visited already in an enclosing call
|
|
// if they were being compared in the same enclosing call, we assume they are equal!
|
|
// (we cannot compare them, that would result in endless recursion)
|
|
return compareSymbols(state.comparing.get(pX))(pY);
|
|
}
|
|
// none have been visited -> recursively compare
|
|
return __compareTypes(state)(pX)(pY);
|
|
})();
|
|
})
|
|
(getParams(typeX))
|
|
(getParams(typeY));
|
|
};
|
|
|
|
export const compareTypes = typeX => typeY => __compareTypes({
|
|
tagsX: new Set(),
|
|
tagsY: new Set(),
|
|
comparing: new Map(),
|
|
nextTag: 0,
|
|
})(typeX)(typeY);
|