From ccaff310c85a64a852d96ee71ecf9640de57ea36 Mon Sep 17 00:00:00 2001 From: Kai Stevenson Date: Thu, 6 Nov 2025 20:25:30 -0800 Subject: runtime works --- src/lang/js-lang/builtin/sbuiltin.ts | 2 +- src/lang/js-lang/core/eval.ts | 29 +++++++++++++---------------- src/lang/ks-lang/index.ts | 13 +++++++++---- 3 files changed, 23 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/lang/js-lang/builtin/sbuiltin.ts b/src/lang/js-lang/builtin/sbuiltin.ts index 663c2f9..013854c 100644 --- a/src/lang/js-lang/builtin/sbuiltin.ts +++ b/src/lang/js-lang/builtin/sbuiltin.ts @@ -7,7 +7,7 @@ export const V_SBUILTIN_Call: SBUILTIN = (node, frame) => { const children = getEvaluatedChildren(node, frame); const fn = children[0] as FnPrim | undefined; - if (!fn?.fn) { + if (!fn) { throw new Error( `Invalid params for function call: ${JSON.stringify( children, diff --git a/src/lang/js-lang/core/eval.ts b/src/lang/js-lang/core/eval.ts index 1a9e292..dfbd3ce 100644 --- a/src/lang/js-lang/core/eval.ts +++ b/src/lang/js-lang/core/eval.ts @@ -6,9 +6,8 @@ import { NodeType, FnPrim, SENTINEL_NO_BUILTIN, - NamedFnPrim, } from "../../ts-lang"; -import { nameToBUILTIN, nameToSBUILTIN, V_SBUILTIN_Map } from "../builtin"; +import { nameToBUILTIN, nameToSBUILTIN } from "../builtin"; const V_SENTINEL_NO_BUILTIN: SENTINEL_NO_BUILTIN = "__NO_BUILTIN__"; @@ -35,14 +34,7 @@ const handleBind = (node: ASTNode, frame: StackFrame) => { const inner = _evaluate(node.children[1], frame); if (inner.fn) { - const named: NamedFnPrim = { - args: inner.args, - fn: inner.fn, - name: node.children[0].name, - frame, - }; - - return named; + return [inner, frame, node.children[0]["name"]]; } return inner; @@ -60,18 +52,23 @@ const handleFn = (node: ASTNode): FnPrim => { const mapZip = (args: ASTNode[], values: any[]) => Object.fromEntries(args.map(({ name }, i) => [name, values[i]])); -export const callFn = (fn: FnPrim, values: any[], frame: StackFrame) => { - if ((fn as NamedFnPrim).frame) { - return _evaluate(fn.fn, { +export const callFn = ( + fn: FnPrim | [FnPrim, StackFrame, ASTNode["name"]], + values: any[], + frame: StackFrame +) => { + if (Array.isArray(fn)) { + const [prim, frame, name] = fn; + return _evaluate(prim.fn, { bindings: { - ...mapZip(fn.args as ASTNode[], values), ...frame.bindings, - ...(fn as NamedFnPrim).frame.bindings, + [name]: fn, + ...mapZip(prim.args as ASTNode[], values), }, }); } return _evaluate(fn.fn, { - bindings: { ...mapZip(fn.args as ASTNode[], values), ...frame.bindings }, + bindings: { ...frame.bindings, ...mapZip(fn.args as ASTNode[], values) }, }); }; diff --git a/src/lang/ks-lang/index.ts b/src/lang/ks-lang/index.ts index 772c9c9..633d9b9 100644 --- a/src/lang/ks-lang/index.ts +++ b/src/lang/ks-lang/index.ts @@ -8,6 +8,7 @@ import { CallFn, EmptyStackFrame, ASTNode, + StackFrame, } from "../ts-lang"; export type TransformArgs = { @@ -40,13 +41,17 @@ export const createFn = : EvalError<`Program's args do not extend args constraint`> : EvalError<"Cannot create a function from a program that does not eval to a function"> : never => { - const [programFn] = evaluate(parse(lex(program))) as Array; - if (!programFn.fn) { + const [e] = evaluate(parse(lex(program))) as [ + FnPrim | [FnPrim, StackFrame, ASTNode["name"]] + ]; + + const fn: FnPrim = Array.isArray(e) ? e[0] : e; + + if (!fn.fn) { throw new Error( "Cannot create a function from a program that does not eval to a function" ); } - return ((...args: any[]) => - callFn(programFn, args, emptyStackFrame)) as any; + return ((...args: any[]) => callFn(e, args, emptyStackFrame)) as any; }; -- cgit v1.2.3-70-g09d2