subscript 7.3.1 → 7.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +6 -6
- package/README.md +337 -376
- package/compile.js +8 -8
- package/justin.js +94 -94
- package/justin.min.js +1 -1
- package/package.json +83 -83
- package/parse.js +85 -85
- package/subscript.js +128 -128
- package/subscript.min.js +1 -1
package/README.md
CHANGED
|
@@ -1,376 +1,337 @@
|
|
|
1
|
-
# <img alt="subscript" src="/subscript2.svg" height=28/> <!--sub͘<em>script</em>--> <!--<sub>SUB͘<em>SCRIPT</em></sub>--> <a href="https://github.com/spectjs/subscript/actions/workflows/node.js.yml"><img src="https://github.com/spectjs/subscript/actions/workflows/node.js.yml/badge.svg"/></a> <a href="http://npmjs.org/subscript"><img src="https://img.shields.io/npm/v/subscript"/></a> <a href="http://microjs.com/#subscript"><img src="https://img.shields.io/badge/microjs-subscript-blue?color=darkslateblue"/></a>
|
|
2
|
-
|
|
3
|
-
_Subscript_ is expression evaluator / microlanguage with [common syntax](https://en.wikipedia.org/wiki/Comparison_of_programming_languages_(syntax)).<br/>
|
|
4
|
-
|
|
5
|
-
* Tiny size <sub><a href="https://bundlephobia.com/package/subscript@6.0.0"><img alt="npm bundle size" src="https://img.shields.io/bundlephobia/minzip/subscript/latest?color=brightgreen&label=gzip"/></a></sub>
|
|
6
|
-
* :rocket: Fast [performance](#performance)
|
|
7
|
-
* Configurable & extensible
|
|
8
|
-
* Trivial to use
|
|
9
|
-
|
|
10
|
-
```js
|
|
11
|
-
import
|
|
12
|
-
|
|
13
|
-
// create expression evaluator
|
|
14
|
-
let fn =
|
|
15
|
-
fn({ a: { b:1 }, c: x => x * 2, d: 3 }) // 5
|
|
16
|
-
|
|
17
|
-
// or
|
|
18
|
-
// parse expression
|
|
19
|
-
let tree = parse('a.b + c')
|
|
20
|
-
tree // ['+', ['.', 'a', 'b'], 'c']
|
|
21
|
-
|
|
22
|
-
// compile tree to evaluable function
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
* `
|
|
46
|
-
* `a
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
* `a
|
|
50
|
-
* `a
|
|
51
|
-
* `a
|
|
52
|
-
* `a
|
|
53
|
-
* `a
|
|
54
|
-
* `a
|
|
55
|
-
* `a
|
|
56
|
-
* `a
|
|
57
|
-
* `a
|
|
58
|
-
* `a
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
* `
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
* `
|
|
71
|
-
* `
|
|
72
|
-
* `
|
|
73
|
-
* `
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
token('
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
<
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
```
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
```
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
```
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
```
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
```
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
```
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
```
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
```
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
math
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
new Function: ~1154 ms
|
|
339
|
-
```
|
|
340
|
-
|
|
341
|
-
Eval 30k times:
|
|
342
|
-
```
|
|
343
|
-
new Function: ~7 ms 🥇
|
|
344
|
-
subscript: ~15 ms 🥈
|
|
345
|
-
justin: ~17 ms
|
|
346
|
-
jexpr: ~23 ms 🥉
|
|
347
|
-
jsep (expression-eval): ~30 ms
|
|
348
|
-
math-expression-evaluator: ~50ms
|
|
349
|
-
expr-eval: ~72 ms
|
|
350
|
-
jexl: ~110 ms
|
|
351
|
-
mathjs: ~119 ms
|
|
352
|
-
mr-parser: -
|
|
353
|
-
math-parser: -
|
|
354
|
-
```
|
|
355
|
-
|
|
356
|
-
## Alternatives
|
|
357
|
-
|
|
358
|
-
* [jexpr](https://github.com/justinfagnani/jexpr)
|
|
359
|
-
* [jsep](https://github.com/EricSmekens/jsep)
|
|
360
|
-
* [jexl](https://github.com/TomFrost/Jexl)
|
|
361
|
-
* [mozjexl](https://github.com/mozilla/mozjexl)
|
|
362
|
-
* [expr-eval](https://github.com/silentmatt/expr-eval)
|
|
363
|
-
* [expression-eval](https://github.com/donmccurdy/expression-eval)
|
|
364
|
-
* [string-math](https://github.com/devrafalko/string-math)
|
|
365
|
-
* [nerdamer](https://github.com/jiggzson/nerdamer)
|
|
366
|
-
* [math-codegen](https://github.com/mauriciopoppe/math-codegen)
|
|
367
|
-
* [math-parser](https://www.npmjs.com/package/math-parser)
|
|
368
|
-
* [math.js](https://mathjs.org/docs/expressions/parsing.html)
|
|
369
|
-
|
|
370
|
-
## JS engines
|
|
371
|
-
|
|
372
|
-
* [engine262](https://github.com/engine262/engine262)
|
|
373
|
-
* [Jessie](https://github.com/endojs/Jessie)
|
|
374
|
-
* [xst](https://github.com/Moddable-OpenSource/moddable-xst)
|
|
375
|
-
|
|
376
|
-
<p align=center><a href="https://github.com/krsnzd/license/">🕉</a></p>
|
|
1
|
+
# <img alt="subscript" src="/subscript2.svg" height=28/> <!--sub͘<em>script</em>--> <!--<sub>SUB͘<em>SCRIPT</em></sub>--> <a href="https://github.com/spectjs/subscript/actions/workflows/node.js.yml"><img src="https://github.com/spectjs/subscript/actions/workflows/node.js.yml/badge.svg"/></a> <a href="http://npmjs.org/subscript"><img src="https://img.shields.io/npm/v/subscript"/></a> <a href="http://microjs.com/#subscript"><img src="https://img.shields.io/badge/microjs-subscript-blue?color=darkslateblue"/></a>
|
|
2
|
+
|
|
3
|
+
_Subscript_ is expression evaluator / microlanguage with [common syntax](https://en.wikipedia.org/wiki/Comparison_of_programming_languages_(syntax)) (JavaScript, Java, C, C++, Rust, Go, Python, Kotlin etc).<br/>
|
|
4
|
+
|
|
5
|
+
* Tiny size <sub><a href="https://bundlephobia.com/package/subscript@6.0.0"><img alt="npm bundle size" src="https://img.shields.io/bundlephobia/minzip/subscript/latest?color=brightgreen&label=gzip"/></a></sub>
|
|
6
|
+
* :rocket: Fast [performance](#performance)
|
|
7
|
+
* Configurable & extensible
|
|
8
|
+
* Trivial to use
|
|
9
|
+
|
|
10
|
+
```js
|
|
11
|
+
import createFn, { parse, compile } from './subscript.js'
|
|
12
|
+
|
|
13
|
+
// create expression evaluator
|
|
14
|
+
let fn = createFn('a.b + c(d - 1)')
|
|
15
|
+
fn({ a: { b:1 }, c: x => x * 2, d: 3 }) // 5
|
|
16
|
+
|
|
17
|
+
// or
|
|
18
|
+
// parse expression
|
|
19
|
+
let tree = parse('a.b + c')
|
|
20
|
+
tree // ['+', ['.', 'a', 'b'], 'c']
|
|
21
|
+
|
|
22
|
+
// compile tree to evaluable function
|
|
23
|
+
fn = compile(tree)
|
|
24
|
+
fn({a:{b:1}, c:2}) // 3
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Motivation
|
|
28
|
+
|
|
29
|
+
_Subscript_ is designed to be useful for:
|
|
30
|
+
|
|
31
|
+
* templates (perfect match with [template parts](https://github.com/github/template-parts), see [templize](https://github.com/spectjs/templize))
|
|
32
|
+
* expressions evaluators, calculators
|
|
33
|
+
* configurable subsets of languages (eg. [justin](#justin))
|
|
34
|
+
* pluggable/mock language features (eg. pipe operator)
|
|
35
|
+
* sandboxes, playgrounds, safe eval
|
|
36
|
+
* custom DSL <!-- see sonr, mineural -->
|
|
37
|
+
|
|
38
|
+
_Subscript_ has [2.8kb](https://npmfs.com/package/subscript/7.0.0/subscript.min.js) footprint, compared to [11.4kb](https://npmfs.com/package/jsep/1.2.0/dist/jsep.min.js) _jsep_ + [4.5kb](https://npmfs.com/package/expression-eval/5.0.0/dist/expression-eval.module.js) _expression-eval_, with better test coverage and better performance.
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
## Operators
|
|
42
|
+
|
|
43
|
+
<small>↑ precedence order</small>
|
|
44
|
+
|
|
45
|
+
* `( a, b, c )`
|
|
46
|
+
* `a.b`, `a[b]`, `a(b, c)`
|
|
47
|
+
* `a++`, `a--` unary postfix
|
|
48
|
+
* `!a`, `+a`, `-a`, `++a`, `--a` unary prefix
|
|
49
|
+
* `a * b`, `a / b`, `a % b`
|
|
50
|
+
* `a + b`, `a - b`
|
|
51
|
+
* `a << b`, `a >> b`, `a >>> b`
|
|
52
|
+
* `a < b`, `a <= b`, `a > b`, `a >= b`
|
|
53
|
+
* `a == b`, `a != b`
|
|
54
|
+
* `a & b`
|
|
55
|
+
* `a ^ b`
|
|
56
|
+
* `a | b`
|
|
57
|
+
* `a && b`
|
|
58
|
+
* `a || b`
|
|
59
|
+
* `a , b`
|
|
60
|
+
|
|
61
|
+
## Literals
|
|
62
|
+
|
|
63
|
+
* `"abc"` strings
|
|
64
|
+
* `1.2e+3` numbers
|
|
65
|
+
|
|
66
|
+
## Extending
|
|
67
|
+
|
|
68
|
+
Operators/tokens can be extended via:
|
|
69
|
+
|
|
70
|
+
* `unary(str, precedence, postfix=false)` − register unary operator, either prefix or postfix.
|
|
71
|
+
* `binary(str, precedence, rightAssoc=false)` − register binary operator, optionally right-associative.
|
|
72
|
+
* `nary(str, precedence, allowSkip=false)` − register n-ary (sequence) operator, optionally allowing skipping args.
|
|
73
|
+
* `token(str, precedence, map)` − register custom token or literal. `map` takes last token argument and returns calltree node.
|
|
74
|
+
* `operator(str, fn)` − register evaluator for operator. `fn` takes node arguments and returns evaluator function.
|
|
75
|
+
|
|
76
|
+
```js
|
|
77
|
+
import script, { operator, unary, binary, token } from './subscript.js'
|
|
78
|
+
|
|
79
|
+
// add ~ unary operator with precedence 15
|
|
80
|
+
unary('~', 15)
|
|
81
|
+
operator('~', a => ~a)
|
|
82
|
+
|
|
83
|
+
// add === binary operator with precedence 9
|
|
84
|
+
binary('===', 9)
|
|
85
|
+
operator('===', (a, b) => a===b)
|
|
86
|
+
|
|
87
|
+
// add boolean literals
|
|
88
|
+
token('true', 20, prev => ['',true])
|
|
89
|
+
token('false', 20, prev => ['',false])
|
|
90
|
+
operator('', boolNode => ctx => boolNode[1]])
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
See [subscript.js](subscript.js) or [justin.js](./justin.js) for examples.
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
## Syntax tree
|
|
97
|
+
|
|
98
|
+
Subscript exposes separate `./parse.js` and `./compile.js` entries. Parser builds AST, compiler converts it to evaluable function.
|
|
99
|
+
|
|
100
|
+
AST has simplified lispy calltree structure (inspired by [frisk](https://ghub.io/frisk) / [nisp](https://github.com/ysmood/nisp)), opposed to [ESTree](https://github.com/estree/estree):
|
|
101
|
+
|
|
102
|
+
* is not limited to particular language, can be compiled to different targets;
|
|
103
|
+
* reflects execution sequence, rather than code layout;
|
|
104
|
+
* has minimal possible overhead, directly maps to operators;
|
|
105
|
+
* simplifies manual evaluation and debugging;
|
|
106
|
+
* has conventional form and one-liner docs:
|
|
107
|
+
|
|
108
|
+
```js
|
|
109
|
+
import { compile } from 'subscript.js'
|
|
110
|
+
|
|
111
|
+
const fn = compile(['+', ['*', 'min', ['',60]], ['','sec']])
|
|
112
|
+
|
|
113
|
+
fn({min: 5}) // min*60 + "sec" == "300sec"
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Justin
|
|
117
|
+
|
|
118
|
+
_Justin_ is minimal JS subset − JSON with JS expressions (see original [thread](https://github.com/endojs/Jessie/issues/66)).<br/>
|
|
119
|
+
|
|
120
|
+
It extends _subscript_ with:
|
|
121
|
+
|
|
122
|
+
+ `===`, `!==` operators
|
|
123
|
+
+ `**` exponentiation operator (right-assoc)
|
|
124
|
+
+ `~` bit inversion operator
|
|
125
|
+
+ `'` strings
|
|
126
|
+
+ `?:` ternary operator
|
|
127
|
+
+ `?.` optional chain operator
|
|
128
|
+
+ `??` nullish coalesce operator
|
|
129
|
+
+ `[...]` Array literal
|
|
130
|
+
+ `{...}` Object literal
|
|
131
|
+
+ `in` binary
|
|
132
|
+
+ `;` expression separator
|
|
133
|
+
+ `//`, `/* */` comments
|
|
134
|
+
+ `true`, `false`, `null`, `undefined` literals
|
|
135
|
+
<!-- + `...x` unary operator -->
|
|
136
|
+
<!-- + strings interpolation -->
|
|
137
|
+
|
|
138
|
+
```js
|
|
139
|
+
import jstin from 'subscript/justin.js'
|
|
140
|
+
|
|
141
|
+
let xy = jstin('{ x: 1, "y": 2+2 }["x"]')
|
|
142
|
+
xy() // 1
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
<!--
|
|
146
|
+
## Ideas
|
|
147
|
+
|
|
148
|
+
These are custom DSL operators snippets for your inspiration:
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
```html
|
|
152
|
+
template-parts proposal
|
|
153
|
+
<template id="timer">
|
|
154
|
+
<time datetime="{{ date.toUTCString() }}">{{ date.toLocaleTimeString() }}</time>
|
|
155
|
+
</template>
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
// a.b.c
|
|
159
|
+
// (node, c) => c === PERIOD ? (index++, space(), ['.', node, '"'+id()+'"']) : node,
|
|
160
|
+
|
|
161
|
+
// a[b][c]
|
|
162
|
+
// (node, c) => c === OBRACK ? (index++, node=['.', node, expr(CBRACK)], index++, node) : node,
|
|
163
|
+
|
|
164
|
+
// a(b)(c)
|
|
165
|
+
// (node, c, arg) => c === OPAREN ? (
|
|
166
|
+
// index++, arg=expr(CPAREN),
|
|
167
|
+
// node = Array.isArray(arg) && arg[0]===',' ? (arg[0]=node, arg) : arg == null ? [node] : [node, arg],
|
|
168
|
+
// index++, node
|
|
169
|
+
// ) : node,
|
|
170
|
+
|
|
171
|
+
<details>
|
|
172
|
+
<summary>Keyed arrays <code>[a:1, b:2, c:3]</code></summary>
|
|
173
|
+
|
|
174
|
+
```js
|
|
175
|
+
|
|
176
|
+
```
|
|
177
|
+
</details>
|
|
178
|
+
|
|
179
|
+
<details>
|
|
180
|
+
<summary>`7!` (factorial)</summary>
|
|
181
|
+
|
|
182
|
+
```js
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
</details>
|
|
186
|
+
<details>
|
|
187
|
+
<summary>`5s`, `5rem` (units)</summary>
|
|
188
|
+
|
|
189
|
+
```js
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
</details>
|
|
193
|
+
<details>
|
|
194
|
+
<summary>`?`, `?.`, `??`</summary>
|
|
195
|
+
|
|
196
|
+
```js
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
</details>
|
|
200
|
+
<details>
|
|
201
|
+
<summary>`arrᵀ` - transpose,</summary>
|
|
202
|
+
|
|
203
|
+
```js
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
</details>
|
|
207
|
+
<details>
|
|
208
|
+
<summary>`int 5` (typecast)</summary>
|
|
209
|
+
|
|
210
|
+
```js
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
</details>
|
|
214
|
+
<details>
|
|
215
|
+
<summary>`$a` (param expansion)</summary>
|
|
216
|
+
|
|
217
|
+
```js
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
</details>
|
|
221
|
+
<details>
|
|
222
|
+
<summary>`1 to 10 by 2`</summary>
|
|
223
|
+
|
|
224
|
+
```js
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
</details>
|
|
228
|
+
<details>
|
|
229
|
+
<summary>`a if b else c`</summary>
|
|
230
|
+
|
|
231
|
+
```js
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
</details>
|
|
235
|
+
<details>
|
|
236
|
+
<summary>`a, b in c`</summary>
|
|
237
|
+
|
|
238
|
+
```js
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
</details>
|
|
242
|
+
<details>
|
|
243
|
+
<summary>`a.xyz` swizzles</summary>
|
|
244
|
+
|
|
245
|
+
```js
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
</details>
|
|
249
|
+
<details>
|
|
250
|
+
<summary>vector operators</summary>
|
|
251
|
+
|
|
252
|
+
```js
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
</details>
|
|
256
|
+
<details>
|
|
257
|
+
<summary>set operators</summary>
|
|
258
|
+
|
|
259
|
+
```js
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
</details>
|
|
263
|
+
<details>
|
|
264
|
+
<summary>polynomial operators</summary>
|
|
265
|
+
|
|
266
|
+
```js
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
</details>
|
|
270
|
+
|
|
271
|
+
like versions, units, hashes, urls, regexes etc
|
|
272
|
+
|
|
273
|
+
2a as `2*a`
|
|
274
|
+
|
|
275
|
+
string interpolation ` ${} 1 ${} `
|
|
276
|
+
|
|
277
|
+
keyed arrays? [a:1, b:2, c:3]
|
|
278
|
+
|
|
279
|
+
Examples: sonr, template-parts, neural-chunks
|
|
280
|
+
-->
|
|
281
|
+
|
|
282
|
+
## Performance
|
|
283
|
+
|
|
284
|
+
Subscript shows relatively good performance within other evaluators. Example expression:
|
|
285
|
+
|
|
286
|
+
```
|
|
287
|
+
1 + (a * b / c % d) - 2.0 + -3e-3 * +4.4e4 / f.g[0] - i.j(+k == 1)(0)
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
Parse 30k times:
|
|
291
|
+
|
|
292
|
+
```
|
|
293
|
+
es-module-lexer: 50ms 🥇
|
|
294
|
+
subscript: ~150 ms 🥈
|
|
295
|
+
justin: ~183 ms
|
|
296
|
+
jsep: ~270 ms 🥉
|
|
297
|
+
jexpr: ~297 ms
|
|
298
|
+
mr-parser: ~420 ms
|
|
299
|
+
expr-eval: ~480 ms
|
|
300
|
+
math-parser: ~570 ms
|
|
301
|
+
math-expression-evaluator: ~900ms
|
|
302
|
+
jexl: ~1056 ms
|
|
303
|
+
mathjs: ~1200 ms
|
|
304
|
+
new Function: ~1154 ms
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
Eval 30k times:
|
|
308
|
+
```
|
|
309
|
+
new Function: ~7 ms 🥇
|
|
310
|
+
subscript: ~15 ms 🥈
|
|
311
|
+
justin: ~17 ms
|
|
312
|
+
jexpr: ~23 ms 🥉
|
|
313
|
+
jsep (expression-eval): ~30 ms
|
|
314
|
+
math-expression-evaluator: ~50ms
|
|
315
|
+
expr-eval: ~72 ms
|
|
316
|
+
jexl: ~110 ms
|
|
317
|
+
mathjs: ~119 ms
|
|
318
|
+
mr-parser: -
|
|
319
|
+
math-parser: -
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
## Alternatives
|
|
323
|
+
|
|
324
|
+
* [jexpr](https://github.com/justinfagnani/jexpr)
|
|
325
|
+
* [jsep](https://github.com/EricSmekens/jsep)
|
|
326
|
+
* [jexl](https://github.com/TomFrost/Jexl)
|
|
327
|
+
* [mozjexl](https://github.com/mozilla/mozjexl)
|
|
328
|
+
* [expr-eval](https://github.com/silentmatt/expr-eval)
|
|
329
|
+
* [expression-eval](https://github.com/donmccurdy/expression-eval)
|
|
330
|
+
* [string-math](https://github.com/devrafalko/string-math)
|
|
331
|
+
* [nerdamer](https://github.com/jiggzson/nerdamer)
|
|
332
|
+
* [math-codegen](https://github.com/mauriciopoppe/math-codegen)
|
|
333
|
+
* [math-parser](https://www.npmjs.com/package/math-parser)
|
|
334
|
+
* [math.js](https://mathjs.org/docs/expressions/parsing.html)
|
|
335
|
+
* [nx-compile](https://github.com/nx-js/compiler-util)
|
|
336
|
+
|
|
337
|
+
<p align=center><a href="https://github.com/krsnzd/license/">🕉</a></p>
|