117 lines
No EOL
3.6 KiB
TypeScript
117 lines
No EOL
3.6 KiB
TypeScript
import { useContext } from "react";
|
|
|
|
import { ExprBlock, type ExprBlockState } from "./ExprBlock";
|
|
import { EnvContext } from "../../context/EnvContext";
|
|
// import { evalExprBlock, makeInnerEnv, scoreResolved, type ResolvedType } from "./eval";
|
|
import { type State2Props } from "./ExprBlock";
|
|
import { GlobalContext } from "../../context/GlobalContext";
|
|
|
|
import "./LetInBlock.css";
|
|
import { Input } from "../other/Input";
|
|
import { inferTypeLet } from "../../eval/infer_type";
|
|
import { Type } from "../other/Type";
|
|
|
|
export interface LetInBlockState {
|
|
kind: "let";
|
|
name: string;
|
|
focus: boolean;
|
|
value: ExprBlockState;
|
|
inner: ExprBlockState;
|
|
}
|
|
|
|
export interface LetInBlockProps extends State2Props<LetInBlockState,ExprBlockState> {
|
|
}
|
|
|
|
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}) {
|
|
const env = useContext(EnvContext);
|
|
const globalContext = useContext(GlobalContext);
|
|
|
|
const setInner = callback => setState(state => ({...state, inner: callback(state.inner)}));
|
|
const setValue = callback => setState(state => ({...state, value: callback(state.value)}));
|
|
|
|
// const valueSuggestionPriority = (suggestion: ResolvedType) => {
|
|
// const innerEnv = makeInnerEnv(env, name, suggestion);
|
|
// const [resolved] = evalExprBlock(inner, innerEnv);
|
|
// return scoreResolved(resolved, score);
|
|
// };
|
|
|
|
// const [valueResolved] = evalExprBlock(value, env);
|
|
// const innerEnv = makeInnerEnv(env, name, valueResolved);
|
|
|
|
const {paramType, innerEnv} = inferTypeLet(state, env);
|
|
|
|
return <>
|
|
<span className="keyword column">let </span>
|
|
<span className="column rightAlign">
|
|
<Input
|
|
placeholder="<name>"
|
|
text={state.name}
|
|
suggestion=""
|
|
onEnter={() => {}}
|
|
onCancel={() => {}}
|
|
onTextChange={name => setState(state => ({...state, name}))}
|
|
extraHandlers={{}}
|
|
/>
|
|
:: <Type type={paramType} />
|
|
</span>
|
|
<span className="keyword column"> = </span>
|
|
<span className="column">
|
|
<ExprBlock
|
|
state={state.value}
|
|
setState={setValue}
|
|
score={() => 0}
|
|
onCancel={() => setState(state => state.inner)} // keep inner
|
|
/>
|
|
</span>
|
|
{state.inner.kind === "let" &&
|
|
globalContext?.syntacticSugar &&
|
|
<EnvContext value={innerEnv}>
|
|
<DeclColumns
|
|
state={state.inner}
|
|
setState={setInner}
|
|
score={score}
|
|
/>
|
|
</EnvContext>
|
|
}
|
|
</>;
|
|
}
|
|
|
|
function InnerMost({state, setState, score}) {
|
|
const env = useContext(EnvContext);
|
|
const globalContext = useContext(GlobalContext);
|
|
const setInner = callback => setState(state => ({...state, inner: callback(state.inner)}));
|
|
// const [valueResolved] = evalExprBlock(state.value, env);
|
|
// const innerEnv = makeInnerEnv(env, state.name, valueResolved);
|
|
const {paramType, innerEnv} = inferTypeLet(state, env);
|
|
const onCancel = () => setState(state => state.value);
|
|
if (state.inner.kind === "let" && globalContext?.syntacticSugar) {
|
|
return <EnvContext value={innerEnv}>
|
|
<InnerMost
|
|
state={state.inner}
|
|
setState={setInner}
|
|
score={score}
|
|
/>
|
|
</EnvContext>;
|
|
}
|
|
else {
|
|
return <EnvContext value={innerEnv}>
|
|
<ExprBlock
|
|
state={state.inner}
|
|
setState={setInner}
|
|
score={score}
|
|
onCancel={onCancel} // keep value
|
|
/>
|
|
</EnvContext>
|
|
}
|
|
} |