nicer looking types
This commit is contained in:
parent
428e8cd298
commit
abd3bd3645
4 changed files with 25 additions and 9 deletions
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 <span className={"editor" + (props.typeInfo.err ? " error" : "")}>
|
||||
{renderBlock[props.state.kind]()}
|
||||
{(props.typeInfo.err !== undefined) &&
|
||||
(<div className="errorMessage">
|
||||
{props.typeInfo.err.message}
|
||||
{props.typeInfo.err.message.trim()}
|
||||
</div>)}
|
||||
<Input
|
||||
placeholder="<c>"
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ function DeclColumns({state, setState, score, typeInfo}) {
|
|||
onTextChange={name => setState(state => ({...state, name}))}
|
||||
extraHandlers={{}}
|
||||
/>
|
||||
<br/>
|
||||
:: <TypeInfoBlock typeInfo={typeInfo.value} />
|
||||
</span>
|
||||
<span className="keyword column"> = </span>
|
||||
|
|
|
|||
|
|
@ -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