Make matrix dependency requried again for subset. Make IndexNodes dependencies explicit. Disable subset in number implementation for now

This commit is contained in:
jos 2019-05-22 11:08:12 +02:00
parent b52c4ca595
commit 9af5206a88
9 changed files with 77 additions and 26 deletions

View File

@ -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)
}
}

View File

@ -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 })

View File

@ -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?

View File

@ -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()
}
})
})

View File

@ -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()

View File

@ -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')
}

View File

@ -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
})

View File

@ -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
})

View File

@ -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