c-next 0.1.69 → 0.1.70

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 (54) hide show
  1. package/package.json +1 -1
  2. package/src/transpiler/logic/analysis/FunctionCallAnalyzer.ts +240 -204
  3. package/src/transpiler/logic/analysis/PassByValueAnalyzer.ts +693 -0
  4. package/src/transpiler/logic/analysis/__tests__/FunctionCallAnalyzer.test.ts +86 -5
  5. package/src/transpiler/{output/codegen → logic/analysis}/helpers/AssignmentTargetExtractor.ts +1 -1
  6. package/src/transpiler/{output/codegen → logic/analysis}/helpers/ChildStatementCollector.ts +1 -1
  7. package/src/transpiler/{output/codegen → logic/analysis}/helpers/StatementExpressionCollector.ts +1 -1
  8. package/src/transpiler/{output/codegen → logic/analysis}/helpers/__tests__/AssignmentTargetExtractor.test.ts +2 -2
  9. package/src/transpiler/{output/codegen → logic/analysis}/helpers/__tests__/ChildStatementCollector.test.ts +2 -2
  10. package/src/transpiler/{output/codegen → logic/analysis}/helpers/__tests__/StatementExpressionCollector.test.ts +2 -2
  11. package/src/transpiler/output/codegen/CodeGenerator.ts +35 -607
  12. package/src/transpiler/output/codegen/TypeRegistrationUtils.ts +4 -6
  13. package/src/transpiler/output/codegen/TypeResolver.ts +2 -2
  14. package/src/transpiler/output/codegen/TypeValidator.ts +5 -5
  15. package/src/transpiler/output/codegen/__tests__/TypeRegistrationUtils.test.ts +36 -51
  16. package/src/transpiler/output/codegen/__tests__/TypeResolver.test.ts +20 -17
  17. package/src/transpiler/output/codegen/__tests__/TypeValidator.resolution.test.ts +3 -3
  18. package/src/transpiler/output/codegen/__tests__/TypeValidator.test.ts +1 -1
  19. package/src/transpiler/output/codegen/analysis/MemberChainAnalyzer.ts +1 -1
  20. package/src/transpiler/output/codegen/analysis/StringLengthCounter.ts +1 -1
  21. package/src/transpiler/output/codegen/analysis/__tests__/MemberChainAnalyzer.test.ts +9 -9
  22. package/src/transpiler/output/codegen/analysis/__tests__/StringLengthCounter.test.ts +12 -12
  23. package/src/transpiler/output/codegen/assignment/AssignmentClassifier.ts +11 -11
  24. package/src/transpiler/output/codegen/assignment/__tests__/AssignmentClassifier.test.ts +23 -17
  25. package/src/transpiler/output/codegen/assignment/handlers/ArrayHandlers.ts +2 -2
  26. package/src/transpiler/output/codegen/assignment/handlers/BitAccessHandlers.ts +3 -3
  27. package/src/transpiler/output/codegen/assignment/handlers/BitmapHandlers.ts +3 -3
  28. package/src/transpiler/output/codegen/assignment/handlers/SpecialHandlers.ts +4 -4
  29. package/src/transpiler/output/codegen/assignment/handlers/StringHandlers.ts +5 -5
  30. package/src/transpiler/output/codegen/assignment/handlers/__tests__/ArrayHandlers.test.ts +23 -25
  31. package/src/transpiler/output/codegen/assignment/handlers/__tests__/BitAccessHandlers.test.ts +20 -36
  32. package/src/transpiler/output/codegen/assignment/handlers/__tests__/BitmapHandlers.test.ts +18 -18
  33. package/src/transpiler/output/codegen/assignment/handlers/__tests__/SpecialHandlers.test.ts +42 -32
  34. package/src/transpiler/output/codegen/assignment/handlers/__tests__/handlerTestUtils.ts +5 -4
  35. package/src/transpiler/output/codegen/generators/expressions/CallExprGenerator.ts +14 -6
  36. package/src/transpiler/output/codegen/generators/expressions/PostfixExpressionGenerator.ts +19 -16
  37. package/src/transpiler/output/codegen/generators/expressions/__tests__/CallExprGenerator.test.ts +21 -4
  38. package/src/transpiler/output/codegen/generators/expressions/__tests__/PostfixExpressionGenerator.test.ts +15 -2
  39. package/src/transpiler/output/codegen/helpers/ArrayInitHelper.ts +2 -1
  40. package/src/transpiler/output/codegen/helpers/AssignmentExpectedTypeResolver.ts +2 -2
  41. package/src/transpiler/output/codegen/helpers/AssignmentValidator.ts +3 -3
  42. package/src/transpiler/output/codegen/helpers/EnumAssignmentValidator.ts +1 -1
  43. package/src/transpiler/output/codegen/helpers/StringDeclHelper.ts +2 -2
  44. package/src/transpiler/output/codegen/helpers/__tests__/ArrayInitHelper.test.ts +1 -1
  45. package/src/transpiler/output/codegen/helpers/__tests__/AssignmentExpectedTypeResolver.test.ts +7 -7
  46. package/src/transpiler/output/codegen/helpers/__tests__/AssignmentValidator.test.ts +7 -7
  47. package/src/transpiler/output/codegen/helpers/__tests__/EnumAssignmentValidator.test.ts +2 -2
  48. package/src/transpiler/output/codegen/helpers/__tests__/StringDeclHelper.test.ts +4 -4
  49. package/src/transpiler/output/codegen/resolution/EnumTypeResolver.ts +2 -2
  50. package/src/transpiler/output/codegen/resolution/__tests__/EnumTypeResolver.test.ts +5 -5
  51. package/src/transpiler/state/CodeGenState.ts +122 -4
  52. package/src/transpiler/state/__tests__/CodeGenState.test.ts +269 -1
  53. /package/src/transpiler/{output/codegen → logic/analysis}/helpers/TransitiveModificationPropagator.ts +0 -0
  54. /package/src/transpiler/{output/codegen → logic/analysis}/helpers/__tests__/TransitiveModificationPropagator.test.ts +0 -0
