UNPKG

@jsonjoy.com/json-expression

Version:

High-performance JSON Pointer implementation

101 lines (100 loc) 3.59 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.JsonExpressionCodegen = void 0; const tslib_1 = require("tslib"); const util = tslib_1.__importStar(require("./util")); const Codegen_1 = require("@jsonjoy.com/util/lib/codegen/Codegen"); const codegen_steps_1 = require("./codegen-steps"); const createEvaluate_1 = require("./createEvaluate"); const Vars_1 = require("./Vars"); class JsonExpressionCodegen { constructor(options) { this.options = options; this.linkedOperandDeps = new Set(); this.linkOperandDeps = (dependency, name) => { if (name) { if (this.linkedOperandDeps.has(name)) return name; this.linkedOperandDeps.add(name); } else { name = this.codegen.getRegister(); } this.codegen.linkDependency(dependency, name); return name; }; this.operatorConst = (js) => { return this.codegen.addConstant(js); }; this.subExpression = (expr) => { const codegen = new JsonExpressionCodegen({ ...this.options, expression: expr }); const fn = codegen.run().compile(); return fn; }; this.codegen = new Codegen_1.Codegen({ args: ['vars'], epilogue: '', }); this.evaluate = (0, createEvaluate_1.createEvaluate)({ ...options }); } onExpression(expr) { if (expr instanceof Array) { if (expr.length === 1) return new codegen_steps_1.Literal(expr[0]); } else return new codegen_steps_1.Literal(expr); const def = this.options.operators.get(expr[0]); if (def) { const [name, , arity, , codegen, impure] = def; util.assertArity(name, arity, expr); const operands = expr.slice(1).map((operand) => this.onExpression(operand)); if (!impure) { const allLiterals = operands.every((expr) => expr instanceof codegen_steps_1.Literal); if (allLiterals) { const result = this.evaluate(expr, { vars: new Vars_1.Vars(undefined) }); return new codegen_steps_1.Literal(result); } } const ctx = { expr, operands, createPattern: this.options.createPattern, operand: (operand) => this.onExpression(operand), link: this.linkOperandDeps, const: this.operatorConst, subExpression: this.subExpression, var: (value) => this.codegen.var(value), }; return codegen(ctx); } return new codegen_steps_1.Literal(false); } run() { const expr = this.onExpression(this.options.expression); this.codegen.js(`return ${expr};`); return this; } generate() { return this.codegen.generate(); } compileRaw() { return this.codegen.compile(); } compile() { const fn = this.compileRaw(); return (vars) => { try { return fn(vars); } catch (err) { if (err instanceof Error) throw err; const error = new Error('Expression evaluation error.'); error.value = err; throw error; } }; } } exports.JsonExpressionCodegen = JsonExpressionCodegen;