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

@ -1,38 +1,43 @@
import { inspect } from 'node:util';
import { symbolFunction, symbolList, symbolProduct, symbolSum } from '../structures/types.js';
import { symbolFunction, symbolList, symbolProduct, symbolSet, symbolSum } from '../structures/types.js';
import { mapRecursiveStructure } from './util.js';
export function pretty(obj) {
return inspect(obj, { colors: true, depth: null, breakLength: 120 });
}
// Pretty print type
export function prettyT(type) {
// console.log("pretty:", type);
if (typeof type === "symbol") {
return type.description;
}
if (type.typeVars) {
if (type.typeVars.size > 0) {
return `${[...type.typeVars].map(prettyT).sort((a, b) => a.localeCompare(b)).join(",")}: ${prettyT(type.type)}`;
export const prettyT = type => {
return mapRecursiveStructure(([type, m, seen], map) => {
if (typeof type === "symbol") {
return type.description;
}
if (!m.has(type)) {
m.add(type); // next time we encounter this type, we'll only render a placeholder
const params = type.params.map(p => map([p(type), m, seen])());
// if while visiting the children, we encountered ourselves, add annotation:
const annot = seen.has(type) ? seen.get(type) : ``;
return renderType(type.symbol, annot, params);
}
else {
return prettyT(type.type);
if (!seen.has(type)) {
seen.set(type, `#${seen.size}`);
}
return seen.get(type);
}
}
if (type.symbol === symbolFunction) {
return `(${prettyT(type.params[0])} -> ${prettyT(type.params[1])})`;
}
if (type.symbol === symbolList) {
return `[${prettyT(type.params[0])}]`;
}
if (type.symbol === symbolProduct) {
return `(${prettyT(type.params[0])} × ${prettyT(type.params[1])})`;
}
if (type.symbol === symbolSum) {
return `(${prettyT(type.params[0])} | ${prettyT(type.params[1])})`;
}
if (type.params.length === 0) {
return type.symbol.description;
}
return `${type.symbol.description}(${type.params.map(prettyT).join(", ")})`;
}
})([type, new Set(), new Map()])();
};
const renderType = (symbol, annot, params) => {
return {
[symbolList] : `${annot}[${params[0]}]`,
[symbolSet] : `${annot}{${params[0]}}`,
[symbolFunction]: `${annot}(${params[0]} -> ${params[1]})`,
[symbolSum] : `${annot}(${params[0]} + ${params[1]})`,
[symbolProduct] : `${annot}(${params[0]} ${params[1]})`,
}[symbol] || symbol.description;
};
export const prettyGenT = genericType => {
return `${[...genericType.typeVars].map(prettyT).sort((a, b) => a.localeCompare(b)).join(",")}: ${prettyT(genericType.type)}`;
};