nicer looking types
This commit is contained in:
parent
428e8cd298
commit
abd3bd3645
4 changed files with 25 additions and 9 deletions
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue