import { callFn, emptyStackFrame, evaluate, lex, parse } from "../js-lang"; import { Evaluate, FnPrim, Lex, Parse, EvalError, CallFn, EmptyStackFrame, ASTNode, } from "../ts-lang"; export type TransformArgs = { [Idx in keyof Args]: any; }; export type AssertArgs< Args extends readonly ASTNode[], ArgsConstraint extends readonly any[] > = TransformArgs extends ArgsConstraint ? ArgsConstraint : never; export const createFn = () => ( program: Program ): Evaluate>> extends [infer ProgramFn extends FnPrim] ? TransformArgs extends ArgsConstraint ? ( ...args: Args ) => CallFn : EvalError<`Program's args do not extend args constraint`> : EvalError<"Cannot create a function from a program that does not eval to a function"> => { const [programFn] = evaluate(parse(lex(program))) as Array; if (!programFn.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; };