@@ -6,6 +6,27 @@ import { describe, it, expect, beforeEach } from "vitest";
6
6
  import CodeGenState from "../CodeGenState";
7
7
  import TTypeInfo from "../../output/codegen/types/TTypeInfo";
8
8
  import ICodeGenSymbols from "../../types/ICodeGenSymbols";
9
+ import ESymbolKind from "../../../utils/types/ESymbolKind";
10
+ import ESourceLanguage from "../../../utils/types/ESourceLanguage";
11
+ import ISymbol from "../../../utils/types/ISymbol";
12
+
13
+ /**
14
+ * Create a minimal ISymbol for testing with required fields.
15
+ */
16
+ function createTestSymbol(
17
+ overrides: Partial<ISymbol> & {
18
+ name: string;
19
+ kind: ESymbolKind;
20
+ sourceLanguage: ESourceLanguage;
21
+ },
22
+ ): ISymbol {
23
+ return {
24
+ sourceFile: "test.cnx",
25
+ sourceLine: 1,
26
+ isExported: false,
27
+ ...overrides,
28
+ };
29
+ }
9
30
 
10
31
  /**
11
32
  * Create a minimal mock ICodeGenSymbols with default empty collections.
@@ -281,7 +302,7 @@ describe("CodeGenState", () => {
281
302
 
282
303
  CodeGenState.registerType("myVar", typeInfo);
283
304
 
284
- expect(CodeGenState.typeRegistry.get("myVar")).toBe(typeInfo);
305
+ expect(CodeGenState.getVariableTypeInfo("myVar")).toBe(typeInfo);
285
306
  });
286
307
 
287
308
  it("registerConstValue adds to constValues", () => {
@@ -348,6 +369,253 @@ describe("CodeGenState", () => {
348
369
  });
349
370
  });
350
371
 
372
+ describe("Variable Type Info API (Issue #786)", () => {
373
+ it("getVariableTypeInfo returns local type info from registry", () => {
374
+ const typeInfo: TTypeInfo = {
375
+ baseType: "u32",
376
+ bitWidth: 32,
377
+ isArray: false,
378
+ isConst: false,
379
+ };
380
+
381
+ CodeGenState.setVariableTypeInfo("localVar", typeInfo);
382
+
383
+ expect(CodeGenState.getVariableTypeInfo("localVar")).toBe(typeInfo);
384
+ });
385
+
386
+ it("getVariableTypeInfo returns undefined for unknown variable", () => {
387
+ expect(CodeGenState.getVariableTypeInfo("unknownVar")).toBeUndefined();
388
+ });
389
+
390
+ it("getVariableTypeInfo falls back to SymbolTable for C-Next variables", () => {
391
+ // Add a C-Next variable to SymbolTable (simulating cross-file include)
392
+ CodeGenState.symbolTable.addSymbol(
393
+ createTestSymbol({
394
+ name: "crossFileVar",
395
+ kind: ESymbolKind.Variable,
396
+ type: "u16",
397
+ sourceLanguage: ESourceLanguage.CNext,
398
+ isArray: true,
399
+ arrayDimensions: ["10"],
400
+ }),
401
+ );
402
+
403
+ const result = CodeGenState.getVariableTypeInfo("crossFileVar");
404
+
405
+ expect(result).toBeDefined();
406
+ expect(result?.baseType).toBe("u16");
407
+ expect(result?.bitWidth).toBe(16);
408
+ expect(result?.isArray).toBe(true);
409
+ expect(result?.arrayDimensions).toEqual([10]);
410
+ });
411
+
412
+ it("getVariableTypeInfo does not use C header symbols", () => {
413
+ // Add a C header variable (should NOT be used)
414
+ CodeGenState.symbolTable.addSymbol(
415
+ createTestSymbol({
416
+ name: "cHeaderVar",
417
+ kind: ESymbolKind.Variable,
418
+ type: "uint32_t",
419
+ sourceLanguage: ESourceLanguage.C,
420
+ }),
421
+ );
422
+
423
+ expect(CodeGenState.getVariableTypeInfo("cHeaderVar")).toBeUndefined();
424
+ });
425
+
426
+ it("getVariableTypeInfo prefers local registry over SymbolTable", () => {
427
+ // Add both local and SymbolTable version
428
+ const localInfo: TTypeInfo = {
429
+ baseType: "i32",
430
+ bitWidth: 32,
431
+ isArray: false,
432
+ isConst: true,
433
+ };
434
+ CodeGenState.setVariableTypeInfo("mixedVar", localInfo);
435
+
436
+ CodeGenState.symbolTable.addSymbol(
437
+ createTestSymbol({
438
+ name: "mixedVar",
439
+ kind: ESymbolKind.Variable,
440
+ type: "u8",
441
+ sourceLanguage: ESourceLanguage.CNext,
442
+ }),
443
+ );
444
+
445
+ // Should return local info, not SymbolTable info
446
+ const result = CodeGenState.getVariableTypeInfo("mixedVar");
447
+ expect(result?.baseType).toBe("i32");
448
+ expect(result?.isConst).toBe(true);
449
+ });
450
+
451
+ it("hasVariableTypeInfo returns true for local registry", () => {
452
+ CodeGenState.setVariableTypeInfo("localVar", {
453
+ baseType: "u8",
454
+ bitWidth: 8,
455
+ isArray: false,
456
+ isConst: false,
457
+ });
458
+
459
+ expect(CodeGenState.hasVariableTypeInfo("localVar")).toBe(true);
460
+ });
461
+
462
+ it("hasVariableTypeInfo returns true for C-Next SymbolTable variable", () => {
463
+ CodeGenState.symbolTable.addSymbol(
464
+ createTestSymbol({
465
+ name: "crossFileVar",
466
+ kind: ESymbolKind.Variable,
467
+ type: "u32",
468
+ sourceLanguage: ESourceLanguage.CNext,
469
+ }),
470
+ );
471
+
472
+ expect(CodeGenState.hasVariableTypeInfo("crossFileVar")).toBe(true);
473
+ });
474
+
475
+ it("hasVariableTypeInfo returns false for unknown variable", () => {
476
+ expect(CodeGenState.hasVariableTypeInfo("unknownVar")).toBe(false);
477
+ });
478
+
479
+ it("hasVariableTypeInfo returns false for C header variable", () => {
480
+ CodeGenState.symbolTable.addSymbol(
481
+ createTestSymbol({
482
+ name: "cVar",
483
+ kind: ESymbolKind.Variable,
484
+ type: "int",
485
+ sourceLanguage: ESourceLanguage.C,
486
+ }),
487
+ );
488
+
489
+ expect(CodeGenState.hasVariableTypeInfo("cVar")).toBe(false);
490
+ });
491
+
492
+ it("setVariableTypeInfo and deleteVariableTypeInfo work correctly", () => {
493
+ const typeInfo: TTypeInfo = {
494
+ baseType: "f32",
495
+ bitWidth: 32,
496
+ isArray: false,
497
+ isConst: false,
498
+ };
499
+
500
+ CodeGenState.setVariableTypeInfo("tempVar", typeInfo);
501
+ expect(CodeGenState.getVariableTypeInfo("tempVar")).toBe(typeInfo);
502
+
503
+ CodeGenState.deleteVariableTypeInfo("tempVar");
504
+ expect(CodeGenState.getVariableTypeInfo("tempVar")).toBeUndefined();
505
+ });
506
+
507
+ it("getTypeRegistryView returns readonly view", () => {
508
+ CodeGenState.setVariableTypeInfo("var1", {
509
+ baseType: "u8",
510
+ bitWidth: 8,
511
+ isArray: false,
512
+ isConst: false,
513
+ });
514
+ CodeGenState.setVariableTypeInfo("var2", {
515
+ baseType: "u16",
516
+ bitWidth: 16,
517
+ isArray: false,
518
+ isConst: false,
519
+ });
520
+
521
+ const view = CodeGenState.getTypeRegistryView();
522
+
523
+ expect(view.size).toBe(2);
524
+ expect(view.has("var1")).toBe(true);
525
+ expect(view.has("var2")).toBe(true);
526
+ });
527
+
528
+ it("getTypeInfo is deprecated alias for getVariableTypeInfo", () => {
529
+ const typeInfo: TTypeInfo = {
530
+ baseType: "u64",
531
+ bitWidth: 64,
532
+ isArray: false,
533
+ isConst: false,
534
+ };
535
+
536
+ CodeGenState.setVariableTypeInfo("aliasVar", typeInfo);
537
+
538
+ // getTypeInfo should return same result
539
+ expect(CodeGenState.getTypeInfo("aliasVar")).toBe(typeInfo);
540
+ });
541
+
542
+ it("convertSymbolToTypeInfo handles string<N> types", () => {
543
+ CodeGenState.symbolTable.addSymbol(
544
+ createTestSymbol({
545
+ name: "myString",
546
+ kind: ESymbolKind.Variable,
547
+ type: "string<32>",
548
+ sourceLanguage: ESourceLanguage.CNext,
549
+ }),
550
+ );
551
+
552
+ const result = CodeGenState.getVariableTypeInfo("myString");
553
+
554
+ expect(result?.baseType).toBe("char");
555
+ expect(result?.bitWidth).toBe(8);
556
+ expect(result?.isString).toBe(true);
557
+ expect(result?.stringCapacity).toBe(32);
558
+ });
559
+
560
+ it("convertSymbolToTypeInfo handles enum types", () => {
561
+ // Register an enum
562
+ CodeGenState.symbols = createMockSymbols({
563
+ knownEnums: new Set(["EColor"]),
564
+ });
565
+
566
+ CodeGenState.symbolTable.addSymbol(
567
+ createTestSymbol({
568
+ name: "color",
569
+ kind: ESymbolKind.Variable,
570
+ type: "EColor",
571
+ sourceLanguage: ESourceLanguage.CNext,
572
+ }),
573
+ );
574
+
575
+ const result = CodeGenState.getVariableTypeInfo("color");
576
+
577
+ expect(result?.baseType).toBe("EColor");
578
+ expect(result?.isEnum).toBe(true);
579
+ expect(result?.enumTypeName).toBe("EColor");
580
+ });
581
+
582
+ it("convertSymbolToTypeInfo handles const and atomic", () => {
583
+ CodeGenState.symbolTable.addSymbol(
584
+ createTestSymbol({
585
+ name: "constAtomicVar",
586
+ kind: ESymbolKind.Variable,
587
+ type: "u32",
588
+ sourceLanguage: ESourceLanguage.CNext,
589
+ isConst: true,
590
+ isAtomic: true,
591
+ }),
592
+ );
593
+
594
+ const result = CodeGenState.getVariableTypeInfo("constAtomicVar");
595
+
596
+ expect(result?.isConst).toBe(true);
597
+ expect(result?.isAtomic).toBe(true);
598
+ });
599
+
600
+ it("convertSymbolToTypeInfo filters invalid array dimensions", () => {
601
+ CodeGenState.symbolTable.addSymbol(
602
+ createTestSymbol({
603
+ name: "arrayVar",
604
+ kind: ESymbolKind.Variable,
605
+ type: "u8",
606
+ sourceLanguage: ESourceLanguage.CNext,
607
+ isArray: true,
608
+ arrayDimensions: ["10", "invalid", "20"],
609
+ }),
610
+ );
611
+
612
+ const result = CodeGenState.getVariableTypeInfo("arrayVar");
613
+
614
+ // Should only include valid numeric dimensions
615
+ expect(result?.arrayDimensions).toEqual([10, 20]);
616
+ });
617
+ });
618
+
351
619
  describe("Overflow Operation Helpers", () => {
352
620
  it("markClampOpUsed adds to usedClampOps", () => {
353
621
  CodeGenState.markClampOpUsed("add", "u8");