@vibe-lang/runtime 0.2.5

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 (250) hide show
  1. package/package.json +46 -0
  2. package/src/ast/index.ts +375 -0
  3. package/src/ast.ts +2 -0
  4. package/src/debug/advanced-features.ts +482 -0
  5. package/src/debug/bun-inspector.ts +424 -0
  6. package/src/debug/handoff-manager.ts +283 -0
  7. package/src/debug/index.ts +150 -0
  8. package/src/debug/runner.ts +365 -0
  9. package/src/debug/server.ts +565 -0
  10. package/src/debug/stack-merger.ts +267 -0
  11. package/src/debug/state.ts +581 -0
  12. package/src/debug/test/advanced-features.test.ts +300 -0
  13. package/src/debug/test/e2e.test.ts +218 -0
  14. package/src/debug/test/handoff-manager.test.ts +256 -0
  15. package/src/debug/test/runner.test.ts +256 -0
  16. package/src/debug/test/stack-merger.test.ts +163 -0
  17. package/src/debug/test/state.test.ts +400 -0
  18. package/src/debug/test/ts-debug-integration.test.ts +374 -0
  19. package/src/debug/test/ts-import-tracker.test.ts +125 -0
  20. package/src/debug/test/ts-source-map.test.ts +169 -0
  21. package/src/debug/ts-import-tracker.ts +151 -0
  22. package/src/debug/ts-source-map.ts +171 -0
  23. package/src/errors/index.ts +124 -0
  24. package/src/index.ts +358 -0
  25. package/src/lexer/index.ts +348 -0
  26. package/src/lexer.ts +2 -0
  27. package/src/parser/index.ts +792 -0
  28. package/src/parser/parse.ts +45 -0
  29. package/src/parser/test/async.test.ts +248 -0
  30. package/src/parser/test/destructuring.test.ts +167 -0
  31. package/src/parser/test/do-expression.test.ts +486 -0
  32. package/src/parser/test/errors/do-expression.test.ts +95 -0
  33. package/src/parser/test/errors/error-locations.test.ts +230 -0
  34. package/src/parser/test/errors/invalid-expressions.test.ts +144 -0
  35. package/src/parser/test/errors/missing-tokens.test.ts +126 -0
  36. package/src/parser/test/errors/model-declaration.test.ts +185 -0
  37. package/src/parser/test/errors/nested-blocks.test.ts +226 -0
  38. package/src/parser/test/errors/unclosed-delimiters.test.ts +122 -0
  39. package/src/parser/test/errors/unexpected-tokens.test.ts +120 -0
  40. package/src/parser/test/import-export.test.ts +143 -0
  41. package/src/parser/test/literals.test.ts +404 -0
  42. package/src/parser/test/model-declaration.test.ts +161 -0
  43. package/src/parser/test/nested-blocks.test.ts +402 -0
  44. package/src/parser/test/parser.test.ts +743 -0
  45. package/src/parser/test/private.test.ts +136 -0
  46. package/src/parser/test/template-literal.test.ts +127 -0
  47. package/src/parser/test/tool-declaration.test.ts +302 -0
  48. package/src/parser/test/ts-block.test.ts +252 -0
  49. package/src/parser/test/type-annotations.test.ts +254 -0
  50. package/src/parser/visitor/helpers.ts +330 -0
  51. package/src/parser/visitor.ts +794 -0
  52. package/src/parser.ts +2 -0
  53. package/src/runtime/ai/cache-chunking.test.ts +69 -0
  54. package/src/runtime/ai/cache-chunking.ts +73 -0
  55. package/src/runtime/ai/client.ts +109 -0
  56. package/src/runtime/ai/context.ts +168 -0
  57. package/src/runtime/ai/formatters.ts +316 -0
  58. package/src/runtime/ai/index.ts +38 -0
  59. package/src/runtime/ai/language-ref.ts +38 -0
  60. package/src/runtime/ai/providers/anthropic.ts +253 -0
  61. package/src/runtime/ai/providers/google.ts +201 -0
  62. package/src/runtime/ai/providers/openai.ts +156 -0
  63. package/src/runtime/ai/retry.ts +100 -0
  64. package/src/runtime/ai/return-tools.ts +301 -0
  65. package/src/runtime/ai/test/client.test.ts +83 -0
  66. package/src/runtime/ai/test/formatters.test.ts +485 -0
  67. package/src/runtime/ai/test/retry.test.ts +137 -0
  68. package/src/runtime/ai/test/return-tools.test.ts +450 -0
  69. package/src/runtime/ai/test/tool-loop.test.ts +319 -0
  70. package/src/runtime/ai/test/tool-schema.test.ts +241 -0
  71. package/src/runtime/ai/tool-loop.ts +203 -0
  72. package/src/runtime/ai/tool-schema.ts +151 -0
  73. package/src/runtime/ai/types.ts +113 -0
  74. package/src/runtime/ai-logger.ts +255 -0
  75. package/src/runtime/ai-provider.ts +347 -0
  76. package/src/runtime/async/dependencies.ts +276 -0
  77. package/src/runtime/async/executor.ts +293 -0
  78. package/src/runtime/async/index.ts +43 -0
  79. package/src/runtime/async/scheduling.ts +163 -0
  80. package/src/runtime/async/test/dependencies.test.ts +284 -0
  81. package/src/runtime/async/test/executor.test.ts +388 -0
  82. package/src/runtime/context.ts +357 -0
  83. package/src/runtime/exec/ai.ts +139 -0
  84. package/src/runtime/exec/expressions.ts +475 -0
  85. package/src/runtime/exec/frames.ts +26 -0
  86. package/src/runtime/exec/functions.ts +305 -0
  87. package/src/runtime/exec/interpolation.ts +312 -0
  88. package/src/runtime/exec/statements.ts +604 -0
  89. package/src/runtime/exec/tools.ts +129 -0
  90. package/src/runtime/exec/typescript.ts +215 -0
  91. package/src/runtime/exec/variables.ts +279 -0
  92. package/src/runtime/index.ts +975 -0
  93. package/src/runtime/modules.ts +452 -0
  94. package/src/runtime/serialize.ts +103 -0
  95. package/src/runtime/state.ts +489 -0
  96. package/src/runtime/stdlib/core.ts +45 -0
  97. package/src/runtime/stdlib/directory.test.ts +156 -0
  98. package/src/runtime/stdlib/edit.test.ts +154 -0
  99. package/src/runtime/stdlib/fastEdit.test.ts +201 -0
  100. package/src/runtime/stdlib/glob.test.ts +106 -0
  101. package/src/runtime/stdlib/grep.test.ts +144 -0
  102. package/src/runtime/stdlib/index.ts +16 -0
  103. package/src/runtime/stdlib/readFile.test.ts +123 -0
  104. package/src/runtime/stdlib/tools/index.ts +707 -0
  105. package/src/runtime/stdlib/writeFile.test.ts +157 -0
  106. package/src/runtime/step.ts +969 -0
  107. package/src/runtime/test/ai-context.test.ts +1086 -0
  108. package/src/runtime/test/ai-result-object.test.ts +419 -0
  109. package/src/runtime/test/ai-tool-flow.test.ts +859 -0
  110. package/src/runtime/test/async-execution-order.test.ts +618 -0
  111. package/src/runtime/test/async-execution.test.ts +344 -0
  112. package/src/runtime/test/async-nested.test.ts +660 -0
  113. package/src/runtime/test/async-parallel-timing.test.ts +546 -0
  114. package/src/runtime/test/basic1.test.ts +154 -0
  115. package/src/runtime/test/binary-operators.test.ts +431 -0
  116. package/src/runtime/test/break-statement.test.ts +257 -0
  117. package/src/runtime/test/context-modes.test.ts +650 -0
  118. package/src/runtime/test/context.test.ts +466 -0
  119. package/src/runtime/test/core-functions.test.ts +228 -0
  120. package/src/runtime/test/e2e.test.ts +88 -0
  121. package/src/runtime/test/error-locations/error-locations.test.ts +80 -0
  122. package/src/runtime/test/error-locations/main-error.vibe +4 -0
  123. package/src/runtime/test/error-locations/main-import-error.vibe +3 -0
  124. package/src/runtime/test/error-locations/utils/helper.vibe +5 -0
  125. package/src/runtime/test/for-in.test.ts +312 -0
  126. package/src/runtime/test/helpers.ts +69 -0
  127. package/src/runtime/test/imports.test.ts +334 -0
  128. package/src/runtime/test/json-expressions.test.ts +232 -0
  129. package/src/runtime/test/literals.test.ts +372 -0
  130. package/src/runtime/test/logical-indexing.test.ts +478 -0
  131. package/src/runtime/test/member-methods.test.ts +324 -0
  132. package/src/runtime/test/model-config.test.ts +338 -0
  133. package/src/runtime/test/null-handling.test.ts +342 -0
  134. package/src/runtime/test/private-visibility.test.ts +332 -0
  135. package/src/runtime/test/runtime-state.test.ts +514 -0
  136. package/src/runtime/test/scoping.test.ts +370 -0
  137. package/src/runtime/test/string-interpolation.test.ts +354 -0
  138. package/src/runtime/test/template-literal.test.ts +181 -0
  139. package/src/runtime/test/tool-execution.test.ts +467 -0
  140. package/src/runtime/test/tool-schema-generation.test.ts +477 -0
  141. package/src/runtime/test/tostring.test.ts +210 -0
  142. package/src/runtime/test/ts-block.test.ts +594 -0
  143. package/src/runtime/test/ts-error-location.test.ts +231 -0
  144. package/src/runtime/test/types.test.ts +732 -0
  145. package/src/runtime/test/verbose-logger.test.ts +710 -0
  146. package/src/runtime/test/vibe-expression.test.ts +54 -0
  147. package/src/runtime/test/vibe-value-errors.test.ts +541 -0
  148. package/src/runtime/test/while.test.ts +232 -0
  149. package/src/runtime/tools/builtin.ts +30 -0
  150. package/src/runtime/tools/directory-tools.ts +70 -0
  151. package/src/runtime/tools/file-tools.ts +228 -0
  152. package/src/runtime/tools/index.ts +5 -0
  153. package/src/runtime/tools/registry.ts +48 -0
  154. package/src/runtime/tools/search-tools.ts +134 -0
  155. package/src/runtime/tools/security.ts +36 -0
  156. package/src/runtime/tools/system-tools.ts +312 -0
  157. package/src/runtime/tools/test/fixtures/base-types.ts +40 -0
  158. package/src/runtime/tools/test/fixtures/test-types.ts +132 -0
  159. package/src/runtime/tools/test/registry.test.ts +713 -0
  160. package/src/runtime/tools/test/security.test.ts +86 -0
  161. package/src/runtime/tools/test/system-tools.test.ts +679 -0
  162. package/src/runtime/tools/test/ts-schema.test.ts +357 -0
  163. package/src/runtime/tools/ts-schema.ts +341 -0
  164. package/src/runtime/tools/types.ts +89 -0
  165. package/src/runtime/tools/utility-tools.ts +198 -0
  166. package/src/runtime/ts-eval.ts +126 -0
  167. package/src/runtime/types.ts +797 -0
  168. package/src/runtime/validation.ts +160 -0
  169. package/src/runtime/verbose-logger.ts +459 -0
  170. package/src/runtime.ts +2 -0
  171. package/src/semantic/analyzer-context.ts +62 -0
  172. package/src/semantic/analyzer-validators.ts +575 -0
  173. package/src/semantic/analyzer-visitors.ts +534 -0
  174. package/src/semantic/analyzer.ts +83 -0
  175. package/src/semantic/index.ts +11 -0
  176. package/src/semantic/symbol-table.ts +58 -0
  177. package/src/semantic/test/async-validation.test.ts +301 -0
  178. package/src/semantic/test/compress-validation.test.ts +179 -0
  179. package/src/semantic/test/const-reassignment.test.ts +111 -0
  180. package/src/semantic/test/control-flow.test.ts +346 -0
  181. package/src/semantic/test/destructuring.test.ts +185 -0
  182. package/src/semantic/test/duplicate-declarations.test.ts +168 -0
  183. package/src/semantic/test/export-validation.test.ts +111 -0
  184. package/src/semantic/test/fixtures/math.ts +31 -0
  185. package/src/semantic/test/imports.test.ts +148 -0
  186. package/src/semantic/test/json-type.test.ts +68 -0
  187. package/src/semantic/test/literals.test.ts +127 -0
  188. package/src/semantic/test/model-validation.test.ts +179 -0
  189. package/src/semantic/test/prompt-validation.test.ts +343 -0
  190. package/src/semantic/test/scoping.test.ts +312 -0
  191. package/src/semantic/test/tool-validation.test.ts +306 -0
  192. package/src/semantic/test/ts-type-checking.test.ts +563 -0
  193. package/src/semantic/test/type-constraints.test.ts +111 -0
  194. package/src/semantic/test/type-inference.test.ts +87 -0
  195. package/src/semantic/test/type-validation.test.ts +552 -0
  196. package/src/semantic/test/undefined-variables.test.ts +163 -0
  197. package/src/semantic/ts-block-checker.ts +204 -0
  198. package/src/semantic/ts-signatures.ts +194 -0
  199. package/src/semantic/ts-types.ts +170 -0
  200. package/src/semantic/types.ts +58 -0
  201. package/tests/fixtures/conditional-logic.vibe +14 -0
  202. package/tests/fixtures/function-call.vibe +16 -0
  203. package/tests/fixtures/imports/cycle-detection/a.vibe +6 -0
  204. package/tests/fixtures/imports/cycle-detection/b.vibe +5 -0
  205. package/tests/fixtures/imports/cycle-detection/main.vibe +3 -0
  206. package/tests/fixtures/imports/module-isolation/main-b.vibe +8 -0
  207. package/tests/fixtures/imports/module-isolation/main.vibe +9 -0
  208. package/tests/fixtures/imports/module-isolation/moduleA.vibe +6 -0
  209. package/tests/fixtures/imports/module-isolation/moduleB.vibe +6 -0
  210. package/tests/fixtures/imports/nested-import/helper.vibe +6 -0
  211. package/tests/fixtures/imports/nested-import/main.vibe +3 -0
  212. package/tests/fixtures/imports/nested-import/utils.ts +3 -0
  213. package/tests/fixtures/imports/nested-isolation/file2.vibe +15 -0
  214. package/tests/fixtures/imports/nested-isolation/file3.vibe +10 -0
  215. package/tests/fixtures/imports/nested-isolation/main.vibe +21 -0
  216. package/tests/fixtures/imports/pure-cycle/a.vibe +5 -0
  217. package/tests/fixtures/imports/pure-cycle/b.vibe +5 -0
  218. package/tests/fixtures/imports/pure-cycle/main.vibe +3 -0
  219. package/tests/fixtures/imports/ts-boolean/checks.ts +14 -0
  220. package/tests/fixtures/imports/ts-boolean/main.vibe +10 -0
  221. package/tests/fixtures/imports/ts-boolean/type-mismatch.vibe +5 -0
  222. package/tests/fixtures/imports/ts-boolean/use-constant.vibe +18 -0
  223. package/tests/fixtures/imports/ts-error-handling/helpers.ts +42 -0
  224. package/tests/fixtures/imports/ts-error-handling/main.vibe +5 -0
  225. package/tests/fixtures/imports/ts-import/main.vibe +4 -0
  226. package/tests/fixtures/imports/ts-import/math.ts +9 -0
  227. package/tests/fixtures/imports/ts-variables/call-non-function.vibe +5 -0
  228. package/tests/fixtures/imports/ts-variables/data.ts +10 -0
  229. package/tests/fixtures/imports/ts-variables/import-json.vibe +5 -0
  230. package/tests/fixtures/imports/ts-variables/import-type-mismatch.vibe +5 -0
  231. package/tests/fixtures/imports/ts-variables/import-variable.vibe +5 -0
  232. package/tests/fixtures/imports/vibe-import/greet.vibe +5 -0
  233. package/tests/fixtures/imports/vibe-import/main.vibe +3 -0
  234. package/tests/fixtures/multiple-ai-calls.vibe +10 -0
  235. package/tests/fixtures/simple-greeting.vibe +6 -0
  236. package/tests/fixtures/template-literals.vibe +11 -0
  237. package/tests/integration/basic-ai/basic-ai.integration.test.ts +166 -0
  238. package/tests/integration/basic-ai/basic-ai.vibe +12 -0
  239. package/tests/integration/bug-fix/bug-fix.integration.test.ts +201 -0
  240. package/tests/integration/bug-fix/buggy-code.ts +22 -0
  241. package/tests/integration/bug-fix/fix-bug.vibe +21 -0
  242. package/tests/integration/compress/compress.integration.test.ts +206 -0
  243. package/tests/integration/destructuring/destructuring.integration.test.ts +92 -0
  244. package/tests/integration/hello-world-translator/hello-world-translator.integration.test.ts +61 -0
  245. package/tests/integration/line-annotator/context-modes.integration.test.ts +261 -0
  246. package/tests/integration/line-annotator/line-annotator.integration.test.ts +148 -0
  247. package/tests/integration/multi-feature/cumulative-sum.integration.test.ts +75 -0
  248. package/tests/integration/multi-feature/number-analyzer.integration.test.ts +191 -0
  249. package/tests/integration/multi-feature/number-analyzer.vibe +59 -0
  250. package/tests/integration/tool-calls/tool-calls.integration.test.ts +93 -0
