@fincity/kirun-js 1.1.7 → 1.3.1

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.
@@ -8,6 +8,7 @@ import { Expression } from './Expression';
8
8
  import { ExpressionToken } from './ExpressionToken';
9
9
  import { ExpressionTokenValue } from './ExpressionTokenValue';
10
10
  import { Operation } from './Operation';
11
+ import { LogicalNullishCoalescingOperator } from './operators/binary/LogicalNullishCoalescingOperator';
11
12
  import { ArithmeticAdditionOperator } from './operators/binary/ArithmeticAdditionOperator';
12
13
  import { ArithmeticDivisionOperator } from './operators/binary/ArithmeticDivisionOperator';
13
14
  import { ArithmeticIntegerDivisionOperator } from './operators/binary/ArithmeticInetgerDivisionOperator';
@@ -38,6 +39,7 @@ import { LogicalNotOperator } from './operators/unary/LogicalNotOperator';
38
39
  import { UnaryOperator } from './operators/unary/UnaryOperator';
39
40
  import { LiteralTokenValueExtractor } from './tokenextractor/LiteralTokenValueExtractor';
40
41
  import { TokenValueExtractor } from './tokenextractor/TokenValueExtractor';
42
+ import { Tuple2 } from '../../util/Tuples';
41
43
 
