UNPKG

9.75 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.createTyped = void 0;
7
8var _is = require("../../utils/is");
9
10var _typedFunction = _interopRequireDefault(require("typed-function"));
11
12var _number = require("../../utils/number");
13
14var _factory = require("../../utils/factory");
15
16function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
17
18/**
19 * Create a typed-function which checks the types of the arguments and
20 * can match them against multiple provided signatures. The typed-function
21 * automatically converts inputs in order to find a matching signature.
22 * Typed functions throw informative errors in case of wrong input arguments.
23 *
24 * See the library [typed-function](https://github.com/josdejong/typed-function)
25 * for detailed documentation.
26 *
27 * Syntax:
28 *
29 * math.typed(name, signatures) : function
30 * math.typed(signatures) : function
31 *
32 * Examples:
33 *
34 * // create a typed function with multiple types per argument (type union)
35 * const fn2 = typed({
36 * 'number | boolean': function (b) {
37 * return 'b is a number or boolean'
38 * },
39 * 'string, number | boolean': function (a, b) {
40 * return 'a is a string, b is a number or boolean'
41 * }
42 * })
43 *
44 * // create a typed function with an any type argument
45 * const log = typed({
46 * 'string, any': function (event, data) {
47 * console.log('event: ' + event + ', data: ' + JSON.stringify(data))
48 * }
49 * })
50 *
51 * @param {string} [name] Optional name for the typed-function
52 * @param {Object<string, function>} signatures Object with one or multiple function signatures
53 * @returns {function} The created typed-function.
54 */
55// returns a new instance of typed-function
56var _createTyped2 = function _createTyped() {
57 // initially, return the original instance of typed-function
58 // consecutively, return a new instance from typed.create.
59 _createTyped2 = _typedFunction["default"].create;
60 return _typedFunction["default"];
61};
62
63var dependencies = ['?BigNumber', '?Complex', '?DenseMatrix', '?Fraction'];
64/**
65 * Factory function for creating a new typed instance
66 * @param {Object} dependencies Object with data types like Complex and BigNumber
67 * @returns {Function}
68 */
69
70var createTyped = /* #__PURE__ */(0, _factory.factory)('typed', dependencies, function createTyped(_ref) {
71 var BigNumber = _ref.BigNumber,
72 Complex = _ref.Complex,
73 DenseMatrix = _ref.DenseMatrix,
74 Fraction = _ref.Fraction;
75
76 // TODO: typed-function must be able to silently ignore signatures with unknown data types
77 // get a new instance of typed-function
78 var typed = _createTyped2(); // define all types. The order of the types determines in which order function
79 // arguments are type-checked (so for performance it's important to put the
80 // most used types first).
81
82
83 typed.types = [{
84 name: 'number',
85 test: _is.isNumber
86 }, {
87 name: 'Complex',
88 test: _is.isComplex
89 }, {
90 name: 'BigNumber',
91 test: _is.isBigNumber
92 }, {
93 name: 'Fraction',
94 test: _is.isFraction
95 }, {
96 name: 'Unit',
97 test: _is.isUnit
98 }, {
99 name: 'string',
100 test: _is.isString
101 }, {
102 name: 'Chain',
103 test: _is.isChain
104 }, {
105 name: 'Array',
106 test: _is.isArray
107 }, {
108 name: 'Matrix',
109 test: _is.isMatrix
110 }, {
111 name: 'DenseMatrix',
112 test: _is.isDenseMatrix
113 }, {
114 name: 'SparseMatrix',
115 test: _is.isSparseMatrix
116 }, {
117 name: 'Range',
118 test: _is.isRange
119 }, {
120 name: 'Index',
121 test: _is.isIndex
122 }, {
123 name: 'boolean',
124 test: _is.isBoolean
125 }, {
126 name: 'ResultSet',
127 test: _is.isResultSet
128 }, {
129 name: 'Help',
130 test: _is.isHelp
131 }, {
132 name: 'function',
133 test: _is.isFunction
134 }, {
135 name: 'Date',
136 test: _is.isDate
137 }, {
138 name: 'RegExp',
139 test: _is.isRegExp
140 }, {
141 name: 'null',
142 test: _is.isNull
143 }, {
144 name: 'undefined',
145 test: _is.isUndefined
146 }, {
147 name: 'AccessorNode',
148 test: _is.isAccessorNode
149 }, {
150 name: 'ArrayNode',
151 test: _is.isArrayNode
152 }, {
153 name: 'AssignmentNode',
154 test: _is.isAssignmentNode
155 }, {
156 name: 'BlockNode',
157 test: _is.isBlockNode
158 }, {
159 name: 'ConditionalNode',
160 test: _is.isConditionalNode
161 }, {
162 name: 'ConstantNode',
163 test: _is.isConstantNode
164 }, {
165 name: 'FunctionNode',
166 test: _is.isFunctionNode
167 }, {
168 name: 'FunctionAssignmentNode',
169 test: _is.isFunctionAssignmentNode
170 }, {
171 name: 'IndexNode',
172 test: _is.isIndexNode
173 }, {
174 name: 'Node',
175 test: _is.isNode
176 }, {
177 name: 'ObjectNode',
178 test: _is.isObjectNode
179 }, {
180 name: 'OperatorNode',
181 test: _is.isOperatorNode
182 }, {
183 name: 'ParenthesisNode',
184 test: _is.isParenthesisNode
185 }, {
186 name: 'RangeNode',
187 test: _is.isRangeNode
188 }, {
189 name: 'SymbolNode',
190 test: _is.isSymbolNode
191 }, {
192 name: 'Object',
193 test: _is.isObject
194 } // order 'Object' last, it matches on other classes too
195 ];
196 typed.conversions = [{
197 from: 'number',
198 to: 'BigNumber',
199 convert: function convert(x) {
200 if (!BigNumber) {
201 throwNoBignumber(x);
202 } // note: conversion from number to BigNumber can fail if x has >15 digits
203
204
205 if ((0, _number.digits)(x) > 15) {
206 throw new TypeError('Cannot implicitly convert a number with >15 significant digits to BigNumber ' + '(value: ' + x + '). ' + 'Use function bignumber(x) to convert to BigNumber.');
207 }
208
209 return new BigNumber(x);
210 }
211 }, {
212 from: 'number',
213 to: 'Complex',
214 convert: function convert(x) {
215 if (!Complex) {
216 throwNoComplex(x);
217 }
218
219 return new Complex(x, 0);
220 }
221 }, {
222 from: 'number',
223 to: 'string',
224 convert: function convert(x) {
225 return x + '';
226 }
227 }, {
228 from: 'BigNumber',
229 to: 'Complex',
230 convert: function convert(x) {
231 if (!Complex) {
232 throwNoComplex(x);
233 }
234
235 return new Complex(x.toNumber(), 0);
236 }
237 }, {
238 from: 'Fraction',
239 to: 'BigNumber',
240 convert: function convert(x) {
241 throw new TypeError('Cannot implicitly convert a Fraction to BigNumber or vice versa. ' + 'Use function bignumber(x) to convert to BigNumber or fraction(x) to convert to Fraction.');
242 }
243 }, {
244 from: 'Fraction',
245 to: 'Complex',
246 convert: function convert(x) {
247 if (!Complex) {
248 throwNoComplex(x);
249 }
250
251 return new Complex(x.valueOf(), 0);
252 }
253 }, {
254 from: 'number',
255 to: 'Fraction',
256 convert: function convert(x) {
257 if (!Fraction) {
258 throwNoFraction(x);
259 }
260
261 var f = new Fraction(x);
262
263 if (f.valueOf() !== x) {
264 throw new TypeError('Cannot implicitly convert a number to a Fraction when there will be a loss of precision ' + '(value: ' + x + '). ' + 'Use function fraction(x) to convert to Fraction.');
265 }
266
267 return f;
268 }
269 }, {
270 // FIXME: add conversion from Fraction to number, for example for `sqrt(fraction(1,3))`
271 // from: 'Fraction',
272 // to: 'number',
273 // convert: function (x) {
274 // return x.valueOf()
275 // }
276 // }, {
277 from: 'string',
278 to: 'number',
279 convert: function convert(x) {
280 var n = Number(x);
281
282 if (isNaN(n)) {
283 throw new Error('Cannot convert "' + x + '" to a number');
284 }
285
286 return n;
287 }
288 }, {
289 from: 'string',
290 to: 'BigNumber',
291 convert: function convert(x) {
292 if (!BigNumber) {
293 throwNoBignumber(x);
294 }
295
296 try {
297 return new BigNumber(x);
298 } catch (err) {
299 throw new Error('Cannot convert "' + x + '" to BigNumber');
300 }
301 }
302 }, {
303 from: 'string',
304 to: 'Fraction',
305 convert: function convert(x) {
306 if (!Fraction) {
307 throwNoFraction(x);
308 }
309
310 try {
311 return new Fraction(x);
312 } catch (err) {
313 throw new Error('Cannot convert "' + x + '" to Fraction');
314 }
315 }
316 }, {
317 from: 'string',
318 to: 'Complex',
319 convert: function convert(x) {
320 if (!Complex) {
321 throwNoComplex(x);
322 }
323
324 try {
325 return new Complex(x);
326 } catch (err) {
327 throw new Error('Cannot convert "' + x + '" to Complex');
328 }
329 }
330 }, {
331 from: 'boolean',
332 to: 'number',
333 convert: function convert(x) {
334 return +x;
335 }
336 }, {
337 from: 'boolean',
338 to: 'BigNumber',
339 convert: function convert(x) {
340 if (!BigNumber) {
341 throwNoBignumber(x);
342 }
343
344 return new BigNumber(+x);
345 }
346 }, {
347 from: 'boolean',
348 to: 'Fraction',
349 convert: function convert(x) {
350 if (!Fraction) {
351 throwNoFraction(x);
352 }
353
354 return new Fraction(+x);
355 }
356 }, {
357 from: 'boolean',
358 to: 'string',
359 convert: function convert(x) {
360 return String(x);
361 }
362 }, {
363 from: 'Array',
364 to: 'Matrix',
365 convert: function convert(array) {
366 if (!DenseMatrix) {
367 throwNoMatrix();
368 }
369
370 return new DenseMatrix(array);
371 }
372 }, {
373 from: 'Matrix',
374 to: 'Array',
375 convert: function convert(matrix) {
376 return matrix.valueOf();
377 }
378 }];
379 return typed;
380});
381exports.createTyped = createTyped;
382
383function throwNoBignumber(x) {
384 throw new Error("Cannot convert value ".concat(x, " into a BigNumber: no class 'BigNumber' provided"));
385}
386
387function throwNoComplex(x) {
388 throw new Error("Cannot convert value ".concat(x, " into a Complex number: no class 'Complex' provided"));
389}
390
391function throwNoMatrix() {
392 throw new Error('Cannot convert array into a Matrix: no class \'DenseMatrix\' provided');
393}
394
395function throwNoFraction(x) {
396 throw new Error("Cannot convert value ".concat(x, " into a Fraction, no class 'Fraction' provided."));
397}
\No newline at end of file