@briza/illogical 1.5.8 → 1.6.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.
@@ -1,3 +1,11 @@
1
+ function _defineProperty(e, r, t) {
2
+ return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
3
+ value: t,
4
+ enumerable: !0,
5
+ configurable: !0,
6
+ writable: !0
7
+ }) : e[r] = t, e;
8
+ }
1
9
  function _toPrimitive(t, r) {
2
10
  if ("object" != typeof t || !t) return t;
3
11
  var e = t[Symbol.toPrimitive];
@@ -10,21 +18,7 @@ function _toPrimitive(t, r) {
10
18
  }
11
19
  function _toPropertyKey(t) {
12
20
  var i = _toPrimitive(t, "string");
13
- return "symbol" == typeof i ? i : String(i);
14
- }
15
- function _defineProperty(obj, key, value) {
16
- key = _toPropertyKey(key);
17
- if (key in obj) {
18
- Object.defineProperty(obj, key, {
19
- value: value,
20
- enumerable: true,
21
- configurable: true,
22
- writable: true
23
- });
24
- } else {
25
- obj[key] = value;
26
- }
27
- return obj;
21
+ return "symbol" == typeof i ? i : i + "";
28
22
  }
29
23
 
30
24
  /**
@@ -32,7 +26,14 @@ function _defineProperty(obj, key, value) {
32
26
  * @param value Tested value.
33
27
  */
34
28
  function isNumber(value) {
35
- return typeof value === 'number' && isFinite(value);
29
+ return typeof value === 'number';
30
+ }
31
+ /**
32
+ * Is number predicate.
33
+ * @param value Tested value.
34
+ */
35
+ function isInfinite(value) {
36
+ return typeof value === 'number' && !isFinite(value);
36
37
  }
37
38
 
38
39
  /**
@@ -54,50 +55,573 @@ function isObject(value) {
54
55
  if (typeof value !== 'object' || (value === null || value === void 0 ? void 0 : value.constructor) !== Object) {
55
56
  return false;
56
57
  }
57
- return true;
58
- }
59
-
60
- /**
61
- * Is Boolean predicate.
62
- * @param value tested value.
63
- * @return result of the test
64
- */
65
- function isBoolean(value) {
66
- return typeof value === 'boolean';
67
- }
58
+ return true;
59
+ }
60
+
61
+ /**
62
+ * Is Boolean predicate.
63
+ * @param value tested value.
64
+ * @return result of the test
65
+ */
66
+ function isBoolean(value) {
67
+ return typeof value === 'boolean';
68
+ }
69
+
70
+ /**
71
+ * Check if a value is a an Evaluable
72
+ * @param {Result | Evaluable} value value to check if is Evaluable
73
+ * @returns {Evaluable}
74
+ */
75
+ function isEvaluable(value) {
76
+ return typeof value === 'object' && value !== null && !Array.isArray(value) && typeof value.evaluate === 'function' && typeof value.simplify === 'function' && typeof value.serialize === 'function' && typeof value.toString === 'function';
77
+ }
78
+
79
+ /**
80
+ * Ensures all values are results.
81
+ * @param {(Result | Evaluable)[]} values results or evaluables
82
+ * @returns {boolean} type guard
83
+ */
84
+ function areAllResults(values) {
85
+ return values.every(value => !isEvaluable(value));
86
+ }
87
+
88
+ /**
89
+ * Ensures all values are numbers.
90
+ * @param {Result[]} results results or evaluables
91
+ * @returns {boolean} type guard
92
+ */
93
+ function areAllNumbers(results) {
94
+ return results.every(isNumber);
95
+ }
96
+
97
+ /**
98
+ * Valid types for context members
99
+ */
100
+
101
+ /**
102
+ * Evaluation Context
103
+ * Holds references used during the evaluation process.
104
+ * Format: key: value.
105
+ */
106
+
107
+ /**
108
+ * Evaluation result
109
+ */
110
+
111
+ let EvaluableType = /*#__PURE__*/function (EvaluableType) {
112
+ EvaluableType["Operand"] = "Operand";
113
+ EvaluableType["Expression"] = "Expression";
114
+ return EvaluableType;
115
+ }({});
116
+
117
+ /**
118
+ * Evaluable
119
+ */
120
+
121
+ /**
122
+ * Abstract arithmetic expression
123
+ */
124
+ class Arithmetic {
125
+ /**
126
+ * @constructor
127
+ * @param {string} operator String representation of the operator.
128
+ * @param {symbol} operatorSymbol Operator symbol.
129
+ * @param {Operand[]} operands Operands.
130
+ */
131
+ constructor(operator, operatorSymbol, operands) {
132
+ this.operator = operator;
133
+ this.operatorSymbol = operatorSymbol;
134
+ this.operands = operands;
135
+ _defineProperty(this, "type", EvaluableType.Expression);
136
+ }
137
+
138
+ /**
139
+ * Performs the arithmetic operation on the operands evaluated values.
140
+ * @param {Result[]} results Operand result values.
141
+ * @returns {Result}
142
+ */
143
+
144
+ /**
145
+ * {@link Evaluable.evaluate}
146
+ */
147
+ evaluate(ctx) {
148
+ return this.operate(this.operands.map(operand => operand.evaluate(ctx)));
149
+ }
150
+
151
+ /**
152
+ * {@link Evaluable.toString}
153
+ */
154
+ toString() {
155
+ return `(${this.operands.map(operand => operand.toString()).join(` ${this.operator} `)})`;
156
+ }
157
+
158
+ /**
159
+ * {@link Evaluable.simplify}
160
+ */
161
+ simplify(...args) {
162
+ const results = this.operands.map(operand => operand.simplify(...args));
163
+ if (areAllResults(results)) {
164
+ return this.operate(results);
165
+ }
166
+ return this;
167
+ }
168
+
169
+ /**
170
+ * {@link Evaluable.serialize}
171
+ */
172
+ serialize(options) {
173
+ const {
174
+ operatorMapping
175
+ } = options;
176
+ const operator = operatorMapping.get(this.operatorSymbol);
177
+ if (operator === undefined) {
178
+ throw new Error(`missing operator ${this.operatorSymbol.toString()}`);
179
+ }
180
+ return [operator, ...this.operands.map(operand => operand.serialize(options))];
181
+ }
182
+ }
183
+
184
+ // Operator key
185
+ const OPERATOR$l = Symbol('DIVIDE');
186
+
187
+ /**
188
+ * Divide operation expression
189
+ */
190
+ class Divide extends Arithmetic {
191
+ /**
192
+ * @constructor Generic constructor
193
+ * @param {Evaluable[]} args
194
+ */
195
+
196
+ /**
197
+ * @constructor
198
+ * @param {Operand[]} operands Operands.
199
+ */
200
+ constructor(...operands) {
201
+ if (operands.length < 2) {
202
+ throw new Error('divide expression requires at least 2 operands');
203
+ }
204
+ super('/', OPERATOR$l, operands);
205
+ }
206
+ operate(results) {
207
+ if (!areAllNumbers(results)) {
208
+ throw new Error('operands must be numbers for divide');
209
+ }
210
+ const result = results.reduce((acc, result) => acc / result);
211
+ return result;
212
+ }
213
+ }
214
+
215
+ const getNumDecimals = num => {
216
+ const numberSplit = num.toString().split('.');
217
+ return numberSplit.length == 2 ? numberSplit[1].length : 0;
218
+ };
219
+ const operateWithExpectedDecimals = operation => (first, second) => {
220
+ const numDecimals1 = getNumDecimals(first);
221
+ const numDecimals2 = getNumDecimals(second);
222
+ const maxDecimals = operation === 'multiply' ? numDecimals1 + numDecimals2 : numDecimals1 > numDecimals2 ? numDecimals1 : numDecimals2;
223
+ return operation === 'sum' ? Number((first + second).toFixed(maxDecimals)) : operation === 'subtract' ? Number((first - second).toFixed(maxDecimals)) : Number((first * second).toFixed(maxDecimals));
224
+ };
225
+
226
+ // Operator key
227
+ const OPERATOR$k = Symbol('MULTIPLY');
228
+ const multiplyWithExpectedDecimals = operateWithExpectedDecimals('multiply');
229
+
230
+ /**
231
+ * Multiply operation expression
232
+ */
233
+ class Multiply extends Arithmetic {
234
+ /**
235
+ * @constructor Generic constructor
236
+ * @param {Evaluable[]} args
237
+ */
238
+
239
+ /**
240
+ * @constructor
241
+ * @param {Operand[]} operands Operands.
242
+ */
243
+ constructor(...operands) {
244
+ if (operands.length < 2) {
245
+ throw new Error('multiply expression requires at least 2 operands');
246
+ }
247
+ super('*', OPERATOR$k, operands);
248
+ }
249
+ operate(results) {
250
+ if (!areAllNumbers(results)) {
251
+ throw new Error('operands must be numbers for multiply');
252
+ }
253
+ return results.reduce((acc, result) => multiplyWithExpectedDecimals(acc, result));
254
+ }
255
+ }
256
+
257
+ // Operator key
258
+ const OPERATOR$j = Symbol('SUBTRACT');
259
+ const subtractWithExpectedDecimals = operateWithExpectedDecimals('subtract');
260
+
261
+ /**
262
+ * Subtract operation expression
263
+ */
264
+ class Subtract extends Arithmetic {
265
+ /**
266
+ * @constructor Generic constructor
267
+ * @param {Evaluable[]} args
268
+ */
269
+
270
+ /**
271
+ * @constructor
272
+ * @param {Operand[]} operands Operands.
273
+ */
274
+ constructor(...operands) {
275
+ if (operands.length < 2) {
276
+ throw new Error('subtract expression requires at least 2 operands');
277
+ }
278
+ super('-', OPERATOR$j, operands);
279
+ }
280
+ operate(results) {
281
+ if (!areAllNumbers(results)) {
282
+ throw new Error('operands must be numbers for subtract');
283
+ }
284
+ return results.reduce((acc, result) => subtractWithExpectedDecimals(acc, result));
285
+ }
286
+ }
287
+
288
+ // Operator key
289
+ const OPERATOR$i = Symbol('SUM');
290
+ const addWithExpectedDecimals = operateWithExpectedDecimals('sum');
291
+
292
+ /**
293
+ * Sum operation expression
294
+ */
295
+ class Sum extends Arithmetic {
296
+ /**
297
+ * @constructor Generic constructor
298
+ * @param {Evaluable[]} args
299
+ */
300
+
301
+ /**
302
+ * @constructor
303
+ * @param {Operand[]} operands Operands.
304
+ */
305
+ constructor(...operands) {
306
+ if (operands.length < 2) {
307
+ throw new Error('sum expression requires at least 2 operands');
308
+ }
309
+ super('+', OPERATOR$i, operands);
310
+ }
311
+ operate(results) {
312
+ if (!areAllNumbers(results)) {
313
+ throw new Error('operands must be numbers for sum');
314
+ }
315
+ return results.reduce((acc, result) => addWithExpectedDecimals(acc, result));
316
+ }
317
+ }
318
+
319
+ /**
320
+ * Abstract operand
321
+ */
322
+ class Operand {
323
+ constructor() {
324
+ _defineProperty(this, "type", EvaluableType.Operand);
325
+ }
326
+ /**
327
+ * {@link Evaluable.evaluate}
328
+ */
329
+ /**
330
+ * {@link Evaluable.simplify}
331
+ */
332
+ /**
333
+ * {@link Evaluable.serialize}
334
+ */
335
+ /**
336
+ * Get the strict representation.
337
+ */
338
+ toString() {
339
+ throw new Error('not implemented exception');
340
+ }
341
+ }
342
+
343
+ /**
344
+ * Print value as string
345
+ * @param {Result} value
346
+ * @return {string}
347
+ */
348
+ function printValue(value) {
349
+ if (isString(value)) {
350
+ return `"${value}"`;
351
+ }
352
+ return `${value}`;
353
+ }
354
+
355
+ /**
356
+ * Static value operand
357
+ */
358
+ class Value extends Operand {
359
+ /**
360
+ * @constructor
361
+ * @param {Result} value Constant value.
362
+ */
363
+ constructor(value) {
364
+ if (Array.isArray(value)) {
365
+ throw new Error('deprecated direct usage of array, please use Collection operand');
366
+ }
367
+ super();
368
+ _defineProperty(this, "value", void 0);
369
+ this.value = value;
370
+ }
371
+
372
+ /**
373
+ * {@link Evaluable.evaluate}
374
+ */
375
+ evaluate() {
376
+ return this.value;
377
+ }
378
+
379
+ /**
380
+ * {@link Evaluable.simplify}
381
+ */
382
+ simplify() {
383
+ return this.value;
384
+ }
385
+
386
+ /**
387
+ * {@link Evaluable.serialize}
388
+ */
389
+ serialize() {
390
+ return this.value;
391
+ }
392
+
393
+ /**
394
+ * Get the strict representation of the operand.
395
+ * @return {string}
396
+ */
397
+ toString() {
398
+ return printValue(this.value);
399
+ }
400
+ }
401
+
402
+ /**
403
+ * Convert a value to number if possible, otherwise return undefined
404
+ * @param value value to be converted to number
405
+ */
406
+ const toNumber = value => {
407
+ const isValueNumber = isNumber(value);
408
+ if (isValueNumber) {
409
+ return value;
410
+ } else if (isString(value)) {
411
+ if (value.match(/^\d+\.\d+$/)) {
412
+ return parseFloat(value);
413
+ } else if (value.match(/^0$|^[1-9]\d*$/)) {
414
+ return parseInt(value);
415
+ }
416
+ }
417
+ return undefined;
418
+ };
419
+
420
+ /**
421
+ * Convert a value to string if possible, otherwise return undefined
422
+ * @param value value to be converted to string
423
+ */
424
+ const toString = value => {
425
+ if (isNumber(value)) {
426
+ return `${value}`;
427
+ } else if (isString(value)) {
428
+ return value;
429
+ }
430
+ return undefined;
431
+ };
432
+ /**
433
+ * Convert a value to number if it's type is string, otherwise return NaN
434
+ * @param value value to be converted to number
435
+ */
436
+ const toDateNumber = value => {
437
+ if (isString(value)) {
438
+ return Date.parse(value);
439
+ }
440
+ return NaN;
441
+ };
442
+
443
+ const keyWithArrayIndexRegex = /^(?<currentKey>[^[\]]+?)(?<indexes>(?:\[\d+])+)?$/;
444
+ const arrayIndexRegex = /\[(\d+)]/g;
445
+ const parseBacktickWrappedKey = key => key.startsWith('`') && key.endsWith('`') ? key.slice(1, -1) : key;
446
+ const parseKey = key => {
447
+ const keys = key.match(/(`[^[\]]+`(\[\d+\])*|[^`.]+)/g);
448
+ return !keys ? [] : keys.flatMap(key => {
449
+ const unwrappedKey = parseBacktickWrappedKey(key);
450
+ const keys = [];
451
+ const parseResult = keyWithArrayIndexRegex.exec(unwrappedKey);
452
+ if (parseResult) {
453
+ var _parseResult$groups$c, _parseResult$groups, _parseResult$groups2;
454
+ const extractedKey = parseBacktickWrappedKey((_parseResult$groups$c = parseResult === null || parseResult === void 0 || (_parseResult$groups = parseResult.groups) === null || _parseResult$groups === void 0 ? void 0 : _parseResult$groups.currentKey) !== null && _parseResult$groups$c !== void 0 ? _parseResult$groups$c : unwrappedKey);
455
+ keys.push(extractedKey);
456
+ const rawIndexes = parseResult === null || parseResult === void 0 || (_parseResult$groups2 = parseResult.groups) === null || _parseResult$groups2 === void 0 ? void 0 : _parseResult$groups2.indexes;
457
+ if (rawIndexes) {
458
+ for (const indexResult of rawIndexes.matchAll(arrayIndexRegex)) {
459
+ keys.push(parseInt(indexResult[1]));
460
+ }
461
+ }
462
+ } else {
463
+ keys.push(unwrappedKey);
464
+ }
465
+ return keys;
466
+ });
467
+ };
468
+ const complexKeyExpression = /{([^{}]+)}/;
469
+ function extractComplexKeys(ctx, key) {
470
+ // Resolve complex keys
471
+ let complexKeyMatches = complexKeyExpression.exec(key);
472
+ while (complexKeyMatches) {
473
+ const resolvedValue = complexValueLookup(ctx, complexKeyMatches[1]);
474
+ if (resolvedValue === undefined) {
475
+ return undefined;
476
+ }
477
+ key = key.replace(complexKeyExpression, `${resolvedValue}`);
478
+ complexKeyMatches = complexKeyExpression.exec(key);
479
+ }
480
+ return parseKey(key);
481
+ }
482
+ const isContext = value => isObject(value);
483
+ const simpleValueLookup = keys => ctx => {
484
+ let pointer = ctx;
485
+ for (const key of keys) {
486
+ if (typeof key === 'number') {
487
+ if (!Array.isArray(pointer)) {
488
+ return undefined;
489
+ }
490
+ pointer = pointer[key];
491
+ } else if (!isContext(pointer)) {
492
+ return undefined;
493
+ } else {
494
+ pointer = pointer[key];
495
+ }
496
+ }
497
+ return pointer;
498
+ };
499
+
500
+ /**
501
+ * Lookup for the reference in the context.
502
+ * The nested context value is annotated with "." delimiter.
503
+ * @example address.city
504
+ * @param {Context} ctx
505
+ * @param {string} key Context lookup key.
506
+ * @return {Result}
507
+ */
508
+ function complexValueLookup(ctx, key) {
509
+ const keys = extractComplexKeys(ctx, key);
510
+ if (!keys) {
511
+ return undefined;
512
+ }
513
+ return simpleValueLookup(keys !== null && keys !== void 0 ? keys : [])(ctx);
514
+ }
515
+ let DataType = /*#__PURE__*/function (DataType) {
516
+ DataType["Number"] = "Number";
517
+ DataType["String"] = "String";
518
+ return DataType;
519
+ }({});
520
+
521
+ // Equivalent to /^.+\.\((Number|String)\)$/
522
+ const dataTypeRegex = new RegExp(`^.+\\.\\((${Object.keys(DataType).join('|')})\\)$`);
523
+ const isComplexKey = key => key.indexOf('{') > -1;
524
+
525
+ /**
526
+ * Reference operand resolved within the context
527
+ */
528
+ class Reference extends Operand {
529
+ /**
530
+ * @constructor
531
+ * @param {string} key Context key.
532
+ */
533
+ constructor(key) {
534
+ if (key.trim() === '') {
535
+ throw new Error('invalid reference key');
536
+ }
537
+ super();
538
+ _defineProperty(this, "key", void 0);
539
+ _defineProperty(this, "dataType", void 0);
540
+ _defineProperty(this, "valueLookup", void 0);
541
+ _defineProperty(this, "getKeys", void 0);
542
+ this.key = key;
543
+ const dataTypeMatch = dataTypeRegex.exec(this.key);
544
+ if (dataTypeMatch) {
545
+ this.dataType = DataType[dataTypeMatch[1]];
546
+ }
547
+ if (this.key.match(/.\(.+\)$/)) {
548
+ this.key = this.key.replace(/.\(.+\)$/, '');
549
+ }
550
+ if (isComplexKey(this.key)) {
551
+ this.valueLookup = context => complexValueLookup(context, this.key);
552
+ this.getKeys = context => extractComplexKeys(context, this.key);
553
+ } else {
554
+ const keys = parseKey(this.key);
555
+ this.valueLookup = simpleValueLookup(keys);
556
+ this.getKeys = () => keys;
557
+ }
558
+ }
68
559
 
69
- /**
70
- * Check if a value is a an Evaluable
71
- * @param {Result | Evaluable} value value to check if is Evaluable
72
- * @returns {Evaluable}
73
- */
74
- function isEvaluable(value) {
75
- return typeof value === 'object' && value !== null && !Array.isArray(value) && typeof value.evaluate === 'function' && typeof value.simplify === 'function' && typeof value.serialize === 'function' && typeof value.toString === 'function';
76
- }
560
+ /**
561
+ * Evaluate in the given context.
562
+ * @param {Context} ctx
563
+ * @return {boolean}
564
+ */
565
+ evaluate(ctx) {
566
+ return this.toDataType(this.valueLookup(ctx));
567
+ }
77
568
 
78
- /**
79
- * Valid types for context members
80
- */
569
+ /**
570
+ * {@link Evaluable.simplify}
571
+ */
572
+ simplify(ctx, strictKeys, optionalKeys) {
573
+ var _this$getKeys;
574
+ const [key] = (_this$getKeys = this.getKeys(ctx)) !== null && _this$getKeys !== void 0 ? _this$getKeys : [];
575
+ if (ctx[key] !== undefined) {
576
+ return this.evaluate(ctx);
577
+ }
578
+ if (!key || typeof key === 'number') {
579
+ return this;
580
+ }
581
+ return strictKeys && strictKeys.includes(key) || optionalKeys && !optionalKeys.includes(key) ? undefined : this;
582
+ }
81
583
 
82
- /**
83
- * Evaluation Context
84
- * Holds references used during the evaluation process.
85
- * Format: key: value.
86
- */
584
+ /**
585
+ * {@link Evaluable.serialize}
586
+ */
587
+ serialize({
588
+ referenceSerialization
589
+ }) {
590
+ const key = this.dataType ? `${this.key}.(${this.dataType})` : this.key;
591
+ return referenceSerialization(key);
592
+ }
87
593
 
88
- /**
89
- * Evaluation result
90
- */
594
+ /**
595
+ * Get the strict representation of the operand.
596
+ * @return {string}
597
+ */
598
+ toString() {
599
+ return `{${this.key}}`;
600
+ }
91
601
 
92
- let EvaluableType = /*#__PURE__*/function (EvaluableType) {
93
- EvaluableType["Operand"] = "Operand";
94
- EvaluableType["Expression"] = "Expression";
95
- return EvaluableType;
96
- }({});
602
+ /**
603
+ * Converts a value to a specified data type
604
+ * Silently returns original value if data type conversion has not been implemented.
605
+ * @param value value to cast as data type
606
+ */
607
+ toDataType(value) {
608
+ let result = value;
609
+ switch (this.dataType) {
610
+ case DataType.Number:
611
+ result = toNumber(value);
612
+ break;
613
+ case DataType.String:
614
+ result = toString(value);
615
+ break;
616
+ }
617
+ if (value && result === undefined) {
618
+ console.warn(`Casting ${value} to ${this.dataType} resulted in ${result}`);
619
+ }
620
+ return result;
621
+ }
622
+ }
97
623
 
98
- /**
99
- * Evaluable
100
- */
624
+ const isSimplifiedArithmeticExpression = (operand, result) => operand instanceof Arithmetic && !isEvaluable(result) && !isInfinite(result) && !(operand instanceof Reference);
101
625
 
102
626
  /**
103
627
  * Abstract comparison expression
@@ -148,6 +672,12 @@ class Comparison {
148
672
  if (!isEvaluable(left) && !isEvaluable(right)) {
149
673
  return this.comparison(left, right);
150
674
  }
675
+ if (isEvaluable(left) && isSimplifiedArithmeticExpression(this.right, right)) {
676
+ return Reflect.construct(this.constructor, [left, new Value(right)]);
677
+ }
678
+ if (isEvaluable(right) && isSimplifiedArithmeticExpression(this.left, left)) {
679
+ return Reflect.construct(this.constructor, [new Value(left), right]);
680
+ }
151
681
  return this;
152
682
  }
153
683
 
@@ -194,47 +724,6 @@ class Equal extends Comparison {
194
724
  }
195
725
  }
196
726
 
197
- /**
198
- * Convert a value to number if possible, otherwise return undefined
199
- * @param value value to be converted to number
200
- */
201
- const toNumber = value => {
202
- const isValueNumber = isNumber(value);
203
- if (isValueNumber) {
204
- return value;
205
- } else if (isString(value)) {
206
- if (value.match(/^\d+\.\d+$/)) {
207
- return parseFloat(value);
208
- } else if (value.match(/^0$|^[1-9]\d*$/)) {
209
- return parseInt(value);
210
- }
211
- }
212
- return undefined;
213
- };
214
-
215
- /**
216
- * Convert a value to string if possible, otherwise return undefined
217
- * @param value value to be converted to string
218
- */
219
- const toString = value => {
220
- if (isNumber(value)) {
221
- return `${value}`;
222
- } else if (isString(value)) {
223
- return value;
224
- }
225
- return undefined;
226
- };
227
- /**
228
- * Convert a value to number if it's type is string, otherwise return NaN
229
- * @param value value to be converted to number
230
- */
231
- const toDateNumber = value => {
232
- if (isString(value)) {
233
- return Date.parse(value);
234
- }
235
- return NaN;
236
- };
237
-
238
727
  // Operator key
239
728
  const OPERATOR$g = Symbol('GE');
240
729
 
@@ -549,141 +1038,61 @@ class Overlap extends Comparison {
549
1038
  }
550
1039
  const leftArray = left;
551
1040
  const rightArray = right;
552
- return leftArray.some(element => rightArray.includes(element));
553
- }
554
-
555
- /**
556
- * Get the strict representation of the expression.
557
- * @return {string}
558
- */
559
- toString() {
560
- const left = this.left.toString();
561
- const right = this.right.toString();
562
- return `(${left} ${this.operator} ${right})`;
563
- }
564
- }
565
-
566
- // Operator key
567
- const OPERATOR$8 = Symbol('PREFIX');
568
-
569
- /**
570
- * Prefix comparison expression
571
- */
572
- class Prefix extends Comparison {
573
- /**
574
- * @constructor
575
- * @param {Evaluable} left Left operand.
576
- * @param {Evaluable} right Right operand.
577
- */
578
-
579
- constructor(left, right) {
580
- if (arguments.length !== 2) {
581
- throw new Error('comparison expression expects left and right operands');
582
- }
583
- super('prefix', OPERATOR$8, left, right);
584
- }
585
-
586
- /**
587
- * {@link Comparison.comparison}
588
- */
589
- comparison(left, right) {
590
- if (isString(left) === false || isString(right) === false) {
591
- return false;
592
- }
593
- return right.startsWith(left);
594
- }
595
-
596
- /**
597
- * Get the strict representation of the expression.
598
- * @return {string}
599
- */
600
- toString() {
601
- const left = this.left.toString();
602
- const right = this.right.toString();
603
- return `(<${left}>${right})`;
604
- }
605
- }
606
-
607
- /**
608
- * Abstract operand
609
- */
610
- class Operand {
611
- constructor() {
612
- _defineProperty(this, "type", EvaluableType.Operand);
613
- }
614
- /**
615
- * {@link Evaluable.evaluate}
616
- */
617
- /**
618
- * {@link Evaluable.simplify}
619
- */
620
- /**
621
- * {@link Evaluable.serialize}
622
- */
623
- /**
624
- * Get the strict representation.
625
- */
626
- toString() {
627
- throw new Error('not implemented exception');
628
- }
629
- }
630
-
631
- /**
632
- * Print value as string
633
- * @param {Result} value
634
- * @return {string}
635
- */
636
- function printValue(value) {
637
- if (isString(value)) {
638
- return `"${value}"`;
639
- }
640
- return `${value}`;
641
- }
642
-
643
- /**
644
- * Static value operand
645
- */
646
- class Value extends Operand {
647
- /**
648
- * @constructor
649
- * @param {Result} value Constant value.
650
- */
651
- constructor(value) {
652
- if (Array.isArray(value)) {
653
- throw new Error('deprecated direct usage of array, please use Collection operand');
654
- }
655
- super();
656
- _defineProperty(this, "value", void 0);
657
- this.value = value;
1041
+ if (leftArray.length === 0 && rightArray.length === 0) {
1042
+ return true;
1043
+ }
1044
+ return leftArray.some(element => rightArray.includes(element));
658
1045
  }
659
1046
 
660
1047
  /**
661
- * {@link Evaluable.evaluate}
1048
+ * Get the strict representation of the expression.
1049
+ * @return {string}
662
1050
  */
663
- evaluate() {
664
- return this.value;
1051
+ toString() {
1052
+ const left = this.left.toString();
1053
+ const right = this.right.toString();
1054
+ return `(${left} ${this.operator} ${right})`;
665
1055
  }
1056
+ }
666
1057
 
1058
+ // Operator key
1059
+ const OPERATOR$8 = Symbol('PREFIX');
1060
+
1061
+ /**
1062
+ * Prefix comparison expression
1063
+ */
1064
+ class Prefix extends Comparison {
667
1065
  /**
668
- * {@link Evaluable.simplify}
1066
+ * @constructor
1067
+ * @param {Evaluable} left Left operand.
1068
+ * @param {Evaluable} right Right operand.
669
1069
  */
670
- simplify() {
671
- return this.value;
1070
+
1071
+ constructor(left, right) {
1072
+ if (arguments.length !== 2) {
1073
+ throw new Error('comparison expression expects left and right operands');
1074
+ }
1075
+ super('prefix', OPERATOR$8, left, right);
672
1076
  }
673
1077
 
674
1078
  /**
675
- * {@link Evaluable.serialize}
1079
+ * {@link Comparison.comparison}
676
1080
  */
677
- serialize() {
678
- return this.value;
1081
+ comparison(left, right) {
1082
+ if (isString(left) === false || isString(right) === false) {
1083
+ return false;
1084
+ }
1085
+ return right.startsWith(left);
679
1086
  }
680
1087
 
681
1088
  /**
682
- * Get the strict representation of the operand.
1089
+ * Get the strict representation of the expression.
683
1090
  * @return {string}
684
1091
  */
685
1092
  toString() {
686
- return printValue(this.value);
1093
+ const left = this.left.toString();
1094
+ const right = this.right.toString();
1095
+ return `(<${left}>${right})`;
687
1096
  }
688
1097
  }
689
1098
 
@@ -1230,187 +1639,6 @@ class Collection extends Operand {
1230
1639
  }
1231
1640
  }
1232
1641
 
1233
- const keyWithArrayIndexRegex = /^(?<currentKey>[^[\]]+?)(?<indexes>(?:\[\d+])+)?$/;
1234
- const arrayIndexRegex = /\[(\d+)]/g;
1235
- const parseBacktickWrappedKey = key => key.startsWith('`') && key.endsWith('`') ? key.slice(1, -1) : key;
1236
- const parseKey = key => {
1237
- const keys = key.match(/(`[^[\]]+`(\[\d+\])*|[^`.]+)/g);
1238
- return !keys ? [] : keys.flatMap(key => {
1239
- const unwrappedKey = parseBacktickWrappedKey(key);
1240
- const keys = [];
1241
- const parseResult = keyWithArrayIndexRegex.exec(unwrappedKey);
1242
- if (parseResult) {
1243
- var _parseResult$groups$c, _parseResult$groups, _parseResult$groups2;
1244
- const extractedKey = parseBacktickWrappedKey((_parseResult$groups$c = parseResult === null || parseResult === void 0 || (_parseResult$groups = parseResult.groups) === null || _parseResult$groups === void 0 ? void 0 : _parseResult$groups.currentKey) !== null && _parseResult$groups$c !== void 0 ? _parseResult$groups$c : unwrappedKey);
1245
- keys.push(extractedKey);
1246
- const rawIndexes = parseResult === null || parseResult === void 0 || (_parseResult$groups2 = parseResult.groups) === null || _parseResult$groups2 === void 0 ? void 0 : _parseResult$groups2.indexes;
1247
- if (rawIndexes) {
1248
- for (const indexResult of rawIndexes.matchAll(arrayIndexRegex)) {
1249
- keys.push(parseInt(indexResult[1]));
1250
- }
1251
- }
1252
- } else {
1253
- keys.push(unwrappedKey);
1254
- }
1255
- return keys;
1256
- });
1257
- };
1258
- const complexKeyExpression = /{([^{}]+)}/;
1259
- function extractComplexKeys(ctx, key) {
1260
- // Resolve complex keys
1261
- let complexKeyMatches = complexKeyExpression.exec(key);
1262
- while (complexKeyMatches) {
1263
- const resolvedValue = complexValueLookup(ctx, complexKeyMatches[1]);
1264
- if (resolvedValue === undefined) {
1265
- return undefined;
1266
- }
1267
- key = key.replace(complexKeyExpression, `${resolvedValue}`);
1268
- complexKeyMatches = complexKeyExpression.exec(key);
1269
- }
1270
- return parseKey(key);
1271
- }
1272
- const isContext = value => isObject(value);
1273
- const simpleValueLookup = keys => ctx => {
1274
- let pointer = ctx;
1275
- for (const key of keys) {
1276
- if (typeof key === 'number') {
1277
- if (!Array.isArray(pointer)) {
1278
- return undefined;
1279
- }
1280
- pointer = pointer[key];
1281
- } else if (!isContext(pointer)) {
1282
- return undefined;
1283
- } else {
1284
- pointer = pointer[key];
1285
- }
1286
- }
1287
- return pointer;
1288
- };
1289
-
1290
- /**
1291
- * Lookup for the reference in the context.
1292
- * The nested context value is annotated with "." delimiter.
1293
- * @example address.city
1294
- * @param {Context} ctx
1295
- * @param {string} key Context lookup key.
1296
- * @return {Result}
1297
- */
1298
- function complexValueLookup(ctx, key) {
1299
- const keys = extractComplexKeys(ctx, key);
1300
- if (!keys) {
1301
- return undefined;
1302
- }
1303
- return simpleValueLookup(keys !== null && keys !== void 0 ? keys : [])(ctx);
1304
- }
1305
- let DataType = /*#__PURE__*/function (DataType) {
1306
- DataType["Number"] = "Number";
1307
- DataType["String"] = "String";
1308
- return DataType;
1309
- }({});
1310
-
1311
- // Equivalent to /^.+\.\((Number|String)\)$/
1312
- const dataTypeRegex = new RegExp(`^.+\\.\\((${Object.keys(DataType).join('|')})\\)$`);
1313
- const isComplexKey = key => key.indexOf('{') > -1;
1314
-
1315
- /**
1316
- * Reference operand resolved within the context
1317
- */
1318
- class Reference extends Operand {
1319
- /**
1320
- * @constructor
1321
- * @param {string} key Context key.
1322
- */
1323
- constructor(key) {
1324
- if (key.trim() === '') {
1325
- throw new Error('invalid reference key');
1326
- }
1327
- super();
1328
- _defineProperty(this, "key", void 0);
1329
- _defineProperty(this, "dataType", void 0);
1330
- _defineProperty(this, "valueLookup", void 0);
1331
- _defineProperty(this, "getKeys", void 0);
1332
- this.key = key;
1333
- const dataTypeMatch = dataTypeRegex.exec(this.key);
1334
- if (dataTypeMatch) {
1335
- this.dataType = DataType[dataTypeMatch[1]];
1336
- }
1337
- if (this.key.match(/.\(.+\)$/)) {
1338
- this.key = this.key.replace(/.\(.+\)$/, '');
1339
- }
1340
- if (isComplexKey(this.key)) {
1341
- this.valueLookup = context => complexValueLookup(context, this.key);
1342
- this.getKeys = context => extractComplexKeys(context, this.key);
1343
- } else {
1344
- const keys = parseKey(this.key);
1345
- this.valueLookup = simpleValueLookup(keys);
1346
- this.getKeys = () => keys;
1347
- }
1348
- }
1349
-
1350
- /**
1351
- * Evaluate in the given context.
1352
- * @param {Context} ctx
1353
- * @return {boolean}
1354
- */
1355
- evaluate(ctx) {
1356
- return this.toDataType(this.valueLookup(ctx));
1357
- }
1358
-
1359
- /**
1360
- * {@link Evaluable.simplify}
1361
- */
1362
- simplify(ctx, strictKeys, optionalKeys) {
1363
- var _this$getKeys;
1364
- const [key] = (_this$getKeys = this.getKeys(ctx)) !== null && _this$getKeys !== void 0 ? _this$getKeys : [];
1365
- if (ctx[key] !== undefined) {
1366
- return this.evaluate(ctx);
1367
- }
1368
- if (!key || typeof key === 'number') {
1369
- return this;
1370
- }
1371
- return strictKeys && strictKeys.includes(key) || optionalKeys && !optionalKeys.includes(key) ? undefined : this;
1372
- }
1373
-
1374
- /**
1375
- * {@link Evaluable.serialize}
1376
- */
1377
- serialize({
1378
- referenceSerialization
1379
- }) {
1380
- const key = this.dataType ? `${this.key}.(${this.dataType})` : this.key;
1381
- return referenceSerialization(key);
1382
- }
1383
-
1384
- /**
1385
- * Get the strict representation of the operand.
1386
- * @return {string}
1387
- */
1388
- toString() {
1389
- return `{${this.key}}`;
1390
- }
1391
-
1392
- /**
1393
- * Converts a value to a specified data type
1394
- * Silently returns original value if data type conversion has not been implemented.
1395
- * @param value value to cast as data type
1396
- */
1397
- toDataType(value) {
1398
- let result = value;
1399
- switch (this.dataType) {
1400
- case DataType.Number:
1401
- result = toNumber(value);
1402
- break;
1403
- case DataType.String:
1404
- result = toString(value);
1405
- break;
1406
- }
1407
- if (value && result === undefined) {
1408
- console.warn(`Casting ${value} to ${this.dataType} resulted in ${result}`);
1409
- }
1410
- return result;
1411
- }
1412
- }
1413
-
1414
1642
  // Option value whitelist
