@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.
- package/package.json +46 -0
- package/src/ast/index.ts +375 -0
- package/src/ast.ts +2 -0
- package/src/debug/advanced-features.ts +482 -0
- package/src/debug/bun-inspector.ts +424 -0
- package/src/debug/handoff-manager.ts +283 -0
- package/src/debug/index.ts +150 -0
- package/src/debug/runner.ts +365 -0
- package/src/debug/server.ts +565 -0
- package/src/debug/stack-merger.ts +267 -0
- package/src/debug/state.ts +581 -0
- package/src/debug/test/advanced-features.test.ts +300 -0
- package/src/debug/test/e2e.test.ts +218 -0
- package/src/debug/test/handoff-manager.test.ts +256 -0
- package/src/debug/test/runner.test.ts +256 -0
- package/src/debug/test/stack-merger.test.ts +163 -0
- package/src/debug/test/state.test.ts +400 -0
- package/src/debug/test/ts-debug-integration.test.ts +374 -0
- package/src/debug/test/ts-import-tracker.test.ts +125 -0
- package/src/debug/test/ts-source-map.test.ts +169 -0
- package/src/debug/ts-import-tracker.ts +151 -0
- package/src/debug/ts-source-map.ts +171 -0
- package/src/errors/index.ts +124 -0
- package/src/index.ts +358 -0
- package/src/lexer/index.ts +348 -0
- package/src/lexer.ts +2 -0
- package/src/parser/index.ts +792 -0
- package/src/parser/parse.ts +45 -0
- package/src/parser/test/async.test.ts +248 -0
- package/src/parser/test/destructuring.test.ts +167 -0
- package/src/parser/test/do-expression.test.ts +486 -0
- package/src/parser/test/errors/do-expression.test.ts +95 -0
- package/src/parser/test/errors/error-locations.test.ts +230 -0
- package/src/parser/test/errors/invalid-expressions.test.ts +144 -0
- package/src/parser/test/errors/missing-tokens.test.ts +126 -0
- package/src/parser/test/errors/model-declaration.test.ts +185 -0
- package/src/parser/test/errors/nested-blocks.test.ts +226 -0
- package/src/parser/test/errors/unclosed-delimiters.test.ts +122 -0
- package/src/parser/test/errors/unexpected-tokens.test.ts +120 -0
- package/src/parser/test/import-export.test.ts +143 -0
- package/src/parser/test/literals.test.ts +404 -0
- package/src/parser/test/model-declaration.test.ts +161 -0
- package/src/parser/test/nested-blocks.test.ts +402 -0
- package/src/parser/test/parser.test.ts +743 -0
- package/src/parser/test/private.test.ts +136 -0
- package/src/parser/test/template-literal.test.ts +127 -0
- package/src/parser/test/tool-declaration.test.ts +302 -0
- package/src/parser/test/ts-block.test.ts +252 -0
- package/src/parser/test/type-annotations.test.ts +254 -0
- package/src/parser/visitor/helpers.ts +330 -0
- package/src/parser/visitor.ts +794 -0
- package/src/parser.ts +2 -0
- package/src/runtime/ai/cache-chunking.test.ts +69 -0
- package/src/runtime/ai/cache-chunking.ts +73 -0
- package/src/runtime/ai/client.ts +109 -0
- package/src/runtime/ai/context.ts +168 -0
- package/src/runtime/ai/formatters.ts +316 -0
- package/src/runtime/ai/index.ts +38 -0
- package/src/runtime/ai/language-ref.ts +38 -0
- package/src/runtime/ai/providers/anthropic.ts +253 -0
- package/src/runtime/ai/providers/google.ts +201 -0
- package/src/runtime/ai/providers/openai.ts +156 -0
- package/src/runtime/ai/retry.ts +100 -0
- package/src/runtime/ai/return-tools.ts +301 -0
- package/src/runtime/ai/test/client.test.ts +83 -0
- package/src/runtime/ai/test/formatters.test.ts +485 -0
- package/src/runtime/ai/test/retry.test.ts +137 -0
- package/src/runtime/ai/test/return-tools.test.ts +450 -0
- package/src/runtime/ai/test/tool-loop.test.ts +319 -0
- package/src/runtime/ai/test/tool-schema.test.ts +241 -0
- package/src/runtime/ai/tool-loop.ts +203 -0
- package/src/runtime/ai/tool-schema.ts +151 -0
- package/src/runtime/ai/types.ts +113 -0
- package/src/runtime/ai-logger.ts +255 -0
- package/src/runtime/ai-provider.ts +347 -0
- package/src/runtime/async/dependencies.ts +276 -0
- package/src/runtime/async/executor.ts +293 -0
- package/src/runtime/async/index.ts +43 -0
- package/src/runtime/async/scheduling.ts +163 -0
- package/src/runtime/async/test/dependencies.test.ts +284 -0
- package/src/runtime/async/test/executor.test.ts +388 -0
- package/src/runtime/context.ts +357 -0
- package/src/runtime/exec/ai.ts +139 -0
- package/src/runtime/exec/expressions.ts +475 -0
- package/src/runtime/exec/frames.ts +26 -0
- package/src/runtime/exec/functions.ts +305 -0
- package/src/runtime/exec/interpolation.ts +312 -0
- package/src/runtime/exec/statements.ts +604 -0
- package/src/runtime/exec/tools.ts +129 -0
- package/src/runtime/exec/typescript.ts +215 -0
- package/src/runtime/exec/variables.ts +279 -0
- package/src/runtime/index.ts +975 -0
- package/src/runtime/modules.ts +452 -0
- package/src/runtime/serialize.ts +103 -0
- package/src/runtime/state.ts +489 -0
- package/src/runtime/stdlib/core.ts +45 -0
- package/src/runtime/stdlib/directory.test.ts +156 -0
- package/src/runtime/stdlib/edit.test.ts +154 -0
- package/src/runtime/stdlib/fastEdit.test.ts +201 -0
- package/src/runtime/stdlib/glob.test.ts +106 -0
- package/src/runtime/stdlib/grep.test.ts +144 -0
- package/src/runtime/stdlib/index.ts +16 -0
- package/src/runtime/stdlib/readFile.test.ts +123 -0
- package/src/runtime/stdlib/tools/index.ts +707 -0
- package/src/runtime/stdlib/writeFile.test.ts +157 -0
- package/src/runtime/step.ts +969 -0
- package/src/runtime/test/ai-context.test.ts +1086 -0
- package/src/runtime/test/ai-result-object.test.ts +419 -0
- package/src/runtime/test/ai-tool-flow.test.ts +859 -0
- package/src/runtime/test/async-execution-order.test.ts +618 -0
- package/src/runtime/test/async-execution.test.ts +344 -0
- package/src/runtime/test/async-nested.test.ts +660 -0
- package/src/runtime/test/async-parallel-timing.test.ts +546 -0
- package/src/runtime/test/basic1.test.ts +154 -0
- package/src/runtime/test/binary-operators.test.ts +431 -0
- package/src/runtime/test/break-statement.test.ts +257 -0
- package/src/runtime/test/context-modes.test.ts +650 -0
- package/src/runtime/test/context.test.ts +466 -0
- package/src/runtime/test/core-functions.test.ts +228 -0
- package/src/runtime/test/e2e.test.ts +88 -0
- package/src/runtime/test/error-locations/error-locations.test.ts +80 -0
- package/src/runtime/test/error-locations/main-error.vibe +4 -0
- package/src/runtime/test/error-locations/main-import-error.vibe +3 -0
- package/src/runtime/test/error-locations/utils/helper.vibe +5 -0
- package/src/runtime/test/for-in.test.ts +312 -0
- package/src/runtime/test/helpers.ts +69 -0
- package/src/runtime/test/imports.test.ts +334 -0
- package/src/runtime/test/json-expressions.test.ts +232 -0
- package/src/runtime/test/literals.test.ts +372 -0
- package/src/runtime/test/logical-indexing.test.ts +478 -0
- package/src/runtime/test/member-methods.test.ts +324 -0
- package/src/runtime/test/model-config.test.ts +338 -0
- package/src/runtime/test/null-handling.test.ts +342 -0
- package/src/runtime/test/private-visibility.test.ts +332 -0
- package/src/runtime/test/runtime-state.test.ts +514 -0
- package/src/runtime/test/scoping.test.ts +370 -0
- package/src/runtime/test/string-interpolation.test.ts +354 -0
- package/src/runtime/test/template-literal.test.ts +181 -0
- package/src/runtime/test/tool-execution.test.ts +467 -0
- package/src/runtime/test/tool-schema-generation.test.ts +477 -0
- package/src/runtime/test/tostring.test.ts +210 -0
- package/src/runtime/test/ts-block.test.ts +594 -0
- package/src/runtime/test/ts-error-location.test.ts +231 -0
- package/src/runtime/test/types.test.ts +732 -0
- package/src/runtime/test/verbose-logger.test.ts +710 -0
- package/src/runtime/test/vibe-expression.test.ts +54 -0
- package/src/runtime/test/vibe-value-errors.test.ts +541 -0
- package/src/runtime/test/while.test.ts +232 -0
- package/src/runtime/tools/builtin.ts +30 -0
- package/src/runtime/tools/directory-tools.ts +70 -0
- package/src/runtime/tools/file-tools.ts +228 -0
- package/src/runtime/tools/index.ts +5 -0
- package/src/runtime/tools/registry.ts +48 -0
- package/src/runtime/tools/search-tools.ts +134 -0
- package/src/runtime/tools/security.ts +36 -0
- package/src/runtime/tools/system-tools.ts +312 -0
- package/src/runtime/tools/test/fixtures/base-types.ts +40 -0
- package/src/runtime/tools/test/fixtures/test-types.ts +132 -0
- package/src/runtime/tools/test/registry.test.ts +713 -0
- package/src/runtime/tools/test/security.test.ts +86 -0
- package/src/runtime/tools/test/system-tools.test.ts +679 -0
- package/src/runtime/tools/test/ts-schema.test.ts +357 -0
- package/src/runtime/tools/ts-schema.ts +341 -0
- package/src/runtime/tools/types.ts +89 -0
- package/src/runtime/tools/utility-tools.ts +198 -0
- package/src/runtime/ts-eval.ts +126 -0
- package/src/runtime/types.ts +797 -0
- package/src/runtime/validation.ts +160 -0
- package/src/runtime/verbose-logger.ts +459 -0
- package/src/runtime.ts +2 -0
- package/src/semantic/analyzer-context.ts +62 -0
- package/src/semantic/analyzer-validators.ts +575 -0
- package/src/semantic/analyzer-visitors.ts +534 -0
- package/src/semantic/analyzer.ts +83 -0
- package/src/semantic/index.ts +11 -0
- package/src/semantic/symbol-table.ts +58 -0
- package/src/semantic/test/async-validation.test.ts +301 -0
- package/src/semantic/test/compress-validation.test.ts +179 -0
- package/src/semantic/test/const-reassignment.test.ts +111 -0
- package/src/semantic/test/control-flow.test.ts +346 -0
- package/src/semantic/test/destructuring.test.ts +185 -0
- package/src/semantic/test/duplicate-declarations.test.ts +168 -0
- package/src/semantic/test/export-validation.test.ts +111 -0
- package/src/semantic/test/fixtures/math.ts +31 -0
- package/src/semantic/test/imports.test.ts +148 -0
- package/src/semantic/test/json-type.test.ts +68 -0
- package/src/semantic/test/literals.test.ts +127 -0
- package/src/semantic/test/model-validation.test.ts +179 -0
- package/src/semantic/test/prompt-validation.test.ts +343 -0
- package/src/semantic/test/scoping.test.ts +312 -0
- package/src/semantic/test/tool-validation.test.ts +306 -0
- package/src/semantic/test/ts-type-checking.test.ts +563 -0
- package/src/semantic/test/type-constraints.test.ts +111 -0
- package/src/semantic/test/type-inference.test.ts +87 -0
- package/src/semantic/test/type-validation.test.ts +552 -0
- package/src/semantic/test/undefined-variables.test.ts +163 -0
- package/src/semantic/ts-block-checker.ts +204 -0
- package/src/semantic/ts-signatures.ts +194 -0
- package/src/semantic/ts-types.ts +170 -0
- package/src/semantic/types.ts +58 -0
- package/tests/fixtures/conditional-logic.vibe +14 -0
- package/tests/fixtures/function-call.vibe +16 -0
- package/tests/fixtures/imports/cycle-detection/a.vibe +6 -0
- package/tests/fixtures/imports/cycle-detection/b.vibe +5 -0
- package/tests/fixtures/imports/cycle-detection/main.vibe +3 -0
- package/tests/fixtures/imports/module-isolation/main-b.vibe +8 -0
- package/tests/fixtures/imports/module-isolation/main.vibe +9 -0
- package/tests/fixtures/imports/module-isolation/moduleA.vibe +6 -0
- package/tests/fixtures/imports/module-isolation/moduleB.vibe +6 -0
- package/tests/fixtures/imports/nested-import/helper.vibe +6 -0
- package/tests/fixtures/imports/nested-import/main.vibe +3 -0
- package/tests/fixtures/imports/nested-import/utils.ts +3 -0
- package/tests/fixtures/imports/nested-isolation/file2.vibe +15 -0
- package/tests/fixtures/imports/nested-isolation/file3.vibe +10 -0
- package/tests/fixtures/imports/nested-isolation/main.vibe +21 -0
- package/tests/fixtures/imports/pure-cycle/a.vibe +5 -0
- package/tests/fixtures/imports/pure-cycle/b.vibe +5 -0
- package/tests/fixtures/imports/pure-cycle/main.vibe +3 -0
- package/tests/fixtures/imports/ts-boolean/checks.ts +14 -0
- package/tests/fixtures/imports/ts-boolean/main.vibe +10 -0
- package/tests/fixtures/imports/ts-boolean/type-mismatch.vibe +5 -0
- package/tests/fixtures/imports/ts-boolean/use-constant.vibe +18 -0
- package/tests/fixtures/imports/ts-error-handling/helpers.ts +42 -0
- package/tests/fixtures/imports/ts-error-handling/main.vibe +5 -0
- package/tests/fixtures/imports/ts-import/main.vibe +4 -0
- package/tests/fixtures/imports/ts-import/math.ts +9 -0
- package/tests/fixtures/imports/ts-variables/call-non-function.vibe +5 -0
- package/tests/fixtures/imports/ts-variables/data.ts +10 -0
- package/tests/fixtures/imports/ts-variables/import-json.vibe +5 -0
- package/tests/fixtures/imports/ts-variables/import-type-mismatch.vibe +5 -0
- package/tests/fixtures/imports/ts-variables/import-variable.vibe +5 -0
- package/tests/fixtures/imports/vibe-import/greet.vibe +5 -0
- package/tests/fixtures/imports/vibe-import/main.vibe +3 -0
- package/tests/fixtures/multiple-ai-calls.vibe +10 -0
- package/tests/fixtures/simple-greeting.vibe +6 -0
- package/tests/fixtures/template-literals.vibe +11 -0
- package/tests/integration/basic-ai/basic-ai.integration.test.ts +166 -0
- package/tests/integration/basic-ai/basic-ai.vibe +12 -0
- package/tests/integration/bug-fix/bug-fix.integration.test.ts +201 -0
- package/tests/integration/bug-fix/buggy-code.ts +22 -0
- package/tests/integration/bug-fix/fix-bug.vibe +21 -0
- package/tests/integration/compress/compress.integration.test.ts +206 -0
- package/tests/integration/destructuring/destructuring.integration.test.ts +92 -0
- package/tests/integration/hello-world-translator/hello-world-translator.integration.test.ts +61 -0
- package/tests/integration/line-annotator/context-modes.integration.test.ts +261 -0
- package/tests/integration/line-annotator/line-annotator.integration.test.ts +148 -0
- package/tests/integration/multi-feature/cumulative-sum.integration.test.ts +75 -0
- package/tests/integration/multi-feature/number-analyzer.integration.test.ts +191 -0
- package/tests/integration/multi-feature/number-analyzer.vibe +59 -0
- package/tests/integration/tool-calls/tool-calls.integration.test.ts +93 -0
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import { describe, expect, test } from 'bun:test';
|
|
2
|
+
import { parse } from '../../parse';
|
|
3
|
+
|
|
4
|
+
describe('Syntax Errors - Nested Blocks', () => {
|
|
5
|
+
// ============================================================================
|
|
6
|
+
// Missing closing braces at different levels
|
|
7
|
+
// ============================================================================
|
|
8
|
+
|
|
9
|
+
test('missing closing brace on outer function', () => {
|
|
10
|
+
expect(() => parse(`
|
|
11
|
+
function outer() {
|
|
12
|
+
function inner() {
|
|
13
|
+
return "nested"
|
|
14
|
+
}
|
|
15
|
+
`)).toThrow();
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
test('missing closing brace on inner function', () => {
|
|
19
|
+
expect(() => parse(`
|
|
20
|
+
function outer() {
|
|
21
|
+
function inner() {
|
|
22
|
+
return "nested"
|
|
23
|
+
}
|
|
24
|
+
`)).toThrow();
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
test('missing closing brace on outer if', () => {
|
|
28
|
+
expect(() => parse(`
|
|
29
|
+
if a {
|
|
30
|
+
if b {
|
|
31
|
+
let x = "nested"
|
|
32
|
+
}
|
|
33
|
+
`)).toThrow();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test('missing closing brace on inner if', () => {
|
|
37
|
+
expect(() => parse(`
|
|
38
|
+
if a {
|
|
39
|
+
if b {
|
|
40
|
+
let x = "nested"
|
|
41
|
+
}
|
|
42
|
+
`)).toThrow();
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
test('missing closing brace on deeply nested block', () => {
|
|
46
|
+
expect(() => parse(`
|
|
47
|
+
{
|
|
48
|
+
{
|
|
49
|
+
{
|
|
50
|
+
let deep = "value"
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
`)).toThrow();
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test('missing middle closing brace', () => {
|
|
57
|
+
expect(() => parse(`
|
|
58
|
+
{
|
|
59
|
+
{
|
|
60
|
+
let inner = "value"
|
|
61
|
+
}
|
|
62
|
+
`)).toThrow();
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// ============================================================================
|
|
66
|
+
// Missing closing braces in mixed nesting
|
|
67
|
+
// ============================================================================
|
|
68
|
+
|
|
69
|
+
test('function with unclosed if inside', () => {
|
|
70
|
+
expect(() => parse(`
|
|
71
|
+
function test() {
|
|
72
|
+
if condition {
|
|
73
|
+
let x = "value"
|
|
74
|
+
}
|
|
75
|
+
`)).toThrow();
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
test('if with unclosed block inside', () => {
|
|
79
|
+
expect(() => parse(`
|
|
80
|
+
if condition {
|
|
81
|
+
{
|
|
82
|
+
let x = "value"
|
|
83
|
+
}
|
|
84
|
+
`)).toThrow();
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
test('function with unclosed nested function', () => {
|
|
88
|
+
expect(() => parse(`
|
|
89
|
+
function outer() {
|
|
90
|
+
function inner() {
|
|
91
|
+
if x {
|
|
92
|
+
return "deep"
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
`)).toThrow();
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// ============================================================================
|
|
99
|
+
// Multiple unclosed braces
|
|
100
|
+
// ============================================================================
|
|
101
|
+
|
|
102
|
+
test('two unclosed braces', () => {
|
|
103
|
+
expect(() => parse(`
|
|
104
|
+
function test() {
|
|
105
|
+
if x {
|
|
106
|
+
let y = "value"
|
|
107
|
+
`)).toThrow();
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
test('three unclosed braces', () => {
|
|
111
|
+
expect(() => parse(`
|
|
112
|
+
function test() {
|
|
113
|
+
{
|
|
114
|
+
if x {
|
|
115
|
+
let y = "value"
|
|
116
|
+
`)).toThrow();
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
// ============================================================================
|
|
120
|
+
// Unclosed else blocks in nesting
|
|
121
|
+
// ============================================================================
|
|
122
|
+
|
|
123
|
+
test('unclosed else in nested if', () => {
|
|
124
|
+
expect(() => parse(`
|
|
125
|
+
function test() {
|
|
126
|
+
if a {
|
|
127
|
+
let x = "yes"
|
|
128
|
+
} else {
|
|
129
|
+
let y = "no"
|
|
130
|
+
}
|
|
131
|
+
`)).toThrow();
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
test('unclosed else-if in nested structure', () => {
|
|
135
|
+
expect(() => parse(`
|
|
136
|
+
function test() {
|
|
137
|
+
if a {
|
|
138
|
+
let x = "first"
|
|
139
|
+
} else if b {
|
|
140
|
+
let y = "second"
|
|
141
|
+
}
|
|
142
|
+
`)).toThrow();
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
// ============================================================================
|
|
146
|
+
// Extra closing braces
|
|
147
|
+
// ============================================================================
|
|
148
|
+
|
|
149
|
+
test('extra closing brace after nested blocks', () => {
|
|
150
|
+
expect(() => parse(`
|
|
151
|
+
function test() {
|
|
152
|
+
if x {
|
|
153
|
+
let y = "value"
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
`)).toThrow();
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
test('extra closing brace inside function', () => {
|
|
161
|
+
expect(() => parse(`
|
|
162
|
+
function test() {
|
|
163
|
+
let x = "value"
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
`)).toThrow();
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
// ============================================================================
|
|
170
|
+
// Misplaced braces
|
|
171
|
+
// ============================================================================
|
|
172
|
+
|
|
173
|
+
test('closing brace before opening in nested context', () => {
|
|
174
|
+
expect(() => parse(`
|
|
175
|
+
function test() {
|
|
176
|
+
}
|
|
177
|
+
if x {
|
|
178
|
+
let y = "value"
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
`)).toThrow();
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
test('opening brace without statement in nesting', () => {
|
|
185
|
+
expect(() => parse(`
|
|
186
|
+
function test() {
|
|
187
|
+
{ {
|
|
188
|
+
let x = "value"
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
`)).toThrow(); // Missing closing brace for inner block
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
// ============================================================================
|
|
195
|
+
// Incomplete statements in nested blocks
|
|
196
|
+
// ============================================================================
|
|
197
|
+
|
|
198
|
+
test('incomplete let in nested block', () => {
|
|
199
|
+
expect(() => parse(`
|
|
200
|
+
function test() {
|
|
201
|
+
if x {
|
|
202
|
+
let y =
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
`)).toThrow();
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
test('incomplete const in deeply nested block', () => {
|
|
209
|
+
expect(() => parse(`
|
|
210
|
+
function outer() {
|
|
211
|
+
function inner() {
|
|
212
|
+
const x =
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
`)).toThrow();
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
test('incomplete function declaration in nested block', () => {
|
|
219
|
+
expect(() => parse(`
|
|
220
|
+
function outer() {
|
|
221
|
+
function inner(
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
`)).toThrow();
|
|
225
|
+
});
|
|
226
|
+
});
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { describe, expect, test } from 'bun:test';
|
|
2
|
+
import { parse } from '../../parse';
|
|
3
|
+
|
|
4
|
+
describe('Syntax Errors - Unclosed Delimiters', () => {
|
|
5
|
+
// ============================================================================
|
|
6
|
+
// Unclosed braces
|
|
7
|
+
// ============================================================================
|
|
8
|
+
|
|
9
|
+
test('unclosed block statement', () => {
|
|
10
|
+
expect(() => parse(`
|
|
11
|
+
{
|
|
12
|
+
let x = "hello"
|
|
13
|
+
`)).toThrow();
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
test('unclosed function body', () => {
|
|
17
|
+
expect(() => parse(`
|
|
18
|
+
function foo() {
|
|
19
|
+
return "hello"
|
|
20
|
+
`)).toThrow();
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test('unclosed if block', () => {
|
|
24
|
+
expect(() => parse(`
|
|
25
|
+
if true {
|
|
26
|
+
let x = "yes"
|
|
27
|
+
`)).toThrow();
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test('unclosed else block', () => {
|
|
31
|
+
expect(() => parse(`
|
|
32
|
+
if true {
|
|
33
|
+
let x = "yes"
|
|
34
|
+
} else {
|
|
35
|
+
let y = "no"
|
|
36
|
+
`)).toThrow();
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
test('nested unclosed braces', () => {
|
|
40
|
+
expect(() => parse(`
|
|
41
|
+
function outer() {
|
|
42
|
+
if true {
|
|
43
|
+
let x = "nested"
|
|
44
|
+
}
|
|
45
|
+
`)).toThrow();
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
// ============================================================================
|
|
49
|
+
// Unclosed parentheses
|
|
50
|
+
// ============================================================================
|
|
51
|
+
|
|
52
|
+
test('unclosed function call', () => {
|
|
53
|
+
expect(() => parse(`
|
|
54
|
+
foo("hello"
|
|
55
|
+
`)).toThrow();
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test('unclosed function params', () => {
|
|
59
|
+
expect(() => parse(`
|
|
60
|
+
function greet(name, age
|
|
61
|
+
`)).toThrow();
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
test('unclosed grouped expression', () => {
|
|
65
|
+
expect(() => parse(`
|
|
66
|
+
let x = ("hello"
|
|
67
|
+
`)).toThrow();
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
test('nested unclosed parens in call', () => {
|
|
71
|
+
expect(() => parse(`
|
|
72
|
+
outer(inner("deep"
|
|
73
|
+
`)).toThrow();
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// ============================================================================
|
|
77
|
+
// Unclosed strings
|
|
78
|
+
// ============================================================================
|
|
79
|
+
|
|
80
|
+
test('unclosed double quote string', () => {
|
|
81
|
+
expect(() => parse(`
|
|
82
|
+
let x = "hello
|
|
83
|
+
`)).toThrow();
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
test('unclosed single quote string', () => {
|
|
87
|
+
expect(() => parse(`
|
|
88
|
+
let x = 'hello
|
|
89
|
+
`)).toThrow();
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
test('unclosed string in function call', () => {
|
|
93
|
+
expect(() => parse(`
|
|
94
|
+
greet("hello)
|
|
95
|
+
`)).toThrow();
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
test('unclosed string in vibe expression', () => {
|
|
99
|
+
expect(() => parse(`
|
|
100
|
+
let x = vibe "what is 2+2?
|
|
101
|
+
`)).toThrow();
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// ============================================================================
|
|
105
|
+
// Mixed unclosed delimiters
|
|
106
|
+
// ============================================================================
|
|
107
|
+
|
|
108
|
+
test('unclosed brace and paren', () => {
|
|
109
|
+
expect(() => parse(`
|
|
110
|
+
function test() {
|
|
111
|
+
foo(
|
|
112
|
+
}
|
|
113
|
+
`)).toThrow();
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
test('unclosed string inside unclosed block', () => {
|
|
117
|
+
expect(() => parse(`
|
|
118
|
+
{
|
|
119
|
+
let x = "hello
|
|
120
|
+
`)).toThrow();
|
|
121
|
+
});
|
|
122
|
+
});
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { describe, expect, test } from 'bun:test';
|
|
2
|
+
import { parse } from '../../parse';
|
|
3
|
+
|
|
4
|
+
describe('Syntax Errors - Unexpected Tokens', () => {
|
|
5
|
+
// ============================================================================
|
|
6
|
+
// Missing identifiers after keywords
|
|
7
|
+
// ============================================================================
|
|
8
|
+
|
|
9
|
+
test('let missing identifier', () => {
|
|
10
|
+
expect(() => parse(`
|
|
11
|
+
let = "hello"
|
|
12
|
+
`)).toThrow();
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
test('const missing identifier', () => {
|
|
16
|
+
expect(() => parse(`
|
|
17
|
+
const = "hello"
|
|
18
|
+
`)).toThrow();
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test('function missing name', () => {
|
|
22
|
+
expect(() => parse(`
|
|
23
|
+
function() {
|
|
24
|
+
return "hello"
|
|
25
|
+
}
|
|
26
|
+
`)).toThrow();
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test('function with keyword as name', () => {
|
|
30
|
+
expect(() => parse(`
|
|
31
|
+
function let() {
|
|
32
|
+
return "hello"
|
|
33
|
+
}
|
|
34
|
+
`)).toThrow();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// ============================================================================
|
|
38
|
+
// Keywords in wrong positions
|
|
39
|
+
// ============================================================================
|
|
40
|
+
|
|
41
|
+
test('return outside function at top level', () => {
|
|
42
|
+
// Note: This may or may not throw depending on parser design
|
|
43
|
+
// Testing the parser's behavior
|
|
44
|
+
expect(() => parse(`
|
|
45
|
+
return "hello"
|
|
46
|
+
`)).not.toThrow(); // return is valid as a statement
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test('break at top level', () => {
|
|
50
|
+
// break is syntactically valid, semantics checked at runtime
|
|
51
|
+
expect(() => parse(`
|
|
52
|
+
break
|
|
53
|
+
`)).not.toThrow();
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test('else without if', () => {
|
|
57
|
+
expect(() => parse(`
|
|
58
|
+
else {
|
|
59
|
+
let x = "no"
|
|
60
|
+
}
|
|
61
|
+
`)).toThrow();
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// ============================================================================
|
|
65
|
+
// Unexpected tokens in declarations
|
|
66
|
+
// ============================================================================
|
|
67
|
+
|
|
68
|
+
test('let with string instead of identifier', () => {
|
|
69
|
+
expect(() => parse(`
|
|
70
|
+
let "name" = "value"
|
|
71
|
+
`)).toThrow();
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
test('const with number-like token instead of identifier', () => {
|
|
75
|
+
expect(() => parse(`
|
|
76
|
+
const 123 = "value"
|
|
77
|
+
`)).toThrow();
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
test('function param is keyword', () => {
|
|
81
|
+
expect(() => parse(`
|
|
82
|
+
function test(return) {
|
|
83
|
+
return "hello"
|
|
84
|
+
}
|
|
85
|
+
`)).toThrow();
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// ============================================================================
|
|
89
|
+
// Unexpected tokens in expressions
|
|
90
|
+
// ============================================================================
|
|
91
|
+
|
|
92
|
+
test('let inside expression', () => {
|
|
93
|
+
expect(() => parse(`
|
|
94
|
+
let x = let y
|
|
95
|
+
`)).toThrow();
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
test('equals in wrong position', () => {
|
|
99
|
+
expect(() => parse(`
|
|
100
|
+
let x = = "hello"
|
|
101
|
+
`)).toThrow();
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// ============================================================================
|
|
105
|
+
// Unexpected tokens in blocks
|
|
106
|
+
// ============================================================================
|
|
107
|
+
|
|
108
|
+
test('closing brace without opening', () => {
|
|
109
|
+
expect(() => parse(`
|
|
110
|
+
let x = "hello"
|
|
111
|
+
}
|
|
112
|
+
`)).toThrow();
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
test('closing paren without opening', () => {
|
|
116
|
+
expect(() => parse(`
|
|
117
|
+
let x = "hello")
|
|
118
|
+
`)).toThrow();
|
|
119
|
+
});
|
|
120
|
+
});
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { describe, expect, test } from 'bun:test';
|
|
2
|
+
import { parse } from '../parse';
|
|
3
|
+
import type * as AST from '../../ast';
|
|
4
|
+
|
|
5
|
+
describe('Parser - Import Declarations', () => {
|
|
6
|
+
test('single import from TypeScript file', () => {
|
|
7
|
+
const source = `import { add } from "./math.ts"`;
|
|
8
|
+
const ast = parse(source);
|
|
9
|
+
|
|
10
|
+
expect(ast.body).toHaveLength(1);
|
|
11
|
+
const importDecl = ast.body[0] as AST.ImportDeclaration;
|
|
12
|
+
expect(importDecl.type).toBe('ImportDeclaration');
|
|
13
|
+
expect(importDecl.specifiers).toEqual([{ imported: 'add', local: 'add' }]);
|
|
14
|
+
expect(importDecl.source).toBe('./math.ts');
|
|
15
|
+
expect(importDecl.sourceType).toBe('ts');
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
test('multiple imports from TypeScript file', () => {
|
|
19
|
+
const source = `import { add, subtract, multiply } from "./math.ts"`;
|
|
20
|
+
const ast = parse(source);
|
|
21
|
+
|
|
22
|
+
const importDecl = ast.body[0] as AST.ImportDeclaration;
|
|
23
|
+
expect(importDecl.specifiers).toEqual([
|
|
24
|
+
{ imported: 'add', local: 'add' },
|
|
25
|
+
{ imported: 'subtract', local: 'subtract' },
|
|
26
|
+
{ imported: 'multiply', local: 'multiply' },
|
|
27
|
+
]);
|
|
28
|
+
expect(importDecl.sourceType).toBe('ts');
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test('import from Vibe file', () => {
|
|
32
|
+
const source = `import { greet } from "./utils.vibe"`;
|
|
33
|
+
const ast = parse(source);
|
|
34
|
+
|
|
35
|
+
const importDecl = ast.body[0] as AST.ImportDeclaration;
|
|
36
|
+
expect(importDecl.specifiers).toEqual([{ imported: 'greet', local: 'greet' }]);
|
|
37
|
+
expect(importDecl.source).toBe('./utils.vibe');
|
|
38
|
+
expect(importDecl.sourceType).toBe('vibe');
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test('import from JavaScript file', () => {
|
|
42
|
+
const source = `import { helper } from "./helper.js"`;
|
|
43
|
+
const ast = parse(source);
|
|
44
|
+
|
|
45
|
+
const importDecl = ast.body[0] as AST.ImportDeclaration;
|
|
46
|
+
expect(importDecl.sourceType).toBe('ts'); // JS files are treated as TS
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test('multiple import statements', () => {
|
|
50
|
+
const source = `
|
|
51
|
+
import { add } from "./math.ts"
|
|
52
|
+
import { greet } from "./greet.vibe"
|
|
53
|
+
let x = add("a", "b")
|
|
54
|
+
`;
|
|
55
|
+
const ast = parse(source);
|
|
56
|
+
|
|
57
|
+
expect(ast.body).toHaveLength(3);
|
|
58
|
+
expect((ast.body[0] as AST.ImportDeclaration).type).toBe('ImportDeclaration');
|
|
59
|
+
expect((ast.body[1] as AST.ImportDeclaration).type).toBe('ImportDeclaration');
|
|
60
|
+
expect((ast.body[2] as AST.LetDeclaration).type).toBe('LetDeclaration');
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
describe('Parser - Export Declarations', () => {
|
|
65
|
+
test('export function', () => {
|
|
66
|
+
const source = `
|
|
67
|
+
export function greet(name: text): text {
|
|
68
|
+
return vibe "Hello {name}" gpt default
|
|
69
|
+
}
|
|
70
|
+
`;
|
|
71
|
+
const ast = parse(source);
|
|
72
|
+
|
|
73
|
+
expect(ast.body).toHaveLength(1);
|
|
74
|
+
const exportDecl = ast.body[0] as AST.ExportDeclaration;
|
|
75
|
+
expect(exportDecl.type).toBe('ExportDeclaration');
|
|
76
|
+
expect(exportDecl.declaration.type).toBe('FunctionDeclaration');
|
|
77
|
+
expect((exportDecl.declaration as AST.FunctionDeclaration).name).toBe('greet');
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
test('export let', () => {
|
|
81
|
+
const source = `export let counter = "0"`;
|
|
82
|
+
const ast = parse(source);
|
|
83
|
+
|
|
84
|
+
const exportDecl = ast.body[0] as AST.ExportDeclaration;
|
|
85
|
+
expect(exportDecl.type).toBe('ExportDeclaration');
|
|
86
|
+
expect(exportDecl.declaration.type).toBe('LetDeclaration');
|
|
87
|
+
expect((exportDecl.declaration as AST.LetDeclaration).name).toBe('counter');
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test('export const', () => {
|
|
91
|
+
const source = `export const API_KEY = "secret123"`;
|
|
92
|
+
const ast = parse(source);
|
|
93
|
+
|
|
94
|
+
const exportDecl = ast.body[0] as AST.ExportDeclaration;
|
|
95
|
+
expect(exportDecl.type).toBe('ExportDeclaration');
|
|
96
|
+
expect(exportDecl.declaration.type).toBe('ConstDeclaration');
|
|
97
|
+
expect((exportDecl.declaration as AST.ConstDeclaration).name).toBe('API_KEY');
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
test('export model', () => {
|
|
101
|
+
const source = `export model gpt = { name: "gpt-4" }`;
|
|
102
|
+
const ast = parse(source);
|
|
103
|
+
|
|
104
|
+
const exportDecl = ast.body[0] as AST.ExportDeclaration;
|
|
105
|
+
expect(exportDecl.type).toBe('ExportDeclaration');
|
|
106
|
+
expect(exportDecl.declaration.type).toBe('ModelDeclaration');
|
|
107
|
+
expect((exportDecl.declaration as AST.ModelDeclaration).name).toBe('gpt');
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
test('multiple exports', () => {
|
|
111
|
+
const source = `
|
|
112
|
+
export function add(a: text, b: text): text {
|
|
113
|
+
return ts(a, b) { return a + b }
|
|
114
|
+
}
|
|
115
|
+
export const PI = "3.14159"
|
|
116
|
+
export model gpt = { name: "gpt-4" }
|
|
117
|
+
`;
|
|
118
|
+
const ast = parse(source);
|
|
119
|
+
|
|
120
|
+
expect(ast.body).toHaveLength(3);
|
|
121
|
+
expect((ast.body[0] as AST.ExportDeclaration).declaration.type).toBe('FunctionDeclaration');
|
|
122
|
+
expect((ast.body[1] as AST.ExportDeclaration).declaration.type).toBe('ConstDeclaration');
|
|
123
|
+
expect((ast.body[2] as AST.ExportDeclaration).declaration.type).toBe('ModelDeclaration');
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
describe('Parser - Import and Export Combined', () => {
|
|
128
|
+
test('import and export in same file', () => {
|
|
129
|
+
const source = `
|
|
130
|
+
import { helper } from "./helper.ts"
|
|
131
|
+
|
|
132
|
+
export function greet(name: text): text {
|
|
133
|
+
let greeting = helper(name)
|
|
134
|
+
return vibe "{greeting}" gpt default
|
|
135
|
+
}
|
|
136
|
+
`;
|
|
137
|
+
const ast = parse(source);
|
|
138
|
+
|
|
139
|
+
expect(ast.body).toHaveLength(2);
|
|
140
|
+
expect((ast.body[0] as AST.ImportDeclaration).type).toBe('ImportDeclaration');
|
|
141
|
+
expect((ast.body[1] as AST.ExportDeclaration).type).toBe('ExportDeclaration');
|
|
142
|
+
});
|
|
143
|
+
});
|