summaryrefslogtreecommitdiff
path: root/src/lang/ts-lang/core/eval.ts
diff options
context:
space:
mode:
authorKai Stevenson <kai@kaistevenson.com>2025-11-05 01:20:07 -0800
committerKai Stevenson <kai@kaistevenson.com>2025-11-06 20:28:00 -0800
commitd8a969e231135978c4dd1fa67559101f506ad6f3 (patch)
tree7a556db33abe541fa3f5902690ca93d782c0ecc7 /src/lang/ts-lang/core/eval.ts
parente86c68dffaffee6ba44d98ba06761245f6d5b670 (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.ts113
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"]>