1415
1643
 
1416
1644
  // Parser options
@@ -1446,7 +1674,9 @@ const defaultOperatorMapping = new Map([
1446
1674
  // Comparison
1447
1675
  [OPERATOR$h, '=='], [OPERATOR$b, '!='], [OPERATOR$f, '>'], [OPERATOR$g, '>='], [OPERATOR$c, '<'], [OPERATOR$d, '<='], [OPERATOR$e, 'IN'], [OPERATOR$a, 'NOT IN'], [OPERATOR$8, 'PREFIX'], [OPERATOR$6, 'SUFFIX'], [OPERATOR$9, 'OVERLAP'], [OPERATOR$5, 'UNDEFINED'], [OPERATOR$7, 'PRESENT'],
1448
1676
  // Logical
1449
- [OPERATOR$4, 'AND'], [OPERATOR$1, 'OR'], [OPERATOR$2, 'NOR'], [OPERATOR, 'XOR'], [OPERATOR$3, 'NOT']]);
1677
+ [OPERATOR$4, 'AND'], [OPERATOR$1, 'OR'], [OPERATOR$2, 'NOR'], [OPERATOR, 'XOR'], [OPERATOR$3, 'NOT'],
1678
+ // Arithmetic
1679
+ [OPERATOR$i, '+'], [OPERATOR$j, '-'], [OPERATOR$k, '*'], [OPERATOR$l, '/']]);
1450
1680
 
