yukigo 0.2.3 → 0.3.2

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 (266) hide show
  1. package/.mocharc.json +3 -3
  2. package/CHANGELOG.md +105 -40
  3. package/README.md +193 -193
  4. package/dist/analyzer/GraphBuilder.d.ts +1 -0
  5. package/dist/analyzer/GraphBuilder.js +2 -1
  6. package/dist/analyzer/index.d.ts +0 -7
  7. package/dist/analyzer/index.js +3 -3
  8. package/dist/analyzer/inspections/functional/functional.d.ts +1 -1
  9. package/dist/analyzer/inspections/functional/functional.js +1 -1
  10. package/dist/analyzer/inspections/functional/smells.d.ts +3 -3
  11. package/dist/analyzer/inspections/functional/smells.js +27 -35
  12. package/dist/analyzer/inspections/generic/generic.d.ts +22 -14
  13. package/dist/analyzer/inspections/generic/generic.js +82 -60
  14. package/dist/analyzer/inspections/generic/smells.d.ts +2 -0
  15. package/dist/analyzer/inspections/generic/smells.js +55 -64
  16. package/dist/analyzer/inspections/imperative/imperative.d.ts +3 -3
  17. package/dist/analyzer/inspections/imperative/imperative.js +3 -3
  18. package/dist/analyzer/inspections/imperative/smells.d.ts +1 -0
  19. package/dist/analyzer/inspections/imperative/smells.js +8 -5
  20. package/dist/analyzer/inspections/logic/logic.d.ts +8 -8
  21. package/dist/analyzer/inspections/logic/logic.js +5 -5
  22. package/dist/analyzer/inspections/logic/smells.js +2 -2
  23. package/dist/analyzer/inspections/object/object.d.ts +5 -5
  24. package/dist/analyzer/inspections/object/object.js +22 -21
  25. package/dist/analyzer/inspections/object/smells.js +11 -23
  26. package/dist/analyzer/utils.d.ts +6 -2
  27. package/dist/analyzer/utils.js +6 -2
  28. package/dist/interpreter/components/EnvBuilder.d.ts +20 -1
  29. package/dist/interpreter/components/EnvBuilder.js +211 -66
  30. package/dist/interpreter/components/EqualityComparer.d.ts +15 -0
  31. package/dist/interpreter/components/EqualityComparer.js +69 -0
  32. package/dist/interpreter/components/Operations.d.ts +17 -14
  33. package/dist/interpreter/components/Operations.js +61 -62
  34. package/dist/interpreter/components/PatternMatcher.d.ts +19 -58
  35. package/dist/interpreter/components/PatternMatcher.js +185 -286
  36. package/dist/interpreter/components/RuntimeContext.d.ts +24 -15
  37. package/dist/interpreter/components/RuntimeContext.js +43 -4
  38. package/dist/interpreter/components/TestRunner.d.ts +15 -13
  39. package/dist/interpreter/components/TestRunner.js +86 -53
  40. package/dist/interpreter/components/evaluators/BaseEvaluator.d.ts +19 -0
  41. package/dist/interpreter/components/evaluators/BaseEvaluator.js +20 -0
  42. package/dist/interpreter/components/evaluators/ExpressionEvaluator.d.ts +34 -0
  43. package/dist/interpreter/components/evaluators/ExpressionEvaluator.js +298 -0
  44. package/dist/interpreter/components/evaluators/OperationEvaluator.d.ts +25 -0
  45. package/dist/interpreter/components/evaluators/OperationEvaluator.js +226 -0
  46. package/dist/interpreter/components/evaluators/PrimitiveEvaluator.d.ts +19 -0
  47. package/dist/interpreter/components/evaluators/PrimitiveEvaluator.js +50 -0
  48. package/dist/interpreter/components/evaluators/StatementEvaluator.d.ts +28 -0
  49. package/dist/interpreter/components/evaluators/StatementEvaluator.js +240 -0
  50. package/dist/interpreter/components/evaluators/TestingEvaluator.d.ts +15 -0
  51. package/dist/interpreter/components/evaluators/TestingEvaluator.js +14 -0
  52. package/dist/interpreter/components/evaluators/index.d.ts +110 -0
  53. package/dist/interpreter/components/evaluators/index.js +21 -0
  54. package/dist/interpreter/components/evaluators/utils.d.ts +7 -0
  55. package/dist/interpreter/components/evaluators/utils.js +50 -0
  56. package/dist/interpreter/components/hooks/YukigoHook.d.ts +27 -0
  57. package/dist/interpreter/components/hooks/YukigoHook.js +1 -0
  58. package/dist/interpreter/components/kernel/commands.d.ts +122 -0
  59. package/dist/interpreter/components/kernel/commands.js +203 -0
  60. package/dist/interpreter/components/kernel/index.d.ts +51 -0
  61. package/dist/interpreter/components/kernel/index.js +176 -0
  62. package/dist/interpreter/components/logic/LogicEngine.d.ts +26 -23
  63. package/dist/interpreter/components/logic/LogicEngine.js +234 -221
  64. package/dist/interpreter/components/logic/LogicResolver.d.ts +22 -51
  65. package/dist/interpreter/components/logic/LogicResolver.js +73 -440
  66. package/dist/interpreter/components/logic/LogicTerm.d.ts +104 -0
  67. package/dist/interpreter/components/logic/LogicTerm.js +423 -0
  68. package/dist/interpreter/components/logic/LogicTranslator.d.ts +25 -9
  69. package/dist/interpreter/components/logic/LogicTranslator.js +211 -74
  70. package/dist/interpreter/components/runtimes/FunctionRuntime.d.ts +6 -4
  71. package/dist/interpreter/components/runtimes/FunctionRuntime.js +82 -84
  72. package/dist/interpreter/components/runtimes/LazyRuntime.d.ts +13 -14
  73. package/dist/interpreter/components/runtimes/LazyRuntime.js +112 -239
  74. package/dist/interpreter/components/runtimes/ObjectRuntime.d.ts +17 -14
  75. package/dist/interpreter/components/runtimes/ObjectRuntime.js +105 -74
  76. package/dist/interpreter/errors.d.ts +10 -0
  77. package/dist/interpreter/errors.js +17 -0
  78. package/dist/interpreter/index.d.ts +9 -5
  79. package/dist/interpreter/index.js +11 -13
  80. package/dist/interpreter/primitives/YuValue.d.ts +21 -0
  81. package/dist/interpreter/primitives/YuValue.js +40 -0
  82. package/dist/interpreter/primitives/capabilities.d.ts +90 -0
  83. package/dist/interpreter/primitives/capabilities.js +1 -0
  84. package/dist/interpreter/primitives/entities/LazyList.d.ts +48 -0
  85. package/dist/interpreter/primitives/entities/LazyList.js +164 -0
  86. package/dist/interpreter/primitives/entities/LogicResult.d.ts +51 -0
  87. package/dist/interpreter/primitives/entities/LogicResult.js +101 -0
  88. package/dist/interpreter/primitives/entities/RuntimeClass.d.ts +24 -0
  89. package/dist/interpreter/primitives/entities/RuntimeClass.js +57 -0
  90. package/dist/interpreter/primitives/entities/RuntimeFunction.d.ts +40 -0
  91. package/dist/interpreter/primitives/entities/RuntimeFunction.js +73 -0
  92. package/dist/interpreter/primitives/entities/RuntimeObject.d.ts +27 -0
  93. package/dist/interpreter/primitives/entities/RuntimeObject.js +82 -0
  94. package/dist/interpreter/primitives/entities/RuntimePredicate.d.ts +19 -0
  95. package/dist/interpreter/primitives/entities/RuntimePredicate.js +59 -0
  96. package/dist/interpreter/primitives/index.d.ts +14 -0
  97. package/dist/interpreter/primitives/index.js +14 -0
  98. package/dist/interpreter/primitives/scalars/YuBoolean.d.ts +24 -0
  99. package/dist/interpreter/primitives/scalars/YuBoolean.js +69 -0
  100. package/dist/interpreter/primitives/scalars/YuChar.d.ts +28 -0
  101. package/dist/interpreter/primitives/scalars/YuChar.js +78 -0
  102. package/dist/interpreter/primitives/scalars/YuNil.d.ts +25 -0
  103. package/dist/interpreter/primitives/scalars/YuNil.js +73 -0
  104. package/dist/interpreter/primitives/scalars/YuNumber.d.ts +49 -0
  105. package/dist/interpreter/primitives/scalars/YuNumber.js +165 -0
  106. package/dist/interpreter/primitives/sequences/YuArray.d.ts +33 -0
  107. package/dist/interpreter/primitives/sequences/YuArray.js +150 -0
  108. package/dist/interpreter/primitives/sequences/YuString.d.ts +40 -0
  109. package/dist/interpreter/primitives/sequences/YuString.js +130 -0
  110. package/dist/interpreter/utils.d.ts +23 -10
  111. package/dist/interpreter/utils.js +25 -30
  112. package/dist/tester/index.d.ts +3 -3
  113. package/dist/tester/index.js +39 -28
  114. package/dist/utils/helpers.d.ts +13 -5
  115. package/dist/utils/helpers.js +38 -85
  116. package/package.json +3 -16
  117. package/src/analyzer/GraphBuilder.ts +143 -142
  118. package/src/analyzer/index.ts +185 -194
  119. package/src/analyzer/inspections/functional/functional.ts +121 -121
  120. package/src/analyzer/inspections/functional/smells.ts +88 -102
  121. package/src/analyzer/inspections/generic/generic.ts +610 -577
  122. package/src/analyzer/inspections/generic/smells.ts +355 -365
  123. package/src/analyzer/inspections/imperative/imperative.ts +104 -101
  124. package/src/analyzer/inspections/imperative/smells.ts +58 -54
  125. package/src/analyzer/inspections/logic/logic.ts +84 -90
  126. package/src/analyzer/inspections/logic/smells.ts +54 -54
  127. package/src/analyzer/inspections/object/object.ts +295 -264
  128. package/src/analyzer/inspections/object/smells.ts +130 -144
  129. package/src/analyzer/utils.ts +115 -109
  130. package/src/index.ts +3 -3
  131. package/src/interpreter/components/EnvBuilder.ts +405 -202
  132. package/src/interpreter/components/EqualityComparer.ts +107 -0
  133. package/src/interpreter/components/Operations.ts +126 -99
  134. package/src/interpreter/components/PatternMatcher.ts +375 -475
  135. package/src/interpreter/components/RuntimeContext.ts +181 -119
  136. package/src/interpreter/components/TestRunner.ts +223 -151
  137. package/src/interpreter/components/evaluators/BaseEvaluator.ts +36 -0
  138. package/src/interpreter/components/evaluators/ExpressionEvaluator.ts +475 -0
  139. package/src/interpreter/components/evaluators/OperationEvaluator.ts +477 -0
  140. package/src/interpreter/components/evaluators/PrimitiveEvaluator.ts +80 -0
  141. package/src/interpreter/components/evaluators/StatementEvaluator.ts +372 -0
  142. package/src/interpreter/components/evaluators/TestingEvaluator.ts +26 -0
  143. package/src/interpreter/components/evaluators/index.ts +34 -0
  144. package/src/interpreter/components/evaluators/utils.ts +64 -0
  145. package/src/interpreter/components/hooks/YukigoHook.ts +45 -0
  146. package/src/interpreter/components/kernel/commands.ts +255 -0
  147. package/src/interpreter/components/kernel/index.ts +222 -0
  148. package/src/interpreter/components/logic/LogicEngine.ts +509 -519
  149. package/src/interpreter/components/logic/LogicResolver.ts +209 -858
  150. package/src/interpreter/components/logic/LogicTerm.ts +477 -0
  151. package/src/interpreter/components/logic/LogicTranslator.ts +362 -149
  152. package/src/interpreter/components/runtimes/FunctionRuntime.ts +249 -227
  153. package/src/interpreter/components/runtimes/LazyRuntime.ts +226 -334
  154. package/src/interpreter/components/runtimes/ObjectRuntime.ts +262 -224
  155. package/src/interpreter/errors.ts +68 -47
  156. package/src/interpreter/index.ts +50 -52
  157. package/src/interpreter/primitives/YuValue.ts +64 -0
  158. package/src/interpreter/primitives/capabilities.ts +111 -0
  159. package/src/interpreter/primitives/entities/LazyList.ts +225 -0
  160. package/src/interpreter/primitives/entities/LogicResult.ts +133 -0
  161. package/src/interpreter/primitives/entities/RuntimeClass.ts +70 -0
  162. package/src/interpreter/primitives/entities/RuntimeFunction.ts +108 -0
  163. package/src/interpreter/primitives/entities/RuntimeObject.ts +110 -0
  164. package/src/interpreter/primitives/entities/RuntimePredicate.ts +77 -0
  165. package/src/interpreter/primitives/index.ts +17 -0
  166. package/src/interpreter/primitives/scalars/YuBoolean.ts +79 -0
  167. package/src/interpreter/primitives/scalars/YuChar.ts +94 -0
  168. package/src/interpreter/primitives/scalars/YuNil.ts +84 -0
  169. package/src/interpreter/primitives/scalars/YuNumber.ts +187 -0
  170. package/src/interpreter/primitives/sequences/YuArray.ts +178 -0
  171. package/src/interpreter/primitives/sequences/YuString.ts +165 -0
  172. package/src/interpreter/utils.ts +105 -84
  173. package/src/tester/index.ts +157 -128
  174. package/src/utils/helpers.ts +113 -169
  175. package/tests/analyzer/functional.spec.ts +221 -207
  176. package/tests/analyzer/generic.spec.ts +178 -178
  177. package/tests/analyzer/helpers.spec.ts +83 -89
  178. package/tests/analyzer/logic.spec.ts +237 -237
  179. package/tests/analyzer/oop.spec.ts +320 -323
  180. package/tests/analyzer/transitive.spec.ts +166 -166
  181. package/tests/interpreter/EnvBuilder.spec.ts +181 -183
  182. package/tests/interpreter/FunctionRuntime.spec.ts +224 -223
  183. package/tests/interpreter/LazyRuntime.spec.ts +227 -225
  184. package/tests/interpreter/LogicEngine.spec.ts +371 -327
  185. package/tests/interpreter/LogicSubstitution.spec.ts +90 -80
  186. package/tests/interpreter/ObjectRuntime.spec.ts +431 -606
  187. package/tests/interpreter/Operations.spec.ts +312 -220
  188. package/tests/interpreter/PatternSystem.spec.ts +254 -213
  189. package/tests/interpreter/Tests.spec.ts +122 -122
  190. package/tests/interpreter/interpreter.spec.ts +1143 -991
  191. package/tests/kernel/YukigoKernel.spec.ts +112 -0
  192. package/tests/tester/Tester.spec.ts +156 -152
  193. package/tsconfig.build.json +16 -15
  194. package/tsconfig.json +27 -25
  195. package/dist/interpreter/components/Visitor.d.ts +0 -70
  196. package/dist/interpreter/components/Visitor.js +0 -634
  197. package/dist/interpreter/entities.d.ts +0 -105
  198. package/dist/interpreter/entities.js +0 -96
  199. package/dist/interpreter/trampoline.d.ts +0 -17
  200. package/dist/interpreter/trampoline.js +0 -38
  201. package/dist/src/analyzer/GraphBuilder.d.ts +0 -30
  202. package/dist/src/analyzer/GraphBuilder.js +0 -100
  203. package/dist/src/analyzer/index.d.ts +0 -59
  204. package/dist/src/analyzer/index.js +0 -152
  205. package/dist/src/analyzer/inspections/functional/functional.d.ts +0 -44
  206. package/dist/src/analyzer/inspections/functional/functional.js +0 -149
  207. package/dist/src/analyzer/inspections/functional/smells.d.ts +0 -16
  208. package/dist/src/analyzer/inspections/functional/smells.js +0 -98
  209. package/dist/src/analyzer/inspections/generic/generic.d.ts +0 -178
  210. package/dist/src/analyzer/inspections/generic/generic.js +0 -604
  211. package/dist/src/analyzer/inspections/generic/smells.d.ts +0 -61
  212. package/dist/src/analyzer/inspections/generic/smells.js +0 -349
  213. package/dist/src/analyzer/inspections/imperative/imperative.d.ts +0 -35
  214. package/dist/src/analyzer/inspections/imperative/imperative.js +0 -109
  215. package/dist/src/analyzer/inspections/imperative/smells.d.ts +0 -16
  216. package/dist/src/analyzer/inspections/imperative/smells.js +0 -58
  217. package/dist/src/analyzer/inspections/logic/logic.d.ts +0 -32
  218. package/dist/src/analyzer/inspections/logic/logic.js +0 -96
  219. package/dist/src/analyzer/inspections/logic/smells.d.ts +0 -15
  220. package/dist/src/analyzer/inspections/logic/smells.js +0 -60
  221. package/dist/src/analyzer/inspections/object/object.d.ts +0 -90
  222. package/dist/src/analyzer/inspections/object/object.js +0 -321
  223. package/dist/src/analyzer/inspections/object/smells.d.ts +0 -30
  224. package/dist/src/analyzer/inspections/object/smells.js +0 -135
  225. package/dist/src/analyzer/utils.d.ts +0 -30
  226. package/dist/src/analyzer/utils.js +0 -78
  227. package/dist/src/index.d.ts +0 -4
  228. package/dist/src/index.js +0 -4
  229. package/dist/src/interpreter/components/EnvBuilder.d.ts +0 -21
  230. package/dist/src/interpreter/components/EnvBuilder.js +0 -155
  231. package/dist/src/interpreter/components/Operations.d.ts +0 -14
  232. package/dist/src/interpreter/components/Operations.js +0 -84
  233. package/dist/src/interpreter/components/PatternMatcher.d.ts +0 -73
  234. package/dist/src/interpreter/components/PatternMatcher.js +0 -358
  235. package/dist/src/interpreter/components/RuntimeContext.d.ts +0 -35
  236. package/dist/src/interpreter/components/RuntimeContext.js +0 -93
  237. package/dist/src/interpreter/components/TestRunner.d.ts +0 -19
  238. package/dist/src/interpreter/components/TestRunner.js +0 -110
  239. package/dist/src/interpreter/components/Visitor.d.ts +0 -71
  240. package/dist/src/interpreter/components/Visitor.js +0 -638
  241. package/dist/src/interpreter/components/logic/LogicEngine.d.ts +0 -29
  242. package/dist/src/interpreter/components/logic/LogicEngine.js +0 -259
  243. package/dist/src/interpreter/components/logic/LogicResolver.d.ts +0 -53
  244. package/dist/src/interpreter/components/logic/LogicResolver.js +0 -484
  245. package/dist/src/interpreter/components/logic/LogicTranslator.d.ts +0 -14
  246. package/dist/src/interpreter/components/logic/LogicTranslator.js +0 -99
  247. package/dist/src/interpreter/components/runtimes/FunctionRuntime.d.ts +0 -12
  248. package/dist/src/interpreter/components/runtimes/FunctionRuntime.js +0 -149
  249. package/dist/src/interpreter/components/runtimes/LazyRuntime.d.ts +0 -19
  250. package/dist/src/interpreter/components/runtimes/LazyRuntime.js +0 -269
  251. package/dist/src/interpreter/components/runtimes/ObjectRuntime.d.ts +0 -35
  252. package/dist/src/interpreter/components/runtimes/ObjectRuntime.js +0 -126
  253. package/dist/src/interpreter/errors.d.ts +0 -19
  254. package/dist/src/interpreter/errors.js +0 -36
  255. package/dist/src/interpreter/index.d.ts +0 -24
  256. package/dist/src/interpreter/index.js +0 -41
  257. package/dist/src/interpreter/trampoline.d.ts +0 -17
  258. package/dist/src/interpreter/trampoline.js +0 -38
  259. package/dist/src/interpreter/utils.d.ts +0 -11
  260. package/dist/src/interpreter/utils.js +0 -65
  261. package/dist/src/tester/index.d.ts +0 -25
  262. package/dist/src/tester/index.js +0 -113
  263. package/dist/src/utils/helpers.d.ts +0 -13
  264. package/dist/src/utils/helpers.js +0 -52
  265. package/src/interpreter/components/Visitor.ts +0 -1065
  266. package/src/interpreter/trampoline.ts +0 -71
@@ -0,0 +1,475 @@
1
+ import {
2
+ Application,
3
+ Call,
4
+ CompositionExpression,
5
+ ConsExpression,
6
+ DataExpression,
7
+ Exist,
8
+ ExpressionVisitor,
9
+ FieldExpression,
10
+ Findall,
11
+ Forall,
12
+ Goal,
13
+ GuardedExpression,
14
+ Lambda,
15
+ LetInExpression,
16
+ ListComprehension,
17
+ NamedArgument,
18
+ New,
19
+ Not,
20
+ Generator as YuGenerator,
21
+ Otherwise,
22
+ RangeExpression,
23
+ Send,
24
+ SymbolPrimitive,
25
+ TupleExpression,
26
+ Expression,
27
+ Return,
28
+ Sequence,
29
+ Super,
30
+ UnguardedBody,
31
+ VariablePattern,
32
+ TypeCast,
33
+ } from "yukigo-ast";
34
+ import {
35
+ BindCommand,
36
+ ExecutionCommand,
37
+ FailCommand,
38
+ RaiseCommand,
39
+ StepCommand,
40
+ } from "../kernel/commands.js";
41
+ import { Constructor, EvaluatorBase } from "./BaseEvaluator.js";
42
+ import { InterpreterError } from "../../errors.js";
43
+ import {
44
+ YuArray,
45
+ YuValue,
46
+ EquationRuntime,
47
+ RuntimeClass,
48
+ RuntimeFunction,
49
+ } from "../../primitives/index.js";
50
+ import { boolean, EnvStack, error, isTrue, raise } from "../../utils.js";
51
+ import { EnvBuilderVisitor } from "../EnvBuilder.js";
52
+ import {
53
+ getClassFields,
54
+ getClassInitializers,
55
+ getLogicEngine,
56
+ } from "./utils.js";
57
+
58
+ export function ExpressionEvaluator<TBase extends Constructor<EvaluatorBase>>(
59
+ Base: TBase,
60
+ ) {
61
+ return class
62
+ extends Base
63
+ implements Partial<ExpressionVisitor<ExecutionCommand>>
64
+ {
65
+ visitTupleExpr(node: TupleExpression): ExecutionCommand {
66
+ const results: YuValue[] = [];
67
+ const evaluateNext = (index: number): ExecutionCommand => {
68
+ if (index >= node.elements.length)
69
+ return new StepCommand(new YuArray(results));
70
+ return new BindCommand(this.evaluate(node.elements[index]), (val) => {
71
+ results.push(val);
72
+ return evaluateNext(index + 1);
73
+ });
74
+ };
75
+ return evaluateNext(0);
76
+ }
77
+ visitFieldExpression(node: FieldExpression): ExecutionCommand {
78
+ return new BindCommand(this.evaluate(node.name), (obj) => {
79
+ return new StepCommand(
80
+ this.context.objRuntime.getField(obj, node.name.value),
81
+ );
82
+ });
83
+ }
84
+ visitDataExpr(node: DataExpression): ExecutionCommand {
85
+ const fieldValues = new Map<string, YuValue>();
86
+
87
+ const evaluateFields = (index: number): ExecutionCommand => {
88
+ if (index >= node.contents.length) {
89
+ const identifier = node.name.value;
90
+ const classDef = new RuntimeClass(
91
+ identifier,
92
+ fieldValues,
93
+ new Map(),
94
+ [],
95
+ );
96
+ return new StepCommand(classDef.instantiate(identifier));
97
+ }
98
+ const field = node.contents[index];
99
+ return new BindCommand(this.evaluate(field.expression), (value) => {
100
+ fieldValues.set(field.name.value, value);
101
+ return evaluateFields(index + 1);
102
+ });
103
+ };
104
+
105
+ return evaluateFields(0);
106
+ }
107
+ visitConsExpr(node: ConsExpression): ExecutionCommand {
108
+ return this.context.lazyRuntime.evaluateCons(node, this);
109
+ }
110
+ visitLetInExpr(node: LetInExpression): ExecutionCommand {
111
+ const oldEnv = this.context.env;
112
+ this.context.pushEnv();
113
+ const envBuilder = new EnvBuilderVisitor(this.context);
114
+ node.declarations.accept(envBuilder);
115
+ return new BindCommand(this.evaluate(node.expression), (result) => {
116
+ this.context.env = oldEnv;
117
+ return new StepCommand(result);
118
+ });
119
+ }
120
+ visitCall(node: Call): ExecutionCommand {
121
+ return new BindCommand(this.evaluate(node.callee), (callee) => {
122
+ const args: YuValue[] = [];
123
+ const evaluateArgs = (index: number): ExecutionCommand => {
124
+ if (index < node.args.length)
125
+ return new BindCommand(this.evaluate(node.args[index]), (val) => {
126
+ args.push(val);
127
+ return evaluateArgs(index + 1);
128
+ });
129
+
130
+ if (!(callee instanceof RuntimeFunction))
131
+ return new FailCommand(
132
+ new InterpreterError("Call", "Target is not a function"),
133
+ );
134
+
135
+ return this.context.funcRuntime.apply(callee, args);
136
+ };
137
+ return evaluateArgs(0);
138
+ });
139
+ }
140
+ visitOtherwise(node: Otherwise): ExecutionCommand {
141
+ return boolean(true);
142
+ }
143
+ visitCompositionExpression(node: CompositionExpression): ExecutionCommand {
144
+ return new BindCommand(this.evaluate(node.left), (f) => {
145
+ return new BindCommand(this.evaluate(node.right), (g) => {
146
+ if (
147
+ !(f instanceof RuntimeFunction) ||
148
+ !(g instanceof RuntimeFunction)
149
+ ) {
150
+ return new FailCommand(
151
+ new InterpreterError(
152
+ "Composition",
153
+ "Both operands of (.) must be functions",
154
+ ),
155
+ );
156
+ }
157
+
158
+ const F_REF = "__internal_f";
159
+ const G_REF = "__internal_g";
160
+ const PARAM_NAME = "__x";
161
+
162
+ const compositionBody = new Application(
163
+ new SymbolPrimitive(F_REF),
164
+ new Application(
165
+ new SymbolPrimitive(G_REF),
166
+ new SymbolPrimitive(PARAM_NAME),
167
+ ),
168
+ );
169
+
170
+ const patterns = [
171
+ new VariablePattern(new SymbolPrimitive(PARAM_NAME)),
172
+ ];
173
+ const equation: EquationRuntime = {
174
+ patterns,
175
+ body: new UnguardedBody(
176
+ new Sequence([new Return(compositionBody)]),
177
+ ),
178
+ };
179
+
180
+ const privateScope = new Map<string, YuValue>();
181
+ privateScope.set(F_REF, f);
182
+ privateScope.set(G_REF, g);
183
+
184
+ const capturedEnv: EnvStack = {
185
+ head: privateScope,
186
+ tail: this.context.env,
187
+ };
188
+ const func = new RuntimeFunction(
189
+ 1,
190
+ [equation],
191
+ `<(${f.identifier} . ${g.identifier})>`,
192
+ [],
193
+ capturedEnv,
194
+ );
195
+ return new StepCommand(func);
196
+ });
197
+ });
198
+ }
199
+
200
+ visitLambda(node: Lambda): ExecutionCommand {
201
+ const patterns = node.parameters;
202
+ const equation: EquationRuntime = {
203
+ patterns,
204
+ body: new UnguardedBody(new Sequence([new Return(node.body)])),
205
+ };
206
+ const func = new RuntimeFunction(
207
+ patterns.length,
208
+ [equation],
209
+ "<lambda>",
210
+ [],
211
+ this.context.env,
212
+ );
213
+ return new StepCommand(func);
214
+ }
215
+ public visitGuardedExpression(expr: GuardedExpression): ExecutionCommand {
216
+ const tryNextGuard = (guardIndex: number): ExecutionCommand => {
217
+ if (guardIndex >= expr.guards.length) {
218
+ return new RaiseCommand(
219
+ new InterpreterError(
220
+ "PatternMatch",
221
+ "Non-exhaustive guards in equation: the pattern matched but no guard succeeded.",
222
+ ),
223
+ );
224
+ }
225
+
226
+ const guard = expr.guards[guardIndex];
227
+ return new BindCommand(this.evaluate(guard.condition), (cond) => {
228
+ if (!isTrue(cond)) return tryNextGuard(guardIndex + 1);
229
+ return this.evaluate(guard.body);
230
+ });
231
+ };
232
+
233
+ return tryNextGuard(0);
234
+ }
235
+ visitApplication(node: Application): ExecutionCommand {
236
+ const { funcRuntime } = this.context;
237
+ return new BindCommand(this.evaluate(node.functionExpr), (func) => {
238
+ if (!(func instanceof RuntimeFunction)) {
239
+ return new FailCommand(
240
+ new InterpreterError("Application", "Cannot apply non-function"),
241
+ );
242
+ }
243
+
244
+ const applyFuncToNode = (func: RuntimeFunction): ExecutionCommand =>
245
+ new BindCommand(this.evaluate(node.parameter), (arg) => {
246
+ return funcRuntime.applyArguments(func, [() => arg]);
247
+ });
248
+
249
+ if (func.arity === 0) {
250
+ return new BindCommand(
251
+ funcRuntime.applyArguments(func),
252
+ (resultOfFunc) => {
253
+ if (!(resultOfFunc instanceof RuntimeFunction))
254
+ return new FailCommand(
255
+ new InterpreterError(
256
+ "Application",
257
+ "Cannot apply non-function result of arity-0 function",
258
+ ),
259
+ );
260
+ return applyFuncToNode(resultOfFunc);
261
+ },
262
+ );
263
+ }
264
+
265
+ return applyFuncToNode(func);
266
+ });
267
+ }
268
+ visitExist(node: Exist): ExecutionCommand {
269
+ return getLogicEngine(this, this.context).solveGoalLike(node);
270
+ }
271
+
272
+ visitNot(node: Not): ExecutionCommand {
273
+ return getLogicEngine(this, this.context).solveNot(node);
274
+ }
275
+ visitFindall(node: Findall): ExecutionCommand {
276
+ return getLogicEngine(this, this.context).solveFindall(node);
277
+ }
278
+ visitForall(node: Forall): ExecutionCommand {
279
+ return getLogicEngine(this, this.context).solveForall(node);
280
+ }
281
+
282
+ visitGoal(node: Goal): ExecutionCommand {
283
+ return getLogicEngine(this, this.context).solveGoalLike(node);
284
+ }
285
+ visitSend(node: Send): ExecutionCommand {
286
+ if (node.receiver instanceof Super) {
287
+ const methodName = node.selector.value;
288
+ const args: YuValue[] = [];
289
+ const evaluateNextArg = (index: number): ExecutionCommand => {
290
+ if (index >= node.args.length) {
291
+ try {
292
+ return this.context.objRuntime.dispatchSuper(methodName, args);
293
+ } catch (error: any) {
294
+ if (error instanceof InterpreterError) {
295
+ const mappedErrors = this.context.dispatchHook(
296
+ "onInterpreterError",
297
+ error,
298
+ this.context,
299
+ );
300
+ const userException = mappedErrors.find(
301
+ (res: any) => res !== undefined && res !== null,
302
+ );
303
+ return new RaiseCommand((userException as any) || error);
304
+ }
305
+ return new RaiseCommand(
306
+ new InterpreterError("RuntimeError", String(error)),
307
+ );
308
+ }
309
+ }
310
+ return new BindCommand(this.evaluate(node.args[index]), (val) => {
311
+ args.push(val);
312
+ return evaluateNextArg(index + 1);
313
+ });
314
+ };
315
+ return evaluateNextArg(0);
316
+ }
317
+
318
+ return new BindCommand(this.evaluate(node.receiver), (receiver) => {
319
+ const methodName = node.selector.value;
320
+ const args: YuValue[] = [];
321
+ const evaluateNextArg = (index: number): ExecutionCommand => {
322
+ if (index >= node.args.length) {
323
+ try {
324
+ return this.context.objRuntime.dispatch(
325
+ receiver,
326
+ methodName,
327
+ args,
328
+ );
329
+ } catch (error: any) {
330
+ if (error instanceof InterpreterError) {
331
+ const mappedErrors = this.context.dispatchHook(
332
+ "onInterpreterError",
333
+ error,
334
+ this.context,
335
+ );
336
+ const userException = mappedErrors.find(
337
+ (res) => res !== undefined && res !== null,
338
+ );
339
+ return new RaiseCommand((userException as any) || error);
340
+ }
341
+ return new RaiseCommand(
342
+ new InterpreterError("RuntimeError", String(error)),
343
+ );
344
+ }
345
+ }
346
+ return new BindCommand(this.evaluate(node.args[index]), (val) => {
347
+ args.push(val);
348
+ return evaluateNextArg(index + 1);
349
+ });
350
+ };
351
+ return evaluateNextArg(0);
352
+ });
353
+ }
354
+
355
+ visitNew(node: New): ExecutionCommand {
356
+ const className = node.identifier.value;
357
+ const classDef = this.context.lookup(className);
358
+ if (!(classDef instanceof RuntimeClass))
359
+ return new FailCommand(
360
+ new InterpreterError("New", `${className} is not a class.`),
361
+ );
362
+
363
+ const instance = classDef.instantiate(node.identifier.value);
364
+ instance.fields = getClassFields(classDef, this.context);
365
+
366
+ const evaluateArgs = (index: number): ExecutionCommand => {
367
+ if (index >= node.args.length) {
368
+ return new StepCommand(instance);
369
+ }
370
+ const arg = node.args[index];
371
+ if (
372
+ arg instanceof NamedArgument ||
373
+ arg.constructor.name === "NamedArgument"
374
+ ) {
375
+ const fieldName = (arg as any).identifier.value;
376
+ return new BindCommand(
377
+ this.evaluate((arg as any).expression),
378
+ (val) => {
379
+ instance.setField(fieldName, val);
380
+ return evaluateArgs(index + 1);
381
+ },
382
+ );
383
+ }
384
+ return evaluateArgs(index + 1);
385
+ };
386
+
387
+ const initializers = getClassInitializers(classDef, this.context);
388
+ const initializerKeys = Array.from(initializers.keys());
389
+
390
+ const evaluateInitializers = (keyIndex: number): ExecutionCommand => {
391
+ if (keyIndex >= initializerKeys.length) {
392
+ return evaluateArgs(0);
393
+ }
394
+ const key = initializerKeys[keyIndex];
395
+ const expr = initializers.get(key);
396
+ return new BindCommand(this.evaluate(expr), (val) => {
397
+ instance.setField(key, val);
398
+ return evaluateInitializers(keyIndex + 1);
399
+ });
400
+ };
401
+
402
+ return evaluateInitializers(0);
403
+ }
404
+
405
+ visitListComprehension(node: ListComprehension): ExecutionCommand {
406
+ const results: YuValue[] = [];
407
+
408
+ const process = (index: number): ExecutionCommand => {
409
+ if (index >= node.generators.length) {
410
+ return new BindCommand(this.evaluate(node.projection), (proj) => {
411
+ results.push(proj);
412
+ return new StepCommand(new YuArray(results));
413
+ });
414
+ }
415
+
416
+ const current = node.generators[index];
417
+
418
+ if (current instanceof YuGenerator) {
419
+ return new BindCommand(
420
+ this.evaluate(current.expression),
421
+ (exprResult) => {
422
+ return new BindCommand(
423
+ this.context.lazyRuntime.realizeList(exprResult),
424
+ (sourceListVal) => {
425
+ const sourceList = sourceListVal.asSequence;
426
+ if (!(sourceList instanceof YuArray))
427
+ return raise(
428
+ error(
429
+ "visitListComprehension",
430
+ `Error expected YuArray and got ${sourceListVal.getType()}`,
431
+ ),
432
+ );
433
+ const iterateSource = (
434
+ sourceIndex: number,
435
+ ): ExecutionCommand => {
436
+ if (sourceIndex >= sourceList.items.length)
437
+ return new StepCommand(new YuArray(results));
438
+
439
+ const item = sourceList.at(sourceIndex);
440
+ const varName = current.variable.value;
441
+ this.context.define(varName, item);
442
+
443
+ return process(index + 1);
444
+ };
445
+ return iterateSource(0);
446
+ },
447
+ );
448
+ },
449
+ );
450
+ } else {
451
+ return new BindCommand(
452
+ this.evaluate(current as Expression),
453
+ (condition) => {
454
+ return isTrue(condition)
455
+ ? process(index + 1)
456
+ : new StepCommand(new YuArray(results));
457
+ },
458
+ );
459
+ }
460
+ };
461
+
462
+ this.context.pushEnv();
463
+ return process(0);
464
+ }
465
+ visitGenerator(node: YuGenerator): ExecutionCommand {
466
+ return this.evaluate(node.expression);
467
+ }
468
+ visitRangeExpression(node: RangeExpression): ExecutionCommand {
469
+ return this.context.lazyRuntime.evaluateRange(node, this);
470
+ }
471
+ visitTypeCast(node: TypeCast): ExecutionCommand {
472
+ return node.expression.accept(this);
473
+ }
474
+ };
475
+ }