From d8a969e231135978c4dd1fa67559101f506ad6f3 Mon Sep 17 00:00:00 2001 From: Kai Stevenson Date: Wed, 5 Nov 2025 01:20:07 -0800 Subject: recursion works for types with depth limit 5 --- src/lang/ts-lang/core/common.ts | 18 ++++--- src/lang/ts-lang/core/eval.ts | 113 ++++++++++++++++++++++++++++++++++------ 2 files changed, 109 insertions(+), 22 deletions(-) (limited to 'src/lang/ts-lang/core') diff --git a/src/lang/ts-lang/core/common.ts b/src/lang/ts-lang/core/common.ts index fa5cb7c..95a9ad3 100644 --- a/src/lang/ts-lang/core/common.ts +++ b/src/lang/ts-lang/core/common.ts @@ -51,16 +51,20 @@ export type ParserCtx = { }; export type StackFrame< - Bindings extends Record = Record, - Parent extends StackFrame | null = any + Bindings extends Record = Record > = { bindings: Bindings; - parent: Parent; }; -export type EmptyStackFrame = StackFrame<{}, null>; +export type EmptyStackFrame = StackFrame<{}>; -export type WithPushedBindings< +export type MergeStackFrames< OldFrame extends StackFrame, - Bindings extends StackFrame["bindings"] -> = StackFrame; + NewFrame extends StackFrame +> = StackFrame<{ + [K in + | keyof OldFrame["bindings"] + | keyof NewFrame["bindings"]]: K extends keyof NewFrame["bindings"] + ? NewFrame["bindings"][K] + : OldFrame["bindings"][K]; +}>; 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 : Node["name"] extends "add" ? BUILTIN_Add + : Node["name"] extends "sub" + ? BUILTIN_Sub : Node["name"] extends "mul" ? BUILTIN_Mul + : Node["name"] extends "eq" + ? BUILTIN_Eq : Node["name"] extends "?" ? BUILTIN_IfElse : 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}" on the stack`> - : FindInStack; + ? Frame["bindings"][NameToFind] extends never + ? EvalError<`Can't find name "${ToString}" on the stack`> + : Frame["bindings"][NameToFind] + : EvalError<`Can't find name "${ToString}" on the stack`>; export type FnPrim< Args extends readonly ASTNode[] = readonly ASTNode[], Fn extends ASTNode = ASTNode > = { args: Args; fn: Fn }; -export type HandleFn = 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, + 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 extends infer U + ? U extends FnPrim + ? NamedFnPrim< + U["args"], + U["fn"], + Name["name"], + Frame + > extends infer NamedFn + ? NamedFn extends NamedFnPrim + ? // RECURSION DEPTH LIMIT = 5 + BuildDeepBinding> + : 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 - : // 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, Frame>>; +> = Fn extends NamedFnPrim< + infer Args, + infer FnBody, + infer Name, + infer CapturedFrame +> + ? _Evaluate< + FnBody, + MergeStackFrames>> + > + : Fn extends FnPrim + ? _Evaluate>>> + : 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 + ? // special builtins + Node["name"] extends "bind" + ? HandleBind + : Node["name"] extends "fn" + ? HandleFn : MapBuiltins extends infer BI ? BI extends SENTINEL_NO_BUILTIN ? FindInStack -- cgit v1.2.3-70-g09d2