dope2-webapp/src/component/expr/LetInBlock.tsx

105 lines
No EOL
3.2 KiB
TypeScript

import { useContext } from "react";
import { EnvContext } from "../../context/EnvContext";
import { GlobalContext } from "../../context/GlobalContext";
import { type TypeInfoLet } from "../../eval/infer_type";
import { Input } from "../other/Input";
import { Type, TypeInfoBlock } from "../other/Type";
import { ExprBlock, type ExprBlockState, type State2Props } from "./ExprBlock";
import "./LetInBlock.css";
export interface LetInBlockState {
kind: "let";
name: string;
focus: boolean;
value: ExprBlockState;
inner: ExprBlockState;
}
export interface LetInBlockProps extends State2Props<LetInBlockState,ExprBlockState> {
typeInfo: TypeInfoLet;
}
export function LetInBlock(props: LetInBlockProps) {
return <span className="letIn">
<div className="decl">
<DeclColumns {...props} />
</div>
<div className="inner">
<InnerMost {...props} />
</div>
</span>
}
function DeclColumns({state, setState, score, typeInfo}) {
const globalContext = useContext(GlobalContext);
const setInner = callback => setState(state => ({...state, inner: callback(state.inner)}));
const setValue = callback => setState(state => ({...state, value: callback(state.value)}));
return <>
<span className="keyword column">let&nbsp;</span>
<span className="column rightAlign">
<Input
placeholder="<name>"
text={state.name}
suggestion=""
onEnter={() => {}}
onCancel={() => {}}
onTextChange={name => setState(state => ({...state, name}))}
extraHandlers={{}}
/>
<br/>
:: <TypeInfoBlock typeInfo={typeInfo.value} />
</span>
<span className="keyword column">&nbsp;=&nbsp;</span>
<span className="column">
<ExprBlock
state={state.value}
setState={setValue}
score={suggestion => score({ ...state, value: suggestion })}
onCancel={() => setState(state => state.inner)} // keep inner
typeInfo={typeInfo.value}
/>
</span>
{state.inner.kind === "let" &&
globalContext?.syntacticSugar &&
<EnvContext value={typeInfo.innerEnv}>
<DeclColumns
state={state.inner}
setState={setInner}
score={suggestion => score({ ...state, inner: suggestion })}
typeInfo={typeInfo.inner}
/>
</EnvContext>
}
</>;
}
function InnerMost({state, setState, score, typeInfo}) {
const globalContext = useContext(GlobalContext);
const setInner = callback => setState(state => ({...state, inner: callback(state.inner)}));
const onCancel = () => setState(state => state.value);
if (state.inner.kind === "let" && globalContext?.syntacticSugar) {
return <EnvContext value={typeInfo.innerEnv}>
<InnerMost
state={state.inner}
setState={setInner}
score={suggestion => score({ ...state, inner: suggestion })}
typeInfo={typeInfo.inner}
/>
</EnvContext>;
}
else {
return <EnvContext value={typeInfo.innerEnv}>
<ExprBlock
state={state.inner}
setState={setInner}
score={suggestion => score({ ...state, inner: suggestion })}
onCancel={onCancel} // keep value
typeInfo={typeInfo.inner}
/>
</EnvContext>
}
}