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.
Files changed (48) hide show
  1. package/README.md +59 -57
  2. package/dist/index.js +641 -191
  3. package/dist/index.js.map +4 -4
  4. package/package.json +1 -1
  5. package/src/cli/Runner.ts +1 -1
  6. package/src/cli/__tests__/Runner.test.ts +8 -8
  7. package/src/cli/serve/ServeCommand.ts +29 -9
  8. package/src/transpiler/Transpiler.ts +105 -200
  9. package/src/transpiler/__tests__/DualCodePaths.test.ts +117 -68
  10. package/src/transpiler/__tests__/Transpiler.coverage.test.ts +87 -51
  11. package/src/transpiler/__tests__/Transpiler.test.ts +150 -48
  12. package/src/transpiler/__tests__/determineProjectRoot.test.ts +2 -2
  13. package/src/transpiler/data/IncludeResolver.ts +11 -3
  14. package/src/transpiler/data/__tests__/IncludeResolver.test.ts +2 -2
  15. package/src/transpiler/logic/analysis/ArrayIndexTypeAnalyzer.ts +346 -0
  16. package/src/transpiler/logic/analysis/FunctionCallAnalyzer.ts +170 -14
  17. package/src/transpiler/logic/analysis/__tests__/ArrayIndexTypeAnalyzer.test.ts +545 -0
  18. package/src/transpiler/logic/analysis/__tests__/FunctionCallAnalyzer.test.ts +327 -0
  19. package/src/transpiler/logic/analysis/runAnalyzers.ts +9 -2
  20. package/src/transpiler/logic/analysis/types/IArrayIndexTypeError.ts +15 -0
  21. package/src/transpiler/logic/symbols/TransitiveEnumCollector.ts +1 -1
  22. package/src/transpiler/logic/symbols/c/index.ts +50 -1
  23. package/src/transpiler/logic/symbols/c/utils/DeclaratorUtils.ts +99 -2
  24. package/src/transpiler/logic/symbols/c/utils/__tests__/DeclaratorUtils.test.ts +128 -0
  25. package/src/transpiler/output/codegen/CodeGenerator.ts +31 -5
  26. package/src/transpiler/output/codegen/TypeValidator.ts +10 -7
  27. package/src/transpiler/output/codegen/__tests__/CodeGenerator.test.ts +49 -36
  28. package/src/transpiler/output/codegen/__tests__/ExpressionWalker.test.ts +9 -3
  29. package/src/transpiler/output/codegen/__tests__/RequireInclude.test.ts +90 -25
  30. package/src/transpiler/output/codegen/__tests__/TrackVariableTypeHelpers.test.ts +3 -1
  31. package/src/transpiler/output/codegen/__tests__/TypeValidator.test.ts +43 -29
  32. package/src/transpiler/output/codegen/generators/IOrchestrator.ts +5 -2
  33. package/src/transpiler/output/codegen/generators/expressions/PostfixExpressionGenerator.ts +23 -14
  34. package/src/transpiler/output/codegen/generators/expressions/__tests__/PostfixExpressionGenerator.test.ts +10 -7
  35. package/src/transpiler/output/codegen/generators/statements/ControlFlowGenerator.ts +12 -3
  36. package/src/transpiler/output/codegen/generators/statements/SwitchGenerator.ts +10 -1
  37. package/src/transpiler/output/codegen/generators/statements/__tests__/ControlFlowGenerator.test.ts +4 -4
  38. package/src/transpiler/output/codegen/helpers/ArrayAccessHelper.ts +6 -3
  39. package/src/transpiler/output/codegen/helpers/FloatBitHelper.ts +36 -22
  40. package/src/transpiler/output/codegen/helpers/FunctionContextManager.ts +9 -1
  41. package/src/transpiler/output/codegen/helpers/__tests__/ArrayAccessHelper.test.ts +8 -6
  42. package/src/transpiler/output/codegen/helpers/__tests__/FloatBitHelper.test.ts +34 -18
  43. package/src/transpiler/output/headers/HeaderGeneratorUtils.ts +5 -2
  44. package/src/transpiler/state/CodeGenState.ts +6 -0
  45. package/src/transpiler/types/IPipelineFile.ts +2 -2
  46. package/src/transpiler/types/IPipelineInput.ts +1 -1
  47. package/src/transpiler/types/TTranspileInput.ts +18 -0
  48. 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 run() and transpileSource() produce identical
