Skip to content

Commit

Permalink
add expression-function evaluation and fix argument order
Browse files Browse the repository at this point in the history
  • Loading branch information
brettfo committed Feb 12, 2024
1 parent c7260d3 commit 64cc5e4
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 18 deletions.
47 changes: 29 additions & 18 deletions src/expression.ts
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ export abstract class Expression {
functionArgs.push(stack.pop()!);
}

stack.push(new FunctionCallExpression(func, functionArgs));
stack.push(new FunctionCallExpression(func, functionArgs.reverse()));
break;
case 'identifier':
stack.push(new VariableExpression((<IdentifierToken>token).text));
Expand Down Expand Up @@ -395,32 +395,44 @@ export abstract class Expression {

protected static get defaultFunctions(): { [key: string]: FunctionDefinition } {
return {
"cos": new FunctionDefinition(1, 1, args => {
const result = Math.cos(args[0]);
"cos": new FunctionDefinition(1, 1, (args, variables) => {
const result = Math.cos(args[0].evaluate(variables));
return result;
}),
"ln": new FunctionDefinition(1, 1, args => {
const result = Math.log(args[0]);
"ln": new FunctionDefinition(1, 1, (args, variables) => {
const result = Math.log(args[0].evaluate(variables));
return result;
}),
"log": new FunctionDefinition(2, 2, args => {
const result = Math.log(args[0]) / Math.log(args[1]);
"log": new FunctionDefinition(2, 2, (args, variables) => {
const result = Math.log(args[0].evaluate(variables)) / Math.log(args[1].evaluate(variables));
return result;
}),
"max": new FunctionDefinition(2, 2, args => {
const result = Math.max(...args);
"max": new FunctionDefinition(2, 2, (args, variables) => {
const result = Math.max(...args.map(a => a.evaluate(variables)));
return result;
}),
"min": new FunctionDefinition(2, 2, args => {
const result = Math.min(...args);
"min": new FunctionDefinition(2, 2, (args, variables) => {
const result = Math.min(...args.map(a => a.evaluate(variables)));
return result;
}),
"sin": new FunctionDefinition(1, 1, args => {
const result = Math.sin(args[0]);
"sin": new FunctionDefinition(1, 1, (args, variables) => {
const result = Math.sin(args[0].evaluate(variables));
return result;
}),
"tan": new FunctionDefinition(1, 1, args => {
const result = Math.tan(args[0]);
"sum": new FunctionDefinition(4, 4, (args, variables) => {
const expr = args[0];
const ident = <VariableExpression>args[1];
const start = args[2].evaluate(variables);
const end = args[3].evaluate(variables);
let sum = 0;
for (let i = start; i <= end; i++) {
sum += expr.evaluate({ ...variables, [ident.name]: new NumberExpression(i) })
}

return sum;
}),
"tan": new FunctionDefinition(1, 1, (args, variables) => {
const result = Math.tan(args[0].evaluate(variables));
return result;
}),
};
Expand Down Expand Up @@ -508,14 +520,13 @@ export class FunctionCallExpression extends Expression {
}

evaluate(variables: { [key: string]: Expression }): number {
const evaluatedArgs = this.args.map(a => a.evaluate(variables));
const result = this._definition.handler(evaluatedArgs);
const result = this._definition.handler(this.args, variables);
return result;
}
}

export class FunctionDefinition {
constructor(readonly minimumArgumentCount: number, readonly maximumArgumentCount: number, readonly handler: (args: number[]) => number) {
constructor(readonly minimumArgumentCount: number, readonly maximumArgumentCount: number, readonly handler: (args: Expression[], variables: { [key: string]: Expression }) => number) {

}
}
4 changes: 4 additions & 0 deletions tests/expression.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,5 +55,9 @@ describe('expression', () => {
const result = Expression.evaluate('min(3, 5)');
expect(result).to.equal(3);
});
it.only('can apply functions with expression arguments', () => {
const result = Expression.evaluate('sum(x^2,x,1,3)');
expect(result).to.equal(14);
});
});
});

0 comments on commit 64cc5e4

Please sign in to comment.