c-next 0.2.2 → 0.2.4
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/README.md +59 -57
- package/dist/index.js +641 -191
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
- package/src/cli/Runner.ts +1 -1
- package/src/cli/__tests__/Runner.test.ts +8 -8
- package/src/cli/serve/ServeCommand.ts +29 -9
- package/src/transpiler/Transpiler.ts +105 -200
- package/src/transpiler/__tests__/DualCodePaths.test.ts +117 -68
- package/src/transpiler/__tests__/Transpiler.coverage.test.ts +87 -51
- package/src/transpiler/__tests__/Transpiler.test.ts +150 -48
- package/src/transpiler/__tests__/determineProjectRoot.test.ts +2 -2
- package/src/transpiler/data/IncludeResolver.ts +11 -3
- package/src/transpiler/data/__tests__/IncludeResolver.test.ts +2 -2
- package/src/transpiler/logic/analysis/ArrayIndexTypeAnalyzer.ts +346 -0
- package/src/transpiler/logic/analysis/FunctionCallAnalyzer.ts +170 -14
- package/src/transpiler/logic/analysis/__tests__/ArrayIndexTypeAnalyzer.test.ts +545 -0
- package/src/transpiler/logic/analysis/__tests__/FunctionCallAnalyzer.test.ts +327 -0
- package/src/transpiler/logic/analysis/runAnalyzers.ts +9 -2
- package/src/transpiler/logic/analysis/types/IArrayIndexTypeError.ts +15 -0
- package/src/transpiler/logic/symbols/TransitiveEnumCollector.ts +1 -1
- package/src/transpiler/logic/symbols/c/index.ts +50 -1
- package/src/transpiler/logic/symbols/c/utils/DeclaratorUtils.ts +99 -2
- package/src/transpiler/logic/symbols/c/utils/__tests__/DeclaratorUtils.test.ts +128 -0
- package/src/transpiler/output/codegen/CodeGenerator.ts +31 -5
- package/src/transpiler/output/codegen/TypeValidator.ts +10 -7
- package/src/transpiler/output/codegen/__tests__/CodeGenerator.test.ts +49 -36
- package/src/transpiler/output/codegen/__tests__/ExpressionWalker.test.ts +9 -3
- package/src/transpiler/output/codegen/__tests__/RequireInclude.test.ts +90 -25
- package/src/transpiler/output/codegen/__tests__/TrackVariableTypeHelpers.test.ts +3 -1
- package/src/transpiler/output/codegen/__tests__/TypeValidator.test.ts +43 -29
- package/src/transpiler/output/codegen/generators/IOrchestrator.ts +5 -2
- package/src/transpiler/output/codegen/generators/expressions/PostfixExpressionGenerator.ts +23 -14
- package/src/transpiler/output/codegen/generators/expressions/__tests__/PostfixExpressionGenerator.test.ts +10 -7
- package/src/transpiler/output/codegen/generators/statements/ControlFlowGenerator.ts +12 -3
- package/src/transpiler/output/codegen/generators/statements/SwitchGenerator.ts +10 -1
- package/src/transpiler/output/codegen/generators/statements/__tests__/ControlFlowGenerator.test.ts +4 -4
- package/src/transpiler/output/codegen/helpers/ArrayAccessHelper.ts +6 -3
- package/src/transpiler/output/codegen/helpers/FloatBitHelper.ts +36 -22
- package/src/transpiler/output/codegen/helpers/FunctionContextManager.ts +9 -1
- package/src/transpiler/output/codegen/helpers/__tests__/ArrayAccessHelper.test.ts +8 -6
- package/src/transpiler/output/codegen/helpers/__tests__/FloatBitHelper.test.ts +34 -18
- package/src/transpiler/output/headers/HeaderGeneratorUtils.ts +5 -2
- package/src/transpiler/state/CodeGenState.ts +6 -0
- package/src/transpiler/types/IPipelineFile.ts +2 -2
- package/src/transpiler/types/IPipelineInput.ts +1 -1
- package/src/transpiler/types/TTranspileInput.ts +18 -0
- package/src/utils/constants/TypeConstants.ts +22 -0
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Tests for dual code path consolidation (Issue #634)
|
|
3
3
|
*
|
|
4
|
-
* These tests verify that
|
|
5
|
-
*
|
|
4
|
+
* These tests verify that transpile({ kind: 'files' }) and
|
|
5
|
+
* transpile({ kind: 'source' }) produce identical output for the same input.
|
|
6
6
|
*
|
|
7
|
-
* Design note: Parity is
|
|
8
|
-
*
|
|
9
|
-
* verify the external behavior still matches.
|
|
7
|
+
* Design note: Parity is guaranteed by architecture — both paths delegate
|
|
8
|
+
* to the same _executePipeline() via the unified transpile() entry point.
|
|
10
9
|
*/
|
|
11
10
|
|
|
12
11
|
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
@@ -55,14 +54,18 @@ void main() {
|
|
|
55
54
|
|
|
56
55
|
// Path 1: Via run()
|
|
57
56
|
const transpiler1 = createTranspiler([filePath]);
|
|
58
|
-
const result1 = await transpiler1.
|
|
57
|
+
const result1 = await transpiler1.transpile({ kind: "files" });
|
|
59
58
|
|
|
60
59
|
// Path 2: Via transpileSource()
|
|
61
60
|
const transpiler2 = createTranspiler([]);
|
|
62
|
-
const result2 =
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
61
|
+
const result2 = (
|
|
62
|
+
await transpiler2.transpile({
|
|
63
|
+
kind: "source",
|
|
64
|
+
source: source,
|
|
65
|
+
workingDir: tempDir,
|
|
66
|
+
sourcePath: filePath,
|
|
67
|
+
})
|
|
68
|
+
).files[0];
|
|
66
69
|
|
|
67
70
|
expect(result1.success).toBe(true);
|
|
68
71
|
expect(result2.success).toBe(true);
|
|
@@ -87,13 +90,17 @@ void main() {
|
|
|
87
90
|
writeFileSync(filePath, source);
|
|
88
91
|
|
|
89
92
|
const transpiler1 = createTranspiler([filePath]);
|
|
90
|
-
const result1 = await transpiler1.
|
|
93
|
+
const result1 = await transpiler1.transpile({ kind: "files" });
|
|
91
94
|
|
|
92
95
|
const transpiler2 = createTranspiler([]);
|
|
93
|
-
const result2 =
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
96
|
+
const result2 = (
|
|
97
|
+
await transpiler2.transpile({
|
|
98
|
+
kind: "source",
|
|
99
|
+
source: source,
|
|
100
|
+
workingDir: tempDir,
|
|
101
|
+
sourcePath: filePath,
|
|
102
|
+
})
|
|
103
|
+
).files[0];
|
|
97
104
|
|
|
98
105
|
expect(result1.success).toBe(true);
|
|
99
106
|
expect(result2.success).toBe(true);
|
|
@@ -113,13 +120,17 @@ void main() {
|
|
|
113
120
|
writeFileSync(filePath, source);
|
|
114
121
|
|
|
115
122
|
const transpiler1 = createTranspiler([filePath]);
|
|
116
|
-
const result1 = await transpiler1.
|
|
123
|
+
const result1 = await transpiler1.transpile({ kind: "files" });
|
|
117
124
|
|
|
118
125
|
const transpiler2 = createTranspiler([]);
|
|
119
|
-
const result2 =
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
126
|
+
const result2 = (
|
|
127
|
+
await transpiler2.transpile({
|
|
128
|
+
kind: "source",
|
|
129
|
+
source: source,
|
|
130
|
+
workingDir: tempDir,
|
|
131
|
+
sourcePath: filePath,
|
|
132
|
+
})
|
|
133
|
+
).files[0];
|
|
123
134
|
|
|
124
135
|
expect(result1.success).toBe(true);
|
|
125
136
|
expect(result2.success).toBe(true);
|
|
@@ -145,13 +156,17 @@ void main() {
|
|
|
145
156
|
writeFileSync(filePath, source);
|
|
146
157
|
|
|
147
158
|
const transpiler1 = createTranspiler([filePath]);
|
|
148
|
-
const result1 = await transpiler1.
|
|
159
|
+
const result1 = await transpiler1.transpile({ kind: "files" });
|
|
149
160
|
|
|
150
161
|
const transpiler2 = createTranspiler([]);
|
|
151
|
-
const result2 =
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
162
|
+
const result2 = (
|
|
163
|
+
await transpiler2.transpile({
|
|
164
|
+
kind: "source",
|
|
165
|
+
source: source,
|
|
166
|
+
workingDir: tempDir,
|
|
167
|
+
sourcePath: filePath,
|
|
168
|
+
})
|
|
169
|
+
).files[0];
|
|
155
170
|
|
|
156
171
|
expect(result1.success).toBe(true);
|
|
157
172
|
expect(result2.success).toBe(true);
|
|
@@ -181,13 +196,17 @@ void main() {
|
|
|
181
196
|
writeFileSync(filePath, source);
|
|
182
197
|
|
|
183
198
|
const transpiler1 = createTranspiler([filePath]);
|
|
184
|
-
const result1 = await transpiler1.
|
|
199
|
+
const result1 = await transpiler1.transpile({ kind: "files" });
|
|
185
200
|
|
|
186
201
|
const transpiler2 = createTranspiler([]);
|
|
187
|
-
const result2 =
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
202
|
+
const result2 = (
|
|
203
|
+
await transpiler2.transpile({
|
|
204
|
+
kind: "source",
|
|
205
|
+
source: source,
|
|
206
|
+
workingDir: tempDir,
|
|
207
|
+
sourcePath: filePath,
|
|
208
|
+
})
|
|
209
|
+
).files[0];
|
|
191
210
|
|
|
192
211
|
expect(result1.success).toBe(true);
|
|
193
212
|
expect(result2.success).toBe(true);
|
|
@@ -228,7 +247,7 @@ void main() {
|
|
|
228
247
|
|
|
229
248
|
// run() should handle cross-file references
|
|
230
249
|
const transpiler = createTranspiler([mainPath]);
|
|
231
|
-
const result = await transpiler.
|
|
250
|
+
const result = await transpiler.transpile({ kind: "files" });
|
|
232
251
|
|
|
233
252
|
expect(result.success).toBe(true);
|
|
234
253
|
expect(result.files.length).toBe(2);
|
|
@@ -265,7 +284,7 @@ void main() {
|
|
|
265
284
|
writeFileSync(mainPath, mainSource);
|
|
266
285
|
|
|
267
286
|
const transpiler = createTranspiler([mainPath]);
|
|
268
|
-
const result = await transpiler.
|
|
287
|
+
const result = await transpiler.transpile({ kind: "files" });
|
|
269
288
|
|
|
270
289
|
expect(result.success).toBe(true);
|
|
271
290
|
});
|
|
@@ -292,7 +311,7 @@ void main() {
|
|
|
292
311
|
writeFileSync(mainPath, mainSource);
|
|
293
312
|
|
|
294
313
|
const transpiler = createTranspiler([mainPath]);
|
|
295
|
-
const result = await transpiler.
|
|
314
|
+
const result = await transpiler.transpile({ kind: "files" });
|
|
296
315
|
|
|
297
316
|
expect(result.success).toBe(true);
|
|
298
317
|
});
|
|
@@ -329,7 +348,7 @@ void main() {
|
|
|
329
348
|
|
|
330
349
|
// Via run()
|
|
331
350
|
const transpiler1 = createTranspiler([consumerPath]);
|
|
332
|
-
const result1 = await transpiler1.
|
|
351
|
+
const result1 = await transpiler1.transpile({ kind: "files" });
|
|
333
352
|
|
|
334
353
|
expect(result1.success).toBe(true);
|
|
335
354
|
|
|
@@ -344,10 +363,14 @@ void main() {
|
|
|
344
363
|
|
|
345
364
|
// Via transpileSource() with context from run()
|
|
346
365
|
const transpiler2 = createTranspiler([]);
|
|
347
|
-
const result2 =
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
366
|
+
const result2 = (
|
|
367
|
+
await transpiler2.transpile({
|
|
368
|
+
kind: "source",
|
|
369
|
+
source: consumerSource,
|
|
370
|
+
workingDir: tempDir,
|
|
371
|
+
sourcePath: consumerPath,
|
|
372
|
+
})
|
|
373
|
+
).files[0];
|
|
351
374
|
|
|
352
375
|
expect(result2.success).toBe(true);
|
|
353
376
|
expect(result2.code).toContain("Provider_getValue()");
|
|
@@ -384,7 +407,7 @@ void main() {
|
|
|
384
407
|
|
|
385
408
|
// Via run()
|
|
386
409
|
const transpiler1 = createTranspiler([writerPath]);
|
|
387
|
-
const result1 = await transpiler1.
|
|
410
|
+
const result1 = await transpiler1.transpile({ kind: "files" });
|
|
388
411
|
|
|
389
412
|
expect(result1.success).toBe(true);
|
|
390
413
|
|
|
@@ -397,10 +420,14 @@ void main() {
|
|
|
397
420
|
|
|
398
421
|
// Via transpileSource()
|
|
399
422
|
const transpiler2 = createTranspiler([]);
|
|
400
|
-
const result2 =
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
423
|
+
const result2 = (
|
|
424
|
+
await transpiler2.transpile({
|
|
425
|
+
kind: "source",
|
|
426
|
+
source: writerSource,
|
|
427
|
+
workingDir: tempDir,
|
|
428
|
+
sourcePath: writerPath,
|
|
429
|
+
})
|
|
430
|
+
).files[0];
|
|
404
431
|
|
|
405
432
|
expect(result2.success).toBe(true);
|
|
406
433
|
expect(result2.code).toContain("Storage_value = 42");
|
|
@@ -422,12 +449,20 @@ void main() {}
|
|
|
422
449
|
// Two separate standalone transpileSource calls
|
|
423
450
|
const transpiler = createTranspiler([]);
|
|
424
451
|
|
|
425
|
-
const result1 =
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
452
|
+
const result1 = (
|
|
453
|
+
await transpiler.transpile({
|
|
454
|
+
kind: "source",
|
|
455
|
+
source: source1,
|
|
456
|
+
sourcePath: "file1.cnx",
|
|
457
|
+
})
|
|
458
|
+
).files[0];
|
|
459
|
+
const result2 = (
|
|
460
|
+
await transpiler.transpile({
|
|
461
|
+
kind: "source",
|
|
462
|
+
source: source2,
|
|
463
|
+
sourcePath: "file2.cnx",
|
|
464
|
+
})
|
|
465
|
+
).files[0];
|
|
431
466
|
|
|
432
467
|
expect(result1.success).toBe(true);
|
|
433
468
|
expect(result2.success).toBe(true);
|
|
@@ -450,12 +485,12 @@ void main() {}
|
|
|
450
485
|
const transpiler = createTranspiler([filePath]);
|
|
451
486
|
|
|
452
487
|
// First run
|
|
453
|
-
const result1 = await transpiler.
|
|
488
|
+
const result1 = await transpiler.transpile({ kind: "files" });
|
|
454
489
|
expect(result1.success).toBe(true);
|
|
455
490
|
expect(result1.symbolsCollected).toBeGreaterThan(0);
|
|
456
491
|
|
|
457
492
|
// Second run should not accumulate symbols from first
|
|
458
|
-
const result2 = await transpiler.
|
|
493
|
+
const result2 = await transpiler.transpile({ kind: "files" });
|
|
459
494
|
expect(result2.success).toBe(true);
|
|
460
495
|
expect(result2.symbolsCollected).toBe(result1.symbolsCollected);
|
|
461
496
|
});
|
|
@@ -486,13 +521,17 @@ void main() {
|
|
|
486
521
|
writeFileSync(filePath, source);
|
|
487
522
|
|
|
488
523
|
const transpiler1 = createTranspiler([filePath]);
|
|
489
|
-
const result1 = await transpiler1.
|
|
524
|
+
const result1 = await transpiler1.transpile({ kind: "files" });
|
|
490
525
|
|
|
491
526
|
const transpiler2 = createTranspiler([]);
|
|
492
|
-
const result2 =
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
527
|
+
const result2 = (
|
|
528
|
+
await transpiler2.transpile({
|
|
529
|
+
kind: "source",
|
|
530
|
+
source: source,
|
|
531
|
+
workingDir: tempDir,
|
|
532
|
+
sourcePath: filePath,
|
|
533
|
+
})
|
|
534
|
+
).files[0];
|
|
496
535
|
|
|
497
536
|
expect(result1.success).toBe(true);
|
|
498
537
|
expect(result2.success).toBe(true);
|
|
@@ -526,13 +565,17 @@ void main() {
|
|
|
526
565
|
writeFileSync(filePath, source);
|
|
527
566
|
|
|
528
567
|
const transpiler1 = createTranspiler([filePath]);
|
|
529
|
-
const result1 = await transpiler1.
|
|
568
|
+
const result1 = await transpiler1.transpile({ kind: "files" });
|
|
530
569
|
|
|
531
570
|
const transpiler2 = createTranspiler([]);
|
|
532
|
-
const result2 =
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
571
|
+
const result2 = (
|
|
572
|
+
await transpiler2.transpile({
|
|
573
|
+
kind: "source",
|
|
574
|
+
source: source,
|
|
575
|
+
workingDir: tempDir,
|
|
576
|
+
sourcePath: filePath,
|
|
577
|
+
})
|
|
578
|
+
).files[0];
|
|
536
579
|
|
|
537
580
|
expect(result1.success).toBe(true);
|
|
538
581
|
expect(result2.success).toBe(true);
|
|
@@ -565,13 +608,17 @@ void main() {
|
|
|
565
608
|
writeFileSync(filePath, source);
|
|
566
609
|
|
|
567
610
|
const transpiler1 = createTranspiler([filePath]);
|
|
568
|
-
const result1 = await transpiler1.
|
|
611
|
+
const result1 = await transpiler1.transpile({ kind: "files" });
|
|
569
612
|
|
|
570
613
|
const transpiler2 = createTranspiler([]);
|
|
571
|
-
const result2 =
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
614
|
+
const result2 = (
|
|
615
|
+
await transpiler2.transpile({
|
|
616
|
+
kind: "source",
|
|
617
|
+
source: source,
|
|
618
|
+
workingDir: tempDir,
|
|
619
|
+
sourcePath: filePath,
|
|
620
|
+
})
|
|
621
|
+
).files[0];
|
|
575
622
|
|
|
576
623
|
expect(result1.success).toBe(true);
|
|
577
624
|
expect(result2.success).toBe(true);
|
|
@@ -588,10 +635,12 @@ u8 x <- ; // Parse error: missing expression
|
|
|
588
635
|
writeFileSync(filePath, invalidSource);
|
|
589
636
|
|
|
590
637
|
const transpiler1 = createTranspiler([filePath]);
|
|
591
|
-
const result1 = await transpiler1.
|
|
638
|
+
const result1 = await transpiler1.transpile({ kind: "files" });
|
|
592
639
|
|
|
593
640
|
const transpiler2 = createTranspiler([]);
|
|
594
|
-
const result2 = await transpiler2.
|
|
641
|
+
const result2 = await transpiler2.transpile({
|
|
642
|
+
kind: "source",
|
|
643
|
+
source: invalidSource,
|
|
595
644
|
sourcePath: filePath,
|
|
596
645
|
});
|
|
597
646
|
|