From abd3bd36451989890cfb478aae8f7f289cb404bf Mon Sep 17 00:00:00 2001 From: Joeri Exelmans Date: Tue, 27 May 2025 13:20:09 +0200 Subject: [PATCH] nicer looking types --- src/component/expr/ExprBlock.css | 4 ++++ src/component/expr/ExprBlock.tsx | 4 +--- src/component/expr/LetInBlock.tsx | 1 + src/eval/infer_type.ts | 25 +++++++++++++++++++------ 4 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/component/expr/ExprBlock.css b/src/component/expr/ExprBlock.css index 81dc5b3..4cae95a 100644 --- a/src/component/expr/ExprBlock.css +++ b/src/component/expr/ExprBlock.css @@ -14,6 +14,10 @@ background-color: pink; margin-top: 4px; z-index: 10; + font-family: var(--my-monospace-font); + white-space-collapse: preserve; + font-size: 10pt; + width: max-content; } .editor:hover > .errorMessage { diff --git a/src/component/expr/ExprBlock.tsx b/src/component/expr/ExprBlock.tsx index f048a65..1990538 100644 --- a/src/component/expr/ExprBlock.tsx +++ b/src/component/expr/ExprBlock.tsx @@ -50,13 +50,11 @@ export function ExprBlock(props: ExprBlockProps) { const actions = getActions(globalContext, props.setState); const extraHandlers = Object.fromEntries(Object.entries(actions).map(([shortcut, action]) => [shortcut, (e) => { e.preventDefault(); action(); }])) - - console.log(props.typeInfo.err); return {renderBlock[props.state.kind]()} {(props.typeInfo.err !== undefined) && (
- {props.typeInfo.err.message} + {props.typeInfo.err.message.trim()}
)} setState(state => ({...state, name}))} extraHandlers={{}} /> +
::
 =  diff --git a/src/eval/infer_type.ts b/src/eval/infer_type.ts index dc77b50..8b0bcf4 100644 --- a/src/eval/infer_type.ts +++ b/src/eval/infer_type.ts @@ -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), + }; + const innerTypeInfoWithoutTypeVar = inferType(expr, innerEnv); + return { + subs: innerTypeInfo.subs, + newEnv: env, + paramType: innerTypeInfoWithoutTypeVar.type, + inner: innerTypeInfoWithoutTypeVar, + innerEnv, + } + } return { subs: subsWithoutPType, newEnv,