mathjs
Version:
Math.js is an extensive math library for JavaScript and Node.js. It features a flexible expression parser and offers an integrated solution to work with numbers, big numbers, complex numbers, units, and matrices.
149 lines (131 loc) • 4.04 kB
JavaScript
var error = require('../../error');
/**
* Node
*/
function Node() {
if (!(this instanceof Node)) {
throw new SyntaxError('Constructor must be called with the new operator');
}
}
/**
* Evaluate the node
* @return {*} result
*/
// TODO: cleanup deprecated code one day. Deprecated since version 0.19.0
Node.prototype.eval = function () {
throw new Error('Node.eval is deprecated. ' +
'Use Node.compile(math).eval([scope]) instead.');
};
/**
* Compile the node to javascript code
* @param {Object} math math.js instance
* @return {{eval: function}} expr Returns an object with a function 'eval',
* which can be invoked as expr.eval([scope]),
* where scope is an optional object with
* variables.
*/
Node.prototype.compile = function (math) {
if (typeof math !== 'object') {
throw new TypeError('Object expected for parameter math');
}
// definitions globally available inside the closure of the compiled expressions
var defs = {
math: math,
error: error
};
var code = this._compile(defs);
var defsCode = Object.keys(defs).map(function (name) {
return ' var ' + name + ' = defs["' + name + '"];';
});
var factoryCode =
defsCode.join(' ') +
'return {' +
' "eval": function (scope) {' +
' try {' +
' scope = scope || {};' +
' return ' + code + ';' +
' } catch (err) {' +
// replace an index-out-of-range-error with a one-based message
' if (err instanceof defs.error.IndexError) {' +
' err = new defs.error.IndexError(err.index + 1, err.min + 1, err.max + 1);' +
' }' +
' throw err;' +
' }' +
' }' +
'};';
var factory = new Function ('defs', factoryCode);
return factory(defs);
};
/**
* Compile the node to javascript code
* @param {Object} defs Object which can be used to define functions
* and constants globally available inside the closure
* of the compiled expression
* @return {String} js
* @private
*/
Node.prototype._compile = function (defs) {
throw new Error('Cannot compile a Node interface');
};
/**
* Find any node in the node tree matching given filter. For example, to
* find all nodes of type SymbolNode having name 'x':
*
* var results = Node.find({
* type: SymbolNode,
* properties: {
* name: 'x'
* }
* });
*
* @param {Object} filter Available parameters:
* {Function} type
* {Object<String, String>} properties
* @return {Node[]} nodes An array with nodes matching given filter criteria
*/
Node.prototype.find = function (filter) {
return this.match(filter) ? [this] : [];
};
/**
* Test if this object matches given filter
* @param {Object} [filter] Available parameters:
* {Function} type
* {Object<String, *>} properties
* @return {Boolean} matches True if there is a match
*/
Node.prototype.match = function (filter) {
var match = true;
if (filter) {
if (filter.type && !(this instanceof filter.type)) {
match = false;
}
var properties = filter.properties;
if (match && properties) {
for (var prop in properties) {
if (properties.hasOwnProperty(prop)) {
if (this[prop] !== properties[prop]) {
match = false;
break;
}
}
}
}
}
return match;
};
/**
* Get string representation
* @return {String}
*/
Node.prototype.toString = function() {
return '';
};
/**
* Test whether an object is a Node
* @param {*} object
* @returns {boolean} isNode
*/
Node.isNode = function isNode (object) {
return object instanceof Node;
}
module.exports = Node;