@briza/illogical 1.5.4 → 1.5.6
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/changelog.md +10 -0
- package/lib/illogical.esm.js +332 -500
- package/lib/illogical.js +334 -500
- package/package.json +25 -25
- package/readme.md +20 -4
- package/types/common/evaluable.d.ts +3 -3
- package/types/common/util.d.ts +5 -0
- package/types/index.d.ts +3 -1
- package/types/operand/reference.d.ts +2 -0
- package/types/parser/index.d.ts +3 -3
- package/types/parser/options.d.ts +1 -1
package/lib/illogical.js
CHANGED
|
@@ -2,6 +2,35 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
+
function _toPrimitive(t, r) {
|
|
6
|
+
if ("object" != typeof t || !t) return t;
|
|
7
|
+
var e = t[Symbol.toPrimitive];
|
|
8
|
+
if (void 0 !== e) {
|
|
9
|
+
var i = e.call(t, r || "default");
|
|
10
|
+
if ("object" != typeof i) return i;
|
|
11
|
+
throw new TypeError("@@toPrimitive must return a primitive value.");
|
|
12
|
+
}
|
|
13
|
+
return ("string" === r ? String : Number)(t);
|
|
14
|
+
}
|
|
15
|
+
function _toPropertyKey(t) {
|
|
16
|
+
var i = _toPrimitive(t, "string");
|
|
17
|
+
return "symbol" == typeof i ? i : String(i);
|
|
18
|
+
}
|
|
19
|
+
function _defineProperty(obj, key, value) {
|
|
20
|
+
key = _toPropertyKey(key);
|
|
21
|
+
if (key in obj) {
|
|
22
|
+
Object.defineProperty(obj, key, {
|
|
23
|
+
value: value,
|
|
24
|
+
enumerable: true,
|
|
25
|
+
configurable: true,
|
|
26
|
+
writable: true
|
|
27
|
+
});
|
|
28
|
+
} else {
|
|
29
|
+
obj[key] = value;
|
|
30
|
+
}
|
|
31
|
+
return obj;
|
|
32
|
+
}
|
|
33
|
+
|
|
5
34
|
/**
|
|
6
35
|
* Is number predicate.
|
|
7
36
|
* @param value Tested value.
|
|
@@ -9,64 +38,47 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
9
38
|
function isNumber(value) {
|
|
10
39
|
return typeof value === 'number' && isFinite(value);
|
|
11
40
|
}
|
|
41
|
+
|
|
12
42
|
/**
|
|
13
43
|
* Is string type predicate.
|
|
14
44
|
* @param value Tested value.
|
|
15
45
|
*/
|
|
16
|
-
|
|
17
46
|
function isString(value) {
|
|
18
47
|
return typeof value === 'string' || value instanceof String;
|
|
19
48
|
}
|
|
49
|
+
|
|
20
50
|
/**
|
|
21
51
|
* Is Object
|
|
22
52
|
* @param value tested value result of the test
|
|
23
53
|
*/
|
|
24
|
-
|
|
25
54
|
function isObject(value) {
|
|
26
55
|
if (value === null || value === undefined) {
|
|
27
56
|
return false;
|
|
28
57
|
}
|
|
29
|
-
|
|
30
58
|
if (typeof value !== 'object' || (value === null || value === void 0 ? void 0 : value.constructor) !== Object) {
|
|
31
59
|
return false;
|
|
32
60
|
}
|
|
33
|
-
|
|
34
61
|
return true;
|
|
35
62
|
}
|
|
63
|
+
|
|
36
64
|
/**
|
|
37
65
|
* Is Boolean predicate.
|
|
38
66
|
* @param value tested value.
|
|
39
67
|
* @return result of the test
|
|
40
68
|
*/
|
|
41
|
-
|
|
42
69
|
function isBoolean(value) {
|
|
43
70
|
return typeof value === 'boolean';
|
|
44
71
|
}
|
|
72
|
+
|
|
45
73
|
/**
|
|
46
74
|
* Check if a value is a an Evaluable
|
|
47
75
|
* @param {Result | Evaluable} value value to check if is Evaluable
|
|
48
76
|
* @returns {Evaluable}
|
|
49
77
|
*/
|
|
50
|
-
|
|
51
78
|
function isEvaluable(value) {
|
|
52
79
|
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';
|
|
53
80
|
}
|
|
54
81
|
|
|
55
|
-
function _defineProperty(obj, key, value) {
|
|
56
|
-
if (key in obj) {
|
|
57
|
-
Object.defineProperty(obj, key, {
|
|
58
|
-
value: value,
|
|
59
|
-
enumerable: true,
|
|
60
|
-
configurable: true,
|
|
61
|
-
writable: true
|
|
62
|
-
});
|
|
63
|
-
} else {
|
|
64
|
-
obj[key] = value;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
return obj;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
82
|
/**
|
|
71
83
|
* Valid types for context members
|
|
72
84
|
*/
|
|
@@ -80,15 +92,16 @@ function _defineProperty(obj, key, value) {
|
|
|
80
92
|
/**
|
|
81
93
|
* Evaluation result
|
|
82
94
|
*/
|
|
83
|
-
let EvaluableType;
|
|
84
|
-
/**
|
|
85
|
-
* Evaluable
|
|
86
|
-
*/
|
|
87
95
|
|
|
88
|
-
|
|
96
|
+
let EvaluableType = /*#__PURE__*/function (EvaluableType) {
|
|
89
97
|
EvaluableType["Operand"] = "Operand";
|
|
90
98
|
EvaluableType["Expression"] = "Expression";
|
|
91
|
-
|
|
99
|
+
return EvaluableType;
|
|
100
|
+
}({});
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Evaluable
|
|
104
|
+
*/
|
|
92
105
|
|
|
93
106
|
/**
|
|
94
107
|
* Abstract comparison expression
|
|
@@ -101,30 +114,28 @@ class Comparison {
|
|
|
101
114
|
* @param {Operand} right Right operand.
|
|
102
115
|
*/
|
|
103
116
|
constructor(operator, operatorSymbol, left, right) {
|
|
104
|
-
_defineProperty(this, "type", EvaluableType.Expression);
|
|
105
|
-
|
|
106
117
|
this.operator = operator;
|
|
107
118
|
this.operatorSymbol = operatorSymbol;
|
|
108
119
|
this.left = left;
|
|
109
120
|
this.right = right;
|
|
121
|
+
_defineProperty(this, "type", EvaluableType.Expression);
|
|
110
122
|
}
|
|
123
|
+
|
|
111
124
|
/**
|
|
112
125
|
* {@link Evaluable.evaluate}
|
|
113
126
|
*/
|
|
114
|
-
|
|
115
|
-
|
|
116
127
|
evaluate(ctx) {
|
|
117
128
|
return this.comparison(this.left.evaluate(ctx), this.right.evaluate(ctx));
|
|
118
129
|
}
|
|
130
|
+
|
|
119
131
|
/**
|
|
120
132
|
* Get the strict representation of the expression.
|
|
121
133
|
* @return {string}
|
|
122
134
|
*/
|
|
123
|
-
|
|
124
|
-
|
|
125
135
|
toString() {
|
|
126
136
|
return `(${this.left.toString()} ${this.operator} ${this.right.toString()})`;
|
|
127
137
|
}
|
|
138
|
+
|
|
128
139
|
/**
|
|
129
140
|
* Compares left and right operands evaluated values.
|
|
130
141
|
* @param {Result} left left operand result value
|
|
@@ -132,450 +143,469 @@ class Comparison {
|
|
|
132
143
|
* @returns {boolean}
|
|
133
144
|
*/
|
|
134
145
|
|
|
135
|
-
|
|
136
146
|
/**
|
|
137
147
|
* {@link Evaluable.simplify}
|
|
138
148
|
*/
|
|
139
|
-
simplify() {
|
|
140
|
-
const left = this.left.simplify(...
|
|
141
|
-
const right = this.right.simplify(...
|
|
142
|
-
|
|
149
|
+
simplify(...args) {
|
|
150
|
+
const left = this.left.simplify(...args);
|
|
151
|
+
const right = this.right.simplify(...args);
|
|
143
152
|
if (!isEvaluable(left) && !isEvaluable(right)) {
|
|
144
153
|
return this.comparison(left, right);
|
|
145
154
|
}
|
|
146
|
-
|
|
147
155
|
return this;
|
|
148
156
|
}
|
|
157
|
+
|
|
149
158
|
/**
|
|
150
159
|
* {@link Evaluable.serialize}
|
|
151
160
|
*/
|
|
152
|
-
|
|
153
|
-
|
|
154
161
|
serialize(options) {
|
|
155
162
|
const {
|
|
156
163
|
operatorMapping
|
|
157
164
|
} = options;
|
|
158
165
|
const operator = operatorMapping.get(this.operatorSymbol);
|
|
159
|
-
|
|
160
166
|
if (operator === undefined) {
|
|
161
167
|
throw new Error(`missing operator ${this.operatorSymbol.toString()}`);
|
|
162
168
|
}
|
|
163
|
-
|
|
164
169
|
return [operator, this.left.serialize(options), this.right.serialize(options)];
|
|
165
170
|
}
|
|
166
|
-
|
|
167
171
|
}
|
|
168
172
|
|
|
173
|
+
// Operator key
|
|
169
174
|
const OPERATOR$h = Symbol('EQ');
|
|
175
|
+
|
|
170
176
|
/**
|
|
171
177
|
* Equal comparison expression
|
|
172
178
|
*/
|
|
173
|
-
|
|
174
179
|
class Equal extends Comparison {
|
|
175
180
|
/**
|
|
176
181
|
* @constructor
|
|
177
182
|
* @param {Evaluable} left Left operand.
|
|
178
183
|
* @param {Evaluable} right Right operand.
|
|
179
184
|
*/
|
|
185
|
+
|
|
180
186
|
constructor(left, right) {
|
|
181
187
|
if (arguments.length !== 2) {
|
|
182
188
|
throw new Error('comparison expression expects left and right operands');
|
|
183
189
|
}
|
|
184
|
-
|
|
185
190
|
super('==', OPERATOR$h, left, right);
|
|
186
191
|
}
|
|
192
|
+
|
|
187
193
|
/**
|
|
188
194
|
* {@link Comparison.comparison}
|
|
189
195
|
*/
|
|
190
|
-
|
|
191
|
-
|
|
192
196
|
comparison(left, right) {
|
|
193
197
|
return left === right;
|
|
194
198
|
}
|
|
195
|
-
|
|
196
199
|
}
|
|
197
200
|
|
|
201
|
+
/**
|
|
202
|
+
* Convert a value to number if possible, otherwise return undefined
|
|
203
|
+
* @param value value to be converted to number
|
|
204
|
+
*/
|
|
205
|
+
const toNumber = value => {
|
|
206
|
+
const isValueNumber = isNumber(value);
|
|
207
|
+
if (isValueNumber) {
|
|
208
|
+
return value;
|
|
209
|
+
} else if (isString(value)) {
|
|
210
|
+
if (value.match(/^\d+\.\d+$/)) {
|
|
211
|
+
return parseFloat(value);
|
|
212
|
+
} else if (value.match(/^0$|^[1-9]\d*$/)) {
|
|
213
|
+
return parseInt(value);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return undefined;
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Convert a value to string if possible, otherwise return undefined
|
|
221
|
+
* @param value value to be converted to string
|
|
222
|
+
*/
|
|
223
|
+
const toString = value => {
|
|
224
|
+
if (isNumber(value)) {
|
|
225
|
+
return `${value}`;
|
|
226
|
+
} else if (isString(value)) {
|
|
227
|
+
return value;
|
|
228
|
+
}
|
|
229
|
+
return undefined;
|
|
230
|
+
};
|
|
231
|
+
/**
|
|
232
|
+
* Convert a value to number if it's type is string, otherwise return NaN
|
|
233
|
+
* @param value value to be converted to number
|
|
234
|
+
*/
|
|
235
|
+
const toDateNumber = value => {
|
|
236
|
+
if (isString(value)) {
|
|
237
|
+
return Date.parse(value);
|
|
238
|
+
}
|
|
239
|
+
return NaN;
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
// Operator key
|
|
198
243
|
const OPERATOR$g = Symbol('GE');
|
|
244
|
+
|
|
199
245
|
/**
|
|
200
246
|
* Greater than or equal comparison expression
|
|
201
247
|
*/
|
|
202
|
-
|
|
203
248
|
class GreaterThanOrEqual extends Comparison {
|
|
204
249
|
/**
|
|
205
250
|
* @constructor
|
|
206
251
|
* @param {Evaluable} left Left operand.
|
|
207
252
|
* @param {Evaluable} right Right operand.
|
|
208
253
|
*/
|
|
254
|
+
|
|
209
255
|
constructor(left, right) {
|
|
210
256
|
if (arguments.length !== 2) {
|
|
211
257
|
throw new Error('comparison expression expects left and right operands');
|
|
212
258
|
}
|
|
213
|
-
|
|
214
259
|
super('>=', OPERATOR$g, left, right);
|
|
215
260
|
}
|
|
261
|
+
|
|
216
262
|
/**
|
|
217
263
|
* {@link Comparison.comparison}
|
|
218
264
|
*/
|
|
219
|
-
|
|
220
|
-
|
|
221
265
|
comparison(left, right) {
|
|
222
266
|
if (isNumber(left) && isNumber(right)) {
|
|
223
267
|
return left >= right;
|
|
224
268
|
}
|
|
225
|
-
|
|
269
|
+
const leftDate = toDateNumber(left),
|
|
270
|
+
rightDate = toDateNumber(right);
|
|
271
|
+
if (leftDate && rightDate) {
|
|
272
|
+
return leftDate >= rightDate;
|
|
273
|
+
}
|
|
226
274
|
return false;
|
|
227
275
|
}
|
|
228
|
-
|
|
229
276
|
}
|
|
230
277
|
|
|
278
|
+
// Operator key
|
|
231
279
|
const OPERATOR$f = Symbol('GT');
|
|
280
|
+
|
|
232
281
|
/**
|
|
233
282
|
* Greater than comparison expression
|
|
234
283
|
*/
|
|
235
|
-
|
|
236
284
|
class GreaterThan extends Comparison {
|
|
237
285
|
/**
|
|
238
286
|
* @constructor
|
|
239
287
|
* @param {Evaluable} left Left operand.
|
|
240
288
|
* @param {Evaluable} right Right operand.
|
|
241
289
|
*/
|
|
290
|
+
|
|
242
291
|
constructor(left, right) {
|
|
243
292
|
if (arguments.length !== 2) {
|
|
244
293
|
throw new Error('comparison expression expects left and right operands');
|
|
245
294
|
}
|
|
246
|
-
|
|
247
295
|
super('>', OPERATOR$f, left, right);
|
|
248
296
|
}
|
|
297
|
+
|
|
249
298
|
/**
|
|
250
299
|
* {@link Comparison.comparison}
|
|
251
300
|
*/
|
|
252
|
-
|
|
253
|
-
|
|
254
301
|
comparison(left, right) {
|
|
255
302
|
if (isNumber(left) && isNumber(right)) {
|
|
256
303
|
return left > right;
|
|
257
304
|
}
|
|
258
|
-
|
|
305
|
+
const leftDate = toDateNumber(left),
|
|
306
|
+
rightDate = toDateNumber(right);
|
|
307
|
+
if (leftDate && rightDate) {
|
|
308
|
+
return leftDate > rightDate;
|
|
309
|
+
}
|
|
259
310
|
return false;
|
|
260
311
|
}
|
|
261
|
-
|
|
262
312
|
}
|
|
263
313
|
|
|
314
|
+
// Operator key
|
|
264
315
|
const OPERATOR$e = Symbol('IN');
|
|
316
|
+
|
|
265
317
|
/**
|
|
266
318
|
* In comparison expression
|
|
267
319
|
*/
|
|
268
|
-
|
|
269
320
|
class In extends Comparison {
|
|
270
321
|
/**
|
|
271
322
|
* @constructor
|
|
272
323
|
* @param {Evaluable} left Left operand.
|
|
273
324
|
* @param {Evaluable} right Right operand.
|
|
274
325
|
*/
|
|
326
|
+
|
|
275
327
|
constructor(left, right) {
|
|
276
328
|
if (arguments.length !== 2) {
|
|
277
329
|
throw new Error('comparison expression expects left and right operands');
|
|
278
330
|
}
|
|
279
|
-
|
|
280
331
|
super('in', OPERATOR$e, left, right);
|
|
281
332
|
}
|
|
333
|
+
|
|
282
334
|
/**
|
|
283
335
|
* {@link Comparison.comparison}
|
|
284
336
|
*/
|
|
285
|
-
|
|
286
|
-
|
|
287
337
|
comparison(left, right) {
|
|
288
338
|
if (left === undefined || left === null || right === undefined || right === null) {
|
|
289
339
|
return false;
|
|
290
340
|
}
|
|
291
|
-
|
|
292
341
|
const leftArray = Array.isArray(left);
|
|
293
342
|
const rightArray = Array.isArray(right);
|
|
294
|
-
|
|
295
343
|
if (leftArray && rightArray) {
|
|
296
344
|
throw new Error('invalid IN expression, both operands are array');
|
|
297
345
|
}
|
|
298
|
-
|
|
299
346
|
if (!leftArray && !rightArray) {
|
|
300
347
|
throw new Error('invalid IN expression, non of the operands is array');
|
|
301
348
|
}
|
|
302
|
-
|
|
303
349
|
if (leftArray) {
|
|
304
350
|
return left.indexOf(right) > -1;
|
|
305
351
|
}
|
|
306
|
-
|
|
307
352
|
return right.indexOf(left) > -1;
|
|
308
353
|
}
|
|
354
|
+
|
|
309
355
|
/**
|
|
310
356
|
* Get the strict representation of the expression.
|
|
311
357
|
* @return {string}
|
|
312
358
|
*/
|
|
313
|
-
|
|
314
|
-
|
|
315
359
|
toString() {
|
|
316
360
|
const left = this.left.toString();
|
|
317
361
|
const right = this.right.toString();
|
|
318
|
-
|
|
319
362
|
if (left.startsWith('[')) {
|
|
320
363
|
return `(${right} ${this.operator} ${left})`;
|
|
321
364
|
}
|
|
322
|
-
|
|
323
365
|
return `(${left} ${this.operator} ${right})`;
|
|
324
366
|
}
|
|
325
|
-
|
|
326
367
|
}
|
|
327
368
|
|
|
369
|
+
// Operator key
|
|
328
370
|
const OPERATOR$d = Symbol('LE');
|
|
371
|
+
|
|
329
372
|
/**
|
|
330
373
|
* Less than or equal comparison expression
|
|
331
374
|
*/
|
|
332
|
-
|
|
333
375
|
class LessThanOrEqual extends Comparison {
|
|
334
376
|
/**
|
|
335
377
|
* @constructor
|
|
336
378
|
* @param {Evaluable} left Left operand.
|
|
337
379
|
* @param {Evaluable} right Right operand.
|
|
338
380
|
*/
|
|
381
|
+
|
|
339
382
|
constructor(left, right) {
|
|
340
383
|
if (arguments.length !== 2) {
|
|
341
384
|
throw new Error('comparison expression expects left and right operands');
|
|
342
385
|
}
|
|
343
|
-
|
|
344
386
|
super('<=', OPERATOR$d, left, right);
|
|
345
387
|
}
|
|
388
|
+
|
|
346
389
|
/**
|
|
347
390
|
* {@link Comparison.comparison}
|
|
348
391
|
*/
|
|
349
|
-
|
|
350
|
-
|
|
351
392
|
comparison(left, right) {
|
|
352
393
|
if (isNumber(left) && isNumber(right)) {
|
|
353
394
|
return left <= right;
|
|
354
395
|
}
|
|
355
|
-
|
|
396
|
+
const leftDate = toDateNumber(left),
|
|
397
|
+
rightDate = toDateNumber(right);
|
|
398
|
+
if (leftDate && rightDate) {
|
|
399
|
+
return leftDate <= rightDate;
|
|
400
|
+
}
|
|
356
401
|
return false;
|
|
357
402
|
}
|
|
358
|
-
|
|
359
403
|
}
|
|
360
404
|
|
|
405
|
+
// Operator key
|
|
361
406
|
const OPERATOR$c = Symbol('LT');
|
|
407
|
+
|
|
362
408
|
/**
|
|
363
409
|
* Less than comparison expression
|
|
364
410
|
*/
|
|
365
|
-
|
|
366
411
|
class LessThan extends Comparison {
|
|
367
412
|
/**
|
|
368
413
|
* @constructor
|
|
369
414
|
* @param {Evaluable} left Left operand.
|
|
370
415
|
* @param {Evaluable} right Right operand.
|
|
371
416
|
*/
|
|
417
|
+
|
|
372
418
|
constructor(left, right) {
|
|
373
419
|
if (arguments.length !== 2) {
|
|
374
420
|
throw new Error('comparison expression expects left and right operands');
|
|
375
421
|
}
|
|
376
|
-
|
|
377
422
|
super('<', OPERATOR$c, left, right);
|
|
378
423
|
}
|
|
424
|
+
|
|
379
425
|
/**
|
|
380
426
|
* {@link Comparison.comparison}
|
|
381
427
|
*/
|
|
382
|
-
|
|
383
|
-
|
|
384
428
|
comparison(left, right) {
|
|
385
429
|
if (isNumber(left) && isNumber(right)) {
|
|
386
430
|
return left < right;
|
|
387
431
|
}
|
|
388
|
-
|
|
432
|
+
const leftDate = toDateNumber(left),
|
|
433
|
+
rightDate = toDateNumber(right);
|
|
434
|
+
if (leftDate && rightDate) {
|
|
435
|
+
return leftDate < rightDate;
|
|
436
|
+
}
|
|
389
437
|
return false;
|
|
390
438
|
}
|
|
391
|
-
|
|
392
439
|
}
|
|
393
440
|
|
|
441
|
+
// Operator key
|
|
394
442
|
const OPERATOR$b = Symbol('NE');
|
|
443
|
+
|
|
395
444
|
/**
|
|
396
445
|
* Not equal comparison expression
|
|
397
446
|
*/
|
|
398
|
-
|
|
399
447
|
class NotEqual extends Comparison {
|
|
400
448
|
/**
|
|
401
449
|
* @constructor
|
|
402
450
|
* @param {Evaluable} left Left operand.
|
|
403
451
|
* @param {Evaluable} right Right operand.
|
|
404
452
|
*/
|
|
453
|
+
|
|
405
454
|
constructor(left, right) {
|
|
406
455
|
if (arguments.length !== 2) {
|
|
407
456
|
throw new Error('comparison expression expects left and right operands');
|
|
408
457
|
}
|
|
409
|
-
|
|
410
458
|
super('!=', OPERATOR$b, left, right);
|
|
411
459
|
}
|
|
460
|
+
|
|
412
461
|
/**
|
|
413
462
|
* {@link Comparison.comparison}
|
|
414
463
|
*/
|
|
415
|
-
|
|
416
|
-
|
|
417
464
|
comparison(left, right) {
|
|
418
465
|
return left !== right;
|
|
419
466
|
}
|
|
420
|
-
|
|
421
467
|
}
|
|
422
468
|
|
|
469
|
+
// Operator key
|
|
423
470
|
const OPERATOR$a = Symbol('NOT IN');
|
|
471
|
+
|
|
424
472
|
/**
|
|
425
473
|
* Not in comparison expression
|
|
426
474
|
*/
|
|
427
|
-
|
|
428
475
|
class NotIn extends Comparison {
|
|
429
476
|
/**
|
|
430
477
|
* @constructor
|
|
431
478
|
* @param {Evaluable} left Left operand.
|
|
432
479
|
* @param {Evaluable} right Right operand.
|
|
433
480
|
*/
|
|
481
|
+
|
|
434
482
|
constructor(left, right) {
|
|
435
483
|
if (arguments.length !== 2) {
|
|
436
484
|
throw new Error('comparison expression expects left and right operands');
|
|
437
485
|
}
|
|
438
|
-
|
|
439
486
|
super('not in', OPERATOR$a, left, right);
|
|
440
487
|
}
|
|
488
|
+
|
|
441
489
|
/**
|
|
442
490
|
* {@link Comparison.comparison}
|
|
443
491
|
*/
|
|
444
|
-
|
|
445
|
-
|
|
446
492
|
comparison(left, right) {
|
|
447
493
|
if (left === undefined || left === null || right === undefined || right === null) {
|
|
448
494
|
return true;
|
|
449
495
|
}
|
|
450
|
-
|
|
451
496
|
const leftArray = Array.isArray(left);
|
|
452
497
|
const rightArray = Array.isArray(right);
|
|
453
|
-
|
|
454
498
|
if (leftArray && rightArray) {
|
|
455
499
|
throw new Error('invalid NOT IN expression, both operands are array');
|
|
456
500
|
}
|
|
457
|
-
|
|
458
501
|
if (!leftArray && !rightArray) {
|
|
459
502
|
throw new Error('invalid NOT IN expression, one operand must be array');
|
|
460
503
|
}
|
|
461
|
-
|
|
462
504
|
if (leftArray) {
|
|
463
505
|
return left.indexOf(right) === -1;
|
|
464
506
|
}
|
|
465
|
-
|
|
466
507
|
return right.indexOf(left) === -1;
|
|
467
508
|
}
|
|
509
|
+
|
|
468
510
|
/**
|
|
469
511
|
* Get the strict representation of the expression
|
|
470
512
|
* @return {string}
|
|
471
513
|
*/
|
|
472
|
-
|
|
473
|
-
|
|
474
514
|
toString() {
|
|
475
515
|
const left = this.left.toString();
|
|
476
516
|
const right = this.right.toString();
|
|
477
|
-
|
|
478
517
|
if (left.startsWith('[')) {
|
|
479
518
|
return `(${right} ${this.operator} ${left})`;
|
|
480
519
|
}
|
|
481
|
-
|
|
482
520
|
return `(${left} ${this.operator} ${right})`;
|
|
483
521
|
}
|
|
484
|
-
|
|
485
522
|
}
|
|
486
523
|
|
|
524
|
+
// Operator key
|
|
487
525
|
const OPERATOR$9 = Symbol('OVERLAP');
|
|
526
|
+
|
|
488
527
|
/**
|
|
489
528
|
* Overlap comparison expression
|
|
490
529
|
*/
|
|
491
|
-
|
|
492
530
|
class Overlap extends Comparison {
|
|
493
531
|
/**
|
|
494
532
|
* @constructor
|
|
495
533
|
* @param {Evaluable} left Left operand.
|
|
496
534
|
* @param {Evaluable} right Right operand.
|
|
497
535
|
*/
|
|
536
|
+
|
|
498
537
|
constructor(left, right) {
|
|
499
538
|
if (arguments.length !== 2) {
|
|
500
539
|
throw new Error('comparison expression expects left and right operands');
|
|
501
540
|
}
|
|
502
|
-
|
|
503
541
|
super('overlap', OPERATOR$9, left, right);
|
|
504
542
|
}
|
|
543
|
+
|
|
505
544
|
/**
|
|
506
545
|
* {@link Comparison.comparison}
|
|
507
546
|
*/
|
|
508
|
-
|
|
509
|
-
|
|
510
547
|
comparison(left, right) {
|
|
511
548
|
if (left === undefined || left === null || right === undefined || right === null) {
|
|
512
549
|
return false;
|
|
513
550
|
}
|
|
514
|
-
|
|
515
551
|
if (!Array.isArray(left) || !Array.isArray(right)) {
|
|
516
552
|
throw new Error('invalid OVERLAP expression, both operands must be array');
|
|
517
553
|
}
|
|
518
|
-
|
|
519
554
|
const leftArray = left;
|
|
520
555
|
const rightArray = right;
|
|
521
556
|
return leftArray.some(element => rightArray.includes(element));
|
|
522
557
|
}
|
|
558
|
+
|
|
523
559
|
/**
|
|
524
560
|
* Get the strict representation of the expression.
|
|
525
561
|
* @return {string}
|
|
526
562
|
*/
|
|
527
|
-
|
|
528
|
-
|
|
529
563
|
toString() {
|
|
530
564
|
const left = this.left.toString();
|
|
531
565
|
const right = this.right.toString();
|
|
532
566
|
return `(${left} ${this.operator} ${right})`;
|
|
533
567
|
}
|
|
534
|
-
|
|
535
568
|
}
|
|
536
569
|
|
|
570
|
+
// Operator key
|
|
537
571
|
const OPERATOR$8 = Symbol('PREFIX');
|
|
572
|
+
|
|
538
573
|
/**
|
|
539
574
|
* Prefix comparison expression
|
|
540
575
|
*/
|
|
541
|
-
|
|
542
576
|
class Prefix extends Comparison {
|
|
543
577
|
/**
|
|
544
578
|
* @constructor
|
|
545
579
|
* @param {Evaluable} left Left operand.
|
|
546
580
|
* @param {Evaluable} right Right operand.
|
|
547
581
|
*/
|
|
582
|
+
|
|
548
583
|
constructor(left, right) {
|
|
549
584
|
if (arguments.length !== 2) {
|
|
550
585
|
throw new Error('comparison expression expects left and right operands');
|
|
551
586
|
}
|
|
552
|
-
|
|
553
587
|
super('prefix', OPERATOR$8, left, right);
|
|
554
588
|
}
|
|
589
|
+
|
|
555
590
|
/**
|
|
556
591
|
* {@link Comparison.comparison}
|
|
557
592
|
*/
|
|
558
|
-
|
|
559
|
-
|
|
560
593
|
comparison(left, right) {
|
|
561
594
|
if (isString(left) === false || isString(right) === false) {
|
|
562
595
|
return false;
|
|
563
596
|
}
|
|
564
|
-
|
|
565
597
|
return right.startsWith(left);
|
|
566
598
|
}
|
|
599
|
+
|
|
567
600
|
/**
|
|
568
601
|
* Get the strict representation of the expression.
|
|
569
602
|
* @return {string}
|
|
570
603
|
*/
|
|
571
|
-
|
|
572
|
-
|
|
573
604
|
toString() {
|
|
574
605
|
const left = this.left.toString();
|
|
575
606
|
const right = this.right.toString();
|
|
576
607
|
return `(<${left}>${right})`;
|
|
577
608
|
}
|
|
578
|
-
|
|
579
609
|
}
|
|
580
610
|
|
|
581
611
|
/**
|
|
@@ -585,14 +615,21 @@ class Operand {
|
|
|
585
615
|
constructor() {
|
|
586
616
|
_defineProperty(this, "type", EvaluableType.Operand);
|
|
587
617
|
}
|
|
588
|
-
|
|
618
|
+
/**
|
|
619
|
+
* {@link Evaluable.evaluate}
|
|
620
|
+
*/
|
|
621
|
+
/**
|
|
622
|
+
* {@link Evaluable.simplify}
|
|
623
|
+
*/
|
|
624
|
+
/**
|
|
625
|
+
* {@link Evaluable.serialize}
|
|
626
|
+
*/
|
|
589
627
|
/**
|
|
590
628
|
* Get the strict representation.
|
|
591
629
|
*/
|
|
592
630
|
toString() {
|
|
593
631
|
throw new Error('not implemented exception');
|
|
594
632
|
}
|
|
595
|
-
|
|
596
633
|
}
|
|
597
634
|
|
|
598
635
|
/**
|
|
@@ -600,19 +637,16 @@ class Operand {
|
|
|
600
637
|
* @param {Result} value
|
|
601
638
|
* @return {string}
|
|
602
639
|
*/
|
|
603
|
-
|
|
604
640
|
function printValue(value) {
|
|
605
641
|
if (isString(value)) {
|
|
606
642
|
return `"${value}"`;
|
|
607
643
|
}
|
|
608
|
-
|
|
609
644
|
return `${value}`;
|
|
610
645
|
}
|
|
646
|
+
|
|
611
647
|
/**
|
|
612
648
|
* Static value operand
|
|
613
649
|
*/
|
|
614
|
-
|
|
615
|
-
|
|
616
650
|
class Value extends Operand {
|
|
617
651
|
/**
|
|
618
652
|
* @constructor
|
|
@@ -622,192 +656,174 @@ class Value extends Operand {
|
|
|
622
656
|
if (Array.isArray(value)) {
|
|
623
657
|
throw new Error('deprecated direct usage of array, please use Collection operand');
|
|
624
658
|
}
|
|
625
|
-
|
|
626
659
|
super();
|
|
660
|
+
_defineProperty(this, "value", void 0);
|
|
627
661
|
this.value = value;
|
|
628
662
|
}
|
|
663
|
+
|
|
629
664
|
/**
|
|
630
665
|
* {@link Evaluable.evaluate}
|
|
631
666
|
*/
|
|
632
|
-
|
|
633
|
-
|
|
634
667
|
evaluate() {
|
|
635
668
|
return this.value;
|
|
636
669
|
}
|
|
670
|
+
|
|
637
671
|
/**
|
|
638
672
|
* {@link Evaluable.simplify}
|
|
639
673
|
*/
|
|
640
|
-
|
|
641
|
-
|
|
642
674
|
simplify() {
|
|
643
675
|
return this.value;
|
|
644
676
|
}
|
|
677
|
+
|
|
645
678
|
/**
|
|
646
679
|
* {@link Evaluable.serialize}
|
|
647
680
|
*/
|
|
648
|
-
|
|
649
|
-
|
|
650
681
|
serialize() {
|
|
651
682
|
return this.value;
|
|
652
683
|
}
|
|
684
|
+
|
|
653
685
|
/**
|
|
654
686
|
* Get the strict representation of the operand.
|
|
655
687
|
* @return {string}
|
|
656
688
|
*/
|
|
657
|
-
|
|
658
|
-
|
|
659
689
|
toString() {
|
|
660
690
|
return printValue(this.value);
|
|
661
691
|
}
|
|
662
|
-
|
|
663
692
|
}
|
|
664
693
|
|
|
694
|
+
// Operator key
|
|
665
695
|
const OPERATOR$7 = Symbol('PRESENT');
|
|
696
|
+
|
|
666
697
|
/**
|
|
667
698
|
* Present comparison expression
|
|
668
699
|
*/
|
|
669
|
-
|
|
670
700
|
class Present extends Comparison {
|
|
671
701
|
/**
|
|
672
702
|
* @constructor
|
|
673
703
|
* @param {Evaluable} operand
|
|
674
704
|
*/
|
|
705
|
+
|
|
675
706
|
constructor(operand) {
|
|
676
707
|
if (arguments.length !== 1) {
|
|
677
708
|
throw new Error('comparison expression PRESENT expects exactly one operand');
|
|
678
709
|
}
|
|
679
|
-
|
|
680
710
|
super('PRESENT', OPERATOR$7, operand, new Value(true));
|
|
681
711
|
}
|
|
712
|
+
|
|
682
713
|
/**
|
|
683
714
|
* {@link Comparison.comparison}
|
|
684
715
|
*/
|
|
685
|
-
|
|
686
|
-
|
|
687
716
|
comparison(left) {
|
|
688
717
|
return left !== undefined && left !== null;
|
|
689
718
|
}
|
|
719
|
+
|
|
690
720
|
/**
|
|
691
721
|
* Get the strict representation of the expression.
|
|
692
722
|
* @return {string}
|
|
693
723
|
*/
|
|
694
|
-
|
|
695
|
-
|
|
696
724
|
toString() {
|
|
697
725
|
return `(${this.left.toString()} is ${this.operator})`;
|
|
698
726
|
}
|
|
699
|
-
|
|
700
727
|
serialize(options) {
|
|
701
728
|
const {
|
|
702
729
|
operatorMapping
|
|
703
730
|
} = options;
|
|
704
731
|
const operator = operatorMapping.get(this.operatorSymbol);
|
|
705
|
-
|
|
706
732
|
if (operator === undefined) {
|
|
707
733
|
throw new Error(`missing operator ${this.operatorSymbol.toString()}`);
|
|
708
734
|
}
|
|
709
|
-
|
|
710
735
|
return [operator, this.left.serialize(options)];
|
|
711
736
|
}
|
|
712
|
-
|
|
713
737
|
}
|
|
714
738
|
|
|
739
|
+
// Operator key
|
|
715
740
|
const OPERATOR$6 = Symbol('PREFIX');
|
|
741
|
+
|
|
716
742
|
/**
|
|
717
743
|
* Suffix comparison expression
|
|
718
744
|
*/
|
|
719
|
-
|
|
720
745
|
class Suffix extends Comparison {
|
|
721
746
|
/**
|
|
722
747
|
* @constructor
|
|
723
748
|
* @param {Evaluable} left Left operand.
|
|
724
749
|
* @param {Evaluable} right Right operand.
|
|
725
750
|
*/
|
|
751
|
+
|
|
726
752
|
constructor(left, right) {
|
|
727
753
|
if (arguments.length !== 2) {
|
|
728
754
|
throw new Error('comparison expression expects left and right operands');
|
|
729
755
|
}
|
|
730
|
-
|
|
731
756
|
super('suffix', OPERATOR$6, left, right);
|
|
732
757
|
}
|
|
758
|
+
|
|
733
759
|
/**
|
|
734
760
|
* {@link Comparison.comparison}
|
|
735
761
|
*/
|
|
736
|
-
|
|
737
|
-
|
|
738
762
|
comparison(left, right) {
|
|
739
763
|
if (isString(left) === false || isString(right) === false) {
|
|
740
764
|
return false;
|
|
741
765
|
}
|
|
742
|
-
|
|
743
766
|
return left.endsWith(right);
|
|
744
767
|
}
|
|
768
|
+
|
|
745
769
|
/**
|
|
746
770
|
* Get the strict representation of the expression.
|
|
747
771
|
* @return {string}
|
|
748
772
|
*/
|
|
749
|
-
|
|
750
|
-
|
|
751
773
|
toString() {
|
|
752
774
|
const left = this.left.toString();
|
|
753
775
|
const right = this.right.toString();
|
|
754
776
|
return `(${left}<${right}>)`;
|
|
755
777
|
}
|
|
756
|
-
|
|
757
778
|
}
|
|
758
779
|
|
|
780
|
+
// Operator key
|
|
759
781
|
const OPERATOR$5 = Symbol('UNDEFINED');
|
|
782
|
+
|
|
760
783
|
/**
|
|
761
784
|
* Undefined comparison expression
|
|
762
785
|
*/
|
|
763
|
-
|
|
764
786
|
class Undefined extends Comparison {
|
|
765
787
|
/**
|
|
766
788
|
* @constructor
|
|
767
789
|
* @param {Evaluable} operand
|
|
768
790
|
*/
|
|
791
|
+
|
|
769
792
|
constructor(operand) {
|
|
770
793
|
if (arguments.length !== 1) {
|
|
771
794
|
throw new Error('comparison expression UNDEFINED expects exactly one operand');
|
|
772
795
|
}
|
|
773
|
-
|
|
774
796
|
super('UNDEFINED', OPERATOR$5, operand, new Value(true));
|
|
775
797
|
}
|
|
798
|
+
|
|
776
799
|
/**
|
|
777
800
|
* {@link Comparison.comparison}
|
|
778
801
|
*/
|
|
779
|
-
|
|
780
|
-
|
|
781
802
|
comparison(left) {
|
|
782
803
|
return left === undefined;
|
|
783
804
|
}
|
|
805
|
+
|
|
784
806
|
/**
|
|
785
807
|
* Get the strict representation of the expression.
|
|
786
808
|
* @return {string}
|
|
787
809
|
*/
|
|
788
|
-
|
|
789
|
-
|
|
790
810
|
toString() {
|
|
791
811
|
return `(${this.left.toString()} is ${this.operator})`;
|
|
792
812
|
}
|
|
813
|
+
|
|
793
814
|
/**
|
|
794
815
|
* {@link Evaluable.serialize}
|
|
795
816
|
*/
|
|
796
|
-
|
|
797
|
-
|
|
798
817
|
serialize(options) {
|
|
799
818
|
const {
|
|
800
819
|
operatorMapping
|
|
801
820
|
} = options;
|
|
802
821
|
const operator = operatorMapping.get(this.operatorSymbol);
|
|
803
|
-
|
|
804
822
|
if (operator === undefined) {
|
|
805
823
|
throw new Error(`missing operator ${this.operatorSymbol.toString()}`);
|
|
806
824
|
}
|
|
807
|
-
|
|
808
825
|
return [operator, this.left.serialize(options)];
|
|
809
826
|
}
|
|
810
|
-
|
|
811
827
|
}
|
|
812
828
|
|
|
813
829
|
/**
|
|
@@ -820,16 +836,19 @@ class Logical {
|
|
|
820
836
|
* @param {Evaluable[]} operands Collection of operands.
|
|
821
837
|
*/
|
|
822
838
|
constructor(operator, operatorSymbol, operands) {
|
|
823
|
-
_defineProperty(this, "type", EvaluableType.Expression);
|
|
824
|
-
|
|
825
839
|
this.operator = operator;
|
|
826
840
|
this.operatorSymbol = operatorSymbol;
|
|
827
841
|
this.operands = operands;
|
|
842
|
+
_defineProperty(this, "type", EvaluableType.Expression);
|
|
828
843
|
}
|
|
844
|
+
|
|
829
845
|
/**
|
|
830
846
|
* {@link Evaluable.evaluate}
|
|
831
847
|
*/
|
|
832
848
|
|
|
849
|
+
/**
|
|
850
|
+
* {@link Evaluable.simplify}
|
|
851
|
+
*/
|
|
833
852
|
|
|
834
853
|
/**
|
|
835
854
|
* Get the strict representation of the expression.
|
|
@@ -838,27 +857,24 @@ class Logical {
|
|
|
838
857
|
toString() {
|
|
839
858
|
return '(' + this.operands.map(operand => operand.toString()).join(` ${this.operator} `) + ')';
|
|
840
859
|
}
|
|
841
|
-
|
|
842
860
|
serialize(options) {
|
|
843
861
|
const {
|
|
844
862
|
operatorMapping
|
|
845
863
|
} = options;
|
|
846
864
|
const operator = operatorMapping.get(this.operatorSymbol);
|
|
847
|
-
|
|
848
865
|
if (operator === undefined) {
|
|
849
866
|
throw new Error(`missing operator ${this.operatorSymbol.toString()}`);
|
|
850
867
|
}
|
|
851
|
-
|
|
852
868
|
return [operator, ...this.operands.map(operand => operand.serialize(options))];
|
|
853
869
|
}
|
|
854
|
-
|
|
855
870
|
}
|
|
856
871
|
|
|
872
|
+
// Operator key
|
|
857
873
|
const OPERATOR$4 = Symbol('AND');
|
|
874
|
+
|
|
858
875
|
/**
|
|
859
876
|
* And logical expression
|
|
860
877
|
*/
|
|
861
|
-
|
|
862
878
|
class And extends Logical {
|
|
863
879
|
/**
|
|
864
880
|
* @constructor
|
|
@@ -868,127 +884,105 @@ class And extends Logical {
|
|
|
868
884
|
if (operands.length < 2) {
|
|
869
885
|
throw new Error('logical expression must have at least two operands');
|
|
870
886
|
}
|
|
871
|
-
|
|
872
887
|
super('AND', OPERATOR$4, operands);
|
|
873
888
|
}
|
|
889
|
+
|
|
874
890
|
/**
|
|
875
891
|
* Evaluate in the given context.
|
|
876
892
|
* @param {Context} ctx
|
|
877
893
|
* @return {Result}
|
|
878
894
|
*/
|
|
879
|
-
|
|
880
|
-
|
|
881
895
|
evaluate(ctx) {
|
|
882
896
|
for (const operand of this.operands) {
|
|
883
897
|
if (operand.evaluate(ctx) === false) {
|
|
884
898
|
return false;
|
|
885
899
|
}
|
|
886
900
|
}
|
|
887
|
-
|
|
888
901
|
return true;
|
|
889
902
|
}
|
|
903
|
+
|
|
890
904
|
/**
|
|
891
905
|
* {@link Evaluable.simplify}
|
|
892
906
|
*/
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
simplify() {
|
|
896
|
-
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
897
|
-
args[_key] = arguments[_key];
|
|
898
|
-
}
|
|
899
|
-
|
|
907
|
+
simplify(...args) {
|
|
900
908
|
const simplified = this.operands.reduce((result, child) => {
|
|
901
909
|
if (result !== false) {
|
|
902
910
|
const childResult = child.simplify(...args);
|
|
903
|
-
|
|
904
911
|
if (isEvaluable(childResult)) {
|
|
905
912
|
if (isBoolean(result)) {
|
|
906
913
|
return [childResult];
|
|
907
914
|
}
|
|
908
|
-
|
|
909
915
|
return [...result, childResult];
|
|
910
916
|
}
|
|
911
|
-
|
|
912
917
|
if (!childResult) {
|
|
913
918
|
return false;
|
|
914
919
|
}
|
|
915
920
|
}
|
|
916
|
-
|
|
917
921
|
return result;
|
|
918
922
|
}, true);
|
|
919
|
-
|
|
920
923
|
if (Array.isArray(simplified)) {
|
|
921
924
|
if (simplified.length === 1) {
|
|
922
925
|
return simplified[0];
|
|
923
926
|
}
|
|
924
|
-
|
|
925
927
|
return new And(simplified);
|
|
926
928
|
}
|
|
927
|
-
|
|
928
929
|
return simplified;
|
|
929
930
|
}
|
|
930
|
-
|
|
931
931
|
}
|
|
932
932
|
|
|
933
|
+
// Operator key
|
|
933
934
|
const OPERATOR$3 = Symbol('NOT');
|
|
935
|
+
|
|
934
936
|
/**
|
|
935
937
|
* Not logical expression
|
|
936
938
|
*/
|
|
937
|
-
|
|
938
939
|
class Not extends Logical {
|
|
939
940
|
/**
|
|
940
941
|
* @constructor
|
|
941
942
|
* @param {Evaluable} operand
|
|
942
943
|
*/
|
|
944
|
+
|
|
943
945
|
constructor(operand) {
|
|
944
946
|
if (arguments.length !== 1) {
|
|
945
947
|
throw new Error('logical NOT expression must have exactly one operand');
|
|
946
948
|
}
|
|
947
|
-
|
|
948
949
|
super('NOT', OPERATOR$3, [operand]);
|
|
949
950
|
}
|
|
951
|
+
|
|
950
952
|
/**
|
|
951
953
|
* Evaluate in the given context.
|
|
952
954
|
* @param {Context} ctx
|
|
953
955
|
* @return {Result}
|
|
954
956
|
*/
|
|
955
|
-
|
|
956
|
-
|
|
957
957
|
evaluate(ctx) {
|
|
958
958
|
const result = this.operands[0].evaluate(ctx);
|
|
959
|
-
|
|
960
959
|
if (result !== true && result !== false) {
|
|
961
960
|
throw new Error("logical NOT expression's operand must be evaluated to boolean value");
|
|
962
961
|
}
|
|
963
|
-
|
|
964
962
|
return !result;
|
|
965
963
|
}
|
|
964
|
+
|
|
966
965
|
/**
|
|
967
966
|
* {@link Evaluable.simplify}
|
|
968
967
|
*/
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
simplify() {
|
|
972
|
-
const simplified = this.operands[0].simplify(...arguments);
|
|
973
|
-
|
|
968
|
+
simplify(...args) {
|
|
969
|
+
const simplified = this.operands[0].simplify(...args);
|
|
974
970
|
if (isBoolean(simplified)) {
|
|
975
971
|
return !simplified;
|
|
976
972
|
}
|
|
977
|
-
|
|
978
973
|
if (isEvaluable(simplified)) {
|
|
979
974
|
return new Not(simplified);
|
|
980
975
|
}
|
|
981
|
-
|
|
982
976
|
throw new Error("logical NOT expression's operand must be evaluated to boolean value");
|
|
983
977
|
}
|
|
984
|
-
|
|
985
978
|
}
|
|
986
979
|
|
|
980
|
+
// Operator key
|
|
987
981
|
const OPERATOR$2 = Symbol('NOR');
|
|
982
|
+
|
|
988
983
|
/**
|
|
989
984
|
* Nor logical expression
|
|
990
985
|
*/
|
|
991
|
-
|
|
992
986
|
class Nor extends Logical {
|
|
993
987
|
/**
|
|
994
988
|
* @constructor
|
|
@@ -998,73 +992,58 @@ class Nor extends Logical {
|
|
|
998
992
|
if (operands.length < 2) {
|
|
999
993
|
throw new Error('logical expression must have at least two operands');
|
|
1000
994
|
}
|
|
1001
|
-
|
|
1002
995
|
super('NOR', OPERATOR$2, operands);
|
|
1003
996
|
}
|
|
997
|
+
|
|
1004
998
|
/**
|
|
1005
999
|
* Evaluate in the given context.
|
|
1006
1000
|
* @param {Context} ctx
|
|
1007
1001
|
* @return {Result}
|
|
1008
1002
|
*/
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
1003
|
evaluate(ctx) {
|
|
1012
1004
|
for (const operand of this.operands) {
|
|
1013
1005
|
if (operand.evaluate(ctx) === true) {
|
|
1014
1006
|
return false;
|
|
1015
1007
|
}
|
|
1016
1008
|
}
|
|
1017
|
-
|
|
1018
1009
|
return true;
|
|
1019
1010
|
}
|
|
1011
|
+
|
|
1020
1012
|
/**
|
|
1021
1013
|
* {@link Evaluable.simplify}
|
|
1022
1014
|
*/
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
simplify() {
|
|
1026
|
-
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
1027
|
-
args[_key] = arguments[_key];
|
|
1028
|
-
}
|
|
1029
|
-
|
|
1015
|
+
simplify(...args) {
|
|
1030
1016
|
const simplified = this.operands.reduce((result, child) => {
|
|
1031
1017
|
if (result !== false) {
|
|
1032
1018
|
const childResult = child.simplify(...args);
|
|
1033
|
-
|
|
1034
1019
|
if (isEvaluable(childResult)) {
|
|
1035
1020
|
if (isBoolean(result)) {
|
|
1036
1021
|
return [childResult];
|
|
1037
1022
|
}
|
|
1038
|
-
|
|
1039
1023
|
return [...result, childResult];
|
|
1040
1024
|
}
|
|
1041
|
-
|
|
1042
1025
|
if (childResult) {
|
|
1043
1026
|
return false;
|
|
1044
1027
|
}
|
|
1045
1028
|
}
|
|
1046
|
-
|
|
1047
1029
|
return result;
|
|
1048
1030
|
}, true);
|
|
1049
|
-
|
|
1050
1031
|
if (Array.isArray(simplified)) {
|
|
1051
1032
|
if (simplified.length === 1) {
|
|
1052
1033
|
return new Not(...simplified);
|
|
1053
1034
|
}
|
|
1054
|
-
|
|
1055
1035
|
return new Nor(simplified);
|
|
1056
1036
|
}
|
|
1057
|
-
|
|
1058
1037
|
return simplified;
|
|
1059
1038
|
}
|
|
1060
|
-
|
|
1061
1039
|
}
|
|
1062
1040
|
|
|
1041
|
+
// Operator key
|
|
1063
1042
|
const OPERATOR$1 = Symbol('OR');
|
|
1043
|
+
|
|
1064
1044
|
/**
|
|
1065
1045
|
* Or logical expression
|
|
1066
1046
|
*/
|
|
1067
|
-
|
|
1068
1047
|
class Or extends Logical {
|
|
1069
1048
|
/**
|
|
1070
1049
|
* @constructor
|
|
@@ -1074,84 +1053,68 @@ class Or extends Logical {
|
|
|
1074
1053
|
if (operands.length < 2) {
|
|
1075
1054
|
throw new Error('logical expression must have at least two operands');
|
|
1076
1055
|
}
|
|
1077
|
-
|
|
1078
1056
|
super('OR', OPERATOR$1, operands);
|
|
1079
1057
|
}
|
|
1058
|
+
|
|
1080
1059
|
/**
|
|
1081
1060
|
* Evaluate in the given context.
|
|
1082
1061
|
* @param {Context} ctx
|
|
1083
1062
|
* @return {Result}
|
|
1084
1063
|
*/
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
1064
|
evaluate(ctx) {
|
|
1088
1065
|
for (const operand of this.operands) {
|
|
1089
1066
|
if (operand.evaluate(ctx) === true) {
|
|
1090
1067
|
return true;
|
|
1091
1068
|
}
|
|
1092
1069
|
}
|
|
1093
|
-
|
|
1094
1070
|
return false;
|
|
1095
1071
|
}
|
|
1072
|
+
|
|
1096
1073
|
/**
|
|
1097
1074
|
* {@link Evaluable.simplify}
|
|
1098
1075
|
*/
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
simplify() {
|
|
1102
|
-
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
1103
|
-
args[_key] = arguments[_key];
|
|
1104
|
-
}
|
|
1105
|
-
|
|
1076
|
+
simplify(...args) {
|
|
1106
1077
|
const simplified = this.operands.reduce((result, child) => {
|
|
1107
1078
|
if (result !== true) {
|
|
1108
1079
|
const childResult = child.simplify(...args);
|
|
1109
|
-
|
|
1110
1080
|
if (isEvaluable(childResult)) {
|
|
1111
1081
|
if (isBoolean(result)) {
|
|
1112
1082
|
return [childResult];
|
|
1113
1083
|
}
|
|
1114
|
-
|
|
1115
1084
|
return [...result, childResult];
|
|
1116
1085
|
}
|
|
1117
|
-
|
|
1118
1086
|
if (childResult) {
|
|
1119
1087
|
return true;
|
|
1120
1088
|
}
|
|
1121
1089
|
}
|
|
1122
|
-
|
|
1123
1090
|
return result;
|
|
1124
1091
|
}, false);
|
|
1125
|
-
|
|
1126
1092
|
if (Array.isArray(simplified)) {
|
|
1127
1093
|
if (simplified.length === 1) {
|
|
1128
1094
|
return simplified[0];
|
|
1129
1095
|
}
|
|
1130
|
-
|
|
1131
1096
|
return new Or(simplified);
|
|
1132
1097
|
}
|
|
1133
|
-
|
|
1134
1098
|
return simplified;
|
|
1135
1099
|
}
|
|
1136
|
-
|
|
1137
1100
|
}
|
|
1138
1101
|
|
|
1102
|
+
// Operator key
|
|
1139
1103
|
const OPERATOR = Symbol('XOR');
|
|
1104
|
+
|
|
1140
1105
|
/**
|
|
1141
1106
|
* Logical xor
|
|
1142
1107
|
* @param {boolean} a
|
|
1143
1108
|
* @param {boolean} b
|
|
1144
1109
|
* @return {boolean}
|
|
1145
1110
|
*/
|
|
1146
|
-
|
|
1147
1111
|
function xor(a, b) {
|
|
1148
1112
|
return (a || b) && !(a && b);
|
|
1149
1113
|
}
|
|
1114
|
+
|
|
1150
1115
|
/**
|
|
1151
1116
|
* Xor logical expression
|
|
1152
1117
|
*/
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
1118
|
class Xor extends Logical {
|
|
1156
1119
|
/**
|
|
1157
1120
|
* @constructor
|
|
@@ -1161,19 +1124,16 @@ class Xor extends Logical {
|
|
|
1161
1124
|
if (operands.length < 2) {
|
|
1162
1125
|
throw new Error('logical expression must have at least two operands');
|
|
1163
1126
|
}
|
|
1164
|
-
|
|
1165
1127
|
super('XOR', OPERATOR, operands);
|
|
1166
1128
|
}
|
|
1129
|
+
|
|
1167
1130
|
/**
|
|
1168
1131
|
* Evaluate in the given context.
|
|
1169
1132
|
* @param {Context} ctx
|
|
1170
1133
|
* @return {Result}
|
|
1171
1134
|
*/
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
1135
|
evaluate(ctx) {
|
|
1175
1136
|
let res = null;
|
|
1176
|
-
|
|
1177
1137
|
for (const operand of this.operands) {
|
|
1178
1138
|
if (res === null) {
|
|
1179
1139
|
res = operand.evaluate(ctx);
|
|
@@ -1181,62 +1141,43 @@ class Xor extends Logical {
|
|
|
1181
1141
|
res = xor(res, operand.evaluate(ctx));
|
|
1182
1142
|
}
|
|
1183
1143
|
}
|
|
1184
|
-
|
|
1185
1144
|
return res;
|
|
1186
1145
|
}
|
|
1146
|
+
|
|
1187
1147
|
/**
|
|
1188
1148
|
* {@link Evaluable.simplify}
|
|
1189
1149
|
*/
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
simplify() {
|
|
1193
|
-
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
1194
|
-
args[_key] = arguments[_key];
|
|
1195
|
-
}
|
|
1196
|
-
|
|
1197
|
-
const [evaluablesLeft, trueCount] = this.operands.reduce((_ref, child) => {
|
|
1198
|
-
let [notSimplifiedConditions, trueCount] = _ref;
|
|
1199
|
-
|
|
1150
|
+
simplify(...args) {
|
|
1151
|
+
const [evaluablesLeft, trueCount] = this.operands.reduce(([notSimplifiedConditions, trueCount], child) => {
|
|
1200
1152
|
if (trueCount > 1) {
|
|
1201
1153
|
return [notSimplifiedConditions, trueCount];
|
|
1202
1154
|
}
|
|
1203
|
-
|
|
1204
1155
|
const childResult = child.simplify(...args);
|
|
1205
|
-
|
|
1206
1156
|
if (isEvaluable(childResult)) {
|
|
1207
1157
|
return [[...notSimplifiedConditions, childResult], trueCount];
|
|
1208
1158
|
}
|
|
1209
|
-
|
|
1210
1159
|
if (childResult) {
|
|
1211
1160
|
return [notSimplifiedConditions, trueCount + 1];
|
|
1212
1161
|
}
|
|
1213
|
-
|
|
1214
1162
|
return [notSimplifiedConditions, trueCount];
|
|
1215
1163
|
}, [[], 0]);
|
|
1216
|
-
|
|
1217
1164
|
if (trueCount > 1) {
|
|
1218
1165
|
return false;
|
|
1219
1166
|
}
|
|
1220
|
-
|
|
1221
1167
|
if (evaluablesLeft.length === 0) {
|
|
1222
1168
|
return trueCount === 1;
|
|
1223
1169
|
}
|
|
1224
|
-
|
|
1225
1170
|
if (evaluablesLeft.length === 1) {
|
|
1226
1171
|
if (trueCount === 1) {
|
|
1227
1172
|
return new Not(...evaluablesLeft);
|
|
1228
1173
|
}
|
|
1229
|
-
|
|
1230
1174
|
return evaluablesLeft[0];
|
|
1231
1175
|
}
|
|
1232
|
-
|
|
1233
1176
|
if (trueCount === 1) {
|
|
1234
1177
|
return new Nor(evaluablesLeft);
|
|
1235
1178
|
}
|
|
1236
|
-
|
|
1237
1179
|
return new Xor(evaluablesLeft);
|
|
1238
1180
|
}
|
|
1239
|
-
|
|
1240
1181
|
}
|
|
1241
1182
|
|
|
1242
1183
|
/**
|
|
@@ -1249,117 +1190,101 @@ class Collection extends Operand {
|
|
|
1249
1190
|
*/
|
|
1250
1191
|
constructor(items) {
|
|
1251
1192
|
super();
|
|
1193
|
+
_defineProperty(this, "items", void 0);
|
|
1252
1194
|
this.items = items;
|
|
1253
1195
|
}
|
|
1196
|
+
|
|
1254
1197
|
/**
|
|
1255
1198
|
* Evaluate in the given context.
|
|
1256
1199
|
* @param {Context} ctx
|
|
1257
1200
|
* @return {boolean}
|
|
1258
1201
|
*/
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
1202
|
evaluate(ctx) {
|
|
1262
1203
|
return this.items.map(item => item.evaluate(ctx));
|
|
1263
1204
|
}
|
|
1205
|
+
|
|
1264
1206
|
/**
|
|
1265
1207
|
* {@link Evaluable.simplify}
|
|
1266
1208
|
*/
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
simplify() {
|
|
1209
|
+
simplify(...args) {
|
|
1270
1210
|
const values = [];
|
|
1271
|
-
|
|
1272
1211
|
for (const item of this.items) {
|
|
1273
|
-
const simplifiedItem = item.simplify(...
|
|
1274
|
-
|
|
1212
|
+
const simplifiedItem = item.simplify(...args);
|
|
1275
1213
|
if (isEvaluable(simplifiedItem)) {
|
|
1276
1214
|
return this;
|
|
1277
1215
|
}
|
|
1278
|
-
|
|
1279
1216
|
values.push(simplifiedItem);
|
|
1280
1217
|
}
|
|
1281
|
-
|
|
1282
1218
|
return values;
|
|
1283
1219
|
}
|
|
1220
|
+
|
|
1284
1221
|
/**
|
|
1285
1222
|
* {@link Evaluable.serialize}
|
|
1286
1223
|
*/
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
1224
|
serialize(options) {
|
|
1290
1225
|
return this.items.map(item => isEvaluable(item) ? item.serialize(options) : item);
|
|
1291
1226
|
}
|
|
1227
|
+
|
|
1292
1228
|
/**
|
|
1293
1229
|
* Get the strict representation of the operand.
|
|
1294
1230
|
* @return {string}
|
|
1295
1231
|
*/
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
1232
|
toString() {
|
|
1299
1233
|
return '[' + this.items.map(item => item.toString()).join(', ') + ']';
|
|
1300
1234
|
}
|
|
1301
|
-
|
|
1302
1235
|
}
|
|
1303
1236
|
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
} else if (value.match(/^0$|^[1-9]\d*$/)) {
|
|
1318
|
-
return parseInt(value);
|
|
1237
|
+
const keyWithArrayIndexRegex = /^(?<currentKey>[^[\]]+?)(?<indexes>(?:\[\d+])+)?$/;
|
|
1238
|
+
const arrayIndexRegex = /\[(\d+)]/g;
|
|
1239
|
+
const parseKey = key => key.split('.').flatMap(key => {
|
|
1240
|
+
const parseResult = keyWithArrayIndexRegex.exec(key);
|
|
1241
|
+
const keys = [];
|
|
1242
|
+
if (parseResult) {
|
|
1243
|
+
var _parseResult$groups$c, _parseResult$groups, _parseResult$groups2;
|
|
1244
|
+
keys.push((_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 : key);
|
|
1245
|
+
const rawIndexes = parseResult === null || parseResult === void 0 || (_parseResult$groups2 = parseResult.groups) === null || _parseResult$groups2 === void 0 ? void 0 : _parseResult$groups2.indexes;
|
|
1246
|
+
if (rawIndexes) {
|
|
1247
|
+
for (const indexResult of rawIndexes.matchAll(arrayIndexRegex)) {
|
|
1248
|
+
keys.push(parseInt(indexResult[1]));
|
|
1249
|
+
}
|
|
1319
1250
|
}
|
|
1251
|
+
} else {
|
|
1252
|
+
keys.push(key);
|
|
1320
1253
|
}
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
}
|
|
1324
|
-
|
|
1325
|
-
* Convert a value to string if possible, otherwise return undefined
|
|
1326
|
-
* @param value value to be converted to string
|
|
1327
|
-
*/
|
|
1328
|
-
|
|
1329
|
-
const toString = value => {
|
|
1330
|
-
if (isNumber(value)) {
|
|
1331
|
-
return `${value}`;
|
|
1332
|
-
} else if (isString(value)) {
|
|
1333
|
-
return value;
|
|
1334
|
-
}
|
|
1335
|
-
|
|
1336
|
-
return undefined;
|
|
1337
|
-
};
|
|
1338
|
-
|
|
1339
|
-
function extractKeys(ctx, key) {
|
|
1254
|
+
return keys;
|
|
1255
|
+
});
|
|
1256
|
+
const complexKeyExpression = /{([^{}]+)}/;
|
|
1257
|
+
function extractComplexKeys(ctx, key) {
|
|
1340
1258
|
// Resolve complex keys
|
|
1341
|
-
const complexKeyExpression = /{([^{}]+)}/;
|
|
1342
1259
|
let complexKeyMatches = complexKeyExpression.exec(key);
|
|
1343
|
-
|
|
1344
1260
|
while (complexKeyMatches) {
|
|
1345
|
-
const resolvedValue =
|
|
1346
|
-
|
|
1261
|
+
const resolvedValue = complexValueLookup(ctx, complexKeyMatches[1]);
|
|
1347
1262
|
if (resolvedValue === undefined) {
|
|
1348
1263
|
return undefined;
|
|
1349
1264
|
}
|
|
1350
|
-
|
|
1351
1265
|
key = key.replace(complexKeyExpression, `${resolvedValue}`);
|
|
1352
1266
|
complexKeyMatches = complexKeyExpression.exec(key);
|
|
1353
1267
|
}
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1268
|
+
return parseKey(key);
|
|
1269
|
+
}
|
|
1270
|
+
const isContext = value => isObject(value);
|
|
1271
|
+
const simpleValueLookup = keys => ctx => {
|
|
1272
|
+
let pointer = ctx;
|
|
1273
|
+
for (const key of keys) {
|
|
1274
|
+
if (typeof key === 'number') {
|
|
1275
|
+
if (!Array.isArray(pointer)) {
|
|
1276
|
+
return undefined;
|
|
1277
|
+
}
|
|
1278
|
+
pointer = pointer[key];
|
|
1279
|
+
} else if (!isContext(pointer)) {
|
|
1280
|
+
return undefined;
|
|
1281
|
+
} else {
|
|
1282
|
+
pointer = pointer[key];
|
|
1283
|
+
}
|
|
1359
1284
|
}
|
|
1285
|
+
return pointer;
|
|
1286
|
+
};
|
|
1360
1287
|
|
|
1361
|
-
return keys;
|
|
1362
|
-
}
|
|
1363
1288
|
/**
|
|
1364
1289
|
* Lookup for the reference in the context.
|
|
1365
1290
|
* The nested context value is annotated with "." delimiter.
|
|
@@ -1368,58 +1293,26 @@ function extractKeys(ctx, key) {
|
|
|
1368
1293
|
* @param {string} key Context lookup key.
|
|
1369
1294
|
* @return {Result}
|
|
1370
1295
|
*/
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
function contextValueLookup(ctx, key) {
|
|
1374
|
-
const keys = extractKeys(ctx, key);
|
|
1375
|
-
|
|
1296
|
+
function complexValueLookup(ctx, key) {
|
|
1297
|
+
const keys = extractComplexKeys(ctx, key);
|
|
1376
1298
|
if (!keys) {
|
|
1377
1299
|
return undefined;
|
|
1378
|
-
} // Context pointer
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
let pointer = ctx;
|
|
1382
|
-
|
|
1383
|
-
for (let i = 0; i < keys.length; i++) {
|
|
1384
|
-
var _keys$i$match;
|
|
1385
|
-
|
|
1386
|
-
const currentKey = keys[i].replace(/\[.+$/, '');
|
|
1387
|
-
let currentValue = pointer[currentKey]; // Resolve array notation
|
|
1388
|
-
|
|
1389
|
-
(_keys$i$match = keys[i].match(/\[\d+\]/g)) === null || _keys$i$match === void 0 ? void 0 : _keys$i$match.forEach(match => {
|
|
1390
|
-
const arrayIndex = parseInt(match.replace(/[[\]]/g, ''));
|
|
1391
|
-
|
|
1392
|
-
if (!Array.isArray(currentValue) || currentValue[arrayIndex] === undefined) {
|
|
1393
|
-
currentValue = undefined;
|
|
1394
|
-
} else {
|
|
1395
|
-
currentValue = currentValue[arrayIndex];
|
|
1396
|
-
}
|
|
1397
|
-
}); // Last node
|
|
1398
|
-
|
|
1399
|
-
if (i === keys.length - 1) {
|
|
1400
|
-
return currentValue; // Nested path
|
|
1401
|
-
} else if (currentValue !== undefined && isObject(currentValue)) {
|
|
1402
|
-
pointer = currentValue; // Invalid nested reference path
|
|
1403
|
-
} else {
|
|
1404
|
-
break;
|
|
1405
|
-
}
|
|
1406
1300
|
}
|
|
1407
|
-
|
|
1408
|
-
return undefined;
|
|
1301
|
+
return simpleValueLookup(keys !== null && keys !== void 0 ? keys : [])(ctx);
|
|
1409
1302
|
}
|
|
1410
|
-
|
|
1411
|
-
let DataType; // Equivalent to /^.+\.\((Number|String)\)$/
|
|
1412
|
-
|
|
1413
|
-
(function (DataType) {
|
|
1303
|
+
let DataType = /*#__PURE__*/function (DataType) {
|
|
1414
1304
|
DataType["Number"] = "Number";
|
|
1415
1305
|
DataType["String"] = "String";
|
|
1416
|
-
|
|
1306
|
+
return DataType;
|
|
1307
|
+
}({});
|
|
1417
1308
|
|
|
1309
|
+
// Equivalent to /^.+\.\((Number|String)\)$/
|
|
1418
1310
|
const dataTypeRegex = new RegExp(`^.+\\.\\((${Object.keys(DataType).join('|')})\\)$`);
|
|
1311
|
+
const isComplexKey = key => key.indexOf('{') > -1;
|
|
1312
|
+
|
|
1419
1313
|
/**
|
|
1420
1314
|
* Reference operand resolved within the context
|
|
1421
1315
|
*/
|
|
1422
|
-
|
|
1423
1316
|
class Reference extends Operand {
|
|
1424
1317
|
/**
|
|
1425
1318
|
* @constructor
|
|
@@ -1429,99 +1322,97 @@ class Reference extends Operand {
|
|
|
1429
1322
|
if (key.trim() === '') {
|
|
1430
1323
|
throw new Error('invalid reference key');
|
|
1431
1324
|
}
|
|
1432
|
-
|
|
1433
1325
|
super();
|
|
1326
|
+
_defineProperty(this, "key", void 0);
|
|
1327
|
+
_defineProperty(this, "dataType", void 0);
|
|
1328
|
+
_defineProperty(this, "valueLookup", void 0);
|
|
1329
|
+
_defineProperty(this, "getKeys", void 0);
|
|
1434
1330
|
this.key = key;
|
|
1435
1331
|
const dataTypeMatch = dataTypeRegex.exec(this.key);
|
|
1436
|
-
|
|
1437
1332
|
if (dataTypeMatch) {
|
|
1438
1333
|
this.dataType = DataType[dataTypeMatch[1]];
|
|
1439
1334
|
}
|
|
1440
|
-
|
|
1441
1335
|
if (this.key.match(/.\(.+\)$/)) {
|
|
1442
1336
|
this.key = this.key.replace(/.\(.+\)$/, '');
|
|
1443
1337
|
}
|
|
1338
|
+
if (isComplexKey(this.key)) {
|
|
1339
|
+
this.valueLookup = context => complexValueLookup(context, this.key);
|
|
1340
|
+
this.getKeys = context => extractComplexKeys(context, this.key);
|
|
1341
|
+
} else {
|
|
1342
|
+
const keys = parseKey(this.key);
|
|
1343
|
+
this.valueLookup = simpleValueLookup(keys);
|
|
1344
|
+
this.getKeys = () => keys;
|
|
1345
|
+
}
|
|
1444
1346
|
}
|
|
1347
|
+
|
|
1445
1348
|
/**
|
|
1446
1349
|
* Evaluate in the given context.
|
|
1447
1350
|
* @param {Context} ctx
|
|
1448
1351
|
* @return {boolean}
|
|
1449
1352
|
*/
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
1353
|
evaluate(ctx) {
|
|
1453
|
-
return this.toDataType(
|
|
1354
|
+
return this.toDataType(this.valueLookup(ctx));
|
|
1454
1355
|
}
|
|
1356
|
+
|
|
1455
1357
|
/**
|
|
1456
1358
|
* {@link Evaluable.simplify}
|
|
1457
1359
|
*/
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
1360
|
simplify(ctx, strictKeys, optionalKeys) {
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
if (!keys) {
|
|
1464
|
-
return this;
|
|
1465
|
-
}
|
|
1466
|
-
|
|
1467
|
-
const key = keys[0].replace(/\[.+$/, '');
|
|
1468
|
-
|
|
1361
|
+
var _this$getKeys;
|
|
1362
|
+
const [key] = (_this$getKeys = this.getKeys(ctx)) !== null && _this$getKeys !== void 0 ? _this$getKeys : [];
|
|
1469
1363
|
if (ctx[key] !== undefined) {
|
|
1470
1364
|
return this.evaluate(ctx);
|
|
1471
1365
|
}
|
|
1472
|
-
|
|
1366
|
+
if (!key || typeof key === 'number') {
|
|
1367
|
+
return this;
|
|
1368
|
+
}
|
|
1473
1369
|
return strictKeys && strictKeys.includes(key) || optionalKeys && !optionalKeys.includes(key) ? undefined : this;
|
|
1474
1370
|
}
|
|
1371
|
+
|
|
1475
1372
|
/**
|
|
1476
1373
|
* {@link Evaluable.serialize}
|
|
1477
1374
|
*/
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
let {
|
|
1482
|
-
referenceSerialization
|
|
1483
|
-
} = _ref;
|
|
1375
|
+
serialize({
|
|
1376
|
+
referenceSerialization
|
|
1377
|
+
}) {
|
|
1484
1378
|
const key = this.dataType ? `${this.key}.(${this.dataType})` : this.key;
|
|
1485
1379
|
return referenceSerialization(key);
|
|
1486
1380
|
}
|
|
1381
|
+
|
|
1487
1382
|
/**
|
|
1488
1383
|
* Get the strict representation of the operand.
|
|
1489
1384
|
* @return {string}
|
|
1490
1385
|
*/
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
1386
|
toString() {
|
|
1494
1387
|
return `{${this.key}}`;
|
|
1495
1388
|
}
|
|
1389
|
+
|
|
1496
1390
|
/**
|
|
1497
1391
|
* Converts a value to a specified data type
|
|
1498
1392
|
* Silently returns original value if data type conversion has not been implemented.
|
|
1499
1393
|
* @param value value to cast as data type
|
|
1500
1394
|
*/
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
1395
|
toDataType(value) {
|
|
1504
1396
|
let result = value;
|
|
1505
|
-
|
|
1506
1397
|
switch (this.dataType) {
|
|
1507
1398
|
case DataType.Number:
|
|
1508
1399
|
result = toNumber(value);
|
|
1509
1400
|
break;
|
|
1510
|
-
|
|
1511
1401
|
case DataType.String:
|
|
1512
1402
|
result = toString(value);
|
|
1513
1403
|
break;
|
|
1514
1404
|
}
|
|
1515
|
-
|
|
1516
1405
|
if (value && result === undefined) {
|
|
1517
1406
|
console.warn(`Casting ${value} to ${this.dataType} resulted in ${result}`);
|
|
1518
1407
|
}
|
|
1519
|
-
|
|
1520
1408
|
return result;
|
|
1521
1409
|
}
|
|
1522
|
-
|
|
1523
1410
|
}
|
|
1524
1411
|
|
|
1412
|
+
// Option value whitelist
|
|
1413
|
+
|
|
1414
|
+
// Parser options
|
|
1415
|
+
|
|
1525
1416
|
/**
|
|
1526
1417
|
* Default reference predicate.
|
|
1527
1418
|
* The "$" symbol at the begging of the operand is used
|
|
@@ -1533,28 +1424,31 @@ class Reference extends Operand {
|
|
|
1533
1424
|
function defaultReferencePredicate(key) {
|
|
1534
1425
|
return isString(key) && key.startsWith('$');
|
|
1535
1426
|
}
|
|
1427
|
+
|
|
1536
1428
|
/**
|
|
1537
1429
|
* Default reference transform.
|
|
1538
1430
|
* It removes the "$" symbol at the begging of the operand name.
|
|
1539
1431
|
* @param {string} key
|
|
1540
1432
|
* @return {string}
|
|
1541
1433
|
*/
|
|
1542
|
-
|
|
1543
1434
|
function defaultReferenceTransform(key) {
|
|
1544
1435
|
return key.slice(1);
|
|
1545
1436
|
}
|
|
1546
1437
|
function defaultReferenceSerialization(key) {
|
|
1547
1438
|
return `$${key}`;
|
|
1548
|
-
}
|
|
1549
|
-
// Unique operator key <-> raw expression key
|
|
1439
|
+
}
|
|
1550
1440
|
|
|
1551
|
-
|
|
1552
|
-
|
|
1441
|
+
// Default operator mapping
|
|
1442
|
+
// Unique operator key <-> raw expression key
|
|
1443
|
+
const defaultOperatorMapping = new Map([
|
|
1444
|
+
// Comparison
|
|
1445
|
+
[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'],
|
|
1446
|
+
// Logical
|
|
1553
1447
|
[OPERATOR$4, 'AND'], [OPERATOR$1, 'OR'], [OPERATOR$2, 'NOR'], [OPERATOR, 'XOR'], [OPERATOR$3, 'NOT']]);
|
|
1448
|
+
|
|
1554
1449
|
/**
|
|
1555
1450
|
* Default parser options
|
|
1556
1451
|
*/
|
|
1557
|
-
|
|
1558
1452
|
const defaultOptions = {
|
|
1559
1453
|
referencePredicate: defaultReferencePredicate,
|
|
1560
1454
|
referenceTransform: defaultReferenceTransform,
|
|
@@ -1562,6 +1456,8 @@ const defaultOptions = {
|
|
|
1562
1456
|
operatorMapping: defaultOperatorMapping
|
|
1563
1457
|
};
|
|
1564
1458
|
|
|
1459
|
+
// Input types
|
|
1460
|
+
|
|
1565
1461
|
/**
|
|
1566
1462
|
* Parser of raw expressions into Evaluable expression
|
|
1567
1463
|
*/
|
|
@@ -1571,9 +1467,12 @@ class Parser {
|
|
|
1571
1467
|
* @param {Options?} options Parser options.
|
|
1572
1468
|
*/
|
|
1573
1469
|
constructor(options) {
|
|
1574
|
-
this
|
|
1575
|
-
|
|
1576
|
-
|
|
1470
|
+
_defineProperty(this, "opts", void 0);
|
|
1471
|
+
_defineProperty(this, "expectedOperators", void 0);
|
|
1472
|
+
this.opts = {
|
|
1473
|
+
...defaultOptions
|
|
1474
|
+
};
|
|
1475
|
+
// Apply exclusive options overrides
|
|
1577
1476
|
if (options) {
|
|
1578
1477
|
for (const key of Object.keys(options)) {
|
|
1579
1478
|
if (key in this.opts) {
|
|
@@ -1581,55 +1480,47 @@ class Parser {
|
|
|
1581
1480
|
}
|
|
1582
1481
|
}
|
|
1583
1482
|
}
|
|
1584
|
-
|
|
1585
1483
|
this.expectedOperators = new Set(this.opts.operatorMapping.values());
|
|
1586
1484
|
}
|
|
1485
|
+
|
|
1587
1486
|
/**
|
|
1588
1487
|
* Parser options
|
|
1589
1488
|
* @type {Options}
|
|
1590
1489
|
*/
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
1490
|
get options() {
|
|
1594
1491
|
return this.opts;
|
|
1595
1492
|
}
|
|
1493
|
+
|
|
1596
1494
|
/**
|
|
1597
1495
|
* Parse raw expression into evaluable expression.
|
|
1598
1496
|
* @param {ExpressionInput} raw Raw expression.
|
|
1599
1497
|
* @return {Evaluable}
|
|
1600
1498
|
*/
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
1499
|
parse(raw) {
|
|
1604
1500
|
if (raw === undefined || raw === null || Array.isArray(raw) === false) {
|
|
1605
1501
|
throw new Error('invalid expression');
|
|
1606
1502
|
}
|
|
1607
|
-
|
|
1608
1503
|
if (raw.length === 0 || !this.expectedOperators.has(`${raw[0]}`)) {
|
|
1609
1504
|
throw new Error('invalid expression');
|
|
1610
1505
|
}
|
|
1611
|
-
|
|
1612
1506
|
return this.parseRawExp(raw);
|
|
1613
1507
|
}
|
|
1508
|
+
|
|
1614
1509
|
/**
|
|
1615
1510
|
* Parse raw expression based on the expression type.
|
|
1616
1511
|
* @param {Input} raw Raw expression.
|
|
1617
1512
|
* @return {Evaluable}
|
|
1618
1513
|
*/
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
1514
|
parseRawExp(raw) {
|
|
1622
|
-
var _this = this;
|
|
1623
|
-
|
|
1624
1515
|
// Value / Reference
|
|
1625
1516
|
if (!Array.isArray(raw)) {
|
|
1626
1517
|
return this.getOperand(raw);
|
|
1627
1518
|
}
|
|
1628
|
-
|
|
1629
1519
|
let expression;
|
|
1630
1520
|
let operandParser = this.getOperand;
|
|
1631
1521
|
const operator = raw[0];
|
|
1632
1522
|
const operands = raw.slice(1);
|
|
1523
|
+
|
|
1633
1524
|
/**
|
|
1634
1525
|
* Simplify the logical expression if possible.
|
|
1635
1526
|
* - AND, OR with one operand is collapsed, i.e. reduced to inner expression
|
|
@@ -1641,192 +1532,139 @@ class Parser {
|
|
|
1641
1532
|
* @param operands
|
|
1642
1533
|
* @param collapsible
|
|
1643
1534
|
*/
|
|
1644
|
-
|
|
1645
|
-
const logicalExpressionReducer = function (operands) {
|
|
1646
|
-
let collapsible = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
1647
|
-
|
|
1535
|
+
const logicalExpressionReducer = (operands, collapsible = false) => {
|
|
1648
1536
|
if (operands.length === 0 || operands.filter(operand => operand.type === EvaluableType.Expression).length === 0) {
|
|
1649
|
-
return
|
|
1537
|
+
return this.getOperand(raw);
|
|
1650
1538
|
}
|
|
1651
|
-
|
|
1652
1539
|
return collapsible && operands.length === 1 ? operands[0] : undefined;
|
|
1653
1540
|
};
|
|
1654
|
-
|
|
1655
1541
|
switch (operator) {
|
|
1656
1542
|
/**
|
|
1657
1543
|
* Logical
|
|
1658
1544
|
*/
|
|
1659
1545
|
case this.opts.operatorMapping.get(OPERATOR$4):
|
|
1660
1546
|
expression = operands => logicalExpressionReducer(operands, true) || new And(operands);
|
|
1661
|
-
|
|
1662
1547
|
operandParser = this.parseRawExp;
|
|
1663
1548
|
break;
|
|
1664
|
-
|
|
1665
1549
|
case this.opts.operatorMapping.get(OPERATOR$1):
|
|
1666
1550
|
expression = operands => logicalExpressionReducer(operands, true) || new Or(operands);
|
|
1667
|
-
|
|
1668
1551
|
operandParser = this.parseRawExp;
|
|
1669
1552
|
break;
|
|
1670
|
-
|
|
1671
1553
|
case this.opts.operatorMapping.get(OPERATOR$2):
|
|
1672
1554
|
expression = operands => logicalExpressionReducer(operands) || new Nor(operands);
|
|
1673
|
-
|
|
1674
1555
|
operandParser = this.parseRawExp;
|
|
1675
1556
|
break;
|
|
1676
|
-
|
|
1677
1557
|
case this.opts.operatorMapping.get(OPERATOR):
|
|
1678
1558
|
expression = operands => logicalExpressionReducer(operands) || new Xor(operands);
|
|
1679
|
-
|
|
1680
1559
|
operandParser = this.parseRawExp;
|
|
1681
1560
|
break;
|
|
1682
|
-
|
|
1683
1561
|
case this.opts.operatorMapping.get(OPERATOR$3):
|
|
1684
1562
|
expression = operands => logicalExpressionReducer(operands) || new Not(...operands);
|
|
1685
|
-
|
|
1686
1563
|
operandParser = this.parseRawExp;
|
|
1687
1564
|
break;
|
|
1688
|
-
|
|
1689
1565
|
/**
|
|
1690
1566
|
* Comparison
|
|
1691
1567
|
*/
|
|
1692
|
-
|
|
1693
1568
|
case this.opts.operatorMapping.get(OPERATOR$h):
|
|
1694
1569
|
expression = operands => new Equal(...operands);
|
|
1695
|
-
|
|
1696
1570
|
break;
|
|
1697
|
-
|
|
1698
1571
|
case this.opts.operatorMapping.get(OPERATOR$b):
|
|
1699
1572
|
expression = operands => new NotEqual(...operands);
|
|
1700
|
-
|
|
1701
1573
|
break;
|
|
1702
|
-
|
|
1703
1574
|
case this.opts.operatorMapping.get(OPERATOR$f):
|
|
1704
1575
|
expression = operands => new GreaterThan(...operands);
|
|
1705
|
-
|
|
1706
1576
|
break;
|
|
1707
|
-
|
|
1708
1577
|
case this.opts.operatorMapping.get(OPERATOR$g):
|
|
1709
1578
|
expression = operands => new GreaterThanOrEqual(...operands);
|
|
1710
|
-
|
|
1711
1579
|
break;
|
|
1712
|
-
|
|
1713
1580
|
case this.opts.operatorMapping.get(OPERATOR$c):
|
|
1714
1581
|
expression = operands => new LessThan(...operands);
|
|
1715
|
-
|
|
1716
1582
|
break;
|
|
1717
|
-
|
|
1718
1583
|
case this.opts.operatorMapping.get(OPERATOR$d):
|
|
1719
1584
|
expression = operands => new LessThanOrEqual(...operands);
|
|
1720
|
-
|
|
1721
1585
|
break;
|
|
1722
|
-
|
|
1723
1586
|
case this.opts.operatorMapping.get(OPERATOR$e):
|
|
1724
1587
|
expression = operands => new In(...operands);
|
|
1725
|
-
|
|
1726
1588
|
break;
|
|
1727
|
-
|
|
1728
1589
|
case this.opts.operatorMapping.get(OPERATOR$a):
|
|
1729
1590
|
expression = operands => new NotIn(...operands);
|
|
1730
|
-
|
|
1731
1591
|
break;
|
|
1732
|
-
|
|
1733
1592
|
case this.opts.operatorMapping.get(OPERATOR$8):
|
|
1734
1593
|
expression = operands => new Prefix(...operands);
|
|
1735
|
-
|
|
1736
1594
|
break;
|
|
1737
|
-
|
|
1738
1595
|
case this.opts.operatorMapping.get(OPERATOR$6):
|
|
1739
1596
|
expression = operands => new Suffix(...operands);
|
|
1740
|
-
|
|
1741
1597
|
break;
|
|
1742
|
-
|
|
1743
1598
|
case this.opts.operatorMapping.get(OPERATOR$9):
|
|
1744
1599
|
expression = operands => new Overlap(...operands);
|
|
1745
|
-
|
|
1746
1600
|
break;
|
|
1747
|
-
|
|
1748
1601
|
case this.opts.operatorMapping.get(OPERATOR$5):
|
|
1749
1602
|
expression = operands => new Undefined(...operands);
|
|
1750
|
-
|
|
1751
1603
|
break;
|
|
1752
|
-
|
|
1753
1604
|
case this.opts.operatorMapping.get(OPERATOR$7):
|
|
1754
1605
|
expression = operands => new Present(...operands);
|
|
1755
|
-
|
|
1756
1606
|
break;
|
|
1757
1607
|
// Collection
|
|
1758
|
-
|
|
1759
1608
|
default:
|
|
1760
1609
|
return this.getOperand(raw);
|
|
1761
1610
|
}
|
|
1762
|
-
|
|
1763
1611
|
return expression(operands.map(operandParser.bind(this)));
|
|
1764
1612
|
}
|
|
1613
|
+
|
|
1765
1614
|
/**
|
|
1766
1615
|
* Get resolved operand
|
|
1767
1616
|
* @param raw Raw data
|
|
1768
1617
|
*/
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
1618
|
getOperand(raw) {
|
|
1772
1619
|
const resolve = raw => this.opts.referencePredicate(raw) ? new Reference(this.opts.referenceTransform(raw)) : new Value(raw);
|
|
1773
|
-
|
|
1774
1620
|
if (Array.isArray(raw)) {
|
|
1775
1621
|
return new Collection(raw.map(item => resolve(item)));
|
|
1776
1622
|
}
|
|
1777
|
-
|
|
1778
1623
|
return resolve(raw);
|
|
1779
1624
|
}
|
|
1780
|
-
|
|
1781
1625
|
}
|
|
1782
1626
|
|
|
1783
|
-
/**
|
|
1784
|
-
* Main module.
|
|
1785
|
-
* @module illogical
|
|
1786
|
-
*/
|
|
1787
1627
|
/**
|
|
1788
1628
|
* Condition engine
|
|
1789
1629
|
*/
|
|
1790
|
-
|
|
1791
1630
|
class Engine {
|
|
1792
1631
|
/**
|
|
1793
1632
|
* @constructor
|
|
1794
1633
|
* @param {Options?} options Parser options.
|
|
1795
1634
|
*/
|
|
1796
1635
|
constructor(options) {
|
|
1636
|
+
_defineProperty(this, "parser", void 0);
|
|
1797
1637
|
this.parser = new Parser(options);
|
|
1798
1638
|
}
|
|
1639
|
+
|
|
1799
1640
|
/**
|
|
1800
1641
|
* Evaluate the expression.
|
|
1801
1642
|
* @param {ExpressionInput} exp Raw expression.
|
|
1802
1643
|
* @param {Context} ctx Evaluation data context.
|
|
1803
1644
|
* @return {boolean}
|
|
1804
1645
|
*/
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
1646
|
evaluate(exp, ctx) {
|
|
1808
1647
|
return this.parse(exp).evaluate(ctx);
|
|
1809
1648
|
}
|
|
1649
|
+
|
|
1810
1650
|
/**
|
|
1811
1651
|
* Get expression statement
|
|
1812
1652
|
* @param {ExpressionInput} exp Raw expression.
|
|
1813
1653
|
* @return {string}
|
|
1814
1654
|
*/
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
1655
|
statement(exp) {
|
|
1818
1656
|
return this.parse(exp).toString();
|
|
1819
1657
|
}
|
|
1658
|
+
|
|
1820
1659
|
/**
|
|
1821
1660
|
* Parse expression.
|
|
1822
1661
|
* @param {ExpressionInput} exp Raw expression.
|
|
1823
1662
|
* @return {Evaluable}
|
|
1824
1663
|
*/
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
1664
|
parse(exp) {
|
|
1828
1665
|
return this.parser.parse(exp);
|
|
1829
1666
|
}
|
|
1667
|
+
|
|
1830
1668
|
/**
|
|
1831
1669
|
* Simplifies an expression with values in context.
|
|
1832
1670
|
*
|
|
@@ -1842,22 +1680,16 @@ class Engine {
|
|
|
1842
1680
|
* `optionalKeys` is considered to be present and thus will be evaluated
|
|
1843
1681
|
* @returns {Inpunt | boolean}
|
|
1844
1682
|
*/
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
1683
|
simplify(exp, context, strictKeys, optionalKeys) {
|
|
1848
1684
|
const result = this.parse(exp).simplify(context, strictKeys, optionalKeys);
|
|
1849
|
-
|
|
1850
1685
|
if (isEvaluable(result)) {
|
|
1851
1686
|
return result.serialize(this.parser.options);
|
|
1852
1687
|
}
|
|
1853
|
-
|
|
1854
1688
|
if (isBoolean(result)) {
|
|
1855
1689
|
return result;
|
|
1856
1690
|
}
|
|
1857
|
-
|
|
1858
1691
|
throw new Error('non expression or boolean result should be returned');
|
|
1859
1692
|
}
|
|
1860
|
-
|
|
1861
1693
|
}
|
|
1862
1694
|
|
|
1863
1695
|
exports.OPERATOR_AND = OPERATOR$4;
|
|
@@ -1878,4 +1710,6 @@ exports.OPERATOR_PRESENT = OPERATOR$7;
|
|
|
1878
1710
|
exports.OPERATOR_SUFFIX = OPERATOR$6;
|
|
1879
1711
|
exports.OPERATOR_UNDEFINED = OPERATOR$5;
|
|
1880
1712
|
exports.OPERATOR_XOR = OPERATOR;
|
|
1881
|
-
exports
|
|
1713
|
+
exports.default = Engine;
|
|
1714
|
+
exports.defaultOptions = defaultOptions;
|
|
1715
|
+
exports.isEvaluable = isEvaluable;
|