@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,87 @@
1
+ import { describe, expect, test } from 'bun:test';
2
+ import { parse } from '../../parser/parse';
3
+ import { SemanticAnalyzer } from '../analyzer';
4
+
5
+ describe('Semantic Analyzer - Type Inference from Literals', () => {
6
+ const analyzer = new SemanticAnalyzer();
7
+
8
+ function getErrors(code: string): string[] {
9
+ const ast = parse(code);
10
+ const errors = analyzer.analyze(ast, code);
11
+ return errors.map((e) => e.message);
12
+ }
13
+
14
+ // ============================================================================
15
+ // String literal inference
16
+ // ============================================================================
17
+
18
+ test('infers text type from string literal', () => {
19
+ const errors = getErrors('let x = "hello"\nlet y: number = x');
20
+ expect(errors).toContain('Type error: cannot assign text to number');
21
+ });
22
+
23
+ test('inferred text assigned to text is valid', () => {
24
+ const errors = getErrors('let x = "hello"\nlet y: text = x');
25
+ expect(errors).toEqual([]);
26
+ });
27
+
28
+ // ============================================================================
29
+ // Number literal inference
30
+ // ============================================================================
31
+
32
+ test('infers number type from number literal', () => {
33
+ const errors = getErrors('const n = 42\nlet s: text = n');
34
+ expect(errors).toContain('Type error: cannot assign number to text');
35
+ });
36
+
37
+ test('inferred number assigned to number is valid', () => {
38
+ const errors = getErrors('let n = 42\nlet m: number = n');
39
+ expect(errors).toEqual([]);
40
+ });
41
+
42
+ // ============================================================================
43
+ // Boolean literal inference
44
+ // ============================================================================
45
+
46
+ test('infers boolean type from boolean literal', () => {
47
+ const errors = getErrors('let b = true\nlet t: text = b');
48
+ expect(errors).toContain('Type error: cannot assign boolean to text');
49
+ });
50
+
51
+ test('inferred boolean assigned to boolean is valid', () => {
52
+ const errors = getErrors('let b = true\nlet c: boolean = b');
53
+ expect(errors).toEqual([]);
54
+ });
55
+
56
+ // ============================================================================
57
+ // Chained inference
58
+ // ============================================================================
59
+
60
+ test('type propagates through multiple assignments', () => {
61
+ const errors = getErrors('let a = "hi"\nlet b = a\nlet c: number = b');
62
+ expect(errors).toContain('Type error: cannot assign text to number');
63
+ });
64
+
65
+ // ============================================================================
66
+ // Function return type inference
67
+ // ============================================================================
68
+
69
+ test('function return type used for variable type', () => {
70
+ const errors = getErrors('function foo(): text { return "hi" }\nlet x = foo()\nlet y: number = x');
71
+ expect(errors).toContain('Type error: cannot assign text to number');
72
+ });
73
+
74
+ // ============================================================================
75
+ // Function parameter type checking with inferred args
76
+ // ============================================================================
77
+
78
+ test('inferred type checked against function parameter', () => {
79
+ const errors = getErrors('function greet(name: text): text { return name }\nlet n = 42\ngreet(n)');
80
+ expect(errors).toContain('Type error: cannot assign number to text');
81
+ });
82
+
83
+ test('inferred type matching parameter is valid', () => {
84
+ const errors = getErrors('function greet(name: text): text { return name }\nlet s = "world"\ngreet(s)');
85
+ expect(errors).toEqual([]);
86
+ });
87
+ });
@@ -0,0 +1,552 @@
1
+ import { describe, expect, test } from 'bun:test';
2
+ import { parse } from '../../parser/parse';
3
+ import { SemanticAnalyzer } from '../analyzer';
4
+
5
+ describe('Semantic Analyzer - Type Validation', () => {
6
+ const analyzer = new SemanticAnalyzer();
7
+
8
+ function getErrors(code: string): string[] {
9
+ const ast = parse(code);
10
+ const errors = analyzer.analyze(ast, code);
11
+ return errors.map((e) => e.message);
12
+ }
13
+
14
+ // ============================================================================
15
+ // Valid type annotations
16
+ // ============================================================================
17
+
18
+ test('text type is valid', () => {
19
+ const errors = getErrors('let x: text = "hello"');
20
+ expect(errors).toEqual([]);
21
+ });
22
+
23
+ test('json type is valid', () => {
24
+ const errors = getErrors('let x: json = "{\\"key\\": \\"value\\"}"');
25
+ expect(errors).toEqual([]);
26
+ });
27
+
28
+ test('prompt type is valid', () => {
29
+ const errors = getErrors('let x: prompt = "What is your name?"');
30
+ expect(errors).toEqual([]);
31
+ });
32
+
33
+ test('no type annotation is valid', () => {
34
+ const errors = getErrors('let x = "hello"');
35
+ expect(errors).toEqual([]);
36
+ });
37
+
38
+ // ============================================================================
39
+ // Compile-time literal type validation
40
+ // ============================================================================
41
+
42
+ test('boolean type is valid', () => {
43
+ const errors = getErrors('let x: boolean = true');
44
+ expect(errors).toEqual([]);
45
+ });
46
+
47
+ test('number type is valid', () => {
48
+ const errors = getErrors('let x: number = 42');
49
+ expect(errors).toEqual([]);
50
+ });
51
+
52
+ test('number type with decimal is valid', () => {
53
+ const errors = getErrors('let x: number = 3.14');
54
+ expect(errors).toEqual([]);
55
+ });
56
+
57
+ test('text type with boolean literal errors', () => {
58
+ const errors = getErrors('let x: text = true');
59
+ expect(errors).toContain('Type error: cannot assign boolean to text');
60
+ });
61
+
62
+ test('text type with number literal errors', () => {
63
+ const errors = getErrors('let x: text = 42');
64
+ expect(errors).toContain('Type error: cannot assign number to text');
65
+ });
66
+
67
+ test('number type with string literal errors', () => {
68
+ const errors = getErrors('let x: number = "hello"');
69
+ expect(errors).toContain('Type error: cannot assign text to number');
70
+ });
71
+
72
+ test('number type with boolean literal errors', () => {
73
+ const errors = getErrors('let x: number = true');
74
+ expect(errors).toContain('Type error: cannot assign boolean to number');
75
+ });
76
+
77
+ test('boolean type with string literal errors', () => {
78
+ const errors = getErrors('let x: boolean = "yes"');
79
+ expect(errors).toContain('Type error: cannot assign text to boolean');
80
+ });
81
+
82
+ test('boolean type with number literal errors', () => {
83
+ const errors = getErrors('let x: boolean = 1');
84
+ expect(errors).toContain('Type error: cannot assign number to boolean');
85
+ });
86
+
87
+ test('const with type mismatch errors', () => {
88
+ const errors = getErrors('const MAX: number = "one hundred"');
89
+ expect(errors).toContain('Type error: cannot assign text to number');
90
+ });
91
+
92
+ test('number array with string element errors', () => {
93
+ const errors = getErrors('let nums: number[] = [1, 2, "three"]');
94
+ expect(errors).toContain('Type error: cannot assign text to number');
95
+ });
96
+
97
+ test('boolean array with number element errors', () => {
98
+ const errors = getErrors('let flags: boolean[] = [true, 0, false]');
99
+ expect(errors).toContain('Type error: cannot assign number to boolean');
100
+ });
101
+
102
+ test('nested array type validation', () => {
103
+ const errors = getErrors('let matrix: number[][] = [[1, 2], [3, "four"]]');
104
+ expect(errors).toContain('Type error: cannot assign text to number');
105
+ });
106
+
107
+ // ============================================================================
108
+ // Variable-to-variable type checking
109
+ // ============================================================================
110
+
111
+ test('text variable assigned to boolean errors', () => {
112
+ const errors = getErrors('const t: text = "hello"\nconst b: boolean = t');
113
+ expect(errors).toContain('Type error: cannot assign text to boolean');
114
+ });
115
+
116
+ test('number variable assigned to text errors', () => {
117
+ const errors = getErrors('let n: number = 42\nlet s: text = n');
118
+ expect(errors).toContain('Type error: cannot assign number to text');
119
+ });
120
+
121
+ test('boolean variable assigned to number errors', () => {
122
+ const errors = getErrors('let b: boolean = true\nlet n: number = b');
123
+ expect(errors).toContain('Type error: cannot assign boolean to number');
124
+ });
125
+
126
+ test('null assigned to boolean errors', () => {
127
+ const errors = getErrors('let b: boolean = null');
128
+ expect(errors).toContain('Type error: cannot assign null to boolean');
129
+ });
130
+
131
+ test('null assigned to const boolean errors', () => {
132
+ const errors = getErrors('const b: boolean = null');
133
+ // Two errors: const can't be null, and null can't be assigned to boolean
134
+ expect(errors).toContain('Cannot initialize const with null - const values cannot be reassigned');
135
+ expect(errors).toContain('Type error: cannot assign null to boolean');
136
+ });
137
+
138
+ test('null assigned to text is valid', () => {
139
+ const errors = getErrors('let t: text = null');
140
+ expect(errors).toEqual([]);
141
+ });
142
+
143
+ test('null assigned to number is valid', () => {
144
+ const errors = getErrors('let n: number = null');
145
+ expect(errors).toEqual([]);
146
+ });
147
+
148
+ test('null passed to boolean parameter errors', () => {
149
+ const errors = getErrors(`
150
+ function check(flag: boolean): boolean { return flag }
151
+ let result = check(null)
152
+ `);
153
+ expect(errors).toContain('Type error: cannot assign null to boolean');
154
+ });
155
+
156
+ test('null as if condition errors', () => {
157
+ const errors = getErrors('if null { let x = 1 }');
158
+ expect(errors).toContain('if condition must be boolean, got null');
159
+ });
160
+
161
+ test('null as while condition errors', () => {
162
+ const errors = getErrors('while null { let x = 1 }');
163
+ expect(errors).toContain('while condition must be boolean, got null');
164
+ });
165
+
166
+ test('nullable text variable as if condition errors', () => {
167
+ const errors = getErrors(`
168
+ let x: text = null
169
+ if x { let y = 1 }
170
+ `);
171
+ expect(errors).toContain('if condition must be boolean, got text');
172
+ });
173
+
174
+ test('nullable text variable as while condition errors', () => {
175
+ const errors = getErrors(`
176
+ let x: text = null
177
+ while x { let y = 1 }
178
+ `);
179
+ expect(errors).toContain('while condition must be boolean, got text');
180
+ });
181
+
182
+ test('text variable assigned to text is valid', () => {
183
+ const errors = getErrors('const t: text = "hello"\nconst t2: text = t');
184
+ expect(errors).toEqual([]);
185
+ });
186
+
187
+ test('prompt variable assigned to text is valid', () => {
188
+ const errors = getErrors('let p: prompt = "ask"\nlet t: text = p');
189
+ expect(errors).toEqual([]);
190
+ });
191
+
192
+ test('text variable assigned to prompt is valid', () => {
193
+ const errors = getErrors('let t: text = "hello"\nlet p: prompt = t');
194
+ expect(errors).toEqual([]);
195
+ });
196
+
197
+ test('text variable keeps text type after prompt assignment', () => {
198
+ // Variable t is declared as text, assigned from prompt p
199
+ // t should still be text type, usable where text is expected
200
+ const errors = getErrors(`
201
+ let p: prompt = "ask"
202
+ let t: text = p
203
+ function needsText(s: text): text { return s }
204
+ needsText(t)
205
+ `);
206
+ expect(errors).toEqual([]);
207
+ });
208
+
209
+ test('prompt variable keeps prompt type after text assignment', () => {
210
+ // Variable p is declared as prompt, assigned from text t
211
+ // p should still be prompt type
212
+ const errors = getErrors(`
213
+ let t: text = "hello"
214
+ let p: prompt = t
215
+ function needsPrompt(s: prompt): prompt { return s }
216
+ needsPrompt(p)
217
+ `);
218
+ expect(errors).toEqual([]);
219
+ });
220
+
221
+ test('text variable assigned to json is valid', () => {
222
+ const errors = getErrors('let t: text = "{}"\nlet j: json = t');
223
+ expect(errors).toEqual([]);
224
+ });
225
+
226
+ // ============================================================================
227
+ // Function parameter type checking
228
+ // ============================================================================
229
+
230
+ test('function parameter type mismatch - number to text', () => {
231
+ const errors = getErrors('function greet(name: text) { return name }\ngreet(42)');
232
+ expect(errors).toContain('Type error: cannot assign number to text');
233
+ });
234
+
235
+ test('function parameter type mismatch - text to number', () => {
236
+ const errors = getErrors('function double(n: number): number { return n }\ndouble("five")');
237
+ expect(errors).toContain('Type error: cannot assign text to number');
238
+ });
239
+
240
+ test('function parameter type mismatch - text to boolean', () => {
241
+ const errors = getErrors('function check(flag: boolean) { return flag }\ncheck("yes")');
242
+ expect(errors).toContain('Type error: cannot assign text to boolean');
243
+ });
244
+
245
+ test('function parameter with variable type mismatch', () => {
246
+ const errors = getErrors('let n: number = 42\nfunction greet(name: text) { return name }\ngreet(n)');
247
+ expect(errors).toContain('Type error: cannot assign number to text');
248
+ });
249
+
250
+ test('function parameter with correct type is valid', () => {
251
+ const errors = getErrors('function greet(name: text) { return name }\ngreet("hello")');
252
+ expect(errors).toEqual([]);
253
+ });
254
+
255
+ // ============================================================================
256
+ // Function return type checking
257
+ // ============================================================================
258
+
259
+ test('function return type mismatch - number to text', () => {
260
+ const errors = getErrors('function getNum(): number { return 42 }\nlet s: text = getNum()');
261
+ expect(errors).toContain('Type error: cannot assign number to text');
262
+ });
263
+
264
+ test('function return type mismatch - boolean to number', () => {
265
+ const errors = getErrors('function isOk(): boolean { return true }\nlet n: number = isOk()');
266
+ expect(errors).toContain('Type error: cannot assign boolean to number');
267
+ });
268
+
269
+ test('function return type mismatch - text to boolean', () => {
270
+ const errors = getErrors('function getName(): text { return "hi" }\nlet b: boolean = getName()');
271
+ expect(errors).toContain('Type error: cannot assign text to boolean');
272
+ });
273
+
274
+ test('function return type with correct assignment is valid', () => {
275
+ const errors = getErrors('function getNum(): number { return 42 }\nlet n: number = getNum()');
276
+ expect(errors).toEqual([]);
277
+ });
278
+
279
+ test('function return type assigned to compatible type is valid', () => {
280
+ const errors = getErrors('function getPrompt(): prompt { return "ask" }\nlet t: text = getPrompt()');
281
+ expect(errors).toEqual([]);
282
+ });
283
+
284
+ // ============================================================================
285
+ // JSON literal validation (compile-time)
286
+ // ============================================================================
287
+
288
+ test('valid JSON object literal passes', () => {
289
+ const errors = getErrors('let x: json = "{\\"name\\": \\"test\\"}"');
290
+ expect(errors).toEqual([]);
291
+ });
292
+
293
+ test('valid JSON array literal passes', () => {
294
+ const errors = getErrors('let x: json = "[1, 2, 3]"');
295
+ expect(errors).toEqual([]);
296
+ });
297
+
298
+ test('valid empty object literal passes', () => {
299
+ const errors = getErrors('let x: json = "{}"');
300
+ expect(errors).toEqual([]);
301
+ });
302
+
303
+ test('valid empty array literal passes', () => {
304
+ const errors = getErrors('let x: json = "[]"');
305
+ expect(errors).toEqual([]);
306
+ });
307
+
308
+ test('invalid JSON literal errors', () => {
309
+ const errors = getErrors('let x: json = "{invalid json}"');
310
+ expect(errors).toContain('Invalid JSON literal');
311
+ });
312
+
313
+ test('invalid JSON - missing quotes errors', () => {
314
+ const errors = getErrors('let x: json = "{key: value}"');
315
+ expect(errors).toContain('Invalid JSON literal');
316
+ });
317
+
318
+ test('invalid JSON - trailing comma errors', () => {
319
+ const errors = getErrors('let x: json = "{\\"key\\": \\"value\\",}"');
320
+ expect(errors).toContain('Invalid JSON literal');
321
+ });
322
+
323
+ test('invalid JSON on const errors', () => {
324
+ const errors = getErrors('const x: json = "not json at all"');
325
+ expect(errors).toContain('Invalid JSON literal');
326
+ });
327
+
328
+ // ============================================================================
329
+ // JSON type with non-literal (no compile-time check)
330
+ // ============================================================================
331
+
332
+ test('json type with variable reference has no compile-time error', () => {
333
+ const code = `
334
+ let source = "{\\"key\\": \\"value\\"}"
335
+ let x: json = source
336
+ `;
337
+ const errors = getErrors(code);
338
+ expect(errors).toEqual([]);
339
+ });
340
+
341
+ test('json type with vibe expression has no compile-time error', () => {
342
+ const code = `
343
+ model myModel = {
344
+ name: "test",
345
+ apiKey: "key",
346
+ url: "http://example.com"
347
+ }
348
+ let x: json = vibe "return JSON" myModel default
349
+ `;
350
+ const errors = getErrors(code);
351
+ expect(errors).toEqual([]);
352
+ });
353
+
354
+ // ============================================================================
355
+ // Range expression validation
356
+ // ============================================================================
357
+
358
+ test('valid range with start <= end passes', () => {
359
+ const errors = getErrors('let range = 1..5');
360
+ expect(errors).toEqual([]);
361
+ });
362
+
363
+ test('valid range with same start and end passes', () => {
364
+ const errors = getErrors('let range = 3..3');
365
+ expect(errors).toEqual([]);
366
+ });
367
+
368
+ test('valid range with negative numbers passes', () => {
369
+ const errors = getErrors('let range = -3..4');
370
+ expect(errors).toEqual([]);
371
+ });
372
+
373
+ test('valid range with negative to negative passes', () => {
374
+ const errors = getErrors('let range = -5..-2');
375
+ expect(errors).toEqual([]);
376
+ });
377
+
378
+ test('invalid range with start > end errors', () => {
379
+ const errors = getErrors('let range = 5..2');
380
+ expect(errors).toContain('Range start (5) must be <= end (2)');
381
+ });
382
+
383
+ test('invalid negative range with start > end errors', () => {
384
+ const errors = getErrors('let range = -2..-5');
385
+ expect(errors).toContain('Range start (-2) must be <= end (-5)');
386
+ });
387
+
388
+ test('range with variable bounds has no compile-time error', () => {
389
+ // Can't check at compile time when bounds are variables
390
+ const code = `
391
+ let start: number = 5
392
+ let end: number = 2
393
+ let range = start..end
394
+ `;
395
+ const errors = getErrors(code);
396
+ expect(errors).toEqual([]);
397
+ });
398
+
399
+ // ============================================================================
400
+ // Function return type handling
401
+ // ============================================================================
402
+
403
+ test('function without return type is valid (side-effect function)', () => {
404
+ const errors = getErrors('function logIt() { let x = "hi" }');
405
+ expect(errors).toEqual([]);
406
+ });
407
+
408
+ test('function with return type is valid', () => {
409
+ const errors = getErrors('function foo(): text { return "hi" }');
410
+ expect(errors).toEqual([]);
411
+ });
412
+
413
+ test('cannot assign void function result to variable', () => {
414
+ const errors = getErrors('function logIt() { let x = "hi" }\nlet y = logIt()');
415
+ expect(errors).toContain("Cannot assign result of 'logIt()' to a variable - function has no return type");
416
+ });
417
+
418
+ test('can assign function with return type to variable', () => {
419
+ const errors = getErrors('function getText(): text { return "hi" }\nlet x = getText()');
420
+ expect(errors).toEqual([]);
421
+ });
422
+
423
+ // ============================================================================
424
+ // Array concatenation type checking
425
+ // ============================================================================
426
+
427
+ test('array concatenation with same types is valid', () => {
428
+ const errors = getErrors('let a: number[] = [1, 2]\nlet b: number[] = [3, 4]\nlet c = a + b');
429
+ expect(errors).toEqual([]);
430
+ });
431
+
432
+ test('array concatenation with different types is error', () => {
433
+ const errors = getErrors('let a: number[] = [1, 2]\nlet b: text[] = ["a", "b"]\nlet c = a + b');
434
+ expect(errors).toContain('Cannot concatenate number[] with text[]: array types must match');
435
+ });
436
+
437
+ test('array concatenation with non-array is error', () => {
438
+ const errors = getErrors('let a: number[] = [1, 2]\nlet b = 5\nlet c = a + b');
439
+ expect(errors).toContain('Cannot concatenate array with non-array using +');
440
+ });
441
+
442
+ test('array literal concatenation is valid', () => {
443
+ const errors = getErrors('let c = [1, 2] + [3, 4]');
444
+ expect(errors).toEqual([]);
445
+ });
446
+
447
+ test('typed array + untyped array literal is valid', () => {
448
+ const errors = getErrors('let a: number[] = [1, 2]\nlet c = a + [3, 4]');
449
+ expect(errors).toEqual([]);
450
+ });
451
+
452
+ test('text array concatenation is valid', () => {
453
+ const errors = getErrors('let a: text[] = ["a"]\nlet b: text[] = ["b"]\nlet c = a + b');
454
+ expect(errors).toEqual([]);
455
+ });
456
+
457
+ test('json array concatenation is valid', () => {
458
+ const errors = getErrors('let a: json[] = [{x: 1}]\nlet b: json[] = [{y: 2}]\nlet c = a + b');
459
+ expect(errors).toEqual([]);
460
+ });
461
+
462
+ test('boolean array concatenation with number array is error', () => {
463
+ const errors = getErrors('let a: boolean[] = [true]\nlet b: number[] = [1]\nlet c = a + b');
464
+ expect(errors).toContain('Cannot concatenate boolean[] with number[]: array types must match');
465
+ });
466
+
467
+ // ============================================================================
468
+ // Array slice concatenation type checking
469
+ // ============================================================================
470
+
471
+ test('same typed array slices concatenation is valid', () => {
472
+ const errors = getErrors('let a: number[] = [1, 2, 3]\nlet b: number[] = [4, 5, 6]\nlet c = a[0:2] + b[1:3]');
473
+ expect(errors).toEqual([]);
474
+ });
475
+
476
+ test('different typed array slices concatenation is error', () => {
477
+ const errors = getErrors('let nums: number[] = [1, 2, 3]\nlet strs: text[] = ["a", "b"]\nlet c = nums[0:2] + strs[0:2]');
478
+ expect(errors).toContain('Cannot concatenate number[] with text[]: array types must match');
479
+ });
480
+
481
+ test('array slice + array literal is valid', () => {
482
+ const errors = getErrors('let a: number[] = [1, 2, 3]\nlet c = a[0:2] + [4, 5]');
483
+ expect(errors).toEqual([]);
484
+ });
485
+
486
+ test('array slice + different typed variable is error', () => {
487
+ const errors = getErrors('let nums: number[] = [1, 2, 3]\nlet strs: text[] = ["a", "b"]\nlet c = nums[0:2] + strs');
488
+ expect(errors).toContain('Cannot concatenate number[] with text[]: array types must match');
489
+ });
490
+
491
+ test('typed array slice assigned to variable preserves type', () => {
492
+ const errors = getErrors(`
493
+ let nums: number[] = [1, 2, 3, 4]
494
+ let slice = nums[0:2]
495
+ let strs: text[] = ["a", "b"]
496
+ let result = slice + strs
497
+ `);
498
+ expect(errors).toContain('Cannot concatenate number[] with text[]: array types must match');
499
+ });
500
+
501
+ test('inferred array types catch concat mismatches', () => {
502
+ // Types are now inferred from array literals
503
+ const errors = getErrors(`
504
+ let a = [1, 2, 3]
505
+ let b = ["x", "y"]
506
+ let c = a[:2] + b[:2]
507
+ `);
508
+ expect(errors).toContain('Cannot concatenate number[] with text[]: array types must match');
509
+ });
510
+
511
+ // ============================================================================
512
+ // Array type inference
513
+ // ============================================================================
514
+
515
+ test('array type is inferred from elements', () => {
516
+ const errors = getErrors(`
517
+ let nums = [1, 2, 3]
518
+ let strs: text[] = ["a", "b"]
519
+ let result = nums + strs
520
+ `);
521
+ expect(errors).toContain('Cannot concatenate number[] with text[]: array types must match');
522
+ });
523
+
524
+ test('mixed array elements are rejected', () => {
525
+ const errors = getErrors('let x = [1, 2, "hello"]');
526
+ expect(errors).toContain('Mixed array types: element 2 is text but expected number');
527
+ });
528
+
529
+ test('homogeneous array elements are valid', () => {
530
+ const errors = getErrors('let x = [1, 2, 3]');
531
+ expect(errors).toEqual([]);
532
+ });
533
+
534
+ test('empty array requires explicit type', () => {
535
+ const errors = getErrors('let x = []');
536
+ expect(errors).toContain('Cannot infer type from empty array - provide a type annotation: let x: <type>[] = []');
537
+ });
538
+
539
+ test('empty array with explicit type is valid', () => {
540
+ const errors = getErrors('let x: number[] = []');
541
+ expect(errors).toEqual([]);
542
+ });
543
+
544
+ test('inferred same types can be concatenated', () => {
545
+ const errors = getErrors(`
546
+ let a = [1, 2]
547
+ let b = [3, 4]
548
+ let c = a + b
549
+ `);
550
+ expect(errors).toEqual([]);
551
+ });
552
+ });