diff options
| author | Kai Stevenson <kai@kaistevenson.com> | 2025-11-05 01:20:07 -0800 |
|---|---|---|
| committer | Kai Stevenson <kai@kaistevenson.com> | 2025-11-06 20:28:00 -0800 |
| commit | d8a969e231135978c4dd1fa67559101f506ad6f3 (patch) | |
| tree | 7a556db33abe541fa3f5902690ca93d782c0ecc7 /src/lang/ts-lang/core/eval.ts | |
| parent | e86c68dffaffee6ba44d98ba06761245f6d5b670 (diff) | |
recursion works for types with depth limit 5
Diffstat (limited to 'src/lang/ts-lang/core/eval.ts')
| -rw-r--r-- | src/lang/ts-lang/core/eval.ts | 113 |
1 files changed, 98 insertions, 15 deletions
diff --git a/src/lang/ts-lang/core/eval.ts b/src/lang/ts-lang/core/eval.ts index b2fecaa..511ada9 100644 --- a/src/lang/ts-lang/core/eval.ts +++ b/src/lang/ts-lang/core/eval.ts @@ -1,14 +1,22 @@ import { BUILTIN_Add, BUILTIN_Arr, + BUILTIN_Eq, BUILTIN_IfElse, BUILTIN_Mul, + BUILTIN_Sub, BUILTIN_ToString, SBUILTIN_Call, SBUILTIN_Map, } from "../builtin"; -import { ToString } from "../util"; -import { ASTNode, EmptyStackFrame, NodeType, StackFrame } from "./common"; +import { NumberToArray, ToString } from "../util"; +import { + ASTNode, + EmptyStackFrame, + MergeStackFrames, + NodeType, + StackFrame, +} from "./common"; export type SENTINEL_NO_BUILTIN = "__NO_BUILTIN__"; export type MapBuiltins< @@ -25,8 +33,12 @@ export type MapBuiltins< ? BUILTIN_Arr<Args> : Node["name"] extends "add" ? BUILTIN_Add<Args> + : Node["name"] extends "sub" + ? BUILTIN_Sub<Args> : Node["name"] extends "mul" ? BUILTIN_Mul<Args> + : Node["name"] extends "eq" + ? BUILTIN_Eq<Args> : Node["name"] extends "?" ? BUILTIN_IfElse<Args> : SENTINEL_NO_BUILTIN @@ -38,25 +50,82 @@ 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>; + ? Frame["bindings"][NameToFind] extends never + ? EvalError<`Can't find name "${ToString<NameToFind>}" on the stack`> + : Frame["bindings"][NameToFind] + : EvalError<`Can't find name "${ToString<NameToFind>}" on the stack`>; 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 [ +export type NamedFnPrim< + Args extends readonly ASTNode[], + Fn extends ASTNode, + Name extends string, + CapturedFrame extends StackFrame +> = { args: Args; fn: Fn; name: Name; frame: CapturedFrame }; + +type BuildDeepBinding< + FnPrim extends NamedFnPrim<any, any, any, any>, + Depth extends readonly any[] = [any, any, any, any, any, any, any] +> = Depth extends [] + ? FnPrim + : BuildDeepBinding< + NamedFnPrim< + FnPrim["args"], + FnPrim["fn"], + FnPrim["name"], + MergeStackFrames< + FnPrim["frame"], + StackFrame<{ + [K in FnPrim["name"]]: NamedFnPrim< + FnPrim["args"], + FnPrim["fn"], + FnPrim["name"], + FnPrim["frame"] + >; + }> + > + >, + Depth extends [infer Head, ...infer Tail] ? Tail : [] + >; + +export type HandleBind< + Node extends ASTNode, + Frame extends StackFrame +> = Node["children"] extends [ + infer Name extends ASTNode, + infer Value extends ASTNode +] + ? _Evaluate<Value, Frame> extends infer U + ? U extends FnPrim + ? NamedFnPrim< + U["args"], + U["fn"], + Name["name"], + Frame + > extends infer NamedFn + ? NamedFn extends NamedFnPrim<infer A, infer F, infer N, any> + ? // RECURSION DEPTH LIMIT = 5 + BuildDeepBinding<NamedFn, NumberToArray<5>> + : never + : never + : U + : never + : never; + +export type HandleFn< + Node extends ASTNode, + Frame extends StackFrame +> = Node["children"] extends [ ...infer Args extends ASTNode[], infer Fn extends ASTNode ] ? FnPrim<Args, Fn> - : // error? - never; + : EvalError<"Invalid args for function call">; -// any[] was propertykey export type MapZip< Args extends readonly ASTNode[], Values extends readonly any[] @@ -70,10 +139,22 @@ export type MapZip< }; export type CallFn< - Fn extends FnPrim, + Fn, Values extends readonly any[], Frame extends StackFrame -> = _Evaluate<Fn["fn"], StackFrame<MapZip<Fn["args"], Values>, Frame>>; +> = Fn extends NamedFnPrim< + infer Args, + infer FnBody, + infer Name, + infer CapturedFrame +> + ? _Evaluate< + FnBody, + MergeStackFrames<CapturedFrame, StackFrame<MapZip<Args, Values>>> + > + : Fn extends FnPrim<infer Args, infer FnBody> + ? _Evaluate<FnBody, MergeStackFrames<Frame, StackFrame<MapZip<Args, Values>>>> + : Fn; export type _Evaluate< Node extends ASTNode, @@ -81,9 +162,11 @@ export type _Evaluate< > = Node["type"] extends NodeType.INT ? Node["value"] : Node["type"] extends NodeType.EXT - ? // special builtin - Node["name"] extends "fn" - ? HandleFn<Node> + ? // special builtins + Node["name"] extends "bind" + ? HandleBind<Node, Frame> + : Node["name"] extends "fn" + ? HandleFn<Node, Frame> : MapBuiltins<Node, Frame> extends infer BI ? BI extends SENTINEL_NO_BUILTIN ? FindInStack<Frame, Node["name"]> |