42
44
  export class ExpressionEvaluator {
43
45
  private static readonly UNARY_OPERATORS_MAP: Map<Operation, UnaryOperator> = new Map([
@@ -70,6 +72,7 @@ export class ExpressionEvaluator {
70
72
  [Operation.LESS_THAN_EQUAL, new LogicalLessThanEqualOperator()],
71
73
  [Operation.OR, new LogicalOrOperator()],
72
74
  [Operation.NOT_EQUAL, new LogicalNotEqualOperator()],
75
+ [Operation.NULLISH_COALESCING_OPERATOR, new LogicalNullishCoalescingOperator()],
73
76
 
74
77
  [Operation.ARRAY_OPERATOR, new ArrayOperator()],
75
78
  [Operation.OBJECT_OPERATOR, new ObjectOperator()],
@@ -92,10 +95,79 @@ export class ExpressionEvaluator {
92
95
  }
93
96
 
94
97
  public evaluate(valuesMap: Map<string, TokenValueExtractor>): any {
95
- if (!this.exp) this.exp = new Expression(this.expression);
98
+ const tuple: Tuple2<string, Expression> = this.processNestingExpression(
99
+ this.expression,
100
+ valuesMap,
101
+ );
102
+ this.expression = tuple.getT1();
103
+ this.exp = tuple.getT2();
104
+
96
105
  return this.evaluateExpression(this.exp, valuesMap);
97
106
  }
98
107
 
108
+ private processNestingExpression(
109
+ expression: string,
110
+ valuesMap: Map<string, TokenValueExtractor>,
111
+ ): Tuple2<string, Expression> {
112
+ let start = 0;
113
+ let i = 0;
114
+
115
+ const tuples: LinkedList<Tuple2<number, number>> = new LinkedList();
116
+
117
+ while (i < expression.length - 1) {
118
+ if (expression.charAt(i) == '{' && expression.charAt(i + 1) == '{') {
119
+ if (start == 0) tuples.push(new Tuple2(i + 2, -1));
120
+
121
+ start++;
122
+ i++;
123
+ } else if (expression.charAt(i) == '}' && expression.charAt(i + 1) == '}') {
124
+ start--;
125
+
126
+ if (start < 0)
127
+ throw new ExpressionEvaluationException(
128
+ expression,
129
+ 'Expecting {{ nesting path operator to be started before closing',
130
+ );
131
+
132
+ if (start == 0) {
133
+ tuples.push(tuples.pop().setT2(i));
134
+ }
135
+ i++;
136
+ }
137
+ i++;
138
+ }
139
+
140
+ let newExpression = this.replaceNestingExpression(expression, valuesMap, tuples);
141
+
142
+ return new Tuple2(newExpression, new Expression(newExpression));
143
+ }
144
+
145
+ private replaceNestingExpression(
146
+ expression: string,
147
+ valuesMap: Map<string, TokenValueExtractor>,
148
+ tuples: LinkedList<Tuple2<number, number>>,
149
+ ): string {
150
+ let newExpression = expression;
151
+
152
+ for (var tuple of tuples.toArray()) {
153
+ if (tuple.getT2() == -1)
154
+ throw new ExpressionEvaluationException(
155
+ expression,
156
+ 'Expecting }} nesting path operator to be closed',
157
+ );
158
+
159
+ let expStr: string = new ExpressionEvaluator(
160
+ newExpression.substring(tuple.getT1(), tuple.getT2()),
161
+ ).evaluate(valuesMap);
162
+
163
+ newExpression =
164
+ newExpression.substring(0, tuple.getT1() - 2) +
165
+ expStr +
166
+ newExpression.substring(tuple.getT2() + 2);
167
+ }
168
+ return newExpression;
169
+ }
170
+
99
171
  public getExpression(): Expression {
100
172
  if (!this.exp) this.exp = new Expression(this.expression);
101
173
 
@@ -161,8 +233,7 @@ export class ExpressionEvaluator {
161
233
  const objTokens: LinkedList<ExpressionToken> = new LinkedList();
162
234
  const objOperations: LinkedList<Operation> = new LinkedList();
163
235
 
164
- if (!operator || !token)
165
- return;
236
+ if (!operator || !token) return;
166
237
 
167
238
  do {
168
239
  objOperations.push(operator);
@@ -173,8 +244,7 @@ export class ExpressionEvaluator {
173
244
  this.evaluateExpression(token as Expression, valuesMap),
174
245
  ),
175
246
  );
176
- else if (token)
177
- objTokens.push(token);
247
+ else if (token) objTokens.push(token);
178
248
  token = tokens.isEmpty() ? undefined : tokens.pop();
179
249
  operator = ops.isEmpty() ? undefined : ops.pop();
180
250
  } while (operator == Operation.OBJECT_OPERATOR || operator == Operation.ARRAY_OPERATOR);
@@ -229,7 +299,13 @@ export class ExpressionEvaluator {
229
299
  let typv1: string = typeof v1;
230
300
  let typv2: string = typeof v2;
231
301
 
232
- if (typv1 === 'object' || typv2 === 'object' || Array.isArray(v1) || Array.isArray(v2))
302
+ let op: BinaryOperator | undefined = ExpressionEvaluator.BINARY_OPERATORS_MAP.get(operator);
303
+
304
+ if (
305
+ (typv1 === 'object' || typv2 === 'object') &&
306
+ operator !== Operation.EQUAL &&
307
+ operator !== Operation.NOT_EQUAL
308
+ )
233
309
  throw new ExpressionEvaluationException(
234
310
  this.expression,
235
311
  StringFormatter.format(
@@ -240,8 +316,6 @@ export class ExpressionEvaluator {
240
316
  ),
241
317
  );
242
318
 
243
- let op: BinaryOperator | undefined = ExpressionEvaluator.BINARY_OPERATORS_MAP.get(operator);
244
-
245
319
  if (!op)
246
320
  throw new ExpressionEvaluationException(
247
321
  this.expression,
@@ -32,6 +32,8 @@ export class Operation {
32
32
  public static readonly ARRAY_OPERATOR: Operation = new Operation('[');
33
33
  public static readonly OBJECT_OPERATOR: Operation = new Operation('.');
34
34
 
35
+ public static readonly NULLISH_COALESCING_OPERATOR: Operation = new Operation('??');
36
+
35
37
  private static readonly VALUE_OF: Map<string, Operation> = new Map([
36
38
  ['MULTIPLICATION', Operation.MULTIPLICATION],
37
39
  ['DIVISION', Operation.DIVISION],
@@ -61,6 +63,7 @@ export class Operation {
61
63
  ['UNARY_BITWISE_COMPLEMENT', Operation.UNARY_BITWISE_COMPLEMENT],
62
64
  ['ARRAY_OPERATOR', Operation.ARRAY_OPERATOR],
63
65
  ['OBJECT_OPERATOR', Operation.OBJECT_OPERATOR],
66
+ ['NULLISH_COALESCING_OPERATOR', Operation.NULLISH_COALESCING_OPERATOR],
64
67
  ]);
65
68
 
66
69
  public static readonly UNARY_OPERATORS: Set<Operation> = new Set([
@@ -93,6 +96,7 @@ export class Operation {
93
96
  Operation.GREATER_THAN_EQUAL,
94
97
  Operation.EQUAL,
95
98
  Operation.NOT_EQUAL,
99
+ Operation.NULLISH_COALESCING_OPERATOR,
96
100
  ]);
97
101
 
98
102
  public static readonly BITWISE_OPERATORS: Set<Operation> = new Set([
@@ -132,6 +136,7 @@ export class Operation {
132
136
  [Operation.BITWISE_OR, 9],
133
137
  [Operation.AND, 10],
134
138
  [Operation.OR, 11],
139
+ [Operation.NULLISH_COALESCING_OPERATOR, 11],
135
140
  ]);
136
141
 
137
142
  public static readonly OPERATORS: Set<string> = new Set(
@@ -1,13 +1,8 @@
1
- import { SchemaType } from '../../../../json/schema/type/SchemaType';
2
- import { PrimitiveUtil } from '../../../../util/primitive/PrimitiveUtil';
3
- import { Tuple2 } from '../../../../util/Tuples';
1
+ import { deepEqual } from '../../../../util/deepEqual';
4
2
  import { BinaryOperator } from './BinaryOperator';
5
3
 
6
4
  export class LogicalEqualOperator extends BinaryOperator {
7
5
  public apply(t: any, u: any): any {
8
- const tType: Tuple2<SchemaType, any> = PrimitiveUtil.findPrimitiveNullAsBoolean(t);
9
- const uType: Tuple2<SchemaType, any> = PrimitiveUtil.findPrimitiveNullAsBoolean(u);
10
-
11
- return tType.getT2() == uType.getT2();
6
+ return deepEqual(t, u);
12
7
  }
13
8
  }
@@ -1,13 +1,8 @@
1
- import { SchemaType } from '../../../../json/schema/type/SchemaType';
2
- import { PrimitiveUtil } from '../../../../util/primitive/PrimitiveUtil';
3
- import { Tuple2 } from '../../../../util/Tuples';
1
+ import { deepEqual } from '../../../../util/deepEqual';
4
2
  import { BinaryOperator } from './BinaryOperator';
5
3
 
6
4
  export class LogicalNotEqualOperator extends BinaryOperator {
7
5
  public apply(t: any, u: any): any {
8
- const tType: Tuple2<SchemaType, any> = PrimitiveUtil.findPrimitiveNullAsBoolean(t);
9
- const uType: Tuple2<SchemaType, any> = PrimitiveUtil.findPrimitiveNullAsBoolean(u);
10
-
11
- return tType.getT2() != uType.getT2();
6
+ return !deepEqual(t, u);
12
7
  }
13
8
  }
@@ -0,0 +1,8 @@
1
+ import { isNullValue } from '../../../../util/NullCheck';
2
+ import { BinaryOperator } from './BinaryOperator';
3
+
4
+ export class LogicalNullishCoalescingOperator extends BinaryOperator {
5
+ public apply(t: any, u: any): any {
6
+ return isNullValue(t) ? u : t;
7
+ }
8
+ }
@@ -21,3 +21,4 @@ export * from './LogicalNotEqualOperator';
21
21
  export * from './LogicalLessThanOperator';
22
22
  export * from './LogicalOrOperator';
23
23
  export * from './ObjectOperator';
24
+ export * from './LogicalNullishCoalescingOperator';
@@ -72,6 +72,16 @@ export class MapUtil {
72
72
  return map;
73
73
  }
74
74
 
75
+ public static ofEntriesArray<K, V>(...entry: [K, V][]): Map<K, V> {
76
+ const map: Map<K, V> = new Map();
77
+
78
+ for (let i = 0; i < entry.length; i++) {
79
+ map.set(entry[i][0], entry[i][1]);
80
+ }
81
+
82
+ return map;
83
+ }
84
+
75
85
  private constructor() {}
76
86
  }
77
87
 
@@ -1,6 +1,6 @@
1
1
  export class Tuple2<F, S> {
2
- private f: F;
3
- private s: S;
2
+ protected f: F;
3
+ protected s: S;
4
4
 
5
5
  constructor(f: F, s: S) {
6
6
  this.f = f;
@@ -14,10 +14,20 @@ export class Tuple2<F, S> {
14
14
  public getT2(): S {
15
15
  return this.s;
16
16
  }
17
+
18
+ public setT1(f: F): Tuple2<F, S> {
19
+ this.f = f;
20
+ return this;
21
+ }
22
+
23
+ public setT2(s: S): Tuple2<F, S> {
24
+ this.s = s;
25
+ return this;
26
+ }
17
27
  }
18
28
 
19
29
  export class Tuple3<F, S, T> extends Tuple2<F, S> {
20
- private t: T;
30
+ protected t: T;
21
31
 
22
32
  constructor(f: F, s: S, t: T) {
23
33
  super(f, s);
@@ -27,10 +37,25 @@ export class Tuple3<F, S, T> extends Tuple2<F, S> {
27
37
  public getT3(): T {
28
38
  return this.t;
29
39
  }
40
+
41
+ public setT1(f: F): Tuple3<F, S, T> {
42
+ this.f = f;
43
+ return this;
44
+ }
45
+
46
+ public setT2(s: S): Tuple3<F, S, T> {
47
+ this.s = s;
48
+ return this;
49
+ }
50
+
51
+ public setT3(t: T): Tuple3<F, S, T> {
52
+ this.t = t;
53
+ return this;
54
+ }
30
55
  }
31
56
 
32
57
  export class Tuple4<F, S, T, FR> extends Tuple3<F, S, T> {
33
- private fr: FR;
58
+ protected fr: FR;
34
59
 
35
60
  constructor(f: F, s: S, t: T, fr: FR) {
36
61
  super(f, s, t);
@@ -40,4 +65,24 @@ export class Tuple4<F, S, T, FR> extends Tuple3<F, S, T> {
40
65
  public getT4(): FR {
41
66
  return this.fr;
42
67
  }
68
+
69
+ public setT1(f: F): Tuple4<F, S, T, FR> {
70
+ this.f = f;
71
+ return this;
72
+ }
73
+
74
+ public setT2(s: S): Tuple4<F, S, T, FR> {
75
+ this.s = s;
76
+ return this;
77
+ }
78
+
79
+ public setT3(t: T): Tuple4<F, S, T, FR> {
80
+ this.t = t;
81
+ return this;
82
+ }
83
+
84
+ public setT4(fr: FR): Tuple4<F, S, T, FR> {
85
+ this.fr = fr;
86
+ return this;
87
+ }
43
88
  }
@@ -0,0 +1,49 @@
1
+ import { LinkedList } from './LinkedList';
2
+
3
+ export function deepEqual(x: any, y: any) {
4
+ let xa = new LinkedList();
5
+ xa.push(x);
6
+ let yb = new LinkedList();
7
+ yb.push(y);
8
+
9
+ while (!xa.isEmpty() && !yb.isEmpty()) {
10
+ const a: any = xa.pop();
11
+ const b: any = yb.pop();
12
+
13
+ if (a === b) continue;
14
+
15
+ const typeOfA = typeof a;
16
+ const typeOfB = typeof b;
17
+
18
+ if (typeOfA === 'undefined' || typeOfB === 'undefined') {
19
+ if (!a && !b) continue;
20
+ return false;
21
+ }
22
+
23
+ if (typeOfA !== typeOfB) return false;
24
+
25
+ if (Array.isArray(a)) {
26
+ if (!Array.isArray(b) || a.length != b.length) return false;
27
+ for (let i = 0; i < a.length; i++) {
28
+ xa.push(a[i]);
29
+ yb.push(b[i]);
30
+ }
31
+ continue;
32
+ }
33
+
34
+ if (typeOfA === 'object') {
35
+ const entriesOfA = Object.entries(a);
36
+ const entriesOfB = Object.entries(b);
37
+ if (entriesOfA.length !== entriesOfB.length) return false;
38
+ for (const [k, v] of entriesOfA) {
39
+ xa.push(v);
40
+ yb.push(b[k]);
41
+ }
42
+
43
+ continue;
44
+ }
45
+ return false;
46
+ }
47
+
48
+ return true;
49
+ }
package/src/index.ts CHANGED
@@ -10,6 +10,7 @@ export * from './engine/util/string/StringFormatter';
10
10
  export * from './engine/util/string/StringUtil';
11
11
  export * from './engine/util/Tuples';
12
12
  export * from './engine/util/ArrayUtil';
13
+ export * from './engine/util/deepEqual';
13
14
  export * from './engine/runtime/StatementExecution';
14
15
  export * from './engine/runtime/StatementMessage';
15
16
  export * from './engine/runtime/ContextElement';