MCPcopy
hub / github.com/josdejong/mathjs / _compile

Method _compile

src/expression/node/FunctionNode.js:142–305  ·  view source on GitHub ↗

* Compile a node into a JavaScript function. * This basically pre-calculates as much as possible and only leaves open * calculations which depend on a dynamic scope with variables. * @param {Object} math Math.js namespace with functions and constants. * @param {Object} argNam

(math, argNames)

Source from the content-addressed store, hash-verified

140 * evalNode(scope: Object, args: Object, context: *)
141 */
142 _compile (math, argNames) {
143 // compile arguments
144 const evalArgs = this.args.map((arg) => arg._compile(math, argNames))
145 const fromOptionalChaining = this.optional ||
146 (isAccessorNode(this.fn) && this.fn.optionalChaining)
147
148 if (isSymbolNode(this.fn)) {
149 const name = this.fn.name
150 if (!argNames[name]) {
151 // we can statically determine whether the function
152 // has the rawArgs property
153 const fn = name in math ? getSafeProperty(math, name) : undefined
154 const isRaw = typeof fn === 'function' && fn.rawArgs === true
155
156 const resolveFn = (scope) => {
157 let value
158 if (scope.has(name)) {
159 value = scope.get(name)
160 } else if (name in math) {
161 value = getSafeProperty(math, name)
162 } else if (fromOptionalChaining) value = undefined
163 else return FunctionNode.onUndefinedFunction(name)
164
165 if (typeof value === 'function' ||
166 (fromOptionalChaining && value === undefined)) {
167 return value
168 }
169
170 throw new TypeError(
171 `'${name}' is not a function; its value is:\n ${strin(value)}`
172 )
173 }
174
175 if (isRaw) {
176 // pass unevaluated parameters (nodes) to the function
177 // "raw" evaluation
178 const rawArgs = this.args
179 return function evalFunctionNode (scope, args, context) {
180 const fn = resolveFn(scope)
181
182 // the original function can be overwritten in the scope with a non-rawArgs function
183 if (fn.rawArgs === true) {
184 return fn(rawArgs, math, createSubScope(scope, args))
185 } else {
186 // "regular" evaluation
187 const values = evalArgs.map((evalArg) => evalArg(scope, args, context))
188 return fn(...values)
189 }
190 }
191 } else {
192 // "regular" evaluation
193 switch (evalArgs.length) {
194 case 0: return function evalFunctionNode (scope, args, context) {
195 const fn = resolveFn(scope)
196 if (fromOptionalChaining && fn === undefined) return undefined
197 return fn()
198 }
199 case 1: return function evalFunctionNode (scope, args, context) {

Callers

nothing calls this directly

Calls 11

isAccessorNodeFunction · 0.90
isSymbolNodeFunction · 0.90
getSafePropertyFunction · 0.90
createSubScopeFunction · 0.90
isIndexNodeFunction · 0.90
getSafeMethodFunction · 0.90
strinFunction · 0.85
isObjectPropertyMethod · 0.80
getObjectPropertyMethod · 0.80
mapMethod · 0.65
toStringMethod · 0.65

Tested by

no test coverage detected