1451
1681
  /**
1452
1682
  * Default parser options
@@ -1460,6 +1690,14 @@ const defaultOptions = {
1460
1690
 
1461
1691
  // Input types
1462
1692
 
1693
+ const invalidExpression = 'invalid expression';
1694
+ const logicalIfValidOperands = (operands, logical) => {
1695
+ if (operands.every(operand => operand instanceof Logical || operand instanceof Comparison)) {
1696
+ return logical;
1697
+ }
1698
+ throw new Error(invalidExpression);
1699
+ };
1700
+
1463
1701
  /**
1464
1702
  * Parser of raw expressions into Evaluable expression
1465
1703
  */
@@ -1470,7 +1708,8 @@ class Parser {
1470
1708
  */
1471
1709
  constructor(options) {
1472
1710
  _defineProperty(this, "opts", void 0);
1473
- _defineProperty(this, "expectedOperators", void 0);
1711
+ _defineProperty(this, "expectedRootOperators", void 0);
1712
+ _defineProperty(this, "unexpectedRootSymbols", new Set([OPERATOR$i, OPERATOR$j, OPERATOR$k, OPERATOR$l]));
1474
1713
  this.opts = {
1475
1714
  ...defaultOptions
1476
1715
  };
@@ -1482,7 +1721,7 @@ class Parser {
1482
1721
  }
1483
1722
  }
1484
1723
  }