5
- * output for the same input, ensuring the refactoring doesn't break anything.
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 now guaranteed by architecture — both run() and
8
- * transpileSource() delegate to the same _executePipeline(). These tests
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.run();
57
+ const result1 = await transpiler1.transpile({ kind: "files" });
59
58
 
60
59
  // Path 2: Via transpileSource()
61
60
  const transpiler2 = createTranspiler([]);
62
- const result2 = await transpiler2.transpileSource(source, {
63
- workingDir: tempDir,
64
- sourcePath: filePath,
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.run();
93
+ const result1 = await transpiler1.transpile({ kind: "files" });
91
94
 
92
95
  const transpiler2 = createTranspiler([]);
93
- const result2 = await transpiler2.transpileSource(source, {
94
- workingDir: tempDir,
95
- sourcePath: filePath,
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.run();
123
+ const result1 = await transpiler1.transpile({ kind: "files" });
117
124
 
118
125
  const transpiler2 = createTranspiler([]);
119
- const result2 = await transpiler2.transpileSource(source, {
120
- workingDir: tempDir,
121
- sourcePath: filePath,
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.run();
159
+ const result1 = await transpiler1.transpile({ kind: "files" });
149
160
 
150
161
  const transpiler2 = createTranspiler([]);
151
- const result2 = await transpiler2.transpileSource(source, {
152
- workingDir: tempDir,
153
- sourcePath: filePath,
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.run();
199
+ const result1 = await transpiler1.transpile({ kind: "files" });
185
200
 
186
201
  const transpiler2 = createTranspiler([]);
187
- const result2 = await transpiler2.transpileSource(source, {
188
- workingDir: tempDir,
189
- sourcePath: filePath,
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.run();
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.run();
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.run();
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.run();
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 = await transpiler2.transpileSource(consumerSource, {
348
- workingDir: tempDir,
349
- sourcePath: consumerPath,
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.run();
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 = await transpiler2.transpileSource(writerSource, {
401
- workingDir: tempDir,
402
- sourcePath: writerPath,
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 = await transpiler.transpileSource(source1, {
426
- sourcePath: "file1.cnx",
427
- });
428
- const result2 = await transpiler.transpileSource(source2, {
429
- sourcePath: "file2.cnx",
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.run();
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.run();
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.run();
524
+ const result1 = await transpiler1.transpile({ kind: "files" });
490
525
 
491
526
  const transpiler2 = createTranspiler([]);
492
- const result2 = await transpiler2.transpileSource(source, {
493
- workingDir: tempDir,
494
- sourcePath: filePath,
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.run();
568
+ const result1 = await transpiler1.transpile({ kind: "files" });
530
569
 
531
570
  const transpiler2 = createTranspiler([]);
532
- const result2 = await transpiler2.transpileSource(source, {
533
- workingDir: tempDir,
534
- sourcePath: filePath,
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.run();
611
+ const result1 = await transpiler1.transpile({ kind: "files" });
569
612
 
570
613
  const transpiler2 = createTranspiler([]);
571
- const result2 = await transpiler2.transpileSource(source, {
572
- workingDir: tempDir,
573
- sourcePath: filePath,
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.run();
638
+ const result1 = await transpiler1.transpile({ kind: "files" });
592
639
 
593
640
  const transpiler2 = createTranspiler([]);
594
- const result2 = await transpiler2.transpileSource(invalidSource, {
641
+ const result2 = await transpiler2.transpile({
642
+ kind: "source",
643
+ source: invalidSource,
595
644
  sourcePath: filePath,
596
645
  });
597
646