decent progress
This commit is contained in:
parent
e901fc3f76
commit
a9ae4f9888
14 changed files with 318 additions and 162 deletions
135
src/Editor.tsx
135
src/Editor.tsx
|
|
@ -3,6 +3,11 @@ import { getSymbol, getType, module2Env, ModuleStd, symbolFunction } from "dope2
|
|||
import { InputBlock, type InputBlockState } from "./InputBlock";
|
||||
import { type Dynamic, type State2Props } from "./util/extra";
|
||||
import { CallBlock, type CallBlockState } from "./CallBlock";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Type } from "./Type";
|
||||
|
||||
import "./Editor.css"
|
||||
import { focusNextElement } from "./util/dom_trickery";
|
||||
|
||||
interface LetInBlockState {
|
||||
kind: "let";
|
||||
|
|
@ -10,12 +15,17 @@ interface LetInBlockState {
|
|||
name: string;
|
||||
value: EditorState;
|
||||
inner: EditorState;
|
||||
resolved: undefined | Dynamic;
|
||||
rollback?: EditorState;
|
||||
}
|
||||
|
||||
interface LambdaBlockState {
|
||||
kind: "lambda";
|
||||
env: any;
|
||||
paramName: string;
|
||||
expr: EditorState;
|
||||
resolved: undefined | Dynamic;
|
||||
rollback?: EditorState;
|
||||
}
|
||||
|
||||
export type EditorState =
|
||||
|
|
@ -29,72 +39,73 @@ export const initialEditorState: EditorState = {
|
|||
env: module2Env(ModuleStd),
|
||||
text: "",
|
||||
resolved: undefined,
|
||||
rollback: undefined,
|
||||
};
|
||||
|
||||
type EditorProps = State2Props<EditorState>;
|
||||
interface EditorProps extends State2Props<EditorState> {
|
||||
onResolve: (state: EditorState) => void;
|
||||
onCancel: () => void;
|
||||
}
|
||||
|
||||
const dontFilter = () => true;
|
||||
|
||||
export function Editor({state, setState}: EditorProps) {
|
||||
let onResolve;
|
||||
switch (state.kind) {
|
||||
case "input":
|
||||
onResolve = (resolved: InputBlockState) => {
|
||||
console.log('resolved!', state, resolved);
|
||||
if (resolved) {
|
||||
const type = getType(resolved.resolved);
|
||||
if (getSymbol(type) === symbolFunction) {
|
||||
console.log('function!');
|
||||
// we were InputBlock
|
||||
// now we become FunctionBlock
|
||||
setState({
|
||||
kind: "call",
|
||||
env: state.env,
|
||||
fn: resolved,
|
||||
input: initialEditorState,
|
||||
})
|
||||
}
|
||||
}
|
||||
// const type = getType(state.resolved);
|
||||
// if (getSymbol(type) === symbolFunction) {
|
||||
// console.log('function!');
|
||||
// console.log('editor state:', state);
|
||||
// }
|
||||
}
|
||||
return <InputBlock state={state} setState={setState} filter={dontFilter} onResolve={onResolve} />;
|
||||
case "call":
|
||||
onResolve = (d: Dynamic) => {}
|
||||
return <CallBlock state={state} setState={setState} onResolve={onResolve} />;
|
||||
case "let":
|
||||
return <></>;
|
||||
case "lambda":
|
||||
return <></>;
|
||||
export function Editor({state, setState, onResolve, onCancel}: EditorProps) {
|
||||
const [proxyState, setProxyState] = useState<'unresolved'|'command'|'resolved'>('unresolved');
|
||||
const onMyResolve = (editorState: EditorState) => {
|
||||
setState(editorState);
|
||||
if (editorState.resolved) {
|
||||
setProxyState('command');
|
||||
}
|
||||
else {
|
||||
setProxyState('unresolved');
|
||||
}
|
||||
}
|
||||
// const onMyCancel
|
||||
const onCommand = (e: React.KeyboardEvent) => {
|
||||
const type = getType(state.resolved);
|
||||
if (e.key === "c" && getSymbol(type) === symbolFunction) {
|
||||
e.preventDefault();
|
||||
// we become CallBlock
|
||||
setState({
|
||||
kind: "call",
|
||||
env: state.env,
|
||||
fn: state,
|
||||
input: initialEditorState,
|
||||
resolved: undefined,
|
||||
rollback: state,
|
||||
});
|
||||
setProxyState('resolved');
|
||||
}
|
||||
if (e.key === "u" || e.key === "Enter") {
|
||||
setProxyState('resolved');
|
||||
onResolve(state);
|
||||
}
|
||||
};
|
||||
|
||||
const renderBlock = () => {
|
||||
switch (state.kind) {
|
||||
case "input":
|
||||
return <InputBlock state={state} setState={setState} filter={dontFilter} onResolve={onMyResolve} onCancel={onCancel} />;
|
||||
case "call":
|
||||
return <CallBlock state={state} setState={setState} onResolve={onMyResolve} />;
|
||||
case "let":
|
||||
return <></>;
|
||||
case "lambda":
|
||||
return <></>;
|
||||
}
|
||||
}
|
||||
return <>
|
||||
{renderBlock()}
|
||||
{
|
||||
(state.resolved)
|
||||
? <div className="typeSignature">
|
||||
:: <Type type={getType(state.resolved)} />
|
||||
{ (proxyState === 'command')
|
||||
? <input autoFocus={true} className="editable command" placeholder="<enter command>" onKeyDown={onCommand} value=""/>
|
||||
: <></>
|
||||
}
|
||||
</div>
|
||||
: <></>
|
||||
}
|
||||
</>;
|
||||
}
|
||||
|
||||
// function DynamicBlock({env, name, dynamic}) {
|
||||
// const type = getType(dynamic);
|
||||
// if (getSymbol(type) === symbolFunction) {
|
||||
// return <FunctionBlock env={env} name={name} funDynamic={dynamic} />;
|
||||
// }
|
||||
// else return <>{getInst(dynamic).toString()} :: <Type type={type}/></>;
|
||||
// }
|
||||
|
||||
// function InputBlock({env, done, type}) {
|
||||
// const filterInputType = ([_, dynamic]) => {
|
||||
// try {
|
||||
// unify(type, getType(dynamic));
|
||||
// return true;
|
||||
// } catch (e) {
|
||||
// if (!(e instanceof UnifyError)) {
|
||||
// console.error(e);
|
||||
// }
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
// return <>
|
||||
// <span className="typeAnnot"><InputBlock env={env} done={done} filter={filterInputType} /></span>
|
||||
// <span className="typeAnnot">:: <Type type={type}/></span>
|
||||
// </>;
|
||||
// }
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue