yukigo 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. package/.mocharc.json +3 -3
  2. package/CHANGELOG.md +26 -0
  3. package/README.md +193 -199
  4. package/dist/analyzer/GraphBuilder.d.ts +29 -0
  5. package/dist/analyzer/GraphBuilder.js +99 -0
  6. package/dist/analyzer/index.d.ts +11 -23
  7. package/dist/analyzer/index.js +100 -58
  8. package/dist/analyzer/inspections/functional/functional.d.ts +44 -0
  9. package/dist/analyzer/inspections/functional/functional.js +149 -0
  10. package/dist/analyzer/inspections/functional/smells.d.ts +16 -0
  11. package/dist/analyzer/inspections/functional/smells.js +98 -0
  12. package/dist/analyzer/inspections/{generic.d.ts → generic/generic.d.ts} +70 -43
  13. package/dist/analyzer/inspections/generic/generic.js +604 -0
  14. package/dist/analyzer/inspections/generic/smells.d.ts +61 -0
  15. package/dist/analyzer/inspections/generic/smells.js +349 -0
  16. package/dist/analyzer/inspections/imperative/imperative.d.ts +35 -0
  17. package/dist/analyzer/inspections/imperative/imperative.js +109 -0
  18. package/dist/analyzer/inspections/imperative/smells.d.ts +16 -0
  19. package/dist/analyzer/inspections/imperative/smells.js +58 -0
  20. package/dist/analyzer/inspections/logic/logic.d.ts +32 -0
  21. package/dist/analyzer/inspections/logic/logic.js +96 -0
  22. package/dist/analyzer/inspections/logic/smells.d.ts +15 -0
  23. package/dist/analyzer/inspections/logic/smells.js +60 -0
  24. package/dist/analyzer/inspections/object/object.d.ts +88 -0
  25. package/dist/analyzer/inspections/object/object.js +319 -0
  26. package/dist/analyzer/inspections/object/smells.d.ts +30 -0
  27. package/dist/analyzer/inspections/object/smells.js +135 -0
  28. package/dist/analyzer/utils.d.ts +26 -4
  29. package/dist/analyzer/utils.js +71 -13
  30. package/dist/index.d.ts +1 -0
  31. package/dist/index.js +1 -0
  32. package/dist/interpreter/components/EnvBuilder.d.ts +9 -5
  33. package/dist/interpreter/components/EnvBuilder.js +100 -30
  34. package/dist/interpreter/components/Operations.d.ts +4 -4
  35. package/dist/interpreter/components/Operations.js +17 -2
  36. package/dist/interpreter/components/PatternMatcher.d.ts +47 -17
  37. package/dist/interpreter/components/PatternMatcher.js +264 -119
  38. package/dist/interpreter/components/RuntimeContext.d.ts +35 -0
  39. package/dist/interpreter/components/RuntimeContext.js +93 -0
  40. package/dist/interpreter/components/TestRunner.d.ts +18 -0
  41. package/dist/interpreter/components/TestRunner.js +103 -0
  42. package/dist/interpreter/components/Visitor.d.ts +63 -57
  43. package/dist/interpreter/components/Visitor.js +508 -173
  44. package/dist/interpreter/components/logic/LogicEngine.d.ts +29 -0
  45. package/dist/interpreter/components/logic/LogicEngine.js +259 -0
  46. package/dist/interpreter/components/logic/LogicResolver.d.ts +53 -0
  47. package/dist/interpreter/components/logic/LogicResolver.js +471 -0
  48. package/dist/interpreter/components/logic/LogicTranslator.d.ts +14 -0
  49. package/dist/interpreter/components/logic/LogicTranslator.js +99 -0
  50. package/dist/interpreter/components/runtimes/FunctionRuntime.d.ts +12 -0
  51. package/dist/interpreter/components/runtimes/FunctionRuntime.js +147 -0
  52. package/dist/interpreter/components/runtimes/LazyRuntime.d.ts +19 -0
  53. package/dist/interpreter/components/runtimes/LazyRuntime.js +269 -0
  54. package/dist/interpreter/components/runtimes/ObjectRuntime.d.ts +35 -0
  55. package/dist/interpreter/components/runtimes/ObjectRuntime.js +126 -0
  56. package/dist/interpreter/entities.d.ts +105 -0
  57. package/dist/interpreter/entities.js +96 -0
  58. package/dist/interpreter/errors.d.ts +1 -1
  59. package/dist/interpreter/index.d.ts +4 -12
  60. package/dist/interpreter/index.js +10 -13
  61. package/dist/interpreter/trampoline.d.ts +17 -0
  62. package/dist/interpreter/trampoline.js +38 -0
  63. package/dist/interpreter/utils.d.ts +4 -7
  64. package/dist/interpreter/utils.js +25 -17
  65. package/dist/tester/index.d.ts +25 -0
  66. package/dist/tester/index.js +108 -0
  67. package/dist/utils/helpers.d.ts +0 -4
  68. package/dist/utils/helpers.js +20 -24
  69. package/package.json +2 -2
  70. package/src/analyzer/GraphBuilder.ts +142 -0
  71. package/src/analyzer/index.ts +185 -132
  72. package/src/analyzer/inspections/functional/functional.ts +121 -0
  73. package/src/analyzer/inspections/functional/smells.ts +102 -0
  74. package/src/analyzer/inspections/{generic.ts → generic/generic.ts} +581 -499
  75. package/src/analyzer/inspections/generic/smells.ts +365 -0
  76. package/src/analyzer/inspections/imperative/imperative.ts +101 -0
  77. package/src/analyzer/inspections/imperative/smells.ts +54 -0
  78. package/src/analyzer/inspections/logic/logic.ts +90 -0
  79. package/src/analyzer/inspections/logic/smells.ts +54 -0
  80. package/src/analyzer/inspections/{object.ts → object/object.ts} +264 -282
  81. package/src/analyzer/inspections/object/smells.ts +144 -0
  82. package/src/analyzer/utils.ts +109 -26
  83. package/src/index.ts +3 -2
  84. package/src/interpreter/components/EnvBuilder.ts +202 -97
  85. package/src/interpreter/components/Operations.ts +99 -81
  86. package/src/interpreter/components/PatternMatcher.ts +475 -254
  87. package/src/interpreter/components/RuntimeContext.ts +119 -0
  88. package/src/interpreter/components/TestRunner.ts +151 -0
  89. package/src/interpreter/components/Visitor.ts +1065 -493
  90. package/src/interpreter/components/logic/LogicEngine.ts +519 -0
  91. package/src/interpreter/components/logic/LogicResolver.ts +858 -0
  92. package/src/interpreter/components/logic/LogicTranslator.ts +149 -0
  93. package/src/interpreter/components/runtimes/FunctionRuntime.ts +227 -0
  94. package/src/interpreter/components/runtimes/LazyRuntime.ts +334 -0
  95. package/src/interpreter/components/runtimes/ObjectRuntime.ts +224 -0
  96. package/src/interpreter/errors.ts +47 -47
  97. package/src/interpreter/index.ts +52 -59
  98. package/src/interpreter/trampoline.ts +71 -0
  99. package/src/interpreter/utils.ts +84 -79
  100. package/src/tester/index.ts +128 -0
  101. package/src/utils/helpers.ts +67 -73
  102. package/tests/analyzer/functional.spec.ts +207 -221
  103. package/tests/analyzer/generic.spec.ts +178 -100
  104. package/tests/analyzer/helpers.spec.ts +83 -83
  105. package/tests/analyzer/logic.spec.ts +237 -292
  106. package/tests/analyzer/oop.spec.ts +323 -338
  107. package/tests/analyzer/transitive.spec.ts +166 -0
  108. package/tests/interpreter/EnvBuilder.spec.ts +183 -178
  109. package/tests/interpreter/FunctionRuntime.spec.ts +223 -234
  110. package/tests/interpreter/LazyRuntime.spec.ts +225 -190
  111. package/tests/interpreter/LogicEngine.spec.ts +327 -194
  112. package/tests/interpreter/LogicSubstitution.spec.ts +80 -0
  113. package/tests/interpreter/ObjectRuntime.spec.ts +606 -0
  114. package/tests/interpreter/Operations.spec.ts +220 -220
  115. package/tests/interpreter/PatternSystem.spec.ts +213 -189
  116. package/tests/interpreter/Tests.spec.ts +122 -0
  117. package/tests/interpreter/interpreter.spec.ts +991 -937
  118. package/tests/tester/Tester.spec.ts +153 -0
  119. package/tsconfig.build.json +15 -7
  120. package/tsconfig.json +25 -17
  121. package/dist/analyzer/inspections/functional.d.ts +0 -46
  122. package/dist/analyzer/inspections/functional.js +0 -123
  123. package/dist/analyzer/inspections/generic.js +0 -427
  124. package/dist/analyzer/inspections/imperative.d.ts +0 -37
  125. package/dist/analyzer/inspections/imperative.js +0 -105
  126. package/dist/analyzer/inspections/logic.d.ts +0 -49
  127. package/dist/analyzer/inspections/logic.js +0 -140
  128. package/dist/analyzer/inspections/object.d.ts +0 -83
  129. package/dist/analyzer/inspections/object.js +0 -235
  130. package/dist/interpreter/components/FunctionRuntime.d.ts +0 -8
  131. package/dist/interpreter/components/FunctionRuntime.js +0 -52
  132. package/dist/interpreter/components/LazyRuntime.d.ts +0 -7
  133. package/dist/interpreter/components/LazyRuntime.js +0 -75
  134. package/dist/interpreter/components/LogicEngine.d.ts +0 -21
  135. package/dist/interpreter/components/LogicEngine.js +0 -152
  136. package/dist/interpreter/components/LogicResolver.d.ts +0 -11
  137. package/dist/interpreter/components/LogicResolver.js +0 -87
  138. package/src/analyzer/inspections/functional.ts +0 -159
  139. package/src/analyzer/inspections/imperative.ts +0 -129
  140. package/src/analyzer/inspections/logic.ts +0 -166
  141. package/src/interpreter/components/FunctionRuntime.ts +0 -79
  142. package/src/interpreter/components/LazyRuntime.ts +0 -97
  143. package/src/interpreter/components/LogicEngine.ts +0 -227
  144. package/src/interpreter/components/LogicResolver.ts +0 -130
@@ -1,937 +1,991 @@
1
- import {
2
- Application,
3
- ArithmeticBinaryOperation,
4
- ArithmeticUnaryOperation,
5
- BitwiseBinaryOperation,
6
- BitwiseUnaryOperation,
7
- BooleanPrimitive,
8
- Call,
9
- ComparisonOperation,
10
- CompositionExpression,
11
- Equation,
12
- Fact,
13
- Function,
14
- FunctorPattern,
15
- Goal,
16
- isLazyList,
17
- Lambda,
18
- ListPrimitive,
19
- ListUnaryOperation,
20
- LiteralPattern,
21
- LogicalBinaryOperation,
22
- LogicalUnaryOperation,
23
- LogicResult,
24
- NumberPrimitive,
25
- Pattern,
26
- Query,
27
- RangeExpression,
28
- Return,
29
- RuntimePredicate,
30
- Sequence,
31
- StringOperation,
32
- StringPrimitive,
33
- SymbolPrimitive,
34
- UnguardedBody,
35
- VariablePattern,
36
- WildcardPattern,
37
- } from "yukigo-ast";
38
- import { Interpreter } from "../../src/interpreter/index.js";
39
- import {
40
- solveGoal,
41
- unify,
42
- } from "../../src/interpreter/components/LogicResolver.js";
43
- import { assert } from "chai";
44
- import {
45
- createEnv,
46
- createGlobalEnv,
47
- pushEnv,
48
- } from "../../src/interpreter/utils.js";
49
- import { YukigoPrologParser } from "yukigo-prolog-parser";
50
-
51
- describe("Interpreter Spec", () => {
52
- let interpreter: Interpreter;
53
- beforeEach(() => {
54
- interpreter = new Interpreter([], { debug: true });
55
- });
56
- it("Evaluates ArithmeticBinaryOperation", () => {
57
- assert.equal(
58
- interpreter.evaluate(
59
- new ArithmeticBinaryOperation(
60
- "Plus",
61
- new NumberPrimitive(3),
62
- new NumberPrimitive(4)
63
- )
64
- ),
65
- 7
66
- );
67
- assert.equal(
68
- interpreter.evaluate(
69
- new ArithmeticBinaryOperation(
70
- "Minus",
71
- new NumberPrimitive(3),
72
- new NumberPrimitive(4)
73
- )
74
- ),
75
- -1
76
- );
77
- assert.equal(
78
- interpreter.evaluate(
79
- new ArithmeticBinaryOperation(
80
- "Multiply",
81
- new NumberPrimitive(3),
82
- new NumberPrimitive(4)
83
- )
84
- ),
85
- 12
86
- );
87
- assert.equal(
88
- interpreter.evaluate(
89
- new ArithmeticBinaryOperation(
90
- "Divide",
91
- new NumberPrimitive(3),
92
- new NumberPrimitive(4)
93
- )
94
- ),
95
- 0.75
96
- );
97
- assert.equal(
98
- interpreter.evaluate(
99
- new ArithmeticBinaryOperation(
100
- "Modulo",
101
- new NumberPrimitive(3),
102
- new NumberPrimitive(4)
103
- )
104
- ),
105
- 3
106
- );
107
- assert.equal(
108
- interpreter.evaluate(
109
- new ArithmeticBinaryOperation(
110
- "Power",
111
- new NumberPrimitive(3),
112
- new NumberPrimitive(4)
113
- )
114
- ),
115
- 81
116
- );
117
- assert.equal(
118
- interpreter.evaluate(
119
- new ArithmeticBinaryOperation(
120
- "Min",
121
- new NumberPrimitive(3),
122
- new NumberPrimitive(4)
123
- )
124
- ),
125
- 3
126
- );
127
- assert.equal(
128
- interpreter.evaluate(
129
- new ArithmeticBinaryOperation(
130
- "Max",
131
- new NumberPrimitive(3),
132
- new NumberPrimitive(4)
133
- )
134
- ),
135
- 4
136
- );
137
- });
138
-
139
- it("Evaluates ArithmeticUnaryOperation", () => {
140
- assert.equal(
141
- interpreter.evaluate(
142
- new ArithmeticUnaryOperation("Round", new NumberPrimitive(3.4))
143
- ),
144
- 3
145
- );
146
- assert.equal(
147
- interpreter.evaluate(
148
- new ArithmeticUnaryOperation("Round", new NumberPrimitive(3.5))
149
- ),
150
- 4
151
- );
152
- assert.equal(
153
- interpreter.evaluate(
154
- new ArithmeticUnaryOperation("Absolute", new NumberPrimitive(-3))
155
- ),
156
- 3
157
- );
158
- assert.equal(
159
- interpreter.evaluate(
160
- new ArithmeticUnaryOperation("Absolute", new NumberPrimitive(3))
161
- ),
162
- 3
163
- );
164
- assert.equal(
165
- interpreter.evaluate(
166
- new ArithmeticUnaryOperation("Ceil", new NumberPrimitive(3.3))
167
- ),
168
- 4
169
- );
170
- assert.equal(
171
- interpreter.evaluate(
172
- new ArithmeticUnaryOperation("Floor", new NumberPrimitive(3.3))
173
- ),
174
- 3
175
- );
176
- assert.equal(
177
- interpreter.evaluate(
178
- new ArithmeticUnaryOperation("Negation", new NumberPrimitive(3.3))
179
- ),
180
- -3.3
181
- );
182
- assert.equal(
183
- interpreter.evaluate(
184
- new ArithmeticUnaryOperation("Sqrt", new NumberPrimitive(25))
185
- ),
186
- 5
187
- );
188
- });
189
- describe("Evaluates ComparisonOperation", () => {
190
- it("Equal Operator", () => {
191
- assert.equal(
192
- interpreter.evaluate(
193
- new ComparisonOperation(
194
- "Equal",
195
- new NumberPrimitive(3.4),
196
- new NumberPrimitive(3.4)
197
- )
198
- ),
199
- true
200
- );
201
- assert.equal(
202
- interpreter.evaluate(
203
- new ComparisonOperation(
204
- "Equal",
205
- new NumberPrimitive(3.4),
206
- new NumberPrimitive(4)
207
- )
208
- ),
209
- false
210
- );
211
- assert.equal(
212
- interpreter.evaluate(
213
- new ComparisonOperation(
214
- "Equal",
215
- new NumberPrimitive(3),
216
- new StringPrimitive("3")
217
- )
218
- ),
219
- true
220
- );
221
- assert.equal(
222
- interpreter.evaluate(
223
- new ComparisonOperation(
224
- "Equal",
225
- new NumberPrimitive(3),
226
- new StringPrimitive("4")
227
- )
228
- ),
229
- false
230
- );
231
- });
232
- it("NotEqual Operator", () => {
233
- assert.equal(
234
- interpreter.evaluate(
235
- new ComparisonOperation(
236
- "NotEqual",
237
- new NumberPrimitive(3.4),
238
- new NumberPrimitive(3.4)
239
- )
240
- ),
241
- false
242
- );
243
- assert.equal(
244
- interpreter.evaluate(
245
- new ComparisonOperation(
246
- "NotEqual",
247
- new NumberPrimitive(3.4),
248
- new NumberPrimitive(4)
249
- )
250
- ),
251
- true
252
- );
253
- assert.equal(
254
- interpreter.evaluate(
255
- new ComparisonOperation(
256
- "NotEqual",
257
- new NumberPrimitive(3),
258
- new StringPrimitive("3")
259
- )
260
- ),
261
- false
262
- );
263
- assert.equal(
264
- interpreter.evaluate(
265
- new ComparisonOperation(
266
- "NotEqual",
267
- new NumberPrimitive(3),
268
- new StringPrimitive("4")
269
- )
270
- ),
271
- true
272
- );
273
- });
274
- it("Same Operator", () => {
275
- assert.equal(
276
- interpreter.evaluate(
277
- new ComparisonOperation(
278
- "Same",
279
- new NumberPrimitive(3.4),
280
- new NumberPrimitive(3.4)
281
- )
282
- ),
283
- true
284
- );
285
- assert.equal(
286
- interpreter.evaluate(
287
- new ComparisonOperation(
288
- "Same",
289
- new NumberPrimitive(3.4),
290
- new NumberPrimitive(4)
291
- )
292
- ),
293
- false
294
- );
295
- assert.equal(
296
- interpreter.evaluate(
297
- new ComparisonOperation(
298
- "Same",
299
- new NumberPrimitive(3),
300
- new StringPrimitive("3")
301
- )
302
- ),
303
- false
304
- );
305
- assert.equal(
306
- interpreter.evaluate(
307
- new ComparisonOperation(
308
- "Same",
309
- new NumberPrimitive(3),
310
- new StringPrimitive("4")
311
- )
312
- ),
313
- false
314
- );
315
- });
316
- it("NotSame Operator", () => {
317
- assert.equal(
318
- interpreter.evaluate(
319
- new ComparisonOperation(
320
- "NotSame",
321
- new NumberPrimitive(3.4),
322
- new NumberPrimitive(3.4)
323
- )
324
- ),
325
- false
326
- );
327
- assert.equal(
328
- interpreter.evaluate(
329
- new ComparisonOperation(
330
- "NotSame",
331
- new NumberPrimitive(3.4),
332
- new NumberPrimitive(4)
333
- )
334
- ),
335
- true
336
- );
337
- assert.equal(
338
- interpreter.evaluate(
339
- new ComparisonOperation(
340
- "NotSame",
341
- new NumberPrimitive(3),
342
- new StringPrimitive("3")
343
- )
344
- ),
345
- true
346
- );
347
- assert.equal(
348
- interpreter.evaluate(
349
- new ComparisonOperation(
350
- "NotSame",
351
- new NumberPrimitive(3),
352
- new StringPrimitive("4")
353
- )
354
- ),
355
- true
356
- );
357
- });
358
- it("GreaterOrEqualThan Operator", () => {
359
- assert.equal(
360
- interpreter.evaluate(
361
- new ComparisonOperation(
362
- "GreaterOrEqualThan",
363
- new NumberPrimitive(3.4),
364
- new NumberPrimitive(3.4)
365
- )
366
- ),
367
- true
368
- );
369
- assert.equal(
370
- interpreter.evaluate(
371
- new ComparisonOperation(
372
- "GreaterOrEqualThan",
373
- new NumberPrimitive(3.4),
374
- new NumberPrimitive(4)
375
- )
376
- ),
377
- false
378
- );
379
- assert.equal(
380
- interpreter.evaluate(
381
- new ComparisonOperation(
382
- "GreaterOrEqualThan",
383
- new NumberPrimitive(3),
384
- new StringPrimitive("3")
385
- )
386
- ),
387
- true
388
- );
389
- assert.equal(
390
- interpreter.evaluate(
391
- new ComparisonOperation(
392
- "GreaterOrEqualThan",
393
- new NumberPrimitive(3),
394
- new StringPrimitive("4")
395
- )
396
- ),
397
- false
398
- );
399
- });
400
- it("GreaterThan Operator", () => {
401
- assert.equal(
402
- interpreter.evaluate(
403
- new ComparisonOperation(
404
- "GreaterThan",
405
- new NumberPrimitive(3.4),
406
- new NumberPrimitive(3.4)
407
- )
408
- ),
409
- false
410
- );
411
- assert.equal(
412
- interpreter.evaluate(
413
- new ComparisonOperation(
414
- "GreaterThan",
415
- new NumberPrimitive(3.4),
416
- new NumberPrimitive(4)
417
- )
418
- ),
419
- false
420
- );
421
- assert.equal(
422
- interpreter.evaluate(
423
- new ComparisonOperation(
424
- "GreaterThan",
425
- new NumberPrimitive(3),
426
- new StringPrimitive("3")
427
- )
428
- ),
429
- false
430
- );
431
- assert.equal(
432
- interpreter.evaluate(
433
- new ComparisonOperation(
434
- "GreaterThan",
435
- new NumberPrimitive(3),
436
- new StringPrimitive("4")
437
- )
438
- ),
439
- false
440
- );
441
- });
442
- it("LessOrEqualThan Operator", () => {
443
- assert.equal(
444
- interpreter.evaluate(
445
- new ComparisonOperation(
446
- "LessOrEqualThan",
447
- new NumberPrimitive(3.4),
448
- new NumberPrimitive(3.4)
449
- )
450
- ),
451
- true
452
- );
453
- assert.equal(
454
- interpreter.evaluate(
455
- new ComparisonOperation(
456
- "LessOrEqualThan",
457
- new NumberPrimitive(3.4),
458
- new NumberPrimitive(4)
459
- )
460
- ),
461
- true
462
- );
463
- assert.equal(
464
- interpreter.evaluate(
465
- new ComparisonOperation(
466
- "LessOrEqualThan",
467
- new NumberPrimitive(3),
468
- new StringPrimitive("3")
469
- )
470
- ),
471
- true
472
- );
473
- assert.equal(
474
- interpreter.evaluate(
475
- new ComparisonOperation(
476
- "LessOrEqualThan",
477
- new NumberPrimitive(3),
478
- new StringPrimitive("4")
479
- )
480
- ),
481
- true
482
- );
483
- });
484
- it("LessThan Operator", () => {
485
- assert.equal(
486
- interpreter.evaluate(
487
- new ComparisonOperation(
488
- "LessThan",
489
- new NumberPrimitive(3.4),
490
- new NumberPrimitive(3.4)
491
- )
492
- ),
493
- false
494
- );
495
- assert.equal(
496
- interpreter.evaluate(
497
- new ComparisonOperation(
498
- "LessThan",
499
- new NumberPrimitive(3.4),
500
- new NumberPrimitive(4)
501
- )
502
- ),
503
- true
504
- );
505
- assert.equal(
506
- interpreter.evaluate(
507
- new ComparisonOperation(
508
- "LessThan",
509
- new NumberPrimitive(3),
510
- new StringPrimitive("3")
511
- )
512
- ),
513
- false
514
- );
515
- assert.equal(
516
- interpreter.evaluate(
517
- new ComparisonOperation(
518
- "LessThan",
519
- new NumberPrimitive(3),
520
- new StringPrimitive("4")
521
- )
522
- ),
523
- true
524
- );
525
- });
526
- });
527
- describe("Evaluates LogicalBinaryOperation", () => {
528
- it("And Operator", () => {
529
- assert.equal(
530
- interpreter.evaluate(
531
- new LogicalBinaryOperation(
532
- "And",
533
- new BooleanPrimitive(true),
534
- new BooleanPrimitive(true)
535
- )
536
- ),
537
- true
538
- );
539
- assert.equal(
540
- interpreter.evaluate(
541
- new LogicalBinaryOperation(
542
- "And",
543
- new BooleanPrimitive(true),
544
- new BooleanPrimitive(false)
545
- )
546
- ),
547
- false
548
- );
549
- assert.equal(
550
- interpreter.evaluate(
551
- new LogicalBinaryOperation(
552
- "And",
553
- new BooleanPrimitive(false),
554
- new BooleanPrimitive(true)
555
- )
556
- ),
557
- false
558
- );
559
- assert.equal(
560
- interpreter.evaluate(
561
- new LogicalBinaryOperation(
562
- "And",
563
- new BooleanPrimitive(false),
564
- new BooleanPrimitive(false)
565
- )
566
- ),
567
- false
568
- );
569
- });
570
- it("Or Operator", () => {
571
- assert.equal(
572
- interpreter.evaluate(
573
- new LogicalBinaryOperation(
574
- "Or",
575
- new BooleanPrimitive(true),
576
- new BooleanPrimitive(true)
577
- )
578
- ),
579
- true
580
- );
581
- assert.equal(
582
- interpreter.evaluate(
583
- new LogicalBinaryOperation(
584
- "Or",
585
- new BooleanPrimitive(true),
586
- new BooleanPrimitive(false)
587
- )
588
- ),
589
- true
590
- );
591
- assert.equal(
592
- interpreter.evaluate(
593
- new LogicalBinaryOperation(
594
- "Or",
595
- new BooleanPrimitive(false),
596
- new BooleanPrimitive(true)
597
- )
598
- ),
599
- true
600
- );
601
- assert.equal(
602
- interpreter.evaluate(
603
- new LogicalBinaryOperation(
604
- "Or",
605
- new BooleanPrimitive(false),
606
- new BooleanPrimitive(false)
607
- )
608
- ),
609
- false
610
- );
611
- });
612
- });
613
- describe("Evaluates LogicalUnaryOperation", () => {
614
- it("Negation Operator", () => {
615
- assert.equal(
616
- interpreter.evaluate(
617
- new LogicalUnaryOperation("Negation", new BooleanPrimitive(true))
618
- ),
619
- false
620
- );
621
- assert.equal(
622
- interpreter.evaluate(
623
- new LogicalUnaryOperation("Negation", new BooleanPrimitive(false))
624
- ),
625
- true
626
- );
627
- });
628
- });
629
- describe("Evaluates StringOperation", () => {
630
- it("Concat Operator", () => {
631
- assert.equal(
632
- interpreter.evaluate(
633
- new StringOperation(
634
- "Concat",
635
- new StringPrimitive("Hello"),
636
- new StringPrimitive(" world!")
637
- )
638
- ),
639
- "Hello world!"
640
- );
641
- });
642
- });
643
- describe("Evaluates ListUnaryOperation", () => {
644
- it("Size Operator", () => {
645
- assert.equal(
646
- interpreter.evaluate(
647
- new ListUnaryOperation(
648
- "Size",
649
- new ListPrimitive([
650
- new StringPrimitive("Hello"),
651
- new StringPrimitive("world!"),
652
- ])
653
- )
654
- ),
655
- 2
656
- );
657
- });
658
- it("DetectMax Operator", () => {
659
- assert.equal(
660
- interpreter.evaluate(
661
- new ListUnaryOperation(
662
- "DetectMax",
663
- new ListPrimitive([new NumberPrimitive(2), new NumberPrimitive(4)])
664
- )
665
- ),
666
- 4
667
- );
668
- });
669
- it("DetectMin Operator", () => {
670
- assert.equal(
671
- interpreter.evaluate(
672
- new ListUnaryOperation(
673
- "DetectMin",
674
- new ListPrimitive([new NumberPrimitive(2), new NumberPrimitive(4)])
675
- )
676
- ),
677
- 2
678
- );
679
- });
680
- it("Flatten Operator", () => {
681
- assert.deepEqual(
682
- interpreter.evaluate(
683
- new ListUnaryOperation(
684
- "Flatten",
685
- new ListPrimitive([
686
- new ListPrimitive([new NumberPrimitive(2)]),
687
- new ListPrimitive([
688
- new NumberPrimitive(3),
689
- new NumberPrimitive(8),
690
- ]),
691
- ])
692
- )
693
- ),
694
- [2, 3, 8]
695
- );
696
- });
697
- });
698
- describe("Evaluates BitwiseBinaryOperation", () => {
699
- it("BitwiseOr Operator", () => {
700
- assert.equal(
701
- interpreter.evaluate(
702
- new BitwiseBinaryOperation(
703
- "BitwiseOr",
704
- new NumberPrimitive(5),
705
- new NumberPrimitive(1)
706
- )
707
- ),
708
- 5
709
- );
710
- });
711
- it("BitwiseAnd Operator", () => {
712
- assert.equal(
713
- interpreter.evaluate(
714
- new BitwiseBinaryOperation(
715
- "BitwiseAnd",
716
- new NumberPrimitive(5),
717
- new NumberPrimitive(1)
718
- )
719
- ),
720
- 1
721
- );
722
- });
723
- it("BitwiseLeftShift Operator", () => {
724
- assert.equal(
725
- interpreter.evaluate(
726
- new BitwiseBinaryOperation(
727
- "BitwiseLeftShift",
728
- new NumberPrimitive(5),
729
- new NumberPrimitive(1)
730
- )
731
- ),
732
- 10
733
- );
734
- });
735
- it("BitwiseRightShift Operator", () => {
736
- assert.equal(
737
- interpreter.evaluate(
738
- new BitwiseBinaryOperation(
739
- "BitwiseRightShift",
740
- new NumberPrimitive(5),
741
- new NumberPrimitive(1)
742
- )
743
- ),
744
- 2
745
- );
746
- });
747
- it("BitwiseUnsignedRightShift Operator", () => {
748
- assert.equal(
749
- interpreter.evaluate(
750
- new BitwiseBinaryOperation(
751
- "BitwiseUnsignedRightShift",
752
- new NumberPrimitive(5),
753
- new NumberPrimitive(1)
754
- )
755
- ),
756
- 2
757
- );
758
- });
759
- it("BitwiseXor Operator", () => {
760
- assert.equal(
761
- interpreter.evaluate(
762
- new BitwiseBinaryOperation(
763
- "BitwiseXor",
764
- new NumberPrimitive(5),
765
- new NumberPrimitive(1)
766
- )
767
- ),
768
- 4
769
- );
770
- });
771
- });
772
- describe("Evaluates BitwiseUnaryOperator", () => {
773
- it("BitwiseNot Operator", () => {
774
- assert.equal(
775
- interpreter.evaluate(
776
- new BitwiseUnaryOperation("BitwiseNot", new NumberPrimitive(5))
777
- ),
778
- -6
779
- );
780
- });
781
- });
782
- describe("Evaluates Application", () => {
783
- beforeEach(() => {
784
- interpreter = new Interpreter([
785
- new Function(new SymbolPrimitive("f"), [
786
- new Equation(
787
- [new LiteralPattern(new NumberPrimitive(3))],
788
- new UnguardedBody(
789
- new Sequence([new Return(new NumberPrimitive(6))])
790
- ),
791
- new Return(new NumberPrimitive(6))
792
- ),
793
- new Equation(
794
- [new VariablePattern(new SymbolPrimitive("y"))],
795
- new UnguardedBody(
796
- new Sequence([
797
- new Return(
798
- new ArithmeticBinaryOperation(
799
- "Plus",
800
- new SymbolPrimitive("y"),
801
- new NumberPrimitive(3)
802
- )
803
- ),
804
- ])
805
- ),
806
- new Return(
807
- new ArithmeticBinaryOperation(
808
- "Plus",
809
- new SymbolPrimitive("y"),
810
- new NumberPrimitive(3)
811
- )
812
- )
813
- ),
814
- ]),
815
- ]);
816
- });
817
- it("Lambda + currified Application", () => {
818
- const lambda = new Lambda(
819
- [
820
- new VariablePattern(new SymbolPrimitive("x")),
821
- new VariablePattern(new SymbolPrimitive("y")),
822
- new VariablePattern(new SymbolPrimitive("z")),
823
- ],
824
- new ArithmeticBinaryOperation(
825
- "Plus",
826
- new ArithmeticBinaryOperation(
827
- "Plus",
828
- new SymbolPrimitive("x"),
829
- new SymbolPrimitive("y")
830
- ),
831
- new SymbolPrimitive("z")
832
- )
833
- );
834
- const app1 = new Application(lambda, new NumberPrimitive(1));
835
- const app2 = new Application(app1, new NumberPrimitive(2));
836
- const app3 = new Application(app2, new NumberPrimitive(3));
837
- assert.equal(interpreter.evaluate(app3), 6);
838
- });
839
- it("Application of Function", () => {
840
- const app1 = new Application(
841
- new SymbolPrimitive("f"),
842
- new NumberPrimitive(3)
843
- );
844
- assert.equal(interpreter.evaluate(app1), 6);
845
- });
846
- });
847
- describe("Evaluates Composition", () => {
848
- beforeEach(() => {
849
- interpreter = new Interpreter(
850
- [
851
- new Function(new SymbolPrimitive("doble"), [
852
- new Equation(
853
- [new VariablePattern(new SymbolPrimitive("x"))],
854
- new UnguardedBody(
855
- new Sequence([
856
- new Return(
857
- new ArithmeticBinaryOperation(
858
- "Multiply",
859
- new SymbolPrimitive("x"),
860
- new NumberPrimitive(2)
861
- )
862
- ),
863
- ])
864
- ),
865
- new Return(
866
- new ArithmeticBinaryOperation(
867
- "Multiply",
868
- new SymbolPrimitive("x"),
869
- new NumberPrimitive(2)
870
- )
871
- )
872
- ),
873
- ]),
874
- new Function(new SymbolPrimitive("cuadrado"), [
875
- new Equation(
876
- [new VariablePattern(new SymbolPrimitive("x"))],
877
- new UnguardedBody(
878
- new Sequence([
879
- new Return(
880
- new ArithmeticBinaryOperation(
881
- "Power",
882
- new SymbolPrimitive("x"),
883
- new NumberPrimitive(2)
884
- )
885
- ),
886
- ])
887
- ),
888
- new Return(
889
- new ArithmeticBinaryOperation(
890
- "Power",
891
- new SymbolPrimitive("x"),
892
- new NumberPrimitive(2)
893
- )
894
- )
895
- ),
896
- ]),
897
- ],
898
- { debug: true }
899
- );
900
- });
901
- it("Composition (cuadrado . doble) 2 should be 16", () => {
902
- const fog = new CompositionExpression(
903
- new SymbolPrimitive("cuadrado"),
904
- new SymbolPrimitive("doble")
905
- );
906
- const app = new Application(fog, new NumberPrimitive(2));
907
- assert.equal(interpreter.evaluate(app), 16);
908
- });
909
- });
910
- describe("Evaluates Range Expression", () => {
911
- it("Evaluates [1..5] to full range", () => {
912
- const range = new RangeExpression(
913
- new NumberPrimitive(1),
914
- new NumberPrimitive(5)
915
- );
916
- assert.deepEqual(interpreter.evaluate(range), [1, 2, 3, 4, 5]);
917
- });
918
- it("Evaluates [0,0.5..2] to full range", () => {
919
- const range = new RangeExpression(
920
- new NumberPrimitive(0),
921
- new NumberPrimitive(2),
922
- new NumberPrimitive(0.5)
923
- );
924
- assert.deepEqual(interpreter.evaluate(range), [0, 0.5, 1, 1.5, 2]);
925
- });
926
- it("Evaluates [1..] lazily", () => {
927
- interpreter = new Interpreter([], { lazyLoading: true });
928
- const range = new RangeExpression(new NumberPrimitive(1));
929
- const evaluatedList = interpreter.evaluate(range);
930
- if (!isLazyList(evaluatedList))
931
- assert.fail("Evaluated list should be LazyList");
932
- const iter = evaluatedList.generator();
933
- assert.equal(iter.next().value, 1);
934
- assert.equal(iter.next().value, 2);
935
- });
936
- });
937
- });
1
+ import {
2
+ Application,
3
+ ArithmeticBinaryOperation,
4
+ ArithmeticUnaryOperation,
5
+ Assignment,
6
+ AssignOperation,
7
+ BitwiseBinaryOperation,
8
+ BitwiseUnaryOperation,
9
+ BooleanPrimitive,
10
+ ComparisonOperation,
11
+ CompositionExpression,
12
+ Equation,
13
+ Function,
14
+ isLazyList,
15
+ Lambda,
16
+ ListPrimitive,
17
+ ListUnaryOperation,
18
+ LiteralPattern,
19
+ LogicalBinaryOperation,
20
+ LogicalUnaryOperation,
21
+ NumberPrimitive,
22
+ RangeExpression,
23
+ Return,
24
+ Sequence,
25
+ SimpleType,
26
+ StringOperation,
27
+ StringPrimitive,
28
+ SymbolPrimitive,
29
+ TypeCast,
30
+ UnguardedBody,
31
+ Variable,
32
+ VariablePattern,
33
+ } from "yukigo-ast";
34
+ import { Interpreter } from "../../src/interpreter/index.js";
35
+ import { assert } from "chai";
36
+
37
+ describe("Interpreter Spec", () => {
38
+ let interpreter: Interpreter;
39
+ beforeEach(() => {
40
+ interpreter = new Interpreter([], { debug: true });
41
+ });
42
+ it("Evaluates ArithmeticBinaryOperation", () => {
43
+ assert.equal(
44
+ interpreter.evaluate(
45
+ new ArithmeticBinaryOperation(
46
+ "Plus",
47
+ new NumberPrimitive(3),
48
+ new NumberPrimitive(4)
49
+ )
50
+ ),
51
+ 7
52
+ );
53
+ assert.equal(
54
+ interpreter.evaluate(
55
+ new ArithmeticBinaryOperation(
56
+ "Minus",
57
+ new NumberPrimitive(3),
58
+ new NumberPrimitive(4)
59
+ )
60
+ ),
61
+ -1
62
+ );
63
+ assert.equal(
64
+ interpreter.evaluate(
65
+ new ArithmeticBinaryOperation(
66
+ "Multiply",
67
+ new NumberPrimitive(3),
68
+ new NumberPrimitive(4)
69
+ )
70
+ ),
71
+ 12
72
+ );
73
+ assert.equal(
74
+ interpreter.evaluate(
75
+ new ArithmeticBinaryOperation(
76
+ "Divide",
77
+ new NumberPrimitive(3),
78
+ new NumberPrimitive(4)
79
+ )
80
+ ),
81
+ 0.75
82
+ );
83
+ assert.equal(
84
+ interpreter.evaluate(
85
+ new ArithmeticBinaryOperation(
86
+ "Modulo",
87
+ new NumberPrimitive(3),
88
+ new NumberPrimitive(4)
89
+ )
90
+ ),
91
+ 3
92
+ );
93
+ assert.equal(
94
+ interpreter.evaluate(
95
+ new ArithmeticBinaryOperation(
96
+ "Power",
97
+ new NumberPrimitive(3),
98
+ new NumberPrimitive(4)
99
+ )
100
+ ),
101
+ 81
102
+ );
103
+ assert.equal(
104
+ interpreter.evaluate(
105
+ new ArithmeticBinaryOperation(
106
+ "Min",
107
+ new NumberPrimitive(3),
108
+ new NumberPrimitive(4)
109
+ )
110
+ ),
111
+ 3
112
+ );
113
+ assert.equal(
114
+ interpreter.evaluate(
115
+ new ArithmeticBinaryOperation(
116
+ "Max",
117
+ new NumberPrimitive(3),
118
+ new NumberPrimitive(4)
119
+ )
120
+ ),
121
+ 4
122
+ );
123
+ });
124
+
125
+ it("Evaluates ArithmeticUnaryOperation", () => {
126
+ assert.equal(
127
+ interpreter.evaluate(
128
+ new ArithmeticUnaryOperation("Round", new NumberPrimitive(3.4))
129
+ ),
130
+ 3
131
+ );
132
+ assert.equal(
133
+ interpreter.evaluate(
134
+ new ArithmeticUnaryOperation("Round", new NumberPrimitive(3.5))
135
+ ),
136
+ 4
137
+ );
138
+ assert.equal(
139
+ interpreter.evaluate(
140
+ new ArithmeticUnaryOperation("Absolute", new NumberPrimitive(-3))
141
+ ),
142
+ 3
143
+ );
144
+ assert.equal(
145
+ interpreter.evaluate(
146
+ new ArithmeticUnaryOperation("Absolute", new NumberPrimitive(3))
147
+ ),
148
+ 3
149
+ );
150
+ assert.equal(
151
+ interpreter.evaluate(
152
+ new ArithmeticUnaryOperation("Ceil", new NumberPrimitive(3.3))
153
+ ),
154
+ 4
155
+ );
156
+ assert.equal(
157
+ interpreter.evaluate(
158
+ new ArithmeticUnaryOperation("Floor", new NumberPrimitive(3.3))
159
+ ),
160
+ 3
161
+ );
162
+ assert.equal(
163
+ interpreter.evaluate(
164
+ new ArithmeticUnaryOperation("Negation", new NumberPrimitive(3.3))
165
+ ),
166
+ -3.3
167
+ );
168
+ assert.equal(
169
+ interpreter.evaluate(
170
+ new ArithmeticUnaryOperation("Sqrt", new NumberPrimitive(25))
171
+ ),
172
+ 5
173
+ );
174
+ });
175
+ describe("Evaluates ComparisonOperation", () => {
176
+ it("Equal Operator", () => {
177
+ assert.equal(
178
+ interpreter.evaluate(
179
+ new ComparisonOperation(
180
+ "Equal",
181
+ new NumberPrimitive(3.4),
182
+ new NumberPrimitive(3.4)
183
+ )
184
+ ),
185
+ true
186
+ );
187
+ assert.equal(
188
+ interpreter.evaluate(
189
+ new ComparisonOperation(
190
+ "Equal",
191
+ new NumberPrimitive(3.4),
192
+ new NumberPrimitive(4)
193
+ )
194
+ ),
195
+ false
196
+ );
197
+ assert.equal(
198
+ interpreter.evaluate(
199
+ new ComparisonOperation(
200
+ "Equal",
201
+ new NumberPrimitive(3),
202
+ new StringPrimitive("3")
203
+ )
204
+ ),
205
+ true
206
+ );
207
+ assert.equal(
208
+ interpreter.evaluate(
209
+ new ComparisonOperation(
210
+ "Equal",
211
+ new NumberPrimitive(3),
212
+ new StringPrimitive("4")
213
+ )
214
+ ),
215
+ false
216
+ );
217
+ });
218
+ it("NotEqual Operator", () => {
219
+ assert.equal(
220
+ interpreter.evaluate(
221
+ new ComparisonOperation(
222
+ "NotEqual",
223
+ new NumberPrimitive(3.4),
224
+ new NumberPrimitive(3.4)
225
+ )
226
+ ),
227
+ false
228
+ );
229
+ assert.equal(
230
+ interpreter.evaluate(
231
+ new ComparisonOperation(
232
+ "NotEqual",
233
+ new NumberPrimitive(3.4),
234
+ new NumberPrimitive(4)
235
+ )
236
+ ),
237
+ true
238
+ );
239
+ assert.equal(
240
+ interpreter.evaluate(
241
+ new ComparisonOperation(
242
+ "NotEqual",
243
+ new NumberPrimitive(3),
244
+ new StringPrimitive("3")
245
+ )
246
+ ),
247
+ false
248
+ );
249
+ assert.equal(
250
+ interpreter.evaluate(
251
+ new ComparisonOperation(
252
+ "NotEqual",
253
+ new NumberPrimitive(3),
254
+ new StringPrimitive("4")
255
+ )
256
+ ),
257
+ true
258
+ );
259
+ });
260
+ it("Same Operator", () => {
261
+ assert.equal(
262
+ interpreter.evaluate(
263
+ new ComparisonOperation(
264
+ "Same",
265
+ new NumberPrimitive(3.4),
266
+ new NumberPrimitive(3.4)
267
+ )
268
+ ),
269
+ true
270
+ );
271
+ assert.equal(
272
+ interpreter.evaluate(
273
+ new ComparisonOperation(
274
+ "Same",
275
+ new NumberPrimitive(3.4),
276
+ new NumberPrimitive(4)
277
+ )
278
+ ),
279
+ false
280
+ );
281
+ assert.equal(
282
+ interpreter.evaluate(
283
+ new ComparisonOperation(
284
+ "Same",
285
+ new NumberPrimitive(3),
286
+ new StringPrimitive("3")
287
+ )
288
+ ),
289
+ false
290
+ );
291
+ assert.equal(
292
+ interpreter.evaluate(
293
+ new ComparisonOperation(
294
+ "Same",
295
+ new NumberPrimitive(3),
296
+ new StringPrimitive("4")
297
+ )
298
+ ),
299
+ false
300
+ );
301
+ });
302
+ it("NotSame Operator", () => {
303
+ assert.equal(
304
+ interpreter.evaluate(
305
+ new ComparisonOperation(
306
+ "NotSame",
307
+ new NumberPrimitive(3.4),
308
+ new NumberPrimitive(3.4)
309
+ )
310
+ ),
311
+ false
312
+ );
313
+ assert.equal(
314
+ interpreter.evaluate(
315
+ new ComparisonOperation(
316
+ "NotSame",
317
+ new NumberPrimitive(3.4),
318
+ new NumberPrimitive(4)
319
+ )
320
+ ),
321
+ true
322
+ );
323
+ assert.equal(
324
+ interpreter.evaluate(
325
+ new ComparisonOperation(
326
+ "NotSame",
327
+ new NumberPrimitive(3),
328
+ new StringPrimitive("3")
329
+ )
330
+ ),
331
+ true
332
+ );
333
+ assert.equal(
334
+ interpreter.evaluate(
335
+ new ComparisonOperation(
336
+ "NotSame",
337
+ new NumberPrimitive(3),
338
+ new StringPrimitive("4")
339
+ )
340
+ ),
341
+ true
342
+ );
343
+ });
344
+ it("GreaterOrEqualThan Operator", () => {
345
+ assert.equal(
346
+ interpreter.evaluate(
347
+ new ComparisonOperation(
348
+ "GreaterOrEqualThan",
349
+ new NumberPrimitive(3.4),
350
+ new NumberPrimitive(3.4)
351
+ )
352
+ ),
353
+ true
354
+ );
355
+ assert.equal(
356
+ interpreter.evaluate(
357
+ new ComparisonOperation(
358
+ "GreaterOrEqualThan",
359
+ new NumberPrimitive(3.4),
360
+ new NumberPrimitive(4)
361
+ )
362
+ ),
363
+ false
364
+ );
365
+ assert.equal(
366
+ interpreter.evaluate(
367
+ new ComparisonOperation(
368
+ "GreaterOrEqualThan",
369
+ new NumberPrimitive(3),
370
+ new StringPrimitive("3")
371
+ )
372
+ ),
373
+ true
374
+ );
375
+ assert.equal(
376
+ interpreter.evaluate(
377
+ new ComparisonOperation(
378
+ "GreaterOrEqualThan",
379
+ new NumberPrimitive(3),
380
+ new StringPrimitive("4")
381
+ )
382
+ ),
383
+ false
384
+ );
385
+ });
386
+ it("GreaterThan Operator", () => {
387
+ assert.equal(
388
+ interpreter.evaluate(
389
+ new ComparisonOperation(
390
+ "GreaterThan",
391
+ new NumberPrimitive(3.4),
392
+ new NumberPrimitive(3.4)
393
+ )
394
+ ),
395
+ false
396
+ );
397
+ assert.equal(
398
+ interpreter.evaluate(
399
+ new ComparisonOperation(
400
+ "GreaterThan",
401
+ new NumberPrimitive(3.4),
402
+ new NumberPrimitive(4)
403
+ )
404
+ ),
405
+ false
406
+ );
407
+ assert.equal(
408
+ interpreter.evaluate(
409
+ new ComparisonOperation(
410
+ "GreaterThan",
411
+ new NumberPrimitive(3),
412
+ new StringPrimitive("3")
413
+ )
414
+ ),
415
+ false
416
+ );
417
+ assert.equal(
418
+ interpreter.evaluate(
419
+ new ComparisonOperation(
420
+ "GreaterThan",
421
+ new NumberPrimitive(3),
422
+ new StringPrimitive("4")
423
+ )
424
+ ),
425
+ false
426
+ );
427
+ });
428
+ it("LessOrEqualThan Operator", () => {
429
+ assert.equal(
430
+ interpreter.evaluate(
431
+ new ComparisonOperation(
432
+ "LessOrEqualThan",
433
+ new NumberPrimitive(3.4),
434
+ new NumberPrimitive(3.4)
435
+ )
436
+ ),
437
+ true
438
+ );
439
+ assert.equal(
440
+ interpreter.evaluate(
441
+ new ComparisonOperation(
442
+ "LessOrEqualThan",
443
+ new NumberPrimitive(3.4),
444
+ new NumberPrimitive(4)
445
+ )
446
+ ),
447
+ true
448
+ );
449
+ assert.equal(
450
+ interpreter.evaluate(
451
+ new ComparisonOperation(
452
+ "LessOrEqualThan",
453
+ new NumberPrimitive(3),
454
+ new StringPrimitive("3")
455
+ )
456
+ ),
457
+ true
458
+ );
459
+ assert.equal(
460
+ interpreter.evaluate(
461
+ new ComparisonOperation(
462
+ "LessOrEqualThan",
463
+ new NumberPrimitive(3),
464
+ new StringPrimitive("4")
465
+ )
466
+ ),
467
+ true
468
+ );
469
+ });
470
+ it("LessThan Operator", () => {
471
+ assert.equal(
472
+ interpreter.evaluate(
473
+ new ComparisonOperation(
474
+ "LessThan",
475
+ new NumberPrimitive(3.4),
476
+ new NumberPrimitive(3.4)
477
+ )
478
+ ),
479
+ false
480
+ );
481
+ assert.equal(
482
+ interpreter.evaluate(
483
+ new ComparisonOperation(
484
+ "LessThan",
485
+ new NumberPrimitive(3.4),
486
+ new NumberPrimitive(4)
487
+ )
488
+ ),
489
+ true
490
+ );
491
+ assert.equal(
492
+ interpreter.evaluate(
493
+ new ComparisonOperation(
494
+ "LessThan",
495
+ new NumberPrimitive(3),
496
+ new StringPrimitive("3")
497
+ )
498
+ ),
499
+ false
500
+ );
501
+ assert.equal(
502
+ interpreter.evaluate(
503
+ new ComparisonOperation(
504
+ "LessThan",
505
+ new NumberPrimitive(3),
506
+ new StringPrimitive("4")
507
+ )
508
+ ),
509
+ true
510
+ );
511
+ });
512
+ });
513
+ describe("Evaluates LogicalBinaryOperation", () => {
514
+ it("And Operator", () => {
515
+ assert.equal(
516
+ interpreter.evaluate(
517
+ new LogicalBinaryOperation(
518
+ "And",
519
+ new BooleanPrimitive(true),
520
+ new BooleanPrimitive(true)
521
+ )
522
+ ),
523
+ true
524
+ );
525
+ assert.equal(
526
+ interpreter.evaluate(
527
+ new LogicalBinaryOperation(
528
+ "And",
529
+ new BooleanPrimitive(true),
530
+ new BooleanPrimitive(false)
531
+ )
532
+ ),
533
+ false
534
+ );
535
+ assert.equal(
536
+ interpreter.evaluate(
537
+ new LogicalBinaryOperation(
538
+ "And",
539
+ new BooleanPrimitive(false),
540
+ new BooleanPrimitive(true)
541
+ )
542
+ ),
543
+ false
544
+ );
545
+ assert.equal(
546
+ interpreter.evaluate(
547
+ new LogicalBinaryOperation(
548
+ "And",
549
+ new BooleanPrimitive(false),
550
+ new BooleanPrimitive(false)
551
+ )
552
+ ),
553
+ false
554
+ );
555
+ });
556
+ it("Or Operator", () => {
557
+ assert.equal(
558
+ interpreter.evaluate(
559
+ new LogicalBinaryOperation(
560
+ "Or",
561
+ new BooleanPrimitive(true),
562
+ new BooleanPrimitive(true)
563
+ )
564
+ ),
565
+ true
566
+ );
567
+ assert.equal(
568
+ interpreter.evaluate(
569
+ new LogicalBinaryOperation(
570
+ "Or",
571
+ new BooleanPrimitive(true),
572
+ new BooleanPrimitive(false)
573
+ )
574
+ ),
575
+ true
576
+ );
577
+ assert.equal(
578
+ interpreter.evaluate(
579
+ new LogicalBinaryOperation(
580
+ "Or",
581
+ new BooleanPrimitive(false),
582
+ new BooleanPrimitive(true)
583
+ )
584
+ ),
585
+ true
586
+ );
587
+ assert.equal(
588
+ interpreter.evaluate(
589
+ new LogicalBinaryOperation(
590
+ "Or",
591
+ new BooleanPrimitive(false),
592
+ new BooleanPrimitive(false)
593
+ )
594
+ ),
595
+ false
596
+ );
597
+ });
598
+ });
599
+ describe("Evaluates LogicalUnaryOperation", () => {
600
+ it("Negation Operator", () => {
601
+ assert.equal(
602
+ interpreter.evaluate(
603
+ new LogicalUnaryOperation("Negation", new BooleanPrimitive(true))
604
+ ),
605
+ false
606
+ );
607
+ assert.equal(
608
+ interpreter.evaluate(
609
+ new LogicalUnaryOperation("Negation", new BooleanPrimitive(false))
610
+ ),
611
+ true
612
+ );
613
+ });
614
+ });
615
+ describe("Evaluates StringOperation", () => {
616
+ it("Concat Operator", () => {
617
+ assert.equal(
618
+ interpreter.evaluate(
619
+ new StringOperation(
620
+ "Concat",
621
+ new StringPrimitive("Hello"),
622
+ new StringPrimitive(" world!")
623
+ )
624
+ ),
625
+ "Hello world!"
626
+ );
627
+ });
628
+ });
629
+ describe("Evaluates ListUnaryOperation", () => {
630
+ it("Size Operator", () => {
631
+ assert.equal(
632
+ interpreter.evaluate(
633
+ new ListUnaryOperation(
634
+ "Size",
635
+ new ListPrimitive([
636
+ new StringPrimitive("Hello"),
637
+ new StringPrimitive("world!"),
638
+ ])
639
+ )
640
+ ),
641
+ 2
642
+ );
643
+ });
644
+ it("DetectMax Operator", () => {
645
+ assert.equal(
646
+ interpreter.evaluate(
647
+ new ListUnaryOperation(
648
+ "DetectMax",
649
+ new ListPrimitive([new NumberPrimitive(2), new NumberPrimitive(4)])
650
+ )
651
+ ),
652
+ 4
653
+ );
654
+ });
655
+ it("DetectMin Operator", () => {
656
+ assert.equal(
657
+ interpreter.evaluate(
658
+ new ListUnaryOperation(
659
+ "DetectMin",
660
+ new ListPrimitive([new NumberPrimitive(2), new NumberPrimitive(4)])
661
+ )
662
+ ),
663
+ 2
664
+ );
665
+ });
666
+ it("Flatten Operator", () => {
667
+ assert.deepEqual(
668
+ interpreter.evaluate(
669
+ new ListUnaryOperation(
670
+ "Flatten",
671
+ new ListPrimitive([
672
+ new ListPrimitive([new NumberPrimitive(2)]),
673
+ new ListPrimitive([
674
+ new NumberPrimitive(3),
675
+ new NumberPrimitive(8),
676
+ ]),
677
+ ])
678
+ )
679
+ ),
680
+ [2, 3, 8]
681
+ );
682
+ });
683
+ });
684
+ describe("Evaluates BitwiseBinaryOperation", () => {
685
+ it("BitwiseOr Operator", () => {
686
+ assert.equal(
687
+ interpreter.evaluate(
688
+ new BitwiseBinaryOperation(
689
+ "BitwiseOr",
690
+ new NumberPrimitive(5),
691
+ new NumberPrimitive(1)
692
+ )
693
+ ),
694
+ 5
695
+ );
696
+ });
697
+ it("BitwiseAnd Operator", () => {
698
+ assert.equal(
699
+ interpreter.evaluate(
700
+ new BitwiseBinaryOperation(
701
+ "BitwiseAnd",
702
+ new NumberPrimitive(5),
703
+ new NumberPrimitive(1)
704
+ )
705
+ ),
706
+ 1
707
+ );
708
+ });
709
+ it("BitwiseLeftShift Operator", () => {
710
+ assert.equal(
711
+ interpreter.evaluate(
712
+ new BitwiseBinaryOperation(
713
+ "BitwiseLeftShift",
714
+ new NumberPrimitive(5),
715
+ new NumberPrimitive(1)
716
+ )
717
+ ),
718
+ 10
719
+ );
720
+ });
721
+ it("BitwiseRightShift Operator", () => {
722
+ assert.equal(
723
+ interpreter.evaluate(
724
+ new BitwiseBinaryOperation(
725
+ "BitwiseRightShift",
726
+ new NumberPrimitive(5),
727
+ new NumberPrimitive(1)
728
+ )
729
+ ),
730
+ 2
731
+ );
732
+ });
733
+ it("BitwiseUnsignedRightShift Operator", () => {
734
+ assert.equal(
735
+ interpreter.evaluate(
736
+ new BitwiseBinaryOperation(
737
+ "BitwiseUnsignedRightShift",
738
+ new NumberPrimitive(5),
739
+ new NumberPrimitive(1)
740
+ )
741
+ ),
742
+ 2
743
+ );
744
+ });
745
+ it("BitwiseXor Operator", () => {
746
+ assert.equal(
747
+ interpreter.evaluate(
748
+ new BitwiseBinaryOperation(
749
+ "BitwiseXor",
750
+ new NumberPrimitive(5),
751
+ new NumberPrimitive(1)
752
+ )
753
+ ),
754
+ 4
755
+ );
756
+ });
757
+ });
758
+ describe("Evaluates BitwiseUnaryOperator", () => {
759
+ it("BitwiseNot Operator", () => {
760
+ assert.equal(
761
+ interpreter.evaluate(
762
+ new BitwiseUnaryOperation("BitwiseNot", new NumberPrimitive(5))
763
+ ),
764
+ -6
765
+ );
766
+ });
767
+ });
768
+ describe("Evaluates Application", () => {
769
+ beforeEach(() => {
770
+ interpreter = new Interpreter([
771
+ new Function(new SymbolPrimitive("f"), [
772
+ new Equation(
773
+ [new LiteralPattern(new NumberPrimitive(3))],
774
+ new UnguardedBody(
775
+ new Sequence([new Return(new NumberPrimitive(6))])
776
+ ),
777
+ new Return(new NumberPrimitive(6))
778
+ ),
779
+ new Equation(
780
+ [new VariablePattern(new SymbolPrimitive("y"))],
781
+ new UnguardedBody(
782
+ new Sequence([
783
+ new Return(
784
+ new ArithmeticBinaryOperation(
785
+ "Plus",
786
+ new SymbolPrimitive("y"),
787
+ new NumberPrimitive(3)
788
+ )
789
+ ),
790
+ ])
791
+ ),
792
+ new Return(
793
+ new ArithmeticBinaryOperation(
794
+ "Plus",
795
+ new SymbolPrimitive("y"),
796
+ new NumberPrimitive(3)
797
+ )
798
+ )
799
+ ),
800
+ ]),
801
+ ]);
802
+ });
803
+ it("Lambda + currified Application", () => {
804
+ const lambda = new Lambda(
805
+ [
806
+ new VariablePattern(new SymbolPrimitive("x")),
807
+ new VariablePattern(new SymbolPrimitive("y")),
808
+ new VariablePattern(new SymbolPrimitive("z")),
809
+ ],
810
+ new ArithmeticBinaryOperation(
811
+ "Plus",
812
+ new ArithmeticBinaryOperation(
813
+ "Plus",
814
+ new SymbolPrimitive("x"),
815
+ new SymbolPrimitive("y")
816
+ ),
817
+ new SymbolPrimitive("z")
818
+ )
819
+ );
820
+ const app1 = new Application(lambda, new NumberPrimitive(1));
821
+ const app2 = new Application(app1, new NumberPrimitive(2));
822
+ const app3 = new Application(app2, new NumberPrimitive(3));
823
+ assert.equal(interpreter.evaluate(app3), 6);
824
+ });
825
+ it("Application of Function", () => {
826
+ const app1 = new Application(
827
+ new SymbolPrimitive("f"),
828
+ new NumberPrimitive(3)
829
+ );
830
+ assert.equal(interpreter.evaluate(app1), 6);
831
+ });
832
+ });
833
+ describe("Evaluates Composition", () => {
834
+ beforeEach(() => {
835
+ interpreter = new Interpreter(
836
+ [
837
+ new Function(new SymbolPrimitive("doble"), [
838
+ new Equation(
839
+ [new VariablePattern(new SymbolPrimitive("x"))],
840
+ new UnguardedBody(
841
+ new Sequence([
842
+ new Return(
843
+ new ArithmeticBinaryOperation(
844
+ "Multiply",
845
+ new SymbolPrimitive("x"),
846
+ new NumberPrimitive(2)
847
+ )
848
+ ),
849
+ ])
850
+ ),
851
+ new Return(
852
+ new ArithmeticBinaryOperation(
853
+ "Multiply",
854
+ new SymbolPrimitive("x"),
855
+ new NumberPrimitive(2)
856
+ )
857
+ )
858
+ ),
859
+ ]),
860
+ new Function(new SymbolPrimitive("cuadrado"), [
861
+ new Equation(
862
+ [new VariablePattern(new SymbolPrimitive("x"))],
863
+ new UnguardedBody(
864
+ new Sequence([
865
+ new Return(
866
+ new ArithmeticBinaryOperation(
867
+ "Power",
868
+ new SymbolPrimitive("x"),
869
+ new NumberPrimitive(2)
870
+ )
871
+ ),
872
+ ])
873
+ ),
874
+ new Return(
875
+ new ArithmeticBinaryOperation(
876
+ "Power",
877
+ new SymbolPrimitive("x"),
878
+ new NumberPrimitive(2)
879
+ )
880
+ )
881
+ ),
882
+ ]),
883
+ ],
884
+ { debug: true }
885
+ );
886
+ });
887
+ it("Composition (cuadrado . doble) 2 should be 16", () => {
888
+ const fog = new CompositionExpression(
889
+ new SymbolPrimitive("cuadrado"),
890
+ new SymbolPrimitive("doble")
891
+ );
892
+ const app = new Application(fog, new NumberPrimitive(2));
893
+ const res = interpreter.evaluate(app)
894
+ assert.equal(res, 16);
895
+ });
896
+ });
897
+ describe("Evaluates TypeCast", () => {
898
+ it("Type casting of number 2 to string should be '2'", () => {
899
+ const res = interpreter.evaluate(
900
+ new TypeCast(new NumberPrimitive(2), new SimpleType("String", [])),
901
+ );
902
+ assert.equal(res, "2");
903
+ });
904
+ });
905
+ describe("Evaluates Range Expression", () => {
906
+ it("Evaluates [1..5] to full range", () => {
907
+ const range = new RangeExpression(
908
+ new NumberPrimitive(1),
909
+ new NumberPrimitive(5)
910
+ );
911
+ assert.deepEqual(interpreter.evaluate(range), [1, 2, 3, 4, 5]);
912
+ });
913
+ it("Evaluates [0,0.5..2] to full range", () => {
914
+ const range = new RangeExpression(
915
+ new NumberPrimitive(0),
916
+ new NumberPrimitive(2),
917
+ new NumberPrimitive(0.5)
918
+ );
919
+ assert.deepEqual(interpreter.evaluate(range), [0, 0.5, 1, 1.5, 2]);
920
+ });
921
+ it("Evaluates [1..] lazily", () => {
922
+ interpreter = new Interpreter([], { lazyLoading: true });
923
+ const range = new RangeExpression(new NumberPrimitive(1));
924
+ const evaluatedList = interpreter.evaluate(range);
925
+ if (!isLazyList(evaluatedList))
926
+ assert.fail("Evaluated list should be LazyList");
927
+ const iter = evaluatedList.generator();
928
+ assert.equal(iter.next().value, 1);
929
+ assert.equal(iter.next().value, 2);
930
+ });
931
+ });
932
+
933
+ describe("Immutability Configuration", () => {
934
+ it("Should allow variable reassignment when mutability is enabled (default)", () => {
935
+ const ast = [
936
+ new Variable(new SymbolPrimitive("x"), new NumberPrimitive(5)),
937
+ new Assignment(new SymbolPrimitive("x"), new NumberPrimitive(10)),
938
+ ];
939
+ interpreter = new Interpreter(ast, { mutability: true });
940
+
941
+ // Should not throw
942
+ assert.doesNotThrow(() => {
943
+ interpreter.evaluate(new SymbolPrimitive("x"));
944
+ });
945
+ });
946
+
947
+ it("Should throw when attempting variable reassignment with mutability disabled", () => {
948
+ const ast = [
949
+ new Variable(new SymbolPrimitive("x"), new NumberPrimitive(5)),
950
+ ];
951
+ interpreter = new Interpreter(ast, { mutability: false });
952
+
953
+ // Attempting reassignment should throw
954
+ assert.throws(
955
+ () => {
956
+ interpreter.evaluate(
957
+ new Assignment(
958
+ new SymbolPrimitive("x"),
959
+ new NumberPrimitive(10)
960
+ )
961
+ );
962
+ },
963
+ /Cannot reassign variable 'x': mutability is disabled/
964
+ );
965
+ });
966
+
967
+ it("Should throw when attempting assignment operation with mutability disabled", () => {
968
+ const ast = [
969
+ new Variable(new SymbolPrimitive("x"), new NumberPrimitive(5)),
970
+ ];
971
+ interpreter = new Interpreter(ast, { mutability: false });
972
+
973
+ // Attempting assignment operation should throw
974
+ assert.throws(
975
+ () => {
976
+ interpreter.evaluate(
977
+ new AssignOperation(
978
+ "Assign",
979
+ new Variable(
980
+ new SymbolPrimitive("x"),
981
+ new NumberPrimitive(5)
982
+ ),
983
+ new NumberPrimitive(3)
984
+ )
985
+ );
986
+ },
987
+ /Cannot perform assignment operation: mutability is disabled/
988
+ );
989
+ });
990
+ });
991
+ });