UNPKG

@1771technologies/lytenyte-pro

Version:

Blazingly fast headless React data grid with 100s of features.

63 lines (62 loc) 2.47 kB
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}`); } }