@@ -0,0 +1,478 @@
1
+ import { describe, expect, test } from 'bun:test';
2
+ import { parse } from '../../parser/parse';
3
+ import { Runtime, AIProvider } from '../index';
4
+
5
+ // Mock AI provider
6
+ function createMockProvider(): AIProvider {
7
+ return {
8
+ async execute() {
9
+ return { value: '' };
10
+ },
11
+ async generateCode() {
12
+ return { value: '' };
13
+ },
14
+ async askUser(): Promise<string> {
15
+ return '';
16
+ },
17
+ };
18
+ }
19
+
20
+ describe('Logical Operators - and', () => {
21
+ test('true and true = true', async () => {
22
+ const ast = parse(`let result = true and true`);
23
+ const runtime = new Runtime(ast, createMockProvider());
24
+ await runtime.run();
25
+ expect(runtime.getValue('result')).toBe(true);
26
+ });
27
+
28
+ test('true and false = false', async () => {
29
+ const ast = parse(`let result = true and false`);
30
+ const runtime = new Runtime(ast, createMockProvider());
31
+ await runtime.run();
32
+ expect(runtime.getValue('result')).toBe(false);
33
+ });
34
+
35
+ test('false and true = false', async () => {
36
+ const ast = parse(`let result = false and true`);
37
+ const runtime = new Runtime(ast, createMockProvider());
38
+ await runtime.run();
39
+ expect(runtime.getValue('result')).toBe(false);
40
+ });
41
+
42
+ test('false and false = false', async () => {
43
+ const ast = parse(`let result = false and false`);
44
+ const runtime = new Runtime(ast, createMockProvider());
45
+ await runtime.run();
46
+ expect(runtime.getValue('result')).toBe(false);
47
+ });
48
+
49
+ test('chained and: true and true and true = true', async () => {
50
+ const ast = parse(`let result = true and true and true`);
51
+ const runtime = new Runtime(ast, createMockProvider());
52
+ await runtime.run();
53
+ expect(runtime.getValue('result')).toBe(true);
54
+ });
55
+
56
+ test('chained and with false: true and false and true = false', async () => {
57
+ const ast = parse(`let result = true and false and true`);
58
+ const runtime = new Runtime(ast, createMockProvider());
59
+ await runtime.run();
60
+ expect(runtime.getValue('result')).toBe(false);
61
+ });
62
+ });
63
+
64
+ describe('Logical Operators - or', () => {
65
+ test('true or true = true', async () => {
66
+ const ast = parse(`let result = true or true`);
67
+ const runtime = new Runtime(ast, createMockProvider());
68
+ await runtime.run();
69
+ expect(runtime.getValue('result')).toBe(true);
70
+ });
71
+
72
+ test('true or false = true', async () => {
73
+ const ast = parse(`let result = true or false`);
74
+ const runtime = new Runtime(ast, createMockProvider());
75
+ await runtime.run();
76
+ expect(runtime.getValue('result')).toBe(true);
77
+ });
78
+
79
+ test('false or true = true', async () => {
80
+ const ast = parse(`let result = false or true`);
81
+ const runtime = new Runtime(ast, createMockProvider());
82
+ await runtime.run();
83
+ expect(runtime.getValue('result')).toBe(true);
84
+ });
85
+
86
+ test('false or false = false', async () => {
87
+ const ast = parse(`let result = false or false`);
88
+ const runtime = new Runtime(ast, createMockProvider());
89
+ await runtime.run();
90
+ expect(runtime.getValue('result')).toBe(false);
91
+ });
92
+
93
+ test('chained or: false or false or true = true', async () => {
94
+ const ast = parse(`let result = false or false or true`);
95
+ const runtime = new Runtime(ast, createMockProvider());
96
+ await runtime.run();
97
+ expect(runtime.getValue('result')).toBe(true);
98
+ });
99
+ });
100
+
101
+ describe('Logical Operators - not', () => {
102
+ test('not true = false', async () => {
103
+ const ast = parse(`let result = not true`);
104
+ const runtime = new Runtime(ast, createMockProvider());
105
+ await runtime.run();
106
+ expect(runtime.getValue('result')).toBe(false);
107
+ });
108
+
109
+ test('not false = true', async () => {
110
+ const ast = parse(`let result = not false`);
111
+ const runtime = new Runtime(ast, createMockProvider());
112
+ await runtime.run();
113
+ expect(runtime.getValue('result')).toBe(true);
114
+ });
115
+
116
+ test('not not true = true', async () => {
117
+ const ast = parse(`let result = not not true`);
118
+ const runtime = new Runtime(ast, createMockProvider());
119
+ await runtime.run();
120
+ expect(runtime.getValue('result')).toBe(true);
121
+ });
122
+ });
123
+
124
+ describe('Logical Operators - Combined', () => {
125
+ test('and has higher precedence than or: true or false and false = true', async () => {
126
+ // Should be: true or (false and false) = true or false = true
127
+ const ast = parse(`let result = true or false and false`);
128
+ const runtime = new Runtime(ast, createMockProvider());
129
+ await runtime.run();
130
+ expect(runtime.getValue('result')).toBe(true);
131
+ });
132
+
133
+ test('parentheses override: (true or false) and false = false', async () => {
134
+ const ast = parse(`let result = (true or false) and false`);
135
+ const runtime = new Runtime(ast, createMockProvider());
136
+ await runtime.run();
137
+ expect(runtime.getValue('result')).toBe(false);
138
+ });
139
+
140
+ test('not with and: not true and true = false', async () => {
141
+ // Should be: (not true) and true = false and true = false
142
+ const ast = parse(`let result = not true and true`);
143
+ const runtime = new Runtime(ast, createMockProvider());
144
+ await runtime.run();
145
+ expect(runtime.getValue('result')).toBe(false);
146
+ });
147
+
148
+ test('not with or: not false or false = true', async () => {
149
+ // Should be: (not false) or false = true or false = true
150
+ const ast = parse(`let result = not false or false`);
151
+ const runtime = new Runtime(ast, createMockProvider());
152
+ await runtime.run();
153
+ expect(runtime.getValue('result')).toBe(true);
154
+ });
155
+
156
+ test('logical with comparison: 1 < 2 and 3 > 1 = true', async () => {
157
+ const ast = parse(`let result = 1 < 2 and 3 > 1`);
158
+ const runtime = new Runtime(ast, createMockProvider());
159
+ await runtime.run();
160
+ expect(runtime.getValue('result')).toBe(true);
161
+ });
162
+
163
+ test('logical in if condition', async () => {
164
+ const ast = parse(`
165
+ let x = 5
166
+ let y = 10
167
+ let result = "none"
168
+ if x < 10 and y > 5 {
169
+ result = "both true"
170
+ }
171
+ `);
172
+ const runtime = new Runtime(ast, createMockProvider());
173
+ await runtime.run();
174
+ expect(runtime.getValue('result')).toBe('both true');
175
+ });
176
+ });
177
+
178
+ describe('Array Indexing - Basic', () => {
179
+ test('access first element: arr[0]', async () => {
180
+ const ast = parse(`
181
+ let arr = [10, 20, 30]
182
+ let result = arr[0]
183
+ `);
184
+ const runtime = new Runtime(ast, createMockProvider());
185
+ await runtime.run();
186
+ expect(runtime.getValue('result')).toBe(10);
187
+ });
188
+
189
+ test('access second element: arr[1]', async () => {
190
+ const ast = parse(`
191
+ let arr = [10, 20, 30]
192
+ let result = arr[1]
193
+ `);
194
+ const runtime = new Runtime(ast, createMockProvider());
195
+ await runtime.run();
196
+ expect(runtime.getValue('result')).toBe(20);
197
+ });
198
+
199
+ test('access last element: arr[2]', async () => {
200
+ const ast = parse(`
201
+ let arr = [10, 20, 30]
202
+ let result = arr[2]
203
+ `);
204
+ const runtime = new Runtime(ast, createMockProvider());
205
+ await runtime.run();
206
+ expect(runtime.getValue('result')).toBe(30);
207
+ });
208
+
209
+ test('access with variable index', async () => {
210
+ const ast = parse(`
211
+ let arr = ["a", "b", "c"]
212
+ let i = 1
213
+ let result = arr[i]
214
+ `);
215
+ const runtime = new Runtime(ast, createMockProvider());
216
+ await runtime.run();
217
+ expect(runtime.getValue('result')).toBe('b');
218
+ });
219
+
220
+ test('access with expression index', async () => {
221
+ const ast = parse(`
222
+ let arr = [100, 200, 300]
223
+ let result = arr[1 + 1]
224
+ `);
225
+ const runtime = new Runtime(ast, createMockProvider());
226
+ await runtime.run();
227
+ expect(runtime.getValue('result')).toBe(300);
228
+ });
229
+
230
+ test('chained array access', async () => {
231
+ const ast = parse(`
232
+ let matrix = [[1, 2], [3, 4], [5, 6]]
233
+ let result = matrix[1][0]
234
+ `);
235
+ const runtime = new Runtime(ast, createMockProvider());
236
+ await runtime.run();
237
+ expect(runtime.getValue('result')).toBe(3);
238
+ });
239
+ });
240
+
241
+ describe('Array Slicing - Basic (Python-style, exclusive end)', () => {
242
+ test('slice with both bounds: arr[1:4]', async () => {
243
+ const ast = parse(`
244
+ let arr = [10, 20, 30, 40, 50]
245
+ let result = arr[1:4]
246
+ `);
247
+ const runtime = new Runtime(ast, createMockProvider());
248
+ await runtime.run();
249
+ // Python-style: indices 1, 2, 3 (end is exclusive)
250
+ expect(runtime.getValue('result')).toEqual([20, 30, 40]);
251
+ });
252
+
253
+ test('slice from start: arr[:3]', async () => {
254
+ const ast = parse(`
255
+ let arr = [10, 20, 30, 40, 50]
256
+ let result = arr[:3]
257
+ `);
258
+ const runtime = new Runtime(ast, createMockProvider());
259
+ await runtime.run();
260
+ // Python-style: indices 0, 1, 2
261
+ expect(runtime.getValue('result')).toEqual([10, 20, 30]);
262
+ });
263
+
264
+ test('slice to end: arr[2:]', async () => {
265
+ const ast = parse(`
266
+ let arr = [10, 20, 30, 40, 50]
267
+ let result = arr[2:]
268
+ `);
269
+ const runtime = new Runtime(ast, createMockProvider());
270
+ await runtime.run();
271
+ // indices 2, 3, 4
272
+ expect(runtime.getValue('result')).toEqual([30, 40, 50]);
273
+ });
274
+
275
+ test('slice with variable bounds', async () => {
276
+ const ast = parse(`
277
+ let arr = [1, 2, 3, 4, 5]
278
+ let start = 1
279
+ let end = 4
280
+ let result = arr[start:end]
281
+ `);
282
+ const runtime = new Runtime(ast, createMockProvider());
283
+ await runtime.run();
284
+ // indices 1, 2, 3
285
+ expect(runtime.getValue('result')).toEqual([2, 3, 4]);
286
+ });
287
+
288
+ test('slice single element: arr[2:3]', async () => {
289
+ const ast = parse(`
290
+ let arr = [10, 20, 30, 40, 50]
291
+ let result = arr[2:3]
292
+ `);
293
+ const runtime = new Runtime(ast, createMockProvider());
294
+ await runtime.run();
295
+ // index 2 only
296
+ expect(runtime.getValue('result')).toEqual([30]);
297
+ });
298
+
299
+ test('slice first element: arr[0:1]', async () => {
300
+ const ast = parse(`
301
+ let arr = [10, 20, 30]
302
+ let result = arr[0:1]
303
+ `);
304
+ const runtime = new Runtime(ast, createMockProvider());
305
+ await runtime.run();
306
+ // index 0 only
307
+ expect(runtime.getValue('result')).toEqual([10]);
308
+ });
309
+
310
+ test('empty slice: arr[2:2]', async () => {
311
+ const ast = parse(`
312
+ let arr = [10, 20, 30]
313
+ let result = arr[2:2]
314
+ `);
315
+ const runtime = new Runtime(ast, createMockProvider());
316
+ await runtime.run();
317
+ // Python-style: empty when start == end
318
+ expect(runtime.getValue('result')).toEqual([]);
319
+ });
320
+
321
+ test('full slice: arr[:]', async () => {
322
+ const ast = parse(`
323
+ let arr = [10, 20, 30]
324
+ let result = arr[:]
325
+ `);
326
+ const runtime = new Runtime(ast, createMockProvider());
327
+ await runtime.run();
328
+ expect(runtime.getValue('result')).toEqual([10, 20, 30]);
329
+ });
330
+
331
+ test('negative index: arr[-1]', async () => {
332
+ const ast = parse(`
333
+ let arr = [10, 20, 30, 40, 50]
334
+ let last = arr[-1]
335
+ let secondLast = arr[-2]
336
+ `);
337
+ const runtime = new Runtime(ast, createMockProvider());
338
+ await runtime.run();
339
+ expect(runtime.getValue('last')).toBe(50);
340
+ expect(runtime.getValue('secondLast')).toBe(40);
341
+ });
342
+
343
+ test('negative slice: arr[-2:]', async () => {
344
+ const ast = parse(`
345
+ let arr = [10, 20, 30, 40, 50]
346
+ let lastTwo = arr[-2:]
347
+ `);
348
+ const runtime = new Runtime(ast, createMockProvider());
349
+ await runtime.run();
350
+ expect(runtime.getValue('lastTwo')).toEqual([40, 50]);
351
+ });
352
+
353
+ test('negative end slice: arr[:-1]', async () => {
354
+ const ast = parse(`
355
+ let arr = [10, 20, 30, 40, 50]
356
+ let allButLast = arr[:-1]
357
+ `);
358
+ const runtime = new Runtime(ast, createMockProvider());
359
+ await runtime.run();
360
+ // Python-style: all but last element
361
+ expect(runtime.getValue('allButLast')).toEqual([10, 20, 30, 40]);
362
+ });
363
+
364
+ test('negative end slice: arr[:-2]', async () => {
365
+ const ast = parse(`
366
+ let arr = [10, 20, 30, 40, 50]
367
+ let allButLastTwo = arr[:-2]
368
+ `);
369
+ const runtime = new Runtime(ast, createMockProvider());
370
+ await runtime.run();
371
+ // Python-style: all but last two elements
372
+ expect(runtime.getValue('allButLastTwo')).toEqual([10, 20, 30]);
373
+ });
374
+ });
375
+
376
+ describe('Array Access in Loops', () => {
377
+ test('iterate and access by index', async () => {
378
+ const ast = parse(`
379
+ let arr = [10, 20, 30]
380
+ let sum = 0
381
+ for i in 3 {
382
+ let idx = i - 1
383
+ sum = sum + arr[idx]
384
+ }
385
+ `);
386
+ const runtime = new Runtime(ast, createMockProvider());
387
+ await runtime.run();
388
+ expect(runtime.getValue('sum')).toBe(60);
389
+ });
390
+
391
+ test('build new array from slices', async () => {
392
+ const ast = parse(`
393
+ let arr = [1, 2, 3, 4, 5]
394
+ let first = arr[:2]
395
+ let last = arr[3:]
396
+ `);
397
+ const runtime = new Runtime(ast, createMockProvider());
398
+ await runtime.run();
399
+ // Python-style: [:2] = indices 0, 1
400
+ expect(runtime.getValue('first')).toEqual([1, 2]);
401
+ // [3:] = indices 3, 4
402
+ expect(runtime.getValue('last')).toEqual([4, 5]);
403
+ });
404
+ });
405
+
406
+ describe('Unary Minus', () => {
407
+ test('negative number literal already works', async () => {
408
+ const ast = parse(`let result = -5`);
409
+ const runtime = new Runtime(ast, createMockProvider());
410
+ await runtime.run();
411
+ expect(runtime.getValue('result')).toBe(-5);
412
+ });
413
+
414
+ test('negate variable', async () => {
415
+ const ast = parse(`
416
+ let x = 10
417
+ let result = -x
418
+ `);
419
+ const runtime = new Runtime(ast, createMockProvider());
420
+ await runtime.run();
421
+ expect(runtime.getValue('result')).toBe(-10);
422
+ });
423
+
424
+ test('double negative', async () => {
425
+ const ast = parse(`
426
+ let x = 10
427
+ let result = - -x
428
+ `);
429
+ const runtime = new Runtime(ast, createMockProvider());
430
+ await runtime.run();
431
+ expect(runtime.getValue('result')).toBe(10);
432
+ });
433
+ });
434
+
435
+ describe('Combined Expressions', () => {
436
+ test('logical with indexing', async () => {
437
+ const ast = parse(`
438
+ let arr = [true, false, true]
439
+ let result = arr[0] and arr[2]
440
+ `);
441
+ const runtime = new Runtime(ast, createMockProvider());
442
+ await runtime.run();
443
+ expect(runtime.getValue('result')).toBe(true);
444
+ });
445
+
446
+ test('arithmetic with indexing', async () => {
447
+ const ast = parse(`
448
+ let arr = [10, 20, 30]
449
+ let result = arr[0] + arr[1] + arr[2]
450
+ `);
451
+ const runtime = new Runtime(ast, createMockProvider());
452
+ await runtime.run();
453
+ expect(runtime.getValue('result')).toBe(60);
454
+ });
455
+
456
+ test('comparison with indexing', async () => {
457
+ const ast = parse(`
458
+ let arr = [5, 10, 15]
459
+ let result = arr[0] < arr[1]
460
+ `);
461
+ const runtime = new Runtime(ast, createMockProvider());
462
+ await runtime.run();
463
+ expect(runtime.getValue('result')).toBe(true);
464
+ });
465
+
466
+ test('function call with index result', async () => {
467
+ const ast = parse(`
468
+ function double(n: number): number {
469
+ return n * 2
470
+ }
471
+ let arr = [5, 10, 15]
472
+ let result = double(arr[1])
473
+ `);
474
+ const runtime = new Runtime(ast, createMockProvider());
475
+ await runtime.run();
476
+ expect(runtime.getValue('result')).toBe(20);
477
+ });
478
+ });