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,606 +1,431 @@
1
- import { expect } from "chai";
2
- import {
3
- PrimitiveValue,
4
- RuntimeFunction,
5
- UnguardedBody,
6
- Sequence,
7
- Return,
8
- SymbolPrimitive,
9
- NumberPrimitive,
10
- VariablePattern,
11
- RuntimeObject,
12
- RuntimeClass,
13
- StringPrimitive,
14
- Primitive,
15
- Super,
16
- ArithmeticBinaryOperation,
17
- EnvStack,
18
- } from "yukigo-ast";
19
- import { createGlobalEnv } from "../../src/interpreter/utils.js";
20
- import {
21
- Continuation,
22
- idContinuation,
23
- Thunk,
24
- trampoline,
25
- } from "../../src/interpreter/trampoline.js";
26
- import { RuntimeContext } from "../../src/interpreter/components/RuntimeContext.js";
27
-
28
- const createEmptyEnv = () => ({ head: new Map(), tail: null });
29
-
30
- const createMethodMap = (
31
- methods: RuntimeFunction[],
32
- ): Map<string, RuntimeFunction> =>
33
- new Map(methods.map((m) => [m.identifier, m]));
34
- const createMethod = (name: string, returnVal: Primitive): RuntimeFunction => {
35
- return {
36
- type: "Function",
37
- identifier: name,
38
- arity: 0,
39
- pendingArgs: [],
40
- equations: [
41
- {
42
- patterns: [],
43
- body: new UnguardedBody(new Sequence([new Return(returnVal)])),
44
- },
45
- ],
46
- };
47
- };
48
-
49
- const createClass = (
50
- name: string,
51
- superclass?: string,
52
- methodDefs: Map<string, RuntimeFunction> = new Map(),
53
- mixins: string[] = [],
54
- ): RuntimeClass => {
55
- return {
56
- type: "Class",
57
- identifier: name,
58
- fields: new Map(),
59
- methods: methodDefs,
60
- superclass,
61
- mixins,
62
- };
63
- };
64
-
65
- describe("ctx.objRuntime", () => {
66
- let objectInstance: RuntimeObject;
67
- const className = "TestClass";
68
- const initialFields = new Map<string, PrimitiveValue>([
69
- ["count", 10],
70
- ["name", "Yukigo"],
71
- ]);
72
- const methods = new Map<string, RuntimeFunction>();
73
- const classDef: RuntimeClass = {
74
- type: "Class",
75
- identifier: className,
76
- fields: initialFields,
77
- methods,
78
- mixins: [],
79
- superclass: undefined,
80
- };
81
- const env: EnvStack = createGlobalEnv();
82
- env.head.set(className, classDef);
83
- const ctx = new RuntimeContext();
84
- ctx.setEnv(env);
85
- beforeEach(() => {
86
- objectInstance = ctx.objRuntime.instantiate(
87
- className,
88
- "obj",
89
- initialFields,
90
- methods,
91
- );
92
- });
93
-
94
- describe("instantiate()", () => {
95
- it("debe crear un objeto con la estructura correcta", () => {
96
- expect(objectInstance.type).to.equal("Object");
97
- expect(objectInstance.className).to.equal(className);
98
- });
99
-
100
- it("debe clonar el mapa de campos (no usar la referencia original)", () => {
101
- const fieldsDef = new Map([["x", 1]]);
102
- const obj = ctx.objRuntime.instantiate("A", "objA", fieldsDef, new Map());
103
-
104
- fieldsDef.set("x", 2);
105
-
106
- expect(obj.fields.get("x")).to.equal(1);
107
- });
108
- });
109
-
110
- describe("Field Access (Get/Set)", () => {
111
- it("getField debe devolver el valor de un campo existente", () => {
112
- const val = ctx.objRuntime.getField(objectInstance, "count");
113
- expect(val).to.equal(10);
114
- });
115
-
116
- it("getField debe lanzar error si el campo no existe", () => {
117
- expect(() => {
118
- ctx.objRuntime.getField(objectInstance, "non_existent");
119
- }).to.throw(/Field 'non_existent' not found/);
120
- });
121
-
122
- it("getField debe lanzar error si el target no es un objeto", () => {
123
- expect(() => {
124
- ctx.objRuntime.getField(123 as any, "count");
125
- }).to.throw(/Target is not an object/);
126
- });
127
-
128
- it("setField debe actualizar el valor de un campo existente", () => {
129
- ctx.objRuntime.setField(objectInstance, "count", 20);
130
- expect(objectInstance.fields.get("count")).to.equal(20);
131
- });
132
-
133
- it("setField debe lanzar error si intentas crear un campo nuevo (strict mode)", () => {
134
- expect(() => {
135
- ctx.objRuntime.setField(objectInstance, "newProp", 99);
136
- }).to.throw(/Cannot set unknown field/);
137
- });
138
- });
139
-
140
- describe("dispatch()", () => {
141
- it("debe ejecutar un método que accede a 'self' (campos del objeto)", () => {
142
- const getCountMethod: RuntimeFunction = {
143
- type: "Function",
144
- identifier: "getCount",
145
- arity: 0,
146
- pendingArgs: [],
147
- equations: [
148
- {
149
- patterns: [],
150
- body: new UnguardedBody(
151
- new Sequence([new Return(new SymbolPrimitive("count"))]),
152
- ),
153
- },
154
- ],
155
- };
156
-
157
- objectInstance.methods.set("getCount", getCountMethod);
158
-
159
- const result = trampoline(
160
- ctx.objRuntime.dispatch(
161
- objectInstance,
162
- "getCount",
163
- [],
164
- env,
165
-
166
- idContinuation,
167
- ),
168
- );
169
-
170
- expect(result).to.equal(10);
171
- });
172
-
173
- it("debe fallar si el método no existe", () => {
174
- expect(() => {
175
- trampoline(
176
- ctx.objRuntime.dispatch(
177
- objectInstance,
178
- "unknownMethod",
179
- [],
180
- env,
181
-
182
- idContinuation,
183
- ),
184
- );
185
- }).to.throw(/does not understand 'unknownMethod'/);
186
- });
187
-
188
- it("debe fallar si el receiver no es un objeto", () => {
189
- expect(() => {
190
- trampoline(
191
- ctx.objRuntime.dispatch(
192
- "soy un string" as any,
193
- "toString",
194
- [],
195
- createEmptyEnv() as any,
196
-
197
- idContinuation,
198
- ),
199
- );
200
- }).to.throw(/is not an object/);
201
- });
202
-
203
- it("debe permitir argumentos en el método", () => {
204
- const returnArgAST = new Return(new SymbolPrimitive("val"));
205
- const addMethod: RuntimeFunction = {
206
- type: "Function",
207
- identifier: "echo",
208
- arity: 1,
209
- pendingArgs: [],
210
- equations: [
211
- {
212
- patterns: [new VariablePattern(new SymbolPrimitive("val"))],
213
- body: new UnguardedBody(new Sequence([returnArgAST])),
214
- },
215
- ],
216
- };
217
-
218
- objectInstance.methods.set("echo", addMethod);
219
-
220
- const result = trampoline(
221
- ctx.objRuntime.dispatch(
222
- objectInstance,
223
- "echo",
224
- [999],
225
- env,
226
-
227
- idContinuation,
228
- ),
229
- );
230
-
231
- expect(result).to.equal(999);
232
- });
233
- });
234
- describe("Method Lookup", () => {
235
- it("debe delegar a la superclase si el método no está en la instancia ni en la clase", () => {
236
- env.head.set(
237
- "Animal",
238
- createClass(
239
- "Animal",
240
- undefined,
241
- createMethodMap([createMethod("speak", new StringPrimitive("Guau"))]),
242
- ),
243
- );
244
- env.head.set("Perro", createClass("Perro", "Animal"));
245
-
246
- const perro = ctx.objRuntime.instantiate(
247
- "Perro",
248
- "dogObj",
249
- new Map(),
250
- new Map(),
251
- );
252
-
253
- const res = trampoline(
254
- ctx.objRuntime.dispatch(
255
- perro,
256
- "speak",
257
- [],
258
- env,
259
-
260
- idContinuation,
261
- ),
262
- );
263
- expect(res).to.equal("Guau");
264
- });
265
-
266
- it("debe subir múltiples niveles en la jerarquía (Abuelo -> Padre -> Hijo)", () => {
267
- env.head.set(
268
- "A",
269
- createClass(
270
- "A",
271
- undefined,
272
- createMethodMap([createMethod("id", new NumberPrimitive(1))]),
273
- ),
274
- );
275
- env.head.set("B", createClass("B", "A"));
276
- env.head.set("C", createClass("C", "B"));
277
-
278
- const objC = ctx.objRuntime.instantiate(
279
- "C",
280
- "objC",
281
- new Map(),
282
- new Map(),
283
- );
284
- expect(
285
- trampoline(
286
- ctx.objRuntime.dispatch(
287
- objC,
288
- "id",
289
- [],
290
- env,
291
-
292
- idContinuation,
293
- ),
294
- ),
295
- ).to.equal(1);
296
- });
297
-
298
- it("debe encontrar métodos definidos en un Mixin", () => {
299
- env.head.set(
300
- "Volador",
301
- createClass(
302
- "Volador",
303
- undefined,
304
- createMethodMap([createMethod("volar", new StringPrimitive("Wosh"))]),
305
- ),
306
- );
307
- env.head.set(
308
- "Ave",
309
- createClass("Ave", undefined, undefined, ["Volador"]),
310
- );
311
-
312
- const pepita = ctx.objRuntime.instantiate(
313
- "Ave",
314
- "birdObj",
315
- new Map(),
316
- new Map(),
317
- );
318
- expect(
319
- trampoline(
320
- ctx.objRuntime.dispatch(
321
- pepita,
322
- "volar",
323
- [],
324
- env,
325
-
326
- idContinuation,
327
- ),
328
- ),
329
- ).to.equal("Wosh");
330
- });
331
-
332
- it("debe soportar Mixines recursivos (Mixin incluye otro Mixin)", () => {
333
- env.head.set(
334
- "HabilidadA",
335
- createClass(
336
- "HabilidadA",
337
- undefined,
338
- createMethodMap([createMethod("skill", new StringPrimitive("Fire"))]),
339
- ),
340
- );
341
- env.head.set(
342
- "HabilidadB",
343
- createClass("HabilidadB", undefined, undefined, ["HabilidadA"]),
344
- );
345
- env.head.set(
346
- "Heroe",
347
- createClass("Heroe", undefined, undefined, ["HabilidadB"]),
348
- );
349
-
350
- const heroe = ctx.objRuntime.instantiate(
351
- "Heroe",
352
- "heroObj",
353
- new Map(),
354
- new Map(),
355
- );
356
- expect(
357
- trampoline(
358
- ctx.objRuntime.dispatch(
359
- heroe,
360
- "skill",
361
- [],
362
- env,
363
-
364
- idContinuation,
365
- ),
366
- ),
367
- ).to.equal("Fire");
368
- });
369
-
370
- it("Prioridad: La Clase Propia gana a Mixines y Superclase", () => {
371
- env.head.set(
372
- "Super",
373
- createClass(
374
- "Super",
375
- undefined,
376
- createMethodMap([createMethod("val", new NumberPrimitive(1))]),
377
- ),
378
- );
379
- env.head.set(
380
- "Mixin",
381
- createClass(
382
- "Mixin",
383
- undefined,
384
- createMethodMap([createMethod("val", new NumberPrimitive(2))]),
385
- ),
386
- );
387
-
388
- env.head.set(
389
- "Child",
390
- createClass(
391
- "Child",
392
- "Super",
393
- createMethodMap([createMethod("val", new NumberPrimitive(3))]),
394
- ["Mixin"],
395
- ),
396
- );
397
-
398
- const child = ctx.objRuntime.instantiate(
399
- "Child",
400
- "childObj",
401
- new Map(),
402
- new Map(),
403
- );
404
- expect(
405
- trampoline(
406
- ctx.objRuntime.dispatch(
407
- child,
408
- "val",
409
- [],
410
- env,
411
-
412
- idContinuation,
413
- ),
414
- ),
415
- ).to.equal(3);
416
- });
417
-
418
- it("Prioridad: El Mixin gana a la Superclase", () => {
419
- env.head.set(
420
- "Super",
421
- createClass(
422
- "Super",
423
- undefined,
424
- createMethodMap([createMethod("val", new NumberPrimitive(1))]),
425
- ),
426
- );
427
- env.head.set(
428
- "Mixin",
429
- createClass(
430
- "Mixin",
431
- undefined,
432
- createMethodMap([createMethod("val", new NumberPrimitive(2))]),
433
- ),
434
- );
435
- env.head.set(
436
- "Child",
437
- createClass("Child", "Super", undefined, ["Mixin"]),
438
- );
439
-
440
- const child = ctx.objRuntime.instantiate(
441
- "Child",
442
- "childObj",
443
- new Map(),
444
- new Map(),
445
- );
446
- expect(
447
- trampoline(
448
- ctx.objRuntime.dispatch(
449
- child,
450
- "val",
451
- [],
452
- env,
453
-
454
- idContinuation,
455
- ),
456
- ),
457
- ).to.equal(2);
458
- });
459
-
460
- it("Prioridad: El último Mixin de la lista gana (Shadowing de derecha a izquierda)", () => {
461
- env.head.set(
462
- "MixinA",
463
- createClass(
464
- "MixinA",
465
- undefined,
466
- createMethodMap([createMethod("val", new NumberPrimitive(10))]),
467
- ),
468
- );
469
- env.head.set(
470
- "MixinB",
471
- createClass(
472
- "MixinB",
473
- undefined,
474
- createMethodMap([createMethod("val", new NumberPrimitive(20))]),
475
- ),
476
- );
477
-
478
- env.head.set(
479
- "Clase",
480
- createClass("Clase", undefined, undefined, ["MixinA", "MixinB"]),
481
- );
482
-
483
- const obj = ctx.objRuntime.instantiate(
484
- "Clase",
485
- "objC",
486
- new Map(),
487
- new Map(),
488
- );
489
- expect(
490
- trampoline(
491
- ctx.objRuntime.dispatch(
492
- obj,
493
- "val",
494
- [],
495
- env,
496
-
497
- idContinuation,
498
- ),
499
- ),
500
- ).to.equal(20);
501
- });
502
-
503
- it("Prioridad: Orden inverso de Mixines", () => {
504
- env.head.set(
505
- "MixinA",
506
- createClass(
507
- "MixinA",
508
- undefined,
509
- createMethodMap([createMethod("val", new NumberPrimitive(10))]),
510
- ),
511
- );
512
- env.head.set(
513
- "MixinB",
514
- createClass(
515
- "MixinB",
516
- undefined,
517
- createMethodMap([createMethod("val", new NumberPrimitive(20))]),
518
- ),
519
- );
520
-
521
- env.head.set(
522
- "Clase",
523
- createClass("Clase", undefined, undefined, ["MixinB", "MixinA"]),
524
- );
525
-
526
- const obj = ctx.objRuntime.instantiate(
527
- "Clase",
528
- "obj",
529
- new Map(),
530
- new Map(),
531
- );
532
- expect(
533
- trampoline(
534
- ctx.objRuntime.dispatch(
535
- obj,
536
- "val",
537
- [],
538
- env,
539
-
540
- idContinuation,
541
- ),
542
- ),
543
- ).to.equal(10);
544
- });
545
- });
546
- describe("Super", () => {
547
- it("debe invocar al método de la superclase y operar con el resultado", () => {
548
- env.head.set(
549
- "Base",
550
- createClass(
551
- "Base",
552
- undefined,
553
- createMethodMap([createMethod("calc", new NumberPrimitive(10))]),
554
- ),
555
- );
556
-
557
- const astBody = new UnguardedBody(
558
- new Sequence([
559
- new Return(
560
- new ArithmeticBinaryOperation(
561
- "Plus",
562
- new Super([]),
563
- new NumberPrimitive(5),
564
- ),
565
- ),
566
- ]),
567
- );
568
-
569
- const methodHijo: RuntimeFunction = {
570
- type: "Function",
571
- identifier: "calc",
572
- arity: 0,
573
- pendingArgs: [],
574
- equations: [
575
- {
576
- patterns: [],
577
- body: astBody,
578
- },
579
- ],
580
- };
581
-
582
- const Hijo: RuntimeClass = {
583
- type: "Class",
584
- identifier: "Hijo",
585
- fields: new Map(),
586
- methods: new Map([["calc", methodHijo]]),
587
- superclass: "Base",
588
- mixins: [],
589
- };
590
- env.head.set("Hijo", Hijo);
591
-
592
- const hijoInstance = ctx.objRuntime.instantiate(
593
- "Hijo",
594
- "childObj",
595
- new Map(),
596
- new Map(),
597
- );
598
-
599
- const result = trampoline(
600
- ctx.objRuntime.dispatch(hijoInstance, "calc", [], env, idContinuation),
601
- );
602
-
603
- expect(result).to.equal(15);
604
- });
605
- });
606
- });
1
+ import { expect } from "chai";
2
+ import {
3
+ UnguardedBody,
4
+ Sequence,
5
+ Return,
6
+ SymbolPrimitive,
7
+ NumberPrimitive,
8
+ VariablePattern,
9
+ StringPrimitive,
10
+ Primitive,
11
+ Super,
12
+ ArithmeticBinaryOperation,
13
+ } from "yukigo-ast";
14
+ import { createGlobalEnv, EnvStack } from "../../src/interpreter/utils.js";
15
+ import { RuntimeContext } from "../../src/interpreter/components/RuntimeContext.js";
16
+ import { YukigoKernel } from "../../src/interpreter/components/kernel/index.js";
17
+ import {
18
+ YuValue,
19
+ RuntimeFunction,
20
+ RuntimeClass,
21
+ RuntimeObject,
22
+ YuNumber,
23
+ YuString,
24
+ } from "../../src/interpreter/primitives/index.js";
25
+ import { InterpreterVisitor } from "../../src/interpreter/components/evaluators/index.js";
26
+
27
+ const createMethodMap = (
28
+ methods: RuntimeFunction[],
29
+ ): Map<string, RuntimeFunction> =>
30
+ new Map(methods.map((m) => [m.identifier!, m]));
31
+ const createMethod = (name: string, returnVal: Primitive): RuntimeFunction => {
32
+ return new RuntimeFunction(
33
+ 0,
34
+ [
35
+ {
36
+ patterns: [],
37
+ body: new UnguardedBody(new Sequence([new Return(returnVal)])),
38
+ },
39
+ ],
40
+ name,
41
+ [],
42
+ );
43
+ };
44
+
45
+ const createClass = (
46
+ env: EnvStack,
47
+ name: string,
48
+ superclass?: string,
49
+ methodDefs: Map<string, RuntimeFunction> = new Map(),
50
+ mixins: string[] = [],
51
+ ): RuntimeClass => {
52
+ const cls = new RuntimeClass(name, new Map(), methodDefs, mixins, superclass);
53
+ env.head.set(name, cls);
54
+ return cls;
55
+ };
56
+
57
+ describe("ctx.objRuntime", () => {
58
+ let objectInstance: RuntimeObject;
59
+ let kernel: YukigoKernel;
60
+ const className = "TestClass";
61
+ const initialFields = new Map<string, YuValue>([
62
+ ["count", new YuNumber(10)],
63
+ ["name", new YuString("Yukigo")],
64
+ ]);
65
+ const methods = new Map<string, RuntimeFunction>();
66
+ const classDef = new RuntimeClass(
67
+ className,
68
+ initialFields,
69
+ methods,
70
+ [],
71
+ undefined,
72
+ );
73
+ const env: EnvStack = createGlobalEnv();
74
+ env.head.set(className, classDef);
75
+ const ctx = new RuntimeContext();
76
+ ctx.setEnv(env);
77
+ beforeEach(() => {
78
+ env.head.clear();
79
+ env.head.set(className, classDef);
80
+ objectInstance = classDef.instantiate("obj");
81
+ kernel = new YukigoKernel(new InterpreterVisitor(ctx));
82
+ });
83
+
84
+ describe("instantiate()", () => {
85
+ it("debe crear un objeto con la estructura correcta", () => {
86
+ expect(objectInstance).to.be.an.instanceOf(RuntimeObject);
87
+ expect(objectInstance.className).to.equal(className);
88
+ });
89
+
90
+ it("debe clonar el mapa de campos (no usar la referencia original)", () => {
91
+ const fieldsDef = new Map([["x", new YuNumber(1)]]);
92
+ const classA = new RuntimeClass("A", fieldsDef, new Map(), []);
93
+ const obj = classA.instantiate("objA");
94
+
95
+ fieldsDef.set("x", new YuNumber(2));
96
+
97
+ expect((obj.fields.get("x") as YuValue).toJSON()).to.equal(1);
98
+ });
99
+ });
100
+
101
+ describe("Field Access (Get/Set)", () => {
102
+ it("getField debe devolver el valor de un campo existente", () => {
103
+ const val = ctx.objRuntime.getField(objectInstance, "count");
104
+ expect(val.toJSON()).to.equal(10);
105
+ });
106
+
107
+ it("getField debe lanzar error si el campo no existe", () => {
108
+ expect(() => {
109
+ ctx.objRuntime.getField(objectInstance, "non_existent");
110
+ }).to.throw(/Field 'non_existent' not found/);
111
+ });
112
+
113
+ it("getField debe lanzar error si el target no es un objeto", () => {
114
+ expect(() => {
115
+ ctx.objRuntime.getField(new YuNumber(123) as any, "count");
116
+ }).to.throw(/Target is not an object/);
117
+ });
118
+
119
+ it("setField debe actualizar el valor de un campo existente", () => {
120
+ ctx.objRuntime.setField(objectInstance, "count", new YuNumber(20));
121
+ expect((objectInstance.fields.get("count") as YuValue).toJSON()).to.equal(
122
+ 20,
123
+ );
124
+ });
125
+
126
+ it("setField debe lanzar error si intentas crear un campo nuevo (strict mode)", () => {
127
+ expect(() => {
128
+ ctx.objRuntime.setField(objectInstance, "newProp", new YuNumber(99));
129
+ }).to.throw(/Cannot set unknown field/);
130
+ });
131
+ });
132
+
133
+ describe("dispatch()", () => {
134
+ it("debe ejecutar un método que accede a 'self' (campos del objeto)", () => {
135
+ const getCountMethod = new RuntimeFunction(
136
+ 0,
137
+ [
138
+ {
139
+ patterns: [],
140
+ body: new UnguardedBody(
141
+ new Sequence([new Return(new SymbolPrimitive("count"))]),
142
+ ),
143
+ },
144
+ ],
145
+ "getCount",
146
+ [],
147
+ );
148
+
149
+ objectInstance.methods.set("getCount", getCountMethod);
150
+
151
+ const result = kernel.run(
152
+ ctx.objRuntime.dispatch(objectInstance, "getCount", []),
153
+ ) as YuValue;
154
+
155
+ expect(result.toJSON()).to.equal(10);
156
+ });
157
+
158
+ it("debe fallar si el método no existe", () => {
159
+ expect(() => {
160
+ kernel.run(
161
+ ctx.objRuntime.dispatch(objectInstance, "unknownMethod", []),
162
+ );
163
+ }).to.throw(/does not understand 'unknownMethod'/);
164
+ });
165
+
166
+ it("debe fallar si el receiver no es un objeto", () => {
167
+ expect(() => {
168
+ kernel.run(
169
+ ctx.objRuntime.dispatch(
170
+ new YuString("soy un string") as any,
171
+ "toString",
172
+ [],
173
+ ),
174
+ );
175
+ }).to.throw(/Primitive type 'YuString' does not understand method 'toString'/);
176
+ });
177
+
178
+ it("debe permitir argumentos en el método", () => {
179
+ const returnArgAST = new Return(new SymbolPrimitive("val"));
180
+ const addMethod = new RuntimeFunction(
181
+ 1,
182
+ [
183
+ {
184
+ patterns: [new VariablePattern(new SymbolPrimitive("val"))],
185
+ body: new UnguardedBody(new Sequence([returnArgAST])),
186
+ },
187
+ ],
188
+ "echo",
189
+ [],
190
+ );
191
+
192
+ objectInstance.methods.set("echo", addMethod);
193
+
194
+ const result = kernel.run(
195
+ ctx.objRuntime.dispatch(objectInstance, "echo", [new YuNumber(999)]),
196
+ ) as YuValue;
197
+
198
+ expect(result.toJSON()).to.equal(999);
199
+ });
200
+ });
201
+ describe("Method Lookup", () => {
202
+ it("debe delegar a la superclase si el método no está en la instancia ni en la clase", () => {
203
+ createClass(
204
+ env,
205
+ "Animal",
206
+ undefined,
207
+ createMethodMap([createMethod("speak", new StringPrimitive("Guau"))]),
208
+ );
209
+ const Perro = createClass(env, "Perro", "Animal");
210
+
211
+ const perro = Perro.instantiate("dogObj");
212
+
213
+ const res = kernel.run(
214
+ ctx.objRuntime.dispatch(perro, "speak", []),
215
+ ) as YuValue;
216
+ expect(res.toJSON()).to.equal("Guau");
217
+ });
218
+
219
+ it("debe subir múltiples niveles en la jerarquía (Abuelo -> Padre -> Hijo)", () => {
220
+ createClass(
221
+ env,
222
+ "A",
223
+ undefined,
224
+ createMethodMap([createMethod("id", new NumberPrimitive(1))]),
225
+ );
226
+ createClass(env, "B", "A");
227
+ const C = createClass(env, "C", "B");
228
+
229
+ const objC = C.instantiate("objC");
230
+ expect(
231
+ (
232
+ kernel.run(ctx.objRuntime.dispatch(objC, "id", [])) as YuValue
233
+ ).toJSON(),
234
+ ).to.equal(1);
235
+ });
236
+
237
+ it("debe encontrar métodos definidos en un Mixin", () => {
238
+ createClass(
239
+ env,
240
+ "Volador",
241
+ undefined,
242
+ createMethodMap([createMethod("volar", new StringPrimitive("Wosh"))]),
243
+ );
244
+ const Ave = createClass(env, "Ave", undefined, undefined, ["Volador"]);
245
+
246
+ const pepita = Ave.instantiate("birdObj");
247
+ expect(
248
+ (
249
+ kernel.run(ctx.objRuntime.dispatch(pepita, "volar", [])) as YuValue
250
+ ).toJSON(),
251
+ ).to.equal("Wosh");
252
+ });
253
+
254
+ it("debe soportar Mixines recursivos (Mixin incluye otro Mixin)", () => {
255
+ createClass(
256
+ env,
257
+ "HabilidadA",
258
+ undefined,
259
+ createMethodMap([createMethod("skill", new StringPrimitive("Fire"))]),
260
+ );
261
+ createClass(env, "HabilidadB", undefined, undefined, ["HabilidadA"]);
262
+ const Heroe = createClass(env, "Heroe", undefined, undefined, [
263
+ "HabilidadB",
264
+ ]);
265
+
266
+ const heroe = Heroe.instantiate("heroObj");
267
+ expect(
268
+ (
269
+ kernel.run(ctx.objRuntime.dispatch(heroe, "skill", [])) as YuValue
270
+ ).toJSON(),
271
+ ).to.equal("Fire");
272
+ });
273
+
274
+ it("Prioridad: La Clase Propia gana a Mixines y Superclase", () => {
275
+ createClass(
276
+ env,
277
+ "Super",
278
+ undefined,
279
+ createMethodMap([createMethod("val", new NumberPrimitive(1))]),
280
+ );
281
+ createClass(
282
+ env,
283
+ "Mixin",
284
+ undefined,
285
+ createMethodMap([createMethod("val", new NumberPrimitive(2))]),
286
+ );
287
+
288
+ const Child = createClass(
289
+ env,
290
+ "Child",
291
+ "Super",
292
+ createMethodMap([createMethod("val", new NumberPrimitive(3))]),
293
+ ["Mixin"],
294
+ );
295
+
296
+ const child = Child.instantiate("childObj");
297
+ expect(
298
+ (
299
+ kernel.run(ctx.objRuntime.dispatch(child, "val", [])) as YuValue
300
+ ).toJSON(),
301
+ ).to.equal(3);
302
+ });
303
+
304
+ it("Prioridad: El Mixin gana a la Superclase", () => {
305
+ createClass(
306
+ env,
307
+ "Super",
308
+ undefined,
309
+ createMethodMap([createMethod("val", new NumberPrimitive(1))]),
310
+ );
311
+ createClass(
312
+ env,
313
+ "Mixin",
314
+ undefined,
315
+ createMethodMap([createMethod("val", new NumberPrimitive(2))]),
316
+ );
317
+ const Child = createClass(env, "Child", "Super", undefined, ["Mixin"]);
318
+
319
+ const child = Child.instantiate("childObj");
320
+ expect(
321
+ (
322
+ kernel.run(ctx.objRuntime.dispatch(child, "val", [])) as YuValue
323
+ ).toJSON(),
324
+ ).to.equal(2);
325
+ });
326
+
327
+ it("Prioridad: El último Mixin de la lista gana (Shadowing de derecha a izquierda)", () => {
328
+ createClass(
329
+ env,
330
+ "MixinA",
331
+ undefined,
332
+ createMethodMap([createMethod("val", new NumberPrimitive(10))]),
333
+ );
334
+ createClass(
335
+ env,
336
+ "MixinB",
337
+ undefined,
338
+ createMethodMap([createMethod("val", new NumberPrimitive(20))]),
339
+ );
340
+
341
+ const Clase = createClass(env, "Clase", undefined, undefined, [
342
+ "MixinA",
343
+ "MixinB",
344
+ ]);
345
+
346
+ const obj = Clase.instantiate("objC");
347
+ expect(
348
+ (
349
+ kernel.run(ctx.objRuntime.dispatch(obj, "val", [])) as YuValue
350
+ ).toJSON(),
351
+ ).to.equal(20);
352
+ });
353
+
354
+ it("Prioridad: Orden inverso de Mixines", () => {
355
+ createClass(
356
+ env,
357
+ "MixinA",
358
+ undefined,
359
+ createMethodMap([createMethod("val", new NumberPrimitive(10))]),
360
+ );
361
+ createClass(
362
+ env,
363
+ "MixinB",
364
+ undefined,
365
+ createMethodMap([createMethod("val", new NumberPrimitive(20))]),
366
+ );
367
+
368
+ const Clase = createClass(env, "Clase", undefined, undefined, [
369
+ "MixinB",
370
+ "MixinA",
371
+ ]);
372
+
373
+ const obj = Clase.instantiate("obj");
374
+ expect(
375
+ (
376
+ kernel.run(ctx.objRuntime.dispatch(obj, "val", [])) as YuValue
377
+ ).toJSON(),
378
+ ).to.equal(10);
379
+ });
380
+ });
381
+ describe("Super", () => {
382
+ it("debe invocar al método de la superclase y operar con el resultado", () => {
383
+ createClass(
384
+ env,
385
+ "Base",
386
+ undefined,
387
+ createMethodMap([createMethod("calc", new NumberPrimitive(10))]),
388
+ );
389
+
390
+ const astBody = new UnguardedBody(
391
+ new Sequence([
392
+ new Return(
393
+ new ArithmeticBinaryOperation(
394
+ "Plus",
395
+ new Super([]),
396
+ new NumberPrimitive(5),
397
+ ),
398
+ ),
399
+ ]),
400
+ );
401
+
402
+ const methodHijo = new RuntimeFunction(
403
+ 0,
404
+ [
405
+ {
406
+ patterns: [],
407
+ body: astBody,
408
+ },
409
+ ],
410
+ "calc",
411
+ [],
412
+ );
413
+
414
+ const Hijo = createClass(
415
+ env,
416
+ "Hijo",
417
+ "Base",
418
+ new Map([["calc", methodHijo]]),
419
+ [],
420
+ );
421
+
422
+ const hijoInstance = Hijo.instantiate("childObj");
423
+
424
+ const result = kernel.run(
425
+ ctx.objRuntime.dispatch(hijoInstance, "calc", []),
426
+ ) as YuValue;
427
+
428
+ expect(result.toJSON()).to.equal(15);
429
+ });
430
+ });
431
+ });