From 955bb17f9a38fe14a1ce85c2ca00ed883698c18d Mon Sep 17 00:00:00 2001 From: Joeri Exelmans Date: Wed, 28 May 2025 08:13:33 +0200 Subject: [PATCH] display dynamic errors too --- src/component/app/App.tsx | 6 ++-- src/component/expr/ExprBlock.tsx | 10 ++++--- src/eval/eval.ts | 47 ++++++++++++++++++++++++-------- 3 files changed, 46 insertions(+), 17 deletions(-) diff --git a/src/component/app/App.tsx b/src/component/app/App.tsx index 15919f3..2509f1f 100644 --- a/src/component/app/App.tsx +++ b/src/component/app/App.tsx @@ -137,8 +137,10 @@ export function App() { const currentState = appState.history.at(-1)!; - // infer types for entire app state + // static evalution const typeInfo = useMemo(() => inferType(currentState, extendedEnv), [currentState]); + // dynamic evalutions + const evalResult = evalExpr(currentState, extendedEnv); return ( <> @@ -186,7 +188,7 @@ export function App() { /> = :: diff --git a/src/component/expr/ExprBlock.tsx b/src/component/expr/ExprBlock.tsx index 1990538..32d7d80 100644 --- a/src/component/expr/ExprBlock.tsx +++ b/src/component/expr/ExprBlock.tsx @@ -11,6 +11,7 @@ import { LambdaBlock, type LambdaBlockProps, type LambdaBlockState } from "./Lam import { LetInBlock, type LetInBlockProps, type LetInBlockState } from "./LetInBlock"; import "./ExprBlock.css"; +import { evalExpr } from "../../eval/eval"; export type ExprBlockState = InputBlockState @@ -49,12 +50,13 @@ 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(); }])) - return + [shortcut, (e) => { e.preventDefault(); action(); }])); + const err = props.typeInfo.err || evalExpr(props.state, env).err; + return {renderBlock[props.state.kind]()} - {(props.typeInfo.err !== undefined) && + {(err !== undefined) && (
- {props.typeInfo.err.message.trim()} + {err.message.trim()}
)} any; - return ctor(s.text); + return { + val: ctor(s.text) + }; } else if (s.value.kind === "name") { const found = trie.get(env.names)(s.text); if (found) { if (found.recursive) { + // dirty return found.i(); } - return found.i; + return {val: found.i}; } } + return { + err: new Error(`'${s.text}' not found`), + } } export function evalCall(s: CallBlockState, env: DynamicEnvironment): EvalResult { const fn = evalExpr(s.fn, env); const input = evalExpr(s.input, env); - if (fn !== undefined && input !== undefined) { + if (fn.val !== undefined && input.val !== undefined) { try { - return fn(input); + const result = fn.val(input.val) + return { val: result } ; + } + catch (e: any) { + return { err: e }; } - catch {} } + return {}; } export function evalLet(s: LetInBlockState, env: DynamicEnvironment): EvalResult { const valueEnv = { names: trie.insert(env.names)(s.name)({ recursive: true, - i: () => { try { return value; } catch (e) {} }, + i: () => { + try { + return { val }; + } catch (e) { + return { err: e }; + } + }, }), }; - const value = evalExpr(s.value, valueEnv); + const {val} = evalExpr(s.value, valueEnv); const innerEnv = { - names: trie.insert(env.names)(s.name)({i: value}), + names: trie.insert(env.names)(s.name)({i: val}), } return evalExpr(s.inner, innerEnv); } @@ -75,7 +99,8 @@ export function evalLambda(s: LambdaBlockState, env: DynamicEnvironment): EvalRe const innerEnv = { names: trie.insert(env.names)(s.paramName)({i: x}) }; - return evalExpr(s.expr, innerEnv); + const result = evalExpr(s.expr, innerEnv); + return result.val; }; - return fn; + return {val: fn}; }