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);