Skip to content

Commit

Permalink
chore: overhaul custom function system & return failure when invalid …
Browse files Browse the repository at this point in the history
…arguments
  • Loading branch information
iyxan23 committed Sep 16, 2024
1 parent 9f71aa7 commit dec7687
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 28 deletions.
10 changes: 5 additions & 5 deletions src/sheet/expression/evaluate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,11 +250,11 @@ describe("expression evaluation", () => {
return s((vName: string) =>
vName === "world" ? "people!" : undefined,
);
}).call
})
: fName === "ret"
? createTemplaterFunction(z.tuple([z.string()]), (s) => {
return success(`ret ${s}`);
}).call
})
: undefined,
(_vName) => undefined,
);
Expand Down Expand Up @@ -322,7 +322,7 @@ describe("expression evaluation", () => {
{ col: 0, row: 0, callTree: ["root"] },
(fName) =>
fName === "getHow"
? createTemplaterNoArgsFunction(() => "how").call
? createTemplaterNoArgsFunction(() => "how")
: undefined,
(vName) =>
vName === "var"
Expand Down Expand Up @@ -396,13 +396,13 @@ describe("expression evaluation", () => {

return success(r, issues);
},
).call,
),
join: createTemplaterFunction(
z.tuple([z.array(z.string()), z.string()]),
(strings, sep) => {
return success(strings.join(sep));
},
).call,
),
})[fName],
(vName) =>
vName === "students"
Expand Down
18 changes: 14 additions & 4 deletions src/sheet/expression/evaluate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,16 @@ export type Issue = {
index?: number;
};

export type TemplaterFunction<R> = {
call: (funcName: string, ...args: any[]) => Result<R>;
export type TemplaterFunctionContext = {
functionName: string;
col: number;
row: number;
callTree: string[];
};
export type TemplaterFunction<R> = (
context: TemplaterFunctionContext,
...args: any[]
) => Result<R>;

export type LambdaFunction<T> = (
lookupLocalVariable?: (name: string) => any,
Expand All @@ -21,7 +28,7 @@ export function evaluateExpression(
context: { col: number; row: number; callTree: string[] },
lookupFunction: (
funcName: string,
) => TemplaterFunction<any>["call"] | undefined,
) => TemplaterFunction<any> | undefined,
lookupVariable: (name: string) => any | undefined,
): Result<any | undefined> {
if (
Expand Down Expand Up @@ -112,7 +119,10 @@ export function evaluateExpression(
]);
}

let result = func(item.identifier, ...funcArgs);
let result = func(
{ functionName: item.identifier, ...context },
...funcArgs,
);

if (result.status === "failed") {
return result;
Expand Down
10 changes: 5 additions & 5 deletions src/sheet/sheet-templater.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ export class SheetTemplater<SheetT extends TemplatableCell> {
const sheetCell = this.sheet.getCell(col, row);
if (sheetCell === null) {
throw new Error(
`cannot find the cell referenced by variable hoist on` +
`fatal: cannot find the cell referenced by variable hoist on` +
` col ${col} row ${row}`,
);
}
Expand All @@ -117,7 +117,7 @@ export class SheetTemplater<SheetT extends TemplatableCell> {
row,
callTree: [`hoisted variable \`${expr.identifier}\``],
},
(funcName) => this.functions[funcName]?.call,
(funcName) => this.functions[funcName],
(variableName) => globalVariables[variableName] ?? data[variableName],
);

Expand All @@ -138,7 +138,7 @@ export class SheetTemplater<SheetT extends TemplatableCell> {
const expandBlocksResult = this.expandBlocks(
parsedExpressions,
blocks,
(fName) => this.functions[fName]?.call,
(fName) => this.functions[fName],
(vName) => globalVariables[vName] ?? data[vName],
sheetShiftEmitter,
);
Expand Down Expand Up @@ -189,7 +189,7 @@ export class SheetTemplater<SheetT extends TemplatableCell> {
blocks: Block[],
lookupFunction: (
name: string,
) => TemplaterFunction<any>["call"] | undefined,
) => TemplaterFunction<any> | undefined,
lookupVariable: (name: string) => any | undefined,
sheetShiftEmitter: SheetShiftEmitter,
): Result<Indexable2DArray<Record<string, any>>> {
Expand Down Expand Up @@ -451,7 +451,7 @@ export class SheetTemplater<SheetT extends TemplatableCell> {
const evalResult = evaluateExpression(
item,
{ ...context, callTree: ["<root>"] },
(funcName) => this.functions[funcName]?.call,
(funcName) => this.functions[funcName],
lookupVariable,
);

Expand Down
29 changes: 15 additions & 14 deletions src/sheet/templater-function.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import { z } from "zod";
import { LambdaFunction, TemplaterFunction } from "./expression/evaluate";
import { Result, success } from "./expression/result";
import { failure, Result, success } from "./expression/result";

export function createTemplaterNoArgsFunction<R>(
call: () => R,
): TemplaterFunction<R> {
return {
call: () => success(call()),
};
return () => success(call());
}

/**
Expand Down Expand Up @@ -80,17 +78,20 @@ export function createTemplaterFunction<T extends z.AnyZodTuple, R>(
schema: T,
call: (...args: MapFunctionsToLambdas<z.infer<T>>) => Result<R>,
): TemplaterFunction<R> {
return {
call: (funcName, ...args: any) => {
const result = schema.safeParse(args);
return ({ functionName, ...context }, ...args: any) => {
const result = schema.safeParse(args);

if (!result.success) {
throw new Error(
`invalid arguments when evaluating function \`${funcName}\`: ${result.error}`,
);
}
if (!result.success) {
return failure(
{
message: `Invalid arguments while calling ${functionName}. trace: ${context.callTree.join(" > ")}`,
col: context.col,
row: context.row,
},
[],
);
}

return call(...(result.data as MapFunctionsToLambdas<z.infer<T>>));
},
return call(...(result.data as MapFunctionsToLambdas<z.infer<T>>));
};
}

0 comments on commit dec7687

Please sign in to comment.