@1771technologies/lytenyte-pro
Version:
Blazingly fast headless React data grid with 100s of features.
63 lines (62 loc) • 2.47 kB
JavaScript
import { parse } from "../parser/parse.js";
import { compile } from "../compiler/compile.js";
import { tokenize, tokenizeSafe } from "../lexer/tokenize/tokenize.js";
import { evaluateBinary } from "./evaluate-binary.js";
import { evaluateUnary } from "./evaluate-unary.js";
const MAX_DEPTH = 1000;
export class Evaluator {
plugins;
constructor(plugins) {
this.plugins = plugins;
}
run = (input, context = {}, options) => {
const node = typeof input === "string" ? compile(parse(input, 0, this.plugins), this.plugins) : input;
return evaluateNode(node, context, 0, this.plugins, options);
};
ast = (input) => {
return compile(parse(input, 0, this.plugins), this.plugins);
};
tokens = (input, tokensizeWhitespace) => {
return tokenize(input, this.plugins, tokensizeWhitespace);
};
tokensSafe = (input, tokensizeWhitespace) => {
return tokenizeSafe(input, this.plugins, tokensizeWhitespace);
};
}
export function evaluateNode(node, context, depth, plugins, options) {
if (depth > MAX_DEPTH) {
throw new Error("Maximum evaluation depth exceeded");
}
// Try plugin evaluation first
if (plugins) {
const evalFn = (n, ctx) => evaluateNode(n, ctx, depth + 1, plugins, options);
for (const plugin of plugins) {
if (plugin.evaluate) {
const result = plugin.evaluate(node, context, evalFn);
if (result !== null)
return result.value;
}
}
}
// Core built-in evaluation
switch (node.type) {
case "NumberLiteral":
return node.value;
case "Identifier": {
if (!(node.name in context)) {
if (options && "undefinedIdentifierFallback" in options)
return options.undefinedIdentifierFallback;
throw new Error(`Identifier "${node.name}" is not defined`);
}
return context[node.name];
}
case "BinaryExpression":
return evaluateBinary(node, context, depth, plugins, options);
case "UnaryExpression":
return evaluateUnary(node.operator, evaluateNode(node.operand, context, depth + 1, plugins, options));
case "SpreadElement":
throw new Error("Unexpected spread element outside of array literal");
default:
throw new Error(`Unknown node type: ${node.type}`);
}
}