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
@@ -1,224 +1,262 @@
1
- import {
2
- PrimitiveValue,
3
- RuntimeFunction,
4
- RuntimeObject,
5
- isRuntimeObject,
6
- isRuntimeClass,
7
- RuntimeClass,
8
- EnvStack,
9
- } from "yukigo-ast";
10
- import { InterpreterError } from "../../errors.js";
11
- import { Continuation, Thunk } from "../../trampoline.js";
12
- import { RuntimeContext } from "../RuntimeContext.js";
13
-
14
- type OOPEntity = RuntimeClass | RuntimeObject;
15
-
16
- type OOPMatch = {
17
- method: RuntimeFunction;
18
- holder: RuntimeObject | RuntimeClass;
19
- };
20
-
21
- export class ObjectRuntime {
22
- constructor(private context: RuntimeContext) {}
23
- /**
24
- * Creates a new instance of an Object.
25
- * Typically called by visitNew()
26
- */
27
- public instantiate(
28
- className: string,
29
- identifier: string,
30
- fieldDefinitions: Map<string, PrimitiveValue>,
31
- methodDefinitions: Map<string, RuntimeFunction>,
32
- ): RuntimeObject {
33
- return {
34
- type: "Object",
35
- className,
36
- identifier,
37
- fields: new Map(fieldDefinitions),
38
- methods: methodDefinitions,
39
- };
40
- }
41
-
42
- /**
43
- * Handles Method Calls (Message Passing).
44
- * Reuses FunctionRuntime to execute the method body.
45
- */
46
- public dispatch(
47
- receiver: PrimitiveValue,
48
- methodName: string,
49
- args: PrimitiveValue[],
50
- env: EnvStack,
51
- k: Continuation<PrimitiveValue>,
52
- ): Thunk<PrimitiveValue> {
53
- if (!isRuntimeObject(receiver))
54
- throw new Error(`${receiver} is not an object`);
55
-
56
- const chain = this.getResolutionChain(receiver, env);
57
- const match = this.findMethodInChain(chain, methodName);
58
-
59
- if (!match)
60
- throw new InterpreterError(
61
- "MethodDispatch",
62
- `${receiver.className} does not understand '${methodName}'.`,
63
- );
64
-
65
- const objectScope = this.createDispatchScope(receiver, match, methodName);
66
- this.context.pushEnv(objectScope);
67
- return this.context.funcRuntime.apply(match.method, args, k);
68
- }
69
-
70
- /**
71
- * Handles calls to super() or super.method()
72
- */
73
- public dispatchSuper(
74
- currentEnv: EnvStack,
75
- methodName: string,
76
- args: PrimitiveValue[],
77
- k: Continuation<PrimitiveValue>,
78
- ): Thunk<PrimitiveValue> {
79
- const self = this.context.lookup("self") as RuntimeObject;
80
- const currentHolder = this.context.lookup("__CONTEXT_CLASS__") as OOPEntity;
81
- const currentMethodName = this.context.lookup("__METHOD_NAME__");
82
- const targetMethodName = methodName || currentMethodName;
83
-
84
- if (!self || !currentHolder)
85
- throw new InterpreterError(
86
- "SuperError",
87
- "'super' used outside of a method context",
88
- );
89
-
90
- const chain = this.getResolutionChain(self, currentEnv);
91
-
92
- const currentIndex = chain.findIndex((c) => c === currentHolder);
93
-
94
- if (currentIndex === -1)
95
- throw new Error("Fatal: Execution context not found in hierarchy chain");
96
-
97
- const remainingChain = chain.slice(currentIndex + 1);
98
- const match = this.findMethodInChain(remainingChain, methodName);
99
-
100
- if (!match)
101
- throw new InterpreterError(
102
- "Super",
103
- `Super method '${methodName}' not found`,
104
- );
105
-
106
- const objectScope = this.createDispatchScope(self, match, targetMethodName);
107
-
108
- this.context.pushEnv(objectScope);
109
- return this.context.funcRuntime.apply(match.method, args, k);
110
- }
111
- private createDispatchScope(
112
- self: RuntimeObject,
113
- match: OOPMatch,
114
- targetName: PrimitiveValue,
115
- ) {
116
- const objectScope = new Map<string, PrimitiveValue>();
117
- objectScope.set("self", self);
118
- objectScope.set("__CONTEXT_CLASS__", match.holder);
119
- objectScope.set("__METHOD_NAME__", targetName);
120
-
121
- for (const [key, val] of self.fields) objectScope.set(key, val);
122
- return objectScope;
123
- }
124
- private getResolutionChain(
125
- receiver: RuntimeObject,
126
- env: EnvStack,
127
- ): Array<RuntimeObject | RuntimeClass> {
128
- const chain: Array<RuntimeObject | RuntimeClass> = [];
129
-
130
- chain.push(receiver);
131
-
132
- if (receiver.className) {
133
- this.expandClassHierarchy(receiver.className, env, chain);
134
- }
135
-
136
- return chain;
137
- }
138
- private expandClassHierarchy(
139
- className: string,
140
- env: EnvStack,
141
- chain: Array<RuntimeObject | RuntimeClass>,
142
- ) {
143
- const classDef = this.context.lookup(className);
144
- if (!isRuntimeClass(classDef))
145
- throw new InterpreterError(
146
- "expandClassHierarchy",
147
- "classDef was expected to be a RuntimeClass",
148
- );
149
-
150
- chain.push(classDef);
151
-
152
- const classDefCopy = [...classDef.mixins];
153
-
154
- if (classDef.mixins)
155
- classDefCopy.reverse().forEach((mixinName) => {
156
- this.expandClassHierarchy(mixinName, env, chain);
157
- });
158
-
159
- if (classDef.superclass)
160
- this.expandClassHierarchy(classDef.superclass, env, chain);
161
- }
162
- private findMethodInChain(
163
- chain: Array<RuntimeObject | RuntimeClass>,
164
- methodName: string,
165
- ): OOPMatch | undefined {
166
- for (const link of chain) {
167
- if (link.methods.has(methodName))
168
- return {
169
- method: link.methods.get(methodName)!,
170
- holder: link,
171
- };
172
- }
173
- return undefined;
174
- }
175
-
176
- /**
177
- * Field Access (Get)
178
- * e.g. self.myField
179
- */
180
- public getField(receiver: PrimitiveValue, fieldName: string): PrimitiveValue {
181
- if (!isRuntimeObject(receiver))
182
- throw new InterpreterError("FieldAccess", "Target is not an object");
183
-
184
- if (!receiver.fields.has(fieldName)) {
185
- if (receiver.methods.has(fieldName))
186
- return receiver.methods.get(fieldName);
187
-
188
- throw new InterpreterError(
189
- "FieldAccess",
190
- `Field '${fieldName}' not found in ${receiver.className}`,
191
- );
192
- }
193
-
194
- return receiver.fields.get(fieldName);
195
- }
196
-
197
- /**
198
- * Field Mutation (Set)
199
- * e.g. self.myField = 10
200
- */
201
- public setField(
202
- receiver: PrimitiveValue,
203
- fieldName: string,
204
- value: PrimitiveValue,
205
- ): PrimitiveValue {
206
- if (!this.context.config.mutability)
207
- throw new InterpreterError(
208
- "FieldAssignment",
209
- `Cannot mutate field '${fieldName}': mutability is disabled`,
210
- );
211
-
212
- if (!isRuntimeObject(receiver))
213
- throw new InterpreterError("FieldAssignment", "Target is not an object");
214
-
215
- if (!receiver.fields.has(fieldName))
216
- throw new InterpreterError(
217
- "FieldAssignment",
218
- `Cannot set unknown field '${fieldName}'`,
219
- );
220
-
221
- receiver.fields.set(fieldName, value);
222
- return value;
223
- }
224
- }
1
+ import { InterpreterError } from "../../errors.js";
2
+ import {
3
+ YuValue,
4
+ RuntimeClass,
5
+ RuntimeObject,
6
+ RuntimeFunction,
7
+ isRuntimeObject,
8
+ YuString,
9
+ isRuntimeClass,
10
+ YuBoolean,
11
+ YuArray,
12
+ YuNumber,
13
+ YuNil,
14
+ } from "../../primitives/index.js";
15
+ import { error, raise } from "../../utils.js";
16
+ import { RuntimeContext } from "../RuntimeContext.js";
17
+ import {
18
+ ExecutionCommand,
19
+ BindCommand,
20
+ StepCommand,
21
+ RaiseCommand,
22
+ } from "../kernel/commands.js";
23
+
24
+ type OOPEntity = RuntimeClass | RuntimeObject;
25
+
26
+ type OOPMatch = {
27
+ method: RuntimeFunction;
28
+ holder: RuntimeObject | RuntimeClass;
29
+ };
30
+
31
+ export class ObjectRuntime {
32
+ constructor(private context: RuntimeContext) {}
33
+ /**
34
+ * Handles Method Calls (Message Passing).
35
+ * Reuses FunctionRuntime to execute the method body.
36
+ */
37
+ public dispatch(
38
+ receiver: YuValue,
39
+ methodName: string,
40
+ args: YuValue[],
41
+ ): ExecutionCommand {
42
+ if (!isRuntimeObject(receiver)) {
43
+ return this.dispatchPrimitive(receiver, methodName, args);
44
+ }
45
+
46
+ const chain = this.getResolutionChain(receiver);
47
+
48
+ const arity = args.length;
49
+ const arityKey = `${methodName}/${arity}`;
50
+ let match = this.findMethodInChain(chain, arityKey);
51
+
52
+ if (!match) {
53
+ match = this.findMethodInChain(chain, methodName);
54
+ }
55
+
56
+ if (!match) {
57
+ if (methodName === "toString") {
58
+ return new StepCommand(new YuString(receiver.toString()));
59
+ }
60
+ if (methodName === "error") {
61
+ const errorMsg = args[0] ? args[0].toString() : "An error occurred";
62
+ return new RaiseCommand(new InterpreterError("Raise", errorMsg));
63
+ }
64
+ return raise(
65
+ error(
66
+ "MethodDispatch",
67
+ `${receiver.className} does not understand '${methodName}'.`,
68
+ ),
69
+ );
70
+ }
71
+
72
+ const objectScope = receiver.createDispatchScope(
73
+ match,
74
+ new YuString(methodName),
75
+ );
76
+ this.context.pushEnv(objectScope);
77
+ return new BindCommand(
78
+ this.context.funcRuntime.apply(match.method, args),
79
+ (res) => {
80
+ this.context.popEnv();
81
+ return new StepCommand(res);
82
+ },
83
+ );
84
+ }
85
+
86
+ /**
87
+ * Handles calls to super() or super.method()
88
+ */
89
+ public dispatchSuper(methodName: string, args: YuValue[]): ExecutionCommand {
90
+ const self = this.context.lookup("self") as RuntimeObject;
91
+ const currentHolder = this.context.lookup("__CONTEXT_CLASS__") as OOPEntity;
92
+ const currentMethodName = this.context.lookup("__METHOD_NAME__");
93
+
94
+ if (!self || !currentHolder)
95
+ return raise(
96
+ error("dispatchSuper", "'super' used outside of a method context"),
97
+ );
98
+
99
+ const chain = this.getResolutionChain(self);
100
+ const currentIndex = chain.findIndex((c) => c === currentHolder);
101
+
102
+ if (currentIndex === -1)
103
+ return raise(
104
+ error(
105
+ "dispatchSuper",
106
+ "Execution context not found in hierarchy chain",
107
+ ),
108
+ );
109
+
110
+ const remainingChain = chain.slice(currentIndex + 1);
111
+
112
+ const baseName = methodName || (currentMethodName as YuString).toJSON();
113
+ const arityKey = `${baseName}/${args.length}`;
114
+
115
+ let match = this.findMethodInChain(remainingChain, arityKey);
116
+
117
+ // Fallback: si no encuentra con aridad, buscar solo por nombre (para compatibilidad)
118
+ if (!match && methodName) {
119
+ match = this.findMethodInChain(remainingChain, methodName);
120
+ }
121
+ if (!match && !methodName) {
122
+ match = this.findMethodInChain(
123
+ remainingChain,
124
+ (currentMethodName as YuString).toJSON(),
125
+ );
126
+ }
127
+
128
+ if (!match)
129
+ return raise(error("Super", `Super method '${baseName}' not found`));
130
+
131
+ const objectScope = self.createDispatchScope(match, new YuString(baseName));
132
+ this.context.pushEnv(objectScope);
133
+
134
+ return new BindCommand(
135
+ this.context.funcRuntime.apply(match.method, args),
136
+ (res) => {
137
+ this.context.popEnv();
138
+ return new StepCommand(res);
139
+ },
140
+ );
141
+ }
142
+
143
+ public getResolutionChain(receiver: RuntimeObject): OOPEntity[] {
144
+ const chain: OOPEntity[] = [receiver];
145
+
146
+ if (receiver.className) {
147
+ const hierarchy = this.expandClassHierarchy(receiver.className);
148
+ chain.push(...hierarchy);
149
+ }
150
+
151
+ return chain;
152
+ }
153
+ private expandClassHierarchy(className: string): OOPEntity[] {
154
+ const chain: OOPEntity[] = [];
155
+ const visited = new Set<string>();
156
+ const queue = [className];
157
+
158
+ while (queue.length > 0) {
159
+ const current = queue.shift()!;
160
+ // occurs check to avoid circular loops
161
+ if (visited.has(current)) continue;
162
+ visited.add(current);
163
+
164
+ const classDef = this.getClassDef(current);
165
+ chain.push(classDef);
166
+ queue.push(...classDef.getHierarchy());
167
+ }
168
+
169
+ return chain;
170
+ }
171
+ private getClassDef(name: string): RuntimeClass {
172
+ const classDef = this.context.lookup(name);
173
+ if (!isRuntimeClass(classDef))
174
+ throw error(
175
+ "expandClassHierarchy",
176
+ "classDef was expected to be a RuntimeClass",
177
+ );
178
+ return classDef;
179
+ }
180
+
181
+ public findMethodInChain(
182
+ chain: Array<OOPEntity>,
183
+ methodName: string,
184
+ ): OOPMatch | undefined {
185
+ const match = chain.find((def) => def.methods.has(methodName));
186
+ if (!match) return undefined;
187
+ return {
188
+ method: match.methods.get(methodName)!,
189
+ holder: match,
190
+ };
191
+ }
192
+
193
+ /**
194
+ * Field Access (Get)
195
+ * e.g. self.myField
196
+ */
197
+ public getField(receiver: YuValue, fieldName: string): YuValue {
198
+ if (!isRuntimeObject(receiver))
199
+ throw new InterpreterError("FieldAccess", "Target is not an object");
200
+
201
+ if (receiver.hasMethod(fieldName)) return receiver.getMethod(fieldName);
202
+ return receiver.getField(fieldName);
203
+ }
204
+
205
+ /**
206
+ * Field Mutation (Set)
207
+ * e.g. self.myField = 10
208
+ */
209
+ public setField(obj: YuValue, fieldName: string, value: YuValue): YuValue {
210
+ if (!this.context.config.mutability)
211
+ throw new InterpreterError(
212
+ "FieldAssignment",
213
+ `Cannot mutate field '${fieldName}': mutability is disabled`,
214
+ );
215
+
216
+ const receiver = this.getReceiver(obj);
217
+
218
+ if (!isRuntimeObject(receiver))
219
+ throw new InterpreterError("FieldAssignment", "Target is not an object");
220
+
221
+ receiver.setField(fieldName, value);
222
+ return new YuBoolean(true);
223
+ }
224
+
225
+ private getReceiver(obj: YuValue): OOPEntity {
226
+ if (isRuntimeObject(obj) || isRuntimeClass(obj)) return obj;
227
+ throw new InterpreterError(
228
+ "ObjectRuntime",
229
+ "Receiver is not an OOP entity",
230
+ );
231
+ }
232
+
233
+ public dispatchPrimitive(
234
+ receiver: YuValue,
235
+ methodName: string,
236
+ args: YuValue[],
237
+ ): ExecutionCommand {
238
+ if (!receiver || receiver.isNil)
239
+ return new StepCommand(YuNil.getInstance());
240
+ // Obtenemos el identificador polimórfico del tipo (ej: "YuArray", "YuNumber", "YuString", "RuntimeFunction")
241
+ const typeKey = receiver.constructor.name;
242
+ const lookupKey = `${typeKey}.${methodName}`;
243
+
244
+ // Buscamos si el ecosistema/lenguaje proveyó una implementación externa para este caso
245
+ const nativeImpl = this.context.config.nativeProviders.get(lookupKey);
246
+
247
+ if (nativeImpl) {
248
+ // Delegamos la subtarea de forma declarativa pasándole el receptor como contexto
249
+ return new BindCommand(
250
+ nativeImpl(receiver, args, this.context),
251
+ (res) => new StepCommand(res),
252
+ );
253
+ }
254
+
255
+ return raise(
256
+ error(
257
+ "ObjectRuntime.dispatch",
258
+ `Primitive type '${typeKey}' does not understand method '${methodName}'.`,
259
+ ),
260
+ );
261
+ }
262
+ }
@@ -1,47 +1,68 @@
1
- import { SourceLocation } from "yukigo-ast";
2
-
3
- export interface ErrorFrame {
4
- nodeType: string;
5
- loc?: SourceLocation;
6
- }
7
-
8
- export class InterpreterError extends Error {
9
- context: string;
10
- frames: ErrorFrame[];
11
-
12
- constructor(context: string, message: string, frames: ErrorFrame[] = []) {
13
- super(`[${context}] ${message}`);
14
- this.context = context;
15
- this.frames = frames;
16
- }
17
-
18
- pushFrame(frame: ErrorFrame) {
19
- this.frames.push(frame);
20
- }
21
-
22
- formatStack(): string {
23
- if (!this.frames.length) return "";
24
- const formatted = this.frames
25
- .map((f) => {
26
- const loc = f.loc ? ` (line ${f.loc.line}, col ${f.loc.column})` : "";
27
- return ` • ${f.nodeType}${loc}`;
28
- })
29
- .join("\n");
30
- return `\nTrace:\n${formatted}`;
31
- }
32
-
33
- override toString(): string {
34
- return `${this.message}${this.formatStack()}`;
35
- }
36
- }
37
- export class UnexpectedValue extends InterpreterError {
38
- constructor(ctx: string, expected: string, got: string) {
39
- super(ctx, `Expected ${expected} but got ${got}`);
40
- }
41
- }
42
-
43
- export class UnboundVariable extends Error {
44
- constructor(name: string) {
45
- super(`Unbound variable: ${name}`);
46
- }
47
- }
1
+ import { SourceLocation } from "yukigo-ast";
2
+ import { YuValue } from "./primitives/YuValue.js";
3
+
4
+ export interface ErrorFrame {
5
+ nodeType: string;
6
+ loc?: SourceLocation;
7
+ }
8
+
9
+ export class InterpreterError extends Error {
10
+ context: string;
11
+ frames: ErrorFrame[];
12
+
13
+ constructor(context: string, message: string, frames: ErrorFrame[] = []) {
14
+ super(`[${context}] ${message}`);
15
+ this.context = context;
16
+ this.frames = frames;
17
+ this.name = "InterpreterError";
18
+ }
19
+
20
+ pushFrame(frame: ErrorFrame) {
21
+ this.frames.push(frame);
22
+ }
23
+
24
+ formatStack(): string {
25
+ if (!this.frames.length) return "";
26
+ const formatted = this.frames
27
+ .map((f) => {
28
+ const loc = f.loc ? ` (line ${f.loc.line}, col ${f.loc.column})` : "";
29
+ return ` • ${f.nodeType}${loc}`;
30
+ })
31
+ .join("\n");
32
+ return `\nTrace:\n${formatted}`;
33
+ }
34
+
35
+ override toString(): string {
36
+ return `${this.message}${this.formatStack()}`;
37
+ }
38
+ }
39
+
40
+ export class UnexpectedNode extends InterpreterError {
41
+ constructor(nodeCons: string, context: string) {
42
+ super(context, `${nodeCons} not expected in ${context}.`);
43
+ this.name = "UnexpectedNode";
44
+ }
45
+ }
46
+ export class UnexpectedValue extends InterpreterError {
47
+ constructor(ctx: string, expected: string, got: string) {
48
+ super(ctx, `Expected ${expected} but got ${got}`);
49
+ }
50
+ }
51
+
52
+ export class UnboundVariable extends Error {
53
+ constructor(name: string) {
54
+ super(`Unbound variable: ${name}`);
55
+ }
56
+ }
57
+
58
+ export class NotConcatenable extends InterpreterError {
59
+ constructor() {
60
+ super("[Concat]", "Cannot concat non-concatenable types.");
61
+ }
62
+ }
63
+
64
+ export class UnsupportedOperation extends InterpreterError {
65
+ constructor(val: YuValue, op: string) {
66
+ super("[Unsupported]", `${val.getType()} does not support '${op}'`);
67
+ }
68
+ }