nicer looking types

This commit is contained in:
Joeri Exelmans 2025-05-27 13:20:09 +02:00
parent 428e8cd298
commit abd3bd3645
4 changed files with 25 additions and 9 deletions

View file

@ -163,10 +163,7 @@ export const inferTypeCall = memoize(function inferTypeCall(s: CallBlockState, e
});
export const inferTypeLet = memoize(function inferTypeLet(s: LetInBlockState, env: StaticEnvironment): TypeInfoLet {
console.log('inferTypeLet..', env.typevars);
const recursiveTypeInfo = iterateRecursiveType(s.name, s.value, env, true);
console.log('end inferTypeLet.');
console.log({recursiveTypeInfo});
// to eval the 'inner' expr, we only need to add our parameter to the environment:
const innerEnv = {
names: trie.insert(env.names)(s.name)({
@ -187,9 +184,7 @@ export const inferTypeLet = memoize(function inferTypeLet(s: LetInBlockState, en
});
export const inferTypeLambda = memoize(function inferTypeLambda(s: LambdaBlockState, env: StaticEnvironment): TypeInfoLambda {
console.log('inferTypeLambda..', env.typevars);
const recursiveTypeInfo = iterateRecursiveType(s.paramName, s.expr, env, false);
console.log('end inferTypeLambda.');
return {
kind: "lambda",
type: fnType(_ => recursiveTypeInfo.paramType)(_ => recursiveTypeInfo.inner.type),
@ -199,7 +194,7 @@ export const inferTypeLambda = memoize(function inferTypeLambda(s: LambdaBlockSt
// Given a named value whose type we know nothing about, and an expression that computes the value (which may recursively contain the value), compute the type of the value.
// Why? Both lambda functions and let-expressions can refer to themselves recursively. To infer their type, we need to recompute the type and feed it back to itself until some fixed point is reached.
function iterateRecursiveType(paramName: string, expr: ExprBlockState, env: StaticEnvironment, paramIsInner: boolean) {
function iterateRecursiveType(paramName: string, expr: ExprBlockState, env: StaticEnvironment, isLet: boolean) {
let [paramType] = typeUnknown(env);
const paramTypeVar = paramType.symbol;
@ -230,6 +225,24 @@ function iterateRecursiveType(paramName: string, expr: ExprBlockState, env: Stat
// console.log("-----------------");
if (eqType(inferredPType2)(paramType)) {
// The following part is not really necessary, but it makes types look nicer (start at the lowest possible typevar) for non-recursive let-expressions.
if (isLet && occurring(paramType).intersection(occurring(innerTypeInfo.type)).size === 0) {
const innerEnv = {
names: trie.insert(env.names)(paramName)({
kind: "unknown",
t: innerTypeInfo.type,
}),
typevars: env.typevars.union(occurring(innerTypeInfo.type) as Set<string>),
};
const innerTypeInfoWithoutTypeVar = inferType(expr, innerEnv);
return {
subs: innerTypeInfo.subs,
newEnv: env,
paramType: innerTypeInfoWithoutTypeVar.type,
inner: innerTypeInfoWithoutTypeVar,
innerEnv,
}
}
return {
subs: subsWithoutPType,
newEnv,