UNPKG

5.35 kBJavaScriptView Raw
1'use strict'
2
3const format = require('../../utils/string').format
4const escapeLatex = require('../../utils/latex').escape
5
6function factory (type, config, load, typed) {
7 const Node = load(require('./Node'))
8 const getType = load(require('../../function/utils/typeof'))
9
10 /**
11 * A ConstantNode holds a constant value like a number or string.
12 *
13 * Usage:
14 *
15 * new ConstantNode(2.3)
16 * new ConstantNode('hello')
17 *
18 * @param {*} value Value can be any type (number, BigNumber, string, ...)
19 * @constructor ConstantNode
20 * @extends {Node}
21 */
22 function ConstantNode (value) {
23 if (!(this instanceof ConstantNode)) {
24 throw new SyntaxError('Constructor must be called with the new operator')
25 }
26
27 if (arguments.length === 2) {
28 // TODO: remove deprecation error some day (created 2018-01-23)
29 throw new SyntaxError('new ConstantNode(valueStr, valueType) is not supported anymore since math v4.0.0. Use new ConstantNode(value) instead, where value is a non-stringified value.')
30 }
31
32 this.value = value
33 }
34
35 ConstantNode.prototype = new Node()
36
37 ConstantNode.prototype.type = 'ConstantNode'
38
39 ConstantNode.prototype.isConstantNode = true
40
41 /**
42 * Compile a node into a JavaScript function.
43 * This basically pre-calculates as much as possible and only leaves open
44 * calculations which depend on a dynamic scope with variables.
45 * @param {Object} math Math.js namespace with functions and constants.
46 * @param {Object} argNames An object with argument names as key and `true`
47 * as value. Used in the SymbolNode to optimize
48 * for arguments from user assigned functions
49 * (see FunctionAssignmentNode) or special symbols
50 * like `end` (see IndexNode).
51 * @return {function} Returns a function which can be called like:
52 * evalNode(scope: Object, args: Object, context: *)
53 */
54 ConstantNode.prototype._compile = function (math, argNames) {
55 const value = this.value
56
57 return function evalConstantNode () {
58 return value
59 }
60 }
61
62 /**
63 * Execute a callback for each of the child nodes of this node
64 * @param {function(child: Node, path: string, parent: Node)} callback
65 */
66 ConstantNode.prototype.forEach = function (callback) {
67 // nothing to do, we don't have childs
68 }
69
70 /**
71 * Create a new ConstantNode having it's childs be the results of calling
72 * the provided callback function for each of the childs of the original node.
73 * @param {function(child: Node, path: string, parent: Node) : Node} callback
74 * @returns {ConstantNode} Returns a clone of the node
75 */
76 ConstantNode.prototype.map = function (callback) {
77 return this.clone()
78 }
79
80 /**
81 * Create a clone of this node, a shallow copy
82 * @return {ConstantNode}
83 */
84 ConstantNode.prototype.clone = function () {
85 return new ConstantNode(this.value)
86 }
87
88 /**
89 * Get string representation
90 * @param {Object} options
91 * @return {string} str
92 */
93 ConstantNode.prototype._toString = function (options) {
94 return format(this.value, options)
95 }
96
97 /**
98 * Get HTML representation
99 * @param {Object} options
100 * @return {string} str
101 */
102 ConstantNode.prototype.toHTML = function (options) {
103 const value = this._toString(options)
104
105 switch (getType(this.value)) {
106 case 'number':
107 case 'BigNumber':
108 case 'Fraction':
109 return '<span class="math-number">' + value + '</span>'
110 case 'string':
111 return '<span class="math-string">' + value + '</span>'
112 case 'boolean':
113 return '<span class="math-boolean">' + value + '</span>'
114 case 'null':
115 return '<span class="math-null-symbol">' + value + '</span>'
116 case 'undefined':
117 return '<span class="math-undefined">' + value + '</span>'
118
119 default:
120 return '<span class="math-symbol">' + value + '</span>'
121 }
122 }
123
124 /**
125 * Get a JSON representation of the node
126 * @returns {Object}
127 */
128 ConstantNode.prototype.toJSON = function () {
129 return {
130 mathjs: 'ConstantNode',
131 value: this.value
132 }
133 }
134
135 /**
136 * Instantiate a ConstantNode from its JSON representation
137 * @param {Object} json An object structured like
138 * `{"mathjs": "SymbolNode", value: 2.3}`,
139 * where mathjs is optional
140 * @returns {ConstantNode}
141 */
142 ConstantNode.fromJSON = function (json) {
143 return new ConstantNode(json.value)
144 }
145
146 /**
147 * Get LaTeX representation
148 * @param {Object} options
149 * @return {string} str
150 */
151 ConstantNode.prototype._toTex = function (options) {
152 const value = this._toString(options)
153
154 switch (getType(this.value)) {
155 case 'string':
156 return '\\mathtt{' + escapeLatex(value) + '}'
157
158 case 'number':
159 case 'BigNumber':
160 const index = value.toLowerCase().indexOf('e')
161 if (index !== -1) {
162 return value.substring(0, index) + '\\cdot10^{' +
163 value.substring(index + 1) + '}'
164 }
165 return value
166
167 case 'Fraction':
168 return this.value.toLatex()
169
170 default:
171 return value
172 }
173 }
174
175 return ConstantNode
176}
177
178exports.name = 'ConstantNode'
179exports.path = 'expression.node'
180exports.factory = factory