|
1 | | -import { isBigNumber, isConstantNode, isNode, isRangeNode, isSymbolNode } from '../../utils/is.js' |
2 | 1 | import { map } from '../../utils/array.js' |
3 | | -import { escape } from '../../utils/string.js' |
4 | | -import { factory } from '../../utils/factory.js' |
5 | 2 | import { getSafeProperty } from '../../utils/customs.js' |
| 3 | +import { factory } from '../../utils/factory.js' |
| 4 | +import { isArray, isConstantNode, isMatrix, isNode, isString, typeOf } from '../../utils/is.js' |
| 5 | +import { escape } from '../../utils/string.js' |
6 | 6 |
|
7 | 7 | const name = 'IndexNode' |
8 | 8 | const dependencies = [ |
9 | | - 'Range', |
10 | 9 | 'Node', |
11 | 10 | 'size' |
12 | 11 | ] |
13 | 12 |
|
14 | | -export const createIndexNode = /* #__PURE__ */ factory(name, dependencies, ({ Range, Node, size }) => { |
| 13 | +export const createIndexNode = /* #__PURE__ */ factory(name, dependencies, ({ Node, size }) => { |
15 | 14 | /** |
16 | 15 | * @constructor IndexNode |
17 | 16 | * @extends Node |
@@ -71,66 +70,34 @@ export const createIndexNode = /* #__PURE__ */ factory(name, dependencies, ({ Ra |
71 | 70 | // we can beforehand resolve the zero-based value |
72 | 71 |
|
73 | 72 | // optimization for a simple object property |
74 | | - const evalDimensions = map(this.dimensions, function (range, i) { |
75 | | - if (isRangeNode(range)) { |
76 | | - if (range.needsEnd()) { |
77 | | - // create a range containing end (like '4:end') |
78 | | - const childArgNames = Object.create(argNames) |
79 | | - childArgNames.end = true |
80 | | - |
81 | | - const evalStart = range.start._compile(math, childArgNames) |
82 | | - const evalEnd = range.end._compile(math, childArgNames) |
83 | | - const evalStep = range.step |
84 | | - ? range.step._compile(math, childArgNames) |
85 | | - : function () { return 1 } |
86 | | - |
87 | | - return function evalDimension (scope, args, context) { |
88 | | - const s = size(context).valueOf() |
89 | | - const childArgs = Object.create(args) |
90 | | - childArgs.end = s[i] |
91 | | - |
92 | | - return createRange( |
93 | | - evalStart(scope, childArgs, context), |
94 | | - evalEnd(scope, childArgs, context), |
95 | | - evalStep(scope, childArgs, context) |
96 | | - ) |
97 | | - } |
98 | | - } else { |
99 | | - // create range |
100 | | - const evalStart = range.start._compile(math, argNames) |
101 | | - const evalEnd = range.end._compile(math, argNames) |
102 | | - const evalStep = range.step |
103 | | - ? range.step._compile(math, argNames) |
104 | | - : function () { return 1 } |
105 | | - |
106 | | - return function evalDimension (scope, args, context) { |
107 | | - return createRange( |
108 | | - evalStart(scope, args, context), |
109 | | - evalEnd(scope, args, context), |
110 | | - evalStep(scope, args, context) |
111 | | - ) |
112 | | - } |
113 | | - } |
114 | | - } else if (isSymbolNode(range) && range.name === 'end') { |
115 | | - // SymbolNode 'end' |
| 73 | + const evalDimensions = map(this.dimensions, function (dimension, i) { |
| 74 | + const needsEnd = dimension |
| 75 | + .filter(node => node.isSymbolNode && node.name === 'end') |
| 76 | + .length > 0 |
| 77 | + |
| 78 | + if (needsEnd) { |
| 79 | + // SymbolNode 'end' is used inside the index, |
| 80 | + // like in `A[end]` or `A[end - 2]` |
116 | 81 | const childArgNames = Object.create(argNames) |
117 | 82 | childArgNames.end = true |
118 | 83 |
|
119 | | - const evalRange = range._compile(math, childArgNames) |
| 84 | + const _evalDimension = dimension._compile(math, childArgNames) |
120 | 85 |
|
121 | 86 | return function evalDimension (scope, args, context) { |
| 87 | + if (!isMatrix(context) && !isArray(context) && !isString(context)) { |
| 88 | + throw new TypeError('Cannot resolve "end": ' + |
| 89 | + 'context must be a Matrix, Array, or string but is ' + typeOf(context)) |
| 90 | + } |
| 91 | + |
122 | 92 | const s = size(context).valueOf() |
123 | 93 | const childArgs = Object.create(args) |
124 | 94 | childArgs.end = s[i] |
125 | 95 |
|
126 | | - return evalRange(scope, childArgs, context) |
| 96 | + return _evalDimension(scope, childArgs, context) |
127 | 97 | } |
128 | 98 | } else { |
129 | | - // ConstantNode |
130 | | - const evalRange = range._compile(math, argNames) |
131 | | - return function evalDimension (scope, args, context) { |
132 | | - return evalRange(scope, args, context) |
133 | | - } |
| 99 | + // SymbolNode `end` not used |
| 100 | + return dimension._compile(math, argNames) |
134 | 101 | } |
135 | 102 | }) |
136 | 103 |
|
@@ -265,14 +232,5 @@ export const createIndexNode = /* #__PURE__ */ factory(name, dependencies, ({ Ra |
265 | 232 | : ('_{' + dimensions.join(',') + '}') |
266 | 233 | } |
267 | 234 |
|
268 | | - // helper function to create a Range from start, step and end |
269 | | - function createRange (start, end, step) { |
270 | | - return new Range( |
271 | | - isBigNumber(start) ? start.toNumber() : start, |
272 | | - isBigNumber(end) ? end.toNumber() : end, |
273 | | - isBigNumber(step) ? step.toNumber() : step |
274 | | - ) |
275 | | - } |
276 | | - |
277 | 235 | return IndexNode |
278 | 236 | }, { isClass: true, isNode: true }) |
0 commit comments