1485
- this.expectedOperators = new Set(this.opts.operatorMapping.values());
1724
+ this.expectedRootOperators = new Set(Array.from(this.opts.operatorMapping.entries()).filter(([symbol]) => !this.unexpectedRootSymbols.has(symbol)).map(([, operator]) => operator));
1486
1725
  }
1487
1726
 
1488
1727
  /**
@@ -1500,10 +1739,10 @@ class Parser {
1500
1739
  */
1501
1740
  parse(raw) {
1502
1741
  if (raw === undefined || raw === null || Array.isArray(raw) === false) {
1503
- throw new Error('invalid expression');
1742
+ throw new Error(invalidExpression);
1504
1743
  }
1505
- if (raw.length === 0 || !this.expectedOperators.has(`${raw[0]}`)) {
1506
- throw new Error('invalid expression');
1744
+ if (raw.length === 0 || !this.expectedRootOperators.has(`${raw[0]}`)) {
1745
+ throw new Error(invalidExpression);
1507
1746
  }
1508
1747
  return this.parseRawExp(raw);
1509
1748
  }
@@ -1541,71 +1780,103 @@ class Parser {
1541
1780
  return collapsible && operands.length === 1 ? operands[0] : undefined;
1542
1781
  };
1543
1782
  switch (operator) {
1544
- /**
1545
- * Logical
1546
- */
1783
+ // Logical
1547
1784
  case this.opts.operatorMapping.get(OPERATOR$4):
1548
- expression = operands => logicalExpressionReducer(operands, true) || new And(operands);
1785
+ expression = operands => logicalExpressionReducer(operands, true) || logicalIfValidOperands(operands, new And(operands));
1549
1786
  operandParser = this.parseRawExp;
1550
1787
  break;
1551
1788
  case this.opts.operatorMapping.get(OPERATOR$1):
1552
- expression = operands => logicalExpressionReducer(operands, true) || new Or(operands);
1789
+ expression = operands => logicalExpressionReducer(operands, true) || logicalIfValidOperands(operands, new Or(operands));
1553
1790
  operandParser = this.parseRawExp;
1554
1791
  break;
1555
1792
  case this.opts.operatorMapping.get(OPERATOR$2):
1556
- expression = operands => logicalExpressionReducer(operands) || new Nor(operands);
1793
+ expression = operands => logicalExpressionReducer(operands) || logicalIfValidOperands(operands, new Nor(operands));
1557
1794
  operandParser = this.parseRawExp;
1558
1795
  break;
1559
1796
  case this.opts.operatorMapping.get(OPERATOR):
1560
- expression = operands => logicalExpressionReducer(operands) || new Xor(operands);
1797
+ expression = operands => logicalExpressionReducer(operands) || logicalIfValidOperands(operands, new Xor(operands));
1561
1798
  operandParser = this.parseRawExp;
1562
1799
  break;
1563
1800
  case this.opts.operatorMapping.get(OPERATOR$3):
1564
- expression = operands => logicalExpressionReducer(operands) || new Not(...operands);
1801
+ expression = operands => logicalExpressionReducer(operands) || logicalIfValidOperands(operands, new Not(...operands));
1565
1802
  operandParser = this.parseRawExp;
1566
1803
  break;
1567
- /**
1568
- * Comparison
1569
- */
1804
+
1805
+ // Comparison
1570
1806
  case this.opts.operatorMapping.get(OPERATOR$h):
1571
1807
  expression = operands => new Equal(...operands);
1808
+ operandParser = this.parseRawExp;
1572
1809
  break;
1573
1810
  case this.opts.operatorMapping.get(OPERATOR$b):
1574
1811
  expression = operands => new NotEqual(...operands);
1812
+ operandParser = this.parseRawExp;
1575
1813
  break;
1576
1814
  case this.opts.operatorMapping.get(OPERATOR$f):
1577
1815
  expression = operands => new GreaterThan(...operands);
1816
+ operandParser = this.parseRawExp;
1578
1817
  break;
1579
1818
  case this.opts.operatorMapping.get(OPERATOR$g):
1580
1819
  expression = operands => new GreaterThanOrEqual(...operands);
1820
+ operandParser = this.parseRawExp;
1581
1821
  break;
1582
1822
  case this.opts.operatorMapping.get(OPERATOR$c):
1583
1823
  expression = operands => new LessThan(...operands);
1824
+ operandParser = this.parseRawExp;
1584
1825
  break;
1585
1826
  case this.opts.operatorMapping.get(OPERATOR$d):
1586
1827
  expression = operands => new LessThanOrEqual(...operands);
1828
+ operandParser = this.parseRawExp;
1587
1829
  break;
1830
+
1831
+ // Containment
1588
1832
  case this.opts.operatorMapping.get(OPERATOR$e):
1589
1833
  expression = operands => new In(...operands);
1590
1834
  break;
1591
1835
  case this.opts.operatorMapping.get(OPERATOR$a):
1592
1836
  expression = operands => new NotIn(...operands);
1593
1837
  break;
1838
+
1839
+ // Prefix
1594
1840
  case this.opts.operatorMapping.get(OPERATOR$8):
1595
1841
  expression = operands => new Prefix(...operands);
1596
1842
  break;
1843
+
1844
+ // Suffix
1597
1845
  case this.opts.operatorMapping.get(OPERATOR$6):
1598
1846
  expression = operands => new Suffix(...operands);
1599
1847
  break;
1848
+
1849
+ // Overlap
1600
1850
  case this.opts.operatorMapping.get(OPERATOR$9):
1601
1851
  expression = operands => new Overlap(...operands);
1602
1852
  break;
1853
+
1854
+ // Presence
1603
1855
  case this.opts.operatorMapping.get(OPERATOR$5):
1604
1856
  expression = operands => new Undefined(...operands);
1605
1857
  break;
1606
1858
  case this.opts.operatorMapping.get(OPERATOR$7):
1607
1859
  expression = operands => new Present(...operands);
1608
1860
  break;
1861
+
1862
+ // Arithmetic
1863
+ case this.opts.operatorMapping.get(OPERATOR$i):
1864
+ expression = operands => new Sum(...operands);
1865
+ operandParser = this.parseRawExp;
1866
+ break;
1867
+ case this.opts.operatorMapping.get(OPERATOR$j):
1868
+ expression = operands => new Subtract(...operands);
1869
+ operandParser = this.parseRawExp;
1870
+ break;
1871
+ case this.opts.operatorMapping.get(OPERATOR$k):
1872
+ expression = operands => new Multiply(...operands);
1873
+ operandParser = this.parseRawExp;
1874
+ break;
1875
+ case this.opts.operatorMapping.get(OPERATOR$l):
1876
+ expression = operands => new Divide(...operands);
1877
+ operandParser = this.parseRawExp;
1878
+ break;
1879
+
1609
1880
  // Collection
1610
1881
  default:
1611
1882
  return this.getOperand(raw);
@@ -1626,6 +1897,8 @@ class Parser {
1626
1897
  }
1627
1898
  }
1628
1899
 
1900
+ const unexpectedResultError = 'non expression or boolean result should be returned';
1901
+
1629
1902
  /**
1630
1903
  * Condition engine
1631
1904
  */
@@ -1646,7 +1919,11 @@ class Engine {
1646
1919
  * @return {boolean}
1647
1920
  */
1648
1921
  evaluate(exp, ctx) {
1649
- return this.parse(exp).evaluate(ctx);
1922
+ const result = this.parse(exp).evaluate(ctx);
1923
+ if (isBoolean(result)) {
1924
+ return result;
1925
+ }
1926
+ throw new Error(unexpectedResultError);
1650
1927
  }
1651
1928
 
1652
1929
  /**
@@ -1690,8 +1967,8 @@ class Engine {
1690
1967
  if (isBoolean(result)) {
1691
1968
  return result;
1692
1969
  }
1693
- throw new Error('non expression or boolean result should be returned');
1970
+ throw new Error(unexpectedResultError);
1694
1971
  }
1695
1972
  }
1696
1973
 
1697
- export { OPERATOR$4 as OPERATOR_AND, OPERATOR$h as OPERATOR_EQ, OPERATOR$g as OPERATOR_GE, OPERATOR$f as OPERATOR_GT, OPERATOR$e as OPERATOR_IN, OPERATOR$d as OPERATOR_LE, OPERATOR$c as OPERATOR_LT, OPERATOR$b as OPERATOR_NE, OPERATOR$2 as OPERATOR_NOR, OPERATOR$3 as OPERATOR_NOT, OPERATOR$a as OPERATOR_NOT_IN, OPERATOR$1 as OPERATOR_OR, OPERATOR$9 as OPERATOR_OVERLAP, OPERATOR$8 as OPERATOR_PREFIX, OPERATOR$7 as OPERATOR_PRESENT, OPERATOR$6 as OPERATOR_SUFFIX, OPERATOR$5 as OPERATOR_UNDEFINED, OPERATOR as OPERATOR_XOR, Engine as default, defaultOptions, isEvaluable };
1974
+ export { OPERATOR$4 as OPERATOR_AND, OPERATOR$l as OPERATOR_DIVIDE, OPERATOR$h as OPERATOR_EQ, OPERATOR$g as OPERATOR_GE, OPERATOR$f as OPERATOR_GT, OPERATOR$e as OPERATOR_IN, OPERATOR$d as OPERATOR_LE, OPERATOR$c as OPERATOR_LT, OPERATOR$k as OPERATOR_MULTIPLY, OPERATOR$b as OPERATOR_NE, OPERATOR$2 as OPERATOR_NOR, OPERATOR$3 as OPERATOR_NOT, OPERATOR$a as OPERATOR_NOT_IN, OPERATOR$1 as OPERATOR_OR, OPERATOR$9 as OPERATOR_OVERLAP, OPERATOR$8 as OPERATOR_PREFIX, OPERATOR$7 as OPERATOR_PRESENT, OPERATOR$j as OPERATOR_SUBTRACT, OPERATOR$6 as OPERATOR_SUFFIX, OPERATOR$i as OPERATOR_SUM, OPERATOR$5 as OPERATOR_UNDEFINED, OPERATOR as OPERATOR_XOR, Engine as default, defaultOptions, isEvaluable };