UNPKG

d3-view

Version:

View-model d3 plugin for building interactive data-driven web interfaces

104 lines (93 loc) • 2.79 kB
import { code } from "./jsep"; export function evaluate(self, expr, nested) { switch (expr.type) { case code.IDENTIFIER: return self[expr.name]; case code.LITERAL: return nested ? self[expr.value] : expr.value; case code.ARRAY_EXP: return expr.elements.map(elem => { return evaluate(self, elem); }); case code.LOGICAL_EXP: case code.BINARY_EXP: return binaryExp( expr.operator, evaluate(self, expr.left), evaluate(self, expr.right) ); case code.CALL_EXP: return callExpression(self, expr.callee, expr.arguments); case code.MEMBER_EXP: return evaluate(evaluate(self, expr.object), expr.property, true); case code.CONDITIONAL_EXP: return evaluate(self, expr.test) ? evaluate(self, expr.consequent) : evaluate(self, expr.alternate); case code.UNARY_EXP: return unaryExp(expr.operator, evaluate(self, expr.argument)); } } // extract identifiers export function identifiers(expr, all) { if (arguments.length === 1) all = new Set(); switch (expr.type) { case code.IDENTIFIER: all.add(expr.name); break; case code.ARRAY_EXP: expr.elements.forEach(elem => identifiers(elem, all)); break; case code.LOGICAL_EXP: case code.BINARY_EXP: identifiers(expr.left, all); identifiers(expr.right, all); break; case code.CALL_EXP: identifiers(expr.callee, all); expr.arguments.forEach(elem => identifiers(elem, all)); break; case code.MEMBER_EXP: all.add(fullName(expr)); break; case code.CONDITIONAL_EXP: identifiers(expr.test, all); identifiers(expr.consequent, all); evaluate(expr.alternate, all); break; case code.UNARY_EXP: identifiers(expr.argument, all); break; } return all; } function callExpression(self, callee, args) { var func; args = args.map(arg => { return evaluate(self, arg); }); if (callee.type !== code.IDENTIFIER) { self = evaluate(self, callee.object); callee = callee.property; } func = self[callee.name]; if (!func) throw new EvalError(`callable "${callee.name}" not found in context`); return func.apply(self, args); } function unaryExp(op, arg) { if (!unaryFunctions[op]) unaryFunctions[op] = new Function("arg", `return ${op} arg`); return unaryFunctions[op](arg); } function binaryExp(op, a, b) { if (!binaryFunctions[op]) binaryFunctions[op] = new Function("a", "b", `return a ${op} b`); return binaryFunctions[op](a, b); } function fullName(expr) { if (expr.type === code.IDENTIFIER) return expr.name; else return `${fullName(expr.object)}.${expr.property.name}`; } const unaryFunctions = {}; const binaryFunctions = {};