diff options
| author | Kai Stevenson <kai@kaistevenson.com> | 2025-11-03 23:41:31 -0800 |
|---|---|---|
| committer | Kai Stevenson <kai@kaistevenson.com> | 2025-11-03 23:41:31 -0800 |
| commit | 8b610f2bcfc223333254ce9679730c42dce6d26e (patch) | |
| tree | ac1eab726395523f8725bda3d040e22214cba409 /src/lang/ts-lang/core/eval.ts | |
| parent | 56040f3ff85e77311f0c864a89afd63fcf1bdb50 (diff) | |
add createFn
Diffstat (limited to 'src/lang/ts-lang/core/eval.ts')
| -rw-r--r-- | src/lang/ts-lang/core/eval.ts | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/src/lang/ts-lang/core/eval.ts b/src/lang/ts-lang/core/eval.ts new file mode 100644 index 0000000..5f22299 --- /dev/null +++ b/src/lang/ts-lang/core/eval.ts @@ -0,0 +1,102 @@ +import { + BUILTIN_Add, + BUILTIN_Arr, + BUILTIN_Mul, + BUILTIN_ToString, + SBUILTIN_Call, + SBUILTIN_Map, +} from "../builtin"; +import { ToString } from "../util"; +import { ASTNode, EmptyStackFrame, NodeType, StackFrame } from "./common"; + +export type SENTINEL_NO_BUILTIN = "__NO_BUILTIN__"; +export type MapBuiltins< + Node extends ASTNode, + Frame extends StackFrame +> = GetEvaluatedChildren<Node, Frame> extends infer Args extends readonly any[] + ? Node["name"] extends "call" + ? SBUILTIN_Call<Node, Frame> + : Node["name"] extends "map" + ? SBUILTIN_Map<Node, Frame> + : Node["name"] extends "tostring" + ? BUILTIN_ToString<Args> + : Node["name"] extends "arr" + ? BUILTIN_Arr<Args> + : Node["name"] extends "add" + ? BUILTIN_Add<Args> + : Node["name"] extends "mul" + ? BUILTIN_Mul<Args> + : SENTINEL_NO_BUILTIN + : never; + +export type EvalError<T extends string> = `Eval error: ${T}`; + +export type FindInStack< + Frame extends StackFrame, + NameToFind +> = NameToFind extends keyof Frame["bindings"] + ? Frame["bindings"][NameToFind] + : Frame["parent"] extends null + ? EvalError<`Can't find name "${ToString<NameToFind>}" on the stack`> + : FindInStack<Frame["parent"], NameToFind>; + +export type FnPrim< + Args extends readonly ASTNode[] = readonly ASTNode[], + Fn extends ASTNode = ASTNode +> = { args: Args; fn: Fn }; + +export type HandleFn<Node extends ASTNode> = Node["children"] extends [ + ...infer Args extends ASTNode[], + infer Fn extends ASTNode +] + ? FnPrim<Args, Fn> + : // error? + never; + +// any[] was propertykey +export type MapZip< + Args extends readonly ASTNode[], + Values extends readonly any[] +> = { + [Idx in Exclude< + keyof Args, + keyof any[] + > as Args[Idx] extends infer Node extends ASTNode + ? Node["name"] + : never]: Idx extends keyof Values ? Values[Idx] : never; +}; + +export type CallFn< + Fn extends FnPrim, + Values extends readonly any[], + Frame extends StackFrame +> = _Evaluate<Fn["fn"], StackFrame<MapZip<Fn["args"], Values>, Frame>>; + +export type _Evaluate< + Node extends ASTNode, + Frame extends StackFrame +> = Node["type"] extends NodeType.INT + ? Node["value"] + : Node["type"] extends NodeType.EXT + ? // special builtin + Node["name"] extends "fn" + ? HandleFn<Node> + : MapBuiltins<Node, Frame> extends infer BI + ? BI extends SENTINEL_NO_BUILTIN + ? FindInStack<Frame, Node["name"]> + : BI + : never + : EvalError<`Unhandled node type ${Node["type"]}`>; + +export type GetEvaluatedChildren< + Node extends ASTNode, + Frame extends StackFrame +> = Node["children"] extends infer Children extends readonly ASTNode[] + ? { + [Idx in keyof Children]: Children[Idx] extends ASTNode + ? _Evaluate<Children[Idx], Frame> + : never; + } + : never; + +export type Evaluate<Node extends ASTNode> = _Evaluate<Node, EmptyStackFrame>; |
