@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,372 @@
1
+ import { describe, expect, test } from 'bun:test';
2
+ import { parse } from '../../parser/parse';
3
+ import { Runtime, type AIProvider } from '../index';
4
+
5
+ describe('Runtime - Object and Array Literals', () => {
6
+ const mockProvider: AIProvider = {
7
+ execute: async (prompt: string) => ({ value: prompt }),
8
+ generateCode: async () => ({ value: '' }),
9
+ askUser: async () => '',
10
+ };
11
+
12
+ function createRuntime(code: string): Runtime {
13
+ const ast = parse(code);
14
+ return new Runtime(ast, mockProvider);
15
+ }
16
+
17
+ // ============================================================================
18
+ // Object Literals
19
+ // ============================================================================
20
+
21
+ test('empty object literal', async () => {
22
+ const runtime = createRuntime('let x = {}');
23
+ await runtime.run();
24
+ expect(runtime.getValue('x')).toEqual({});
25
+ });
26
+
27
+ test('object literal with properties', async () => {
28
+ const runtime = createRuntime('let x = {name: "test", active: true}');
29
+ await runtime.run();
30
+ expect(runtime.getValue('x')).toEqual({ name: 'test', active: true });
31
+ });
32
+
33
+ test('nested object literal', async () => {
34
+ const runtime = createRuntime('let x = {user: {name: "alice", role: "admin"}}');
35
+ await runtime.run();
36
+ expect(runtime.getValue('x')).toEqual({
37
+ user: { name: 'alice', role: 'admin' },
38
+ });
39
+ });
40
+
41
+ test('object literal with variable reference', async () => {
42
+ const runtime = createRuntime(`
43
+ let name = "test"
44
+ let x = {title: name}
45
+ `);
46
+ await runtime.run();
47
+ expect(runtime.getValue('x')).toEqual({ title: 'test' });
48
+ });
49
+
50
+ // ============================================================================
51
+ // Array Literals
52
+ // ============================================================================
53
+
54
+ test('empty array literal', async () => {
55
+ const runtime = createRuntime('let x = []');
56
+ await runtime.run();
57
+ expect(runtime.getValue('x')).toEqual([]);
58
+ });
59
+
60
+ test('array literal with elements', async () => {
61
+ const runtime = createRuntime('let x = ["a", "b", "c"]');
62
+ await runtime.run();
63
+ expect(runtime.getValue('x')).toEqual(['a', 'b', 'c']);
64
+ });
65
+
66
+ test('array literal with mixed types', async () => {
67
+ const runtime = createRuntime('let x = ["text", true, false]');
68
+ await runtime.run();
69
+ expect(runtime.getValue('x')).toEqual(['text', true, false]);
70
+ });
71
+
72
+ test('nested array literal', async () => {
73
+ const runtime = createRuntime('let x = [["a"], ["b", "c"]]');
74
+ await runtime.run();
75
+ expect(runtime.getValue('x')).toEqual([['a'], ['b', 'c']]);
76
+ });
77
+
78
+ test('array literal with variable reference', async () => {
79
+ const runtime = createRuntime(`
80
+ let item = "first"
81
+ let x = [item, "second"]
82
+ `);
83
+ await runtime.run();
84
+ expect(runtime.getValue('x')).toEqual(['first', 'second']);
85
+ });
86
+
87
+ // ============================================================================
88
+ // Combined
89
+ // ============================================================================
90
+
91
+ test('array of objects', async () => {
92
+ const runtime = createRuntime('let x = [{name: "alice"}, {name: "bob"}]');
93
+ await runtime.run();
94
+ expect(runtime.getValue('x')).toEqual([
95
+ { name: 'alice' },
96
+ { name: 'bob' },
97
+ ]);
98
+ });
99
+
100
+ test('object with array property', async () => {
101
+ const runtime = createRuntime('let x = {items: ["a", "b"], count: "2"}');
102
+ await runtime.run();
103
+ expect(runtime.getValue('x')).toEqual({
104
+ items: ['a', 'b'],
105
+ count: '2',
106
+ });
107
+ });
108
+
109
+ // ============================================================================
110
+ // With json type annotation
111
+ // ============================================================================
112
+
113
+ test('json type with object literal', async () => {
114
+ const runtime = createRuntime('let x: json = {name: "test"}');
115
+ await runtime.run();
116
+ expect(runtime.getValue('x')).toEqual({ name: 'test' });
117
+ });
118
+
119
+ test('json type rejects array literal (use json[])', async () => {
120
+ const runtime = createRuntime('let x: json = ["a", "b"]');
121
+ await expect(runtime.run()).rejects.toThrow('json type expects an object, not an array');
122
+ });
123
+
124
+ test('json type with complex nested structure', async () => {
125
+ const runtime = createRuntime(`
126
+ let x: json = {
127
+ users: [
128
+ {name: "alice", roles: ["admin", "user"]},
129
+ {name: "bob", roles: ["user"]}
130
+ ],
131
+ meta: {version: "1"}
132
+ }
133
+ `);
134
+ await runtime.run();
135
+ expect(runtime.getValue('x')).toEqual({
136
+ users: [
137
+ { name: 'alice', roles: ['admin', 'user'] },
138
+ { name: 'bob', roles: ['user'] },
139
+ ],
140
+ meta: { version: '1' },
141
+ });
142
+ });
143
+
144
+ test('const json with object literal', async () => {
145
+ const runtime = createRuntime('const config: json = {debug: true}');
146
+ await runtime.run();
147
+ expect(runtime.getValue('config')).toEqual({ debug: true });
148
+ });
149
+
150
+ // ============================================================================
151
+ // Deep nesting (2+ levels)
152
+ // ============================================================================
153
+
154
+ test('3-level nested objects', async () => {
155
+ const runtime = createRuntime(`
156
+ let x = {
157
+ level1: {
158
+ level2: {
159
+ level3: "deep"
160
+ }
161
+ }
162
+ }
163
+ `);
164
+ await runtime.run();
165
+ expect(runtime.getValue('x')).toEqual({
166
+ level1: { level2: { level3: 'deep' } },
167
+ });
168
+ });
169
+
170
+ test('3-level nested arrays', async () => {
171
+ const runtime = createRuntime('let x = [[["a", "b"], ["c"]], [["d"]]]');
172
+ await runtime.run();
173
+ expect(runtime.getValue('x')).toEqual([[['a', 'b'], ['c']], [['d']]]);
174
+ });
175
+
176
+ test('objects inside arrays inside objects', async () => {
177
+ const runtime = createRuntime(`
178
+ let x = {
179
+ groups: [
180
+ {
181
+ members: [
182
+ {name: "alice"},
183
+ {name: "bob"}
184
+ ]
185
+ },
186
+ {
187
+ members: [
188
+ {name: "charlie"}
189
+ ]
190
+ }
191
+ ]
192
+ }
193
+ `);
194
+ await runtime.run();
195
+ expect(runtime.getValue('x')).toEqual({
196
+ groups: [
197
+ { members: [{ name: 'alice' }, { name: 'bob' }] },
198
+ { members: [{ name: 'charlie' }] },
199
+ ],
200
+ });
201
+ });
202
+
203
+ test('arrays inside objects inside arrays', async () => {
204
+ const runtime = createRuntime(`
205
+ let x = [
206
+ {tags: ["a", "b"], scores: ["1", "2"]},
207
+ {tags: ["c"], scores: ["3", "4", "5"]}
208
+ ]
209
+ `);
210
+ await runtime.run();
211
+ expect(runtime.getValue('x')).toEqual([
212
+ { tags: ['a', 'b'], scores: ['1', '2'] },
213
+ { tags: ['c'], scores: ['3', '4', '5'] },
214
+ ]);
215
+ });
216
+
217
+ test('mixed deep nesting with variables', async () => {
218
+ const runtime = createRuntime(`
219
+ let name = "test"
220
+ let x = {
221
+ config: {
222
+ items: [
223
+ {label: name, values: ["v1", "v2"]}
224
+ ]
225
+ }
226
+ }
227
+ `);
228
+ await runtime.run();
229
+ expect(runtime.getValue('x')).toEqual({
230
+ config: {
231
+ items: [{ label: 'test', values: ['v1', 'v2'] }],
232
+ },
233
+ });
234
+ });
235
+
236
+ test('4-level deep structure', async () => {
237
+ const runtime = createRuntime(`
238
+ let x = {
239
+ a: {
240
+ b: {
241
+ c: {
242
+ d: "four levels"
243
+ }
244
+ }
245
+ }
246
+ }
247
+ `);
248
+ await runtime.run();
249
+ const val = runtime.getValue('x') as any;
250
+ expect(val.a.b.c.d).toBe('four levels');
251
+ });
252
+
253
+ // ============================================================================
254
+ // Array Concatenation
255
+ // ============================================================================
256
+
257
+ test('array concatenation with +', async () => {
258
+ const runtime = createRuntime(`
259
+ let a = [1, 2]
260
+ let b = [3, 4]
261
+ let c = a + b
262
+ `);
263
+ await runtime.run();
264
+ expect(runtime.getValue('c')).toEqual([1, 2, 3, 4]);
265
+ });
266
+
267
+ test('concatenate empty arrays', async () => {
268
+ const runtime = createRuntime(`
269
+ let a = []
270
+ let b = []
271
+ let c = a + b
272
+ `);
273
+ await runtime.run();
274
+ expect(runtime.getValue('c')).toEqual([]);
275
+ });
276
+
277
+ test('concatenate with empty array', async () => {
278
+ const runtime = createRuntime(`
279
+ let a = [1, 2, 3]
280
+ let b = []
281
+ let c = a + b
282
+ `);
283
+ await runtime.run();
284
+ expect(runtime.getValue('c')).toEqual([1, 2, 3]);
285
+ });
286
+
287
+ test('concatenate array literals directly', async () => {
288
+ const runtime = createRuntime('let x = [1] + [2, 3]');
289
+ await runtime.run();
290
+ expect(runtime.getValue('x')).toEqual([1, 2, 3]);
291
+ });
292
+
293
+ test('chain multiple array concatenations', async () => {
294
+ const runtime = createRuntime(`
295
+ let a = [1]
296
+ let b = [2]
297
+ let c = [3]
298
+ let result = a + b + c
299
+ `);
300
+ await runtime.run();
301
+ expect(runtime.getValue('result')).toEqual([1, 2, 3]);
302
+ });
303
+
304
+ test('concatenate arrays of objects', async () => {
305
+ const runtime = createRuntime(`
306
+ let a = [{name: "alice"}]
307
+ let b = [{name: "bob"}]
308
+ let c = a + b
309
+ `);
310
+ await runtime.run();
311
+ expect(runtime.getValue('c')).toEqual([{ name: 'alice' }, { name: 'bob' }]);
312
+ });
313
+
314
+ test('concatenate string arrays', async () => {
315
+ const runtime = createRuntime(`
316
+ let a = ["hello"]
317
+ let b = ["world"]
318
+ let c = a + b
319
+ `);
320
+ await runtime.run();
321
+ expect(runtime.getValue('c')).toEqual(['hello', 'world']);
322
+ });
323
+
324
+ test('original arrays unchanged after concatenation', async () => {
325
+ const runtime = createRuntime(`
326
+ let a = [1, 2]
327
+ let b = [3, 4]
328
+ let c = a + b
329
+ `);
330
+ await runtime.run();
331
+ expect(runtime.getValue('a')).toEqual([1, 2]);
332
+ expect(runtime.getValue('b')).toEqual([3, 4]);
333
+ expect(runtime.getValue('c')).toEqual([1, 2, 3, 4]);
334
+ });
335
+
336
+ test('concatenate two array slices', async () => {
337
+ const runtime = createRuntime(`
338
+ let arr = [1, 2, 3, 4, 5]
339
+ let result = arr[0:2] + arr[3:5]
340
+ `);
341
+ await runtime.run();
342
+ expect(runtime.getValue('result')).toEqual([1, 2, 4, 5]);
343
+ });
344
+
345
+ test('concatenate array literal with slice', async () => {
346
+ const runtime = createRuntime(`
347
+ let arr = [1, 2, 3, 4, 5]
348
+ let result = [0] + arr[1:3]
349
+ `);
350
+ await runtime.run();
351
+ expect(runtime.getValue('result')).toEqual([0, 2, 3]);
352
+ });
353
+
354
+ test('concatenate slice with array literal', async () => {
355
+ const runtime = createRuntime(`
356
+ let arr = [1, 2, 3, 4, 5]
357
+ let result = arr[2:4] + [6, 7]
358
+ `);
359
+ await runtime.run();
360
+ expect(runtime.getValue('result')).toEqual([3, 4, 6, 7]);
361
+ });
362
+
363
+ test('concatenate slice with variable array', async () => {
364
+ const runtime = createRuntime(`
365
+ let arr = [1, 2, 3, 4, 5]
366
+ let suffix = [10, 11]
367
+ let result = arr[0:2] + suffix
368
+ `);
369
+ await runtime.run();
370
+ expect(runtime.getValue('result')).toEqual([1, 2, 10, 11]);
371
+ });
372
+ });