@jsonjoy.com/json-expression
Version:
High-performance JSON Pointer implementation
101 lines (100 loc) • 3.59 kB
JavaScript
"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;