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;
|
background-color: pink;
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
|
font-family: var(--my-monospace-font);
|
||||||
|
white-space-collapse: preserve;
|
||||||
|
font-size: 10pt;
|
||||||
|
width: max-content;
|
||||||
}
|
}
|
||||||
|
|
||||||
.editor:hover > .errorMessage {
|
.editor:hover > .errorMessage {
|
||||||
|
|
|
||||||
|
|
@ -50,13 +50,11 @@ export function ExprBlock(props: ExprBlockProps) {
|
||||||
const actions = getActions(globalContext, props.setState);
|
const actions = getActions(globalContext, props.setState);
|
||||||
const extraHandlers = Object.fromEntries(Object.entries(actions).map(([shortcut, action]) =>
|
const extraHandlers = Object.fromEntries(Object.entries(actions).map(([shortcut, action]) =>
|
||||||
[shortcut, (e) => { e.preventDefault(); action(); }]))
|
[shortcut, (e) => { e.preventDefault(); action(); }]))
|
||||||
|
|
||||||
console.log(props.typeInfo.err);
|
|
||||||
return <span className={"editor" + (props.typeInfo.err ? " error" : "")}>
|
return <span className={"editor" + (props.typeInfo.err ? " error" : "")}>
|
||||||
{renderBlock[props.state.kind]()}
|
{renderBlock[props.state.kind]()}
|
||||||
{(props.typeInfo.err !== undefined) &&
|
{(props.typeInfo.err !== undefined) &&
|
||||||
(<div className="errorMessage">
|
(<div className="errorMessage">
|
||||||
{props.typeInfo.err.message}
|
{props.typeInfo.err.message.trim()}
|
||||||
</div>)}
|
</div>)}
|
||||||
<Input
|
<Input
|
||||||
placeholder="<c>"
|
placeholder="<c>"
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,7 @@ function DeclColumns({state, setState, score, typeInfo}) {
|
||||||
onTextChange={name => setState(state => ({...state, name}))}
|
onTextChange={name => setState(state => ({...state, name}))}
|
||||||
extraHandlers={{}}
|
extraHandlers={{}}
|
||||||
/>
|
/>
|
||||||
|
<br/>
|
||||||
:: <TypeInfoBlock typeInfo={typeInfo.value} />
|
:: <TypeInfoBlock typeInfo={typeInfo.value} />
|
||||||
</span>
|
</span>
|
||||||
<span className="keyword column"> = </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 {
|
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);
|
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:
|
// to eval the 'inner' expr, we only need to add our parameter to the environment:
|
||||||
const innerEnv = {
|
const innerEnv = {
|
||||||
names: trie.insert(env.names)(s.name)({
|
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 {
|
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);
|
const recursiveTypeInfo = iterateRecursiveType(s.paramName, s.expr, env, false);
|
||||||
console.log('end inferTypeLambda.');
|
|
||||||
return {
|
return {
|
||||||
kind: "lambda",
|
kind: "lambda",
|
||||||
type: fnType(_ => recursiveTypeInfo.paramType)(_ => recursiveTypeInfo.inner.type),
|
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.
|
// 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.
|
// 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);
|
let [paramType] = typeUnknown(env);
|
||||||
const paramTypeVar = paramType.symbol;
|
const paramTypeVar = paramType.symbol;
|
||||||
|
|
||||||
|
|
@ -230,6 +225,24 @@ function iterateRecursiveType(paramName: string, expr: ExprBlockState, env: Stat
|
||||||
// console.log("-----------------");
|
// console.log("-----------------");
|
||||||
|
|
||||||
if (eqType(inferredPType2)(paramType)) {
|
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 {
|
return {
|
||||||
subs: subsWithoutPType,
|
subs: subsWithoutPType,
|
||||||
newEnv,
|
newEnv,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue