yukigo 0.2.2 → 0.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.
Files changed (266) hide show
  1. package/.mocharc.json +3 -3
  2. package/CHANGELOG.md +102 -41
  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 +21 -14
  13. package/dist/analyzer/inspections/generic/generic.js +78 -59
  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 +12 -5
  115. package/dist/utils/helpers.js +6 -79
  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 -581
  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 +81 -168
  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 +188 -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
@@ -1,183 +1,181 @@
1
- import { expect } from "chai";
2
- import {
3
- Function as AstFunction,
4
- Fact,
5
- Rule,
6
- SymbolPrimitive,
7
- Equation,
8
- EnvStack,
9
- RuntimeFunction,
10
- RuntimePredicate,
11
- Function,
12
- AST,
13
- } from "yukigo-ast";
14
- import { EnvBuilderVisitor } from "../../src/interpreter/components/EnvBuilder.js";
15
- import { RuntimeContext } from "../../src/interpreter/components/RuntimeContext.js";
16
-
17
- const id = (val: string) => ({ value: val }) as SymbolPrimitive;
18
-
19
- const makeEq = (arity: number): Equation =>
20
- ({
21
- patterns: new Array(arity).fill({ type: "MockPattern" }),
22
- body: { type: "MockBody" } as any,
23
- }) as any;
24
-
25
- const makeFunc = (
26
- name: string,
27
- arity: number,
28
- eqCount: number = 1,
29
- ): AstFunction => new Function(id(name), Array(eqCount).fill(makeEq(arity)));
30
-
31
- const makeFact = (name: string): Fact => {
32
- const node = {
33
- type: "Fact",
34
- identifier: id(name),
35
- patterns: [],
36
- } as any;
37
- node.accept = (v: any) => v.visitFact(node);
38
- return node;
39
- };
40
-
41
- const makeRule = (name: string): Rule => {
42
- const node = {
43
- type: "Rule",
44
- identifier: id(name),
45
- patterns: [],
46
- expressions: [],
47
- } as any;
48
- node.accept = (v: any) => v.visitRule(node);
49
- return node;
50
- };
51
-
52
- describe("EnvBuilderVisitor", () => {
53
- let ctx: RuntimeContext;
54
- let visitor: EnvBuilderVisitor;
55
- let env: EnvStack;
56
-
57
- beforeEach(() => {
58
- ctx = new RuntimeContext();
59
- visitor = new EnvBuilderVisitor(ctx);
60
- env = ctx.env;
61
- });
62
-
63
- describe("Function Declarations", () => {
64
- it("should register a valid function", () => {
65
- const funcNode = makeFunc("myFunc", 1);
66
-
67
- visitor.visitFunction(funcNode);
68
-
69
- expect(ctx.isDefined("myFunc")).to.be.true;
70
- const entry = ctx.lookup("myFunc") as RuntimeFunction;
71
-
72
- expect(entry).to.have.property("identifier", "myFunc");
73
- expect(entry).to.have.property("arity", 1);
74
- expect(entry.equations).to.have.lengthOf(1);
75
- });
76
-
77
- it("should register a function with multiple equations", () => {
78
- const funcNode = makeFunc("fib", 1, 2);
79
-
80
- visitor.visitFunction(funcNode);
81
-
82
- const entry = ctx.lookup("fib") as RuntimeFunction;
83
- expect(entry.equations).to.have.lengthOf(2);
84
- });
85
-
86
- it("should throw error if function has no equations", () => {
87
- const funcNode = makeFunc("empty", 0, 0);
88
-
89
- expect(() => visitor.visitFunction(funcNode)).to.throw(
90
- /has no equations/,
91
- );
92
- });
93
-
94
- it("should throw error if equations have different arity", () => {
95
- const funcNode = makeFunc("badFunc", 1);
96
- funcNode.equations.push(makeEq(2));
97
-
98
- expect(() => visitor.visitFunction(funcNode)).to.throw(
99
- /must have the same arity/,
100
- );
101
- });
102
- });
103
-
104
- describe("Logic Programming (Facts)", () => {
105
- it("should register a new Fact", () => {
106
- const factNode = makeFact("parent");
107
-
108
- visitor.visitFact(factNode);
109
-
110
- expect(ctx.isDefined("parent")).to.be.true;
111
- const entry = ctx.lookup("parent") as RuntimePredicate;
112
- expect(entry).to.have.property("kind", "Predicate");
113
- expect(entry.equations).to.have.lengthOf(1);
114
- expect(entry.equations[0]).to.equal(factNode);
115
- });
116
-
117
- it("should append to existing Fact if identifier exists", () => {
118
- const f1 = makeFact("parent");
119
- const f2 = makeFact("parent");
120
-
121
- visitor.visitFact(f1);
122
- visitor.visitFact(f2);
123
-
124
- const entry = ctx.lookup("parent") as RuntimePredicate;
125
- expect(entry.kind).to.equal("Predicate");
126
- expect(entry.equations).to.have.lengthOf(2);
127
- expect(entry.equations[0]).to.equal(f1);
128
- expect(entry.equations[1]).to.equal(f2);
129
- });
130
-
131
- it("should overwrite existing entry if it is not a Fact", () => {
132
- ctx.define("test", { type: "SomethingElse", equations: [] } as any);
133
- const factNode = makeFact("test");
134
- visitor.visitFact(factNode);
135
-
136
- const entry = ctx.lookup("test") as RuntimePredicate;
137
- expect(entry.kind).to.equal("Predicate");
138
- expect(entry.equations).to.have.lengthOf(1);
139
- expect(entry.equations[0]).to.equal(factNode);
140
- });
141
- });
142
-
143
- describe("Logic Programming (Rules)", () => {
144
- it("should register a new Rule", () => {
145
- const ruleNode = makeRule("grandparent");
146
-
147
- visitor.visitRule(ruleNode);
148
-
149
- expect(ctx.isDefined("grandparent")).to.be.true;
150
- const entry = ctx.lookup("grandparent") as RuntimePredicate;
151
- expect(entry).to.have.property("kind", "Predicate");
152
- expect(entry.equations).to.have.lengthOf(1);
153
- expect(entry.equations[0]).to.equal(ruleNode);
154
- });
155
-
156
- it("should append to existing Rule group", () => {
157
- const r1 = makeRule("ancestor");
158
- const r2 = makeRule("ancestor");
159
-
160
- visitor.visitRule(r1);
161
- visitor.visitRule(r2);
162
-
163
- const entry = ctx.lookup("ancestor") as RuntimePredicate;
164
- expect(entry.kind).to.equal("Predicate");
165
- expect(entry.equations).to.have.lengthOf(2);
166
- expect(entry.equations[0]).to.equal(r1);
167
- expect(entry.equations[1]).to.equal(r2);
168
- });
169
- });
170
-
171
- it("should traverse the AST and build the complete environment", () => {
172
- const nodes: AST = [
173
- makeFunc("add", 2),
174
- makeFact("is_human"),
175
- makeRule("is_mortal"),
176
- ];
177
-
178
- visitor.build(nodes);
179
- expect(ctx.isDefined("add")).to.be.true;
180
- expect(ctx.isDefined("is_human")).to.be.true;
181
- expect(ctx.isDefined("is_mortal")).to.be.true;
182
- });
183
- });
1
+ import { expect } from "chai";
2
+ import {
3
+ Fact,
4
+ Rule,
5
+ SymbolPrimitive,
6
+ Equation,
7
+ Function as AstFunction,
8
+ AST,
9
+ UnguardedBody,
10
+ Sequence,
11
+ } from "yukigo-ast";
12
+ import { EnvBuilderVisitor } from "../../src/interpreter/components/EnvBuilder.js";
13
+ import { RuntimeContext } from "../../src/interpreter/components/RuntimeContext.js";
14
+ import { RuntimeFunction, RuntimePredicate } from "../../src/interpreter/primitives/index.js";
15
+
16
+ const id = (val: string) => new SymbolPrimitive(val);
17
+
18
+ const makeEq = (arity: number): Equation =>
19
+ new Equation(
20
+ new Array(arity).fill({ type: "MockPattern", accept: () => {} } as any),
21
+ new UnguardedBody(new Sequence([])),
22
+ );
23
+
24
+ const makeFunc = (
25
+ name: string,
26
+ arity: number,
27
+ eqCount: number = 1,
28
+ ): AstFunction =>
29
+ new AstFunction(id(name), Array(eqCount).fill(null).map(() => makeEq(arity)));
30
+
31
+ const makeFact = (name: string, arity: number = 0): Fact => {
32
+ return new Fact(
33
+ id(name),
34
+ new Array(arity).fill({ type: "MockPattern", accept: () => {} } as any),
35
+ );
36
+ };
37
+
38
+ const makeRule = (name: string, arity: number = 0): Rule => {
39
+ return new Rule(id(name), [makeEq(arity)]);
40
+ };
41
+
42
+ describe("EnvBuilderVisitor", () => {
43
+ let ctx: RuntimeContext;
44
+ let visitor: EnvBuilderVisitor;
45
+
46
+ beforeEach(() => {
47
+ ctx = new RuntimeContext();
48
+ visitor = new EnvBuilderVisitor(ctx);
49
+ });
50
+
51
+ describe("Function Declarations", () => {
52
+ it("should register a valid function", () => {
53
+ const funcNode = makeFunc("myFunc", 1);
54
+
55
+ visitor.visitFunction(funcNode);
56
+
57
+ expect(ctx.isDefined("myFunc")).to.be.true;
58
+ const entry = ctx.lookup("myFunc") as RuntimeFunction;
59
+
60
+ expect(entry).to.have.property("identifier", "myFunc");
61
+ expect(entry).to.have.property("arity", 1);
62
+ expect(entry.equations).to.have.lengthOf(1);
63
+ });
64
+
65
+ it("should register a function with multiple equations", () => {
66
+ const funcNode = makeFunc("fib", 1, 2);
67
+
68
+ visitor.visitFunction(funcNode);
69
+
70
+ const entry = ctx.lookup("fib") as RuntimeFunction;
71
+ expect(entry.equations).to.have.lengthOf(2);
72
+ });
73
+
74
+ it("should throw error if function has no equations", () => {
75
+ const funcNode = makeFunc("empty", 0, 0);
76
+ funcNode.equations = [];
77
+
78
+ expect(() => visitor.visitFunction(funcNode)).to.throw(
79
+ /has no equations/,
80
+ );
81
+ });
82
+
83
+ it("should throw error if equations have different arity", () => {
84
+ const funcNode = makeFunc("badFunc", 1);
85
+ funcNode.equations.push(makeEq(2));
86
+
87
+ expect(() => visitor.visitFunction(funcNode)).to.throw(
88
+ /must have the same arity/,
89
+ );
90
+ });
91
+ });
92
+
93
+ describe("Logic Programming (Facts)", () => {
94
+ it("should register a new Fact", () => {
95
+ const factNode = makeFact("parent");
96
+
97
+ visitor.visitFact(factNode);
98
+
99
+ expect(ctx.isDefined("parent")).to.be.true;
100
+ const entry = ctx.lookup("parent") as RuntimePredicate;
101
+ expect(entry.equations).to.have.lengthOf(1);
102
+ expect(entry.equations[0]).to.equal(factNode);
103
+ });
104
+
105
+ it("should append to existing Fact if identifier exists", () => {
106
+ const f1 = makeFact("parent");
107
+ const f2 = makeFact("parent");
108
+
109
+ visitor.visitFact(f1);
110
+ visitor.visitFact(f2);
111
+
112
+ const entry = ctx.lookup("parent") as RuntimePredicate;
113
+ expect(entry.equations).to.have.lengthOf(2);
114
+ expect(entry.equations[0]).to.equal(f1);
115
+ expect(entry.equations[1]).to.equal(f2);
116
+ });
117
+
118
+ it("should throw error if existing entry is not a Fact", () => {
119
+ ctx.define("test", { type: "SomethingElse", equations: [] } as any);
120
+ const factNode = makeFact("test");
121
+ expect(() => visitor.visitFact(factNode)).to.throw(
122
+ /is not a predicate/,
123
+ );
124
+ });
125
+
126
+ it("should throw error if arity mismatch in Fact", () => {
127
+ const f1 = makeFact("parent", 2);
128
+ const f2 = makeFact("parent", 1);
129
+
130
+ visitor.visitFact(f1);
131
+ expect(() => visitor.visitFact(f2)).to.throw(/Arity mismatch/);
132
+ });
133
+ });
134
+
135
+ describe("Logic Programming (Rules)", () => {
136
+ it("should register a new Rule", () => {
137
+ const ruleNode = makeRule("grandparent");
138
+
139
+ visitor.visitRule(ruleNode);
140
+
141
+ expect(ctx.isDefined("grandparent")).to.be.true;
142
+ const entry = ctx.lookup("grandparent") as RuntimePredicate;
143
+ expect(entry.equations).to.have.lengthOf(1);
144
+ expect(entry.equations[0]).to.equal(ruleNode);
145
+ });
146
+
147
+ it("should append to existing Rule group", () => {
148
+ const r1 = makeRule("ancestor");
149
+ const r2 = makeRule("ancestor");
150
+
151
+ visitor.visitRule(r1);
152
+ visitor.visitRule(r2);
153
+
154
+ const entry = ctx.lookup("ancestor") as RuntimePredicate;
155
+ expect(entry.equations).to.have.lengthOf(2);
156
+ expect(entry.equations[0]).to.equal(r1);
157
+ expect(entry.equations[1]).to.equal(r2);
158
+ });
159
+
160
+ it("should throw error if arity mismatch in Rule", () => {
161
+ const r1 = makeRule("sibling", 2);
162
+ const r2 = makeRule("sibling", 3);
163
+
164
+ visitor.visitRule(r1);
165
+ expect(() => visitor.visitRule(r2)).to.throw(/Arity mismatch/);
166
+ });
167
+ });
168
+
169
+ it("should traverse the AST and build the complete environment", () => {
170
+ const nodes: AST = [
171
+ makeFunc("add", 2),
172
+ makeFact("is_human"),
173
+ makeRule("is_mortal"),
174
+ ];
175
+
176
+ visitor.build(nodes);
177
+ expect(ctx.isDefined("add")).to.be.true;
178
+ expect(ctx.isDefined("is_human")).to.be.true;
179
+ expect(ctx.isDefined("is_mortal")).to.be.true;
180
+ });
181
+ });