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