From 9af5206a88d571a4378536d24a125b2b7e8dda57 Mon Sep 17 00:00:00 2001 From: jos Date: Wed, 22 May 2019 11:08:12 +0200 Subject: [PATCH] Make matrix dependency requried again for subset. Make IndexNodes dependencies explicit. Disable subset in number implementation for now --- src/expression/node/IndexNode.js | 20 ++++++++++------ src/expression/transform/subset.transform.js | 2 +- src/factoriesNumber.js | 5 +++- src/function/matrix/size.js | 10 ++++---- src/function/matrix/subset.js | 7 +----- src/utils/noop.js | 4 ++++ test-generated/entry/mainAny.test.js | 24 +++++++++++++++++-- test-generated/entry/mainNumber.test.js | 25 ++++++++++++++++++-- tools/entryGenerator.js | 6 ++--- 9 files changed, 77 insertions(+), 26 deletions(-) diff --git a/src/expression/node/IndexNode.js b/src/expression/node/IndexNode.js index 8fbfb7e79..099dc98f9 100644 --- a/src/expression/node/IndexNode.js +++ b/src/expression/node/IndexNode.js @@ -1,6 +1,7 @@ 'use strict' import { isBigNumber, isConstantNode, isNode, isRangeNode, isSymbolNode } from '../../utils/is' +import { createIndexTransform } from '../transform/index.transform' import { map } from '../../utils/array' import { escape } from '../../utils/string' import { factory } from '../../utils/factory' @@ -8,10 +9,14 @@ import { factory } from '../../utils/factory' const name = 'IndexNode' const dependencies = [ 'Range', - 'Node' + 'Node', + 'Index', + 'size' ] -export const createIndexNode = /* #__PURE__ */ factory(name, dependencies, ({ Range, Node }) => { +export const createIndexNode = /* #__PURE__ */ factory(name, dependencies, ({ Range, Node, Index, size }) => { + const index = createIndexTransform({ Index }) + /** * @constructor IndexNode * @extends Node @@ -91,9 +96,9 @@ export const createIndexNode = /* #__PURE__ */ factory(name, dependencies, ({ Ra : function () { return 1 } return function evalDimension (scope, args, context) { - const size = math.size(context).valueOf() + const s = size(context).valueOf() const childArgs = Object.create(args) - childArgs['end'] = size[i] + childArgs['end'] = s[i] return createRange( evalStart(scope, childArgs, context), @@ -125,9 +130,9 @@ export const createIndexNode = /* #__PURE__ */ factory(name, dependencies, ({ Ra const evalRange = range._compile(math, childArgNames) return function evalDimension (scope, args, context) { - const size = math.size(context).valueOf() + const s = size(context).valueOf() const childArgs = Object.create(args) - childArgs['end'] = size[i] + childArgs['end'] = s[i] return evalRange(scope, childArgs, context) } @@ -144,7 +149,8 @@ export const createIndexNode = /* #__PURE__ */ factory(name, dependencies, ({ Ra const dimensions = map(evalDimensions, function (evalDimension) { return evalDimension(scope, args, context) }) - return math.index.apply(math, dimensions) + + return index(...dimensions) } } diff --git a/src/expression/transform/subset.transform.js b/src/expression/transform/subset.transform.js index 332868f04..f62613481 100644 --- a/src/expression/transform/subset.transform.js +++ b/src/expression/transform/subset.transform.js @@ -5,7 +5,7 @@ import { errorTransform } from './utils/errorTransform' import { createSubset } from '../../function/matrix/subset' const name = 'subset' -const dependencies = ['typed', '?matrix'] +const dependencies = ['typed', 'matrix'] export const createSubsetTransform = /* #__PURE__ */ factory(name, dependencies, ({ typed, matrix }) => { const subset = createSubset({ typed, matrix }) diff --git a/src/factoriesNumber.js b/src/factoriesNumber.js index 0bb4c61ab..b0dc74697 100644 --- a/src/factoriesNumber.js +++ b/src/factoriesNumber.js @@ -72,7 +72,7 @@ import { } from './plain/number' import { factory } from './utils/factory' -import { noSubset } from './utils/noop' +import { noIndexClass, noMatrix, noSubset } from './utils/noop' // ---------------------------------------------------------------------------- // classes and functions @@ -206,7 +206,10 @@ export { createFilter } from './function/matrix/filter' export { createForEach } from './function/matrix/forEach' export { createMap } from './function/matrix/map' export { createRange } from './function/matrix/range' +export { createSize } from './function/matrix/size' // FIXME: create a lightweight "number" implementation of subset only supporting plain objects/arrays +export const createIndexClass = /* #__PURE__ */ factory('Index', [], () => noIndexClass, { isClass: true }) +export const createMatrix = /* #__PURE__ */ factory('matrix', [], () => noMatrix) // FIXME: needed now because subset transform needs it. Remove the need for it in subset export const createSubset = /* #__PURE__ */ factory('subset', [], () => noSubset) // TODO: provide number+array implementations for map, filter, forEach, zeros, ...? // TODO: create range implementation for range? diff --git a/src/function/matrix/size.js b/src/function/matrix/size.js index a2cb53261..9708fc777 100644 --- a/src/function/matrix/size.js +++ b/src/function/matrix/size.js @@ -2,9 +2,10 @@ import { arraySize } from '../../utils/array' import { factory } from '../../utils/factory' +import { noMatrix } from '../../utils/noop' const name = 'size' -const dependencies = ['typed', 'config', 'matrix'] +const dependencies = ['typed', 'config', '?matrix'] export const createSize = /* #__PURE__ */ factory(name, dependencies, ({ typed, config, matrix }) => { /** @@ -32,8 +33,7 @@ export const createSize = /* #__PURE__ */ factory(name, dependencies, ({ typed, */ return typed(name, { 'Matrix': function (x) { - // TODO: return the same matrix type as the input - return matrix(x.size()) + return x.create(x.size()) }, 'Array': arraySize, @@ -44,7 +44,9 @@ export const createSize = /* #__PURE__ */ factory(name, dependencies, ({ typed, 'number | Complex | BigNumber | Unit | boolean | null': function (x) { // scalar - return (config.matrix === 'Array') ? [] : matrix([]) + return (config.matrix === 'Array') + ? [] + : matrix ? matrix([]) : noMatrix() } }) }) diff --git a/src/function/matrix/subset.js b/src/function/matrix/subset.js index e42ed1264..bcfe7849b 100644 --- a/src/function/matrix/subset.js +++ b/src/function/matrix/subset.js @@ -6,10 +6,9 @@ import { validateIndex } from '../../utils/array' import { getSafeProperty, setSafeProperty } from '../../utils/customs' import { DimensionError } from '../../error/DimensionError' import { factory } from '../../utils/factory' -import { noMatrix } from '../../utils/noop' const name = 'subset' -const dependencies = ['typed', '?matrix'] +const dependencies = ['typed', 'matrix'] export const createSubset = /* #__PURE__ */ factory(name, dependencies, ({ typed, matrix }) => { /** @@ -49,10 +48,6 @@ export const createSubset = /* #__PURE__ */ factory(name, dependencies, ({ typed return typed(name, { // get subset 'Array, Index': function (value, index) { - if (!matrix) { - noMatrix() - } - const m = matrix(value) const subset = m.subset(index) // returns a Matrix return index.isScalar() diff --git a/src/utils/noop.js b/src/utils/noop.js index 2c81e334b..f68303c2d 100644 --- a/src/utils/noop.js +++ b/src/utils/noop.js @@ -11,6 +11,10 @@ export function noMatrix () { throw new Error('No "matrix" implementation available') } +export function noIndexClass () { + throw new Error('No "Index" implementation available') +} + export function noSubset () { throw new Error('No "matrix" implementation available') } diff --git a/test-generated/entry/mainAny.test.js b/test-generated/entry/mainAny.test.js index ae0ee7922..c7af7fc0b 100644 --- a/test-generated/entry/mainAny.test.js +++ b/test-generated/entry/mainAny.test.js @@ -99,6 +99,28 @@ describe('mainAny', function () { assert.strictEqual(chain('x + 2 * x').simplify().done().toString(), '3 * x') }) + it('should get/set scope variables', () => { + const math = create(all) + const evaluate = math.evaluate + + assert.strictEqual(evaluate('b + 2', { b: 3 }), 5) + + const scope = {} + assert.strictEqual(evaluate('b = 2', scope), 2) + assert.deepStrictEqual(scope, { b: 2 }) + }) + + it('should evaluate assignement and access', () => { + const math = create(all) + const evaluate = math.evaluate + + assert.strictEqual(evaluate('A[2]', { A: [10, 20, 30] }), 20) + + const scope = { A: [10, 20, 30] } + assert.strictEqual(evaluate('A[2] = 200', scope), 200) + assert.deepStrictEqual(scope, { A: [10, 200, 30] }) + }) + it('should export evaluate having help and embedded docs', () => { const h = evaluate('help(simplify)') @@ -118,6 +140,4 @@ describe('mainAny', function () { // TODO: test export of create and core // TODO: test export of errors // TODO: test export of classes - // TODO: test export of default instance - // TODO: test snapshot of all exported things }) diff --git a/test-generated/entry/mainNumber.test.js b/test-generated/entry/mainNumber.test.js index 09be60d6a..bcb865ce3 100644 --- a/test-generated/entry/mainNumber.test.js +++ b/test-generated/entry/mainNumber.test.js @@ -119,6 +119,29 @@ describe('mainNumber', function () { assert(h.toString().indexOf('Name: simplify') >= 0, true) }) + it('should get/set scope variables', () => { + const math = create(all) + const evaluate = math.evaluate + + assert.strictEqual(evaluate('b + 2', { b: 3 }), 5) + + const scope = {} + assert.strictEqual(evaluate('b = 2', scope), 2) + assert.deepStrictEqual(scope, { b: 2 }) + }) + + it('doe not support assignement and access right now', () => { + // TODO: implement support for subset in number implementation + assert.throws(function () { + evaluate('A[2]', { A: [10, 20, 30] }) + }, /No "Index" implementation available/) + + assert.throws(function () { + const scope = { A: [10, 20, 30] } + evaluate('A[2] = 200', scope) + }, /No "Index" implementation available/) + }) + it('should export reviver', () => { const json = '{"mathjs":"Range","start":2,"end":10}' const r = new Range(2, 10) @@ -131,6 +154,4 @@ describe('mainNumber', function () { // TODO: test export of errors // TODO: test export of classes - // TODO: test export of default instance - // TODO: test snapshot of all exported things }) diff --git a/tools/entryGenerator.js b/tools/entryGenerator.js index 502ef2182..e2d97e1f7 100644 --- a/tools/entryGenerator.js +++ b/tools/entryGenerator.js @@ -122,7 +122,7 @@ Object.assign(math, { {{else}} {{name}}, {{/if}} -{{/math}} +{{/math}} config }) @@ -221,7 +221,7 @@ function generateDependenciesFiles ({ suffix, factories, entryFolder }) { .filter(dependency => { if (!exists[dependency]) { if (factory.dependencies.indexOf(dependency) !== -1) { - throw new Error(`Required dependency "${dependency}" missing for factory "${factory.fn}"`) + throw new Error(`Required dependency "${dependency}" missing for factory "${factory.fn}" (suffix: ${suffix})`) } return false @@ -348,7 +348,7 @@ function generateFunctionsFiles ({ suffix, factories, entryFolder }) { // TODO: this code is duplicated. extract it in a separate function if (!pureExists[dependency]) { if (factory.dependencies.indexOf(dependency) !== -1) { - throw new Error(`Required dependency "${dependency}" missing for factory "${factory.fn}"`) + throw new Error(`Required dependency "${dependency}" missing for factory "${factory.fn}" (suffix: ${suffix})`) } return false