Skip to content

Commit a2fd057

Browse files
gwhitneyjosdejong
andauthored
fix(simplify): Array and object simplification (#2382)
* fix(simplify): Allow simplify to work in arrays, objects, and indexing Mostly ArrayNode, ObjectNode, AccessorNode, and IndexNode nodes are simply transparent to simplification -- they simply allow it to occur within subexpressions. Then main exception is that if an array or object is indexed by a constant, the expression can be replaced by the corresponding subitem, e.g. `[3,4,5][2]` simplifies to `4`. This at least partially resolves #1913 (see my latest comment there). * fix(simplify): Resolve operations on constant arrays This involves allowing ArrayNodes containing only constant entries to temporarily convert to Matrix type inside of simplifyConstant, so that function and operator calls can occur on them. I also had to add a special case for the function `size` because it can be computed even on symbolic arrays, since the result depends only on the shape, not the entries. Deals with additional cases of #1913; unclear if there are remaining aspects of that issue on which further work is desirable. * chore: fix alphabetization of dependencies And restores inadvertent deletion of a blank line. Co-authored-by: Jos de Jong <[email protected]>
1 parent 84c3abd commit a2fd057

File tree

5 files changed

+290
-51
lines changed

5 files changed

+290
-51
lines changed

src/function/algebra/rationalize.js

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,14 @@ const dependencies = [
1919
'?bignumber',
2020
'?fraction',
2121
'mathWithTransform',
22+
'matrix',
23+
'AccessorNode',
2224
'ArrayNode',
2325
'ConstantNode',
24-
'OperatorNode',
2526
'FunctionNode',
27+
'IndexNode',
28+
'ObjectNode',
29+
'OperatorNode',
2630
'SymbolNode',
2731
'ParenthesisNode'
2832
]
@@ -42,23 +46,31 @@ export const createRationalize = /* #__PURE__ */ factory(name, dependencies, ({
4246
fraction,
4347
bignumber,
4448
mathWithTransform,
49+
matrix,
50+
AccessorNode,
4551
ArrayNode,
4652
ConstantNode,
47-
OperatorNode,
4853
FunctionNode,
54+
IndexNode,
55+
ObjectNode,
56+
OperatorNode,
4957
SymbolNode,
5058
ParenthesisNode
5159
}) => {
5260
const simplifyConstant = createSimplifyConstant({
5361
typed,
5462
config,
5563
mathWithTransform,
64+
matrix,
5665
fraction,
5766
bignumber,
67+
AccessorNode,
5868
ArrayNode,
5969
ConstantNode,
60-
OperatorNode,
6170
FunctionNode,
71+
IndexNode,
72+
ObjectNode,
73+
OperatorNode,
6274
SymbolNode
6375
})
6476
const simplifyCore = createSimplifyCore({
@@ -69,9 +81,13 @@ export const createRationalize = /* #__PURE__ */ factory(name, dependencies, ({
6981
multiply,
7082
divide,
7183
pow,
84+
AccessorNode,
85+
ArrayNode,
7286
ConstantNode,
73-
OperatorNode,
7487
FunctionNode,
88+
IndexNode,
89+
ObjectNode,
90+
OperatorNode,
7591
ParenthesisNode
7692
})
7793

src/function/algebra/simplify.js

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,13 @@ const dependencies = [
2222
'?fraction',
2323
'?bignumber',
2424
'mathWithTransform',
25+
'matrix',
26+
'AccessorNode',
2527
'ArrayNode',
2628
'ConstantNode',
2729
'FunctionNode',
30+
'IndexNode',
31+
'ObjectNode',
2832
'OperatorNode',
2933
'ParenthesisNode',
3034
'SymbolNode'
@@ -45,9 +49,13 @@ export const createSimplify = /* #__PURE__ */ factory(name, dependencies, (
4549
fraction,
4650
bignumber,
4751
mathWithTransform,
52+
matrix,
53+
AccessorNode,
4854
ArrayNode,
4955
ConstantNode,
5056
FunctionNode,
57+
IndexNode,
58+
ObjectNode,
5159
OperatorNode,
5260
ParenthesisNode,
5361
SymbolNode
@@ -57,12 +65,16 @@ export const createSimplify = /* #__PURE__ */ factory(name, dependencies, (
5765
typed,
5866
config,
5967
mathWithTransform,
68+
matrix,
6069
fraction,
6170
bignumber,
71+
AccessorNode,
6272
ArrayNode,
6373
ConstantNode,
64-
OperatorNode,
6574
FunctionNode,
75+
IndexNode,
76+
ObjectNode,
77+
OperatorNode,
6678
SymbolNode
6779
})
6880
const simplifyCore = createSimplifyCore({
@@ -73,9 +85,13 @@ export const createSimplify = /* #__PURE__ */ factory(name, dependencies, (
7385
multiply,
7486
divide,
7587
pow,
88+
AccessorNode,
89+
ArrayNode,
7690
ConstantNode,
77-
OperatorNode,
7891
FunctionNode,
92+
IndexNode,
93+
ObjectNode,
94+
OperatorNode,
7995
ParenthesisNode
8096
})
8197
const resolve = createResolve({
@@ -418,6 +434,14 @@ export const createSimplify = /* #__PURE__ */ factory(name, dependencies, (
418434
return new SymbolNode('_p' + _lastsym++)
419435
}
420436

437+
function mapRule (nodes, rule) {
438+
if (nodes) {
439+
for (let i = 0; i < nodes.length; ++i) {
440+
nodes[i] = applyRule(nodes[i], rule)
441+
}
442+
}
443+
}
444+
421445
/**
422446
* Returns a simplfied form of node, or the original node if no simplification was possible.
423447
*
@@ -432,18 +456,29 @@ export const createSimplify = /* #__PURE__ */ factory(name, dependencies, (
432456
let res = node
433457

434458
// First replace our child nodes with their simplified versions
435-
// If a child could not be simplified, the assignments will have
436-
// no effect since the node is returned unchanged
459+
// If a child could not be simplified, applying the rule to it
460+
// will have no effect since the node is returned unchanged
437461
if (res instanceof OperatorNode || res instanceof FunctionNode) {
438-
if (res.args) {
439-
for (let i = 0; i < res.args.length; i++) {
440-
res.args[i] = applyRule(res.args[i], rule)
441-
}
442-
}
462+
mapRule(res.args, rule)
443463
} else if (res instanceof ParenthesisNode) {
444464
if (res.content) {
445465
res.content = applyRule(res.content, rule)
446466
}
467+
} else if (res instanceof ArrayNode) {
468+
mapRule(res.items, rule)
469+
} else if (res instanceof AccessorNode) {
470+
if (res.object) {
471+
res.object = applyRule(res.object, rule)
472+
}
473+
if (res.index) {
474+
res.index = applyRule(res.index, rule)
475+
}
476+
} else if (res instanceof IndexNode) {
477+
mapRule(res.dimensions, rule)
478+
} else if (res instanceof ObjectNode) {
479+
for (const prop in res.properties) {
480+
res.properties[prop] = applyRule(res.properties[prop], rule)
481+
}
447482
}
448483

449484
// Try to match a rule against this node

0 commit comments

Comments
 (0)