recursive types (and operations on them, like pretty-printing, comparison and unification) seem to be working.

big part of the code base still needs to be 'ported' to the updated type constructors.
This commit is contained in:
Joeri Exelmans 2025-05-05 17:17:45 +02:00
parent 55c5d7cffa
commit 8eec5b9239
34 changed files with 523 additions and 295 deletions

View file

@ -26,4 +26,4 @@ export const compareUnits = x => y => 0;
// Note: dirty assumption that every symbol has unique description.
// This will be fixed once we move from symbols to real UUIDs.
export const compareSymbols = a => b => (a !== b) && compareStrings(a.description)(b.description);
export const compareSymbols = a => b => Number(a !== b) && compareStrings(a.description)(b.description);

View file

@ -1,7 +1,38 @@
import { getParams, getSymbol } from "../type_constructor.js";
import { compareSymbols } from "./primitives.js";
import { compareBools, compareSymbols } from "./primitives.js";
import { compareLists } from "./structures.js";
export const compareTypes = x => y =>
compareSymbols(getSymbol(x))(getSymbol(y))
|| compareLists(compareTypes)(getParams(x))(getParams(y));
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);