From 5fdaa70d0af1356652de38f66fccef4bd3088a26 Mon Sep 17 00:00:00 2001 From: Kai Stevenson Date: Sun, 2 Nov 2025 19:42:39 -0800 Subject: fn, call --- src/lang/core/eval.ts | 123 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 102 insertions(+), 21 deletions(-) (limited to 'src/lang/core/eval.ts') diff --git a/src/lang/core/eval.ts b/src/lang/core/eval.ts index 6a25a6c..258999a 100644 --- a/src/lang/core/eval.ts +++ b/src/lang/core/eval.ts @@ -3,40 +3,121 @@ import { BUILTIN_Arr, BUILTIN_Mul, BUILTIN_ToString, + SBUILTIN_Call, + SBUILTIN_Map, } from "../builtin"; +import { ToString } from "../util"; import { ASTNode, NodeType } from "./common"; import { Lex } from "./lexer"; import { Parse } from "./parser"; +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 + : never; + } + : never; + export type SENTINEL_NO_BUILTIN = "__NO_BUILTIN__"; -export type MapBuiltins = - Node["children"] extends infer Children extends readonly ASTNode[] - ? { - [Idx in keyof Children]: Children[Idx] extends ASTNode - ? Evaluate - : never; - } extends infer Args extends readonly any[] - ? Node["name"] extends "tostring" - ? BUILTIN_ToString - : Node["name"] extends "arr" - ? BUILTIN_Arr - : Node["name"] extends "add" - ? BUILTIN_Add - : Node["name"] extends "mul" - ? BUILTIN_Mul - : SENTINEL_NO_BUILTIN - : never - : never; +export type MapBuiltins< + Node extends ASTNode, + Frame extends StackFrame +> = GetEvaluatedChildren extends infer Args extends readonly any[] + ? Node["name"] extends "call" + ? SBUILTIN_Call + : Node["name"] extends "map" + ? SBUILTIN_Map + : Node["name"] extends "tostring" + ? BUILTIN_ToString + : Node["name"] extends "arr" + ? BUILTIN_Arr + : Node["name"] extends "add" + ? BUILTIN_Add + : Node["name"] extends "mul" + ? BUILTIN_Mul + : SENTINEL_NO_BUILTIN + : never; export type EvalError = `Eval error: ${T}`; -export type Evaluate = Node["type"] extends NodeType.INT +export type StackFrame< + Bindings extends Record = Record, + Parent extends StackFrame | null = any +> = { + bindings: Bindings; + parent: Parent; +}; + +export type EmptyStackFrame = StackFrame<{}, null>; + +export type WithPushedBindings< + OldFrame extends StackFrame, + Bindings extends StackFrame["bindings"] +> = StackFrame; + +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; + +export type MapOnStack< + Node extends ASTNode, + Frame extends StackFrame +> = FindInStack; + +export type FnPrim< + Args extends readonly ASTNode[] = readonly ASTNode[], + Fn extends ASTNode = ASTNode +> = { args: Args; fn: Fn }; + +// Can support multiple args, just need to make the last arg be the fn +export type HandleFn = Node["children"] extends [ + infer Arg extends ASTNode, + infer Fn extends ASTNode +] + ? FnPrim<[Arg], Fn> + : never; + +type MapZip = { + [Idx in Exclude< + keyof T, + keyof any[] + > as T[Idx] extends infer Node extends ASTNode + ? Node["name"] + : never]: Idx extends keyof U ? U[Idx] : never; +}; + +export type CallFn< + Fn extends FnPrim, + Values extends readonly any[], + Frame extends StackFrame +> = Evaluate, Frame>>; + +export type Evaluate< + Node extends ASTNode, + Frame extends StackFrame = EmptyStackFrame +> = Node["type"] extends NodeType.INT ? Node["value"] : Node["type"] extends NodeType.EXT - ? MapBuiltins + ? // special builtin + Node["name"] extends "fn" + ? HandleFn + : MapBuiltins extends infer BI + ? BI extends SENTINEL_NO_BUILTIN + ? MapOnStack + : BI + : never : EvalError<`Unhandled node type ${Node["type"]}`>; -const input = `` as const; +const input = `map(arr(5,5,5), fn(n, add(n, 1)))` as const; const lex_result = null as unknown as Lex; const parse_result = null as unknown as Parse; const eval_result = null as unknown as Evaluate; -- cgit v1.2.3-70-g09d2