c-next 0.1.61 → 0.1.63

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 (104) hide show
  1. package/README.md +86 -63
  2. package/grammar/CNext.g4 +3 -17
  3. package/package.json +1 -1
  4. package/src/cli/serve/ServeCommand.ts +57 -45
  5. package/src/lib/__tests__/parseCHeader.mocked.test.ts +145 -0
  6. package/src/transpiler/Transpiler.ts +603 -613
  7. package/src/transpiler/__tests__/DualCodePaths.test.ts +5 -1
  8. package/src/transpiler/__tests__/Transpiler.coverage.test.ts +2 -99
  9. package/src/transpiler/__tests__/Transpiler.test.ts +3 -26
  10. package/src/transpiler/data/IncludeTreeWalker.ts +1 -1
  11. package/src/transpiler/logic/analysis/InitializationAnalyzer.ts +23 -52
  12. package/src/transpiler/logic/parser/grammar/CNext.interp +1 -3
  13. package/src/transpiler/logic/parser/grammar/CNextListener.ts +0 -22
  14. package/src/transpiler/logic/parser/grammar/CNextParser.ts +665 -1084
  15. package/src/transpiler/logic/parser/grammar/CNextVisitor.ts +0 -14
  16. package/src/transpiler/logic/symbols/CppSymbolCollector.ts +67 -43
  17. package/src/transpiler/logic/symbols/cnext/collectors/StructCollector.ts +156 -70
  18. package/src/transpiler/logic/symbols/cnext/collectors/VariableCollector.ts +31 -6
  19. package/src/transpiler/logic/symbols/cnext/utils/TypeUtils.ts +43 -11
  20. package/src/transpiler/output/codegen/CodeGenState.ts +811 -0
  21. package/src/transpiler/output/codegen/CodeGenerator.ts +1410 -2587
  22. package/src/transpiler/output/codegen/TypeResolver.ts +193 -149
  23. package/src/transpiler/output/codegen/TypeValidator.ts +148 -370
  24. package/src/transpiler/output/codegen/__tests__/CodeGenState.test.ts +446 -0
  25. package/src/transpiler/output/codegen/__tests__/CodeGenerator.test.ts +2082 -52
  26. package/src/transpiler/output/codegen/__tests__/TrackVariableTypeHelpers.test.ts +1 -1
  27. package/src/transpiler/output/codegen/__tests__/TypeResolver.test.ts +435 -196
  28. package/src/transpiler/output/codegen/__tests__/TypeValidator.resolution.test.ts +51 -67
  29. package/src/transpiler/output/codegen/__tests__/TypeValidator.test.ts +495 -471
  30. package/src/transpiler/output/codegen/analysis/MemberChainAnalyzer.ts +227 -66
  31. package/src/transpiler/output/codegen/analysis/StringLengthCounter.ts +55 -58
  32. package/src/transpiler/output/codegen/analysis/__tests__/MemberChainAnalyzer.test.ts +288 -275
  33. package/src/transpiler/output/codegen/analysis/__tests__/StringLengthCounter.test.ts +101 -144
  34. package/src/transpiler/output/codegen/assignment/AssignmentClassifier.ts +195 -133
  35. package/src/transpiler/output/codegen/assignment/AssignmentContextBuilder.ts +24 -74
  36. package/src/transpiler/output/codegen/assignment/AssignmentKind.ts +3 -0
  37. package/src/transpiler/output/codegen/assignment/IAssignmentContext.ts +3 -0
  38. package/src/transpiler/output/codegen/assignment/__tests__/AssignmentClassifier.test.ts +290 -320
  39. package/src/transpiler/output/codegen/assignment/handlers/BitAccessHandlers.ts +42 -0
  40. package/src/transpiler/output/codegen/assignment/handlers/__tests__/BitAccessHandlers.test.ts +76 -2
  41. package/src/transpiler/output/codegen/generators/GeneratorRegistry.ts +12 -0
  42. package/src/transpiler/output/codegen/generators/IOrchestrator.ts +5 -1
  43. package/src/transpiler/output/codegen/generators/__tests__/GeneratorRegistry.test.ts +28 -1
  44. package/src/transpiler/output/codegen/generators/declarationGenerators/ArrayDimensionUtils.ts +67 -0
  45. package/src/transpiler/output/codegen/generators/declarationGenerators/RegisterGenerator.ts +11 -24
  46. package/src/transpiler/output/codegen/generators/declarationGenerators/RegisterMacroGenerator.ts +64 -0
  47. package/src/transpiler/output/codegen/generators/declarationGenerators/ScopeGenerator.ts +137 -61
  48. package/src/transpiler/output/codegen/generators/declarationGenerators/ScopedRegisterGenerator.ts +18 -27
  49. package/src/transpiler/output/codegen/generators/declarationGenerators/StructGenerator.ts +100 -23
  50. package/src/transpiler/output/codegen/generators/declarationGenerators/__tests__/ArrayDimensionUtils.test.ts +125 -0
  51. package/src/transpiler/output/codegen/generators/declarationGenerators/__tests__/ScopeGenerator.test.ts +157 -4
  52. package/src/transpiler/output/codegen/generators/expressions/PostfixExpressionGenerator.ts +5 -1
  53. package/src/transpiler/output/codegen/generators/statements/ControlFlowGenerator.ts +1 -17
  54. package/src/transpiler/output/codegen/generators/support/HelperGenerator.ts +23 -22
  55. package/src/transpiler/output/codegen/helpers/ArrayAccessHelper.ts +129 -0
  56. package/src/transpiler/output/codegen/helpers/ArrayInitHelper.ts +54 -61
  57. package/src/transpiler/output/codegen/helpers/AssignmentExpectedTypeResolver.ts +40 -44
  58. package/src/transpiler/output/codegen/helpers/AssignmentTargetExtractor.ts +17 -45
  59. package/src/transpiler/output/codegen/helpers/AssignmentValidator.ts +83 -78
  60. package/src/transpiler/output/codegen/helpers/CppModeHelper.ts +22 -30
  61. package/src/transpiler/output/codegen/helpers/EnumAssignmentValidator.ts +108 -50
  62. package/src/transpiler/output/codegen/helpers/FloatBitHelper.ts +16 -31
  63. package/src/transpiler/output/codegen/helpers/MemberSeparatorResolver.ts +10 -3
  64. package/src/transpiler/output/codegen/helpers/StringDeclHelper.ts +103 -96
  65. package/src/transpiler/output/codegen/helpers/SymbolLookupHelper.ts +44 -0
  66. package/src/transpiler/output/codegen/helpers/TypeGenerationHelper.ts +9 -0
  67. package/src/transpiler/output/codegen/helpers/__tests__/ArrayAccessHelper.test.ts +479 -0
  68. package/src/transpiler/output/codegen/helpers/__tests__/ArrayInitHelper.test.ts +58 -103
  69. package/src/transpiler/output/codegen/helpers/__tests__/AssignmentExpectedTypeResolver.test.ts +97 -40
  70. package/src/transpiler/output/codegen/helpers/__tests__/AssignmentValidator.test.ts +223 -128
  71. package/src/transpiler/output/codegen/helpers/__tests__/CppModeHelper.test.ts +68 -41
  72. package/src/transpiler/output/codegen/helpers/__tests__/EnumAssignmentValidator.test.ts +198 -47
  73. package/src/transpiler/output/codegen/helpers/__tests__/FloatBitHelper.test.ts +39 -37
  74. package/src/transpiler/output/codegen/helpers/__tests__/MemberSeparatorResolver.test.ts +1 -0
  75. package/src/transpiler/output/codegen/helpers/__tests__/StringDeclHelper.test.ts +191 -453
  76. package/src/transpiler/output/codegen/helpers/__tests__/SymbolLookupHelper.test.ts +201 -0
  77. package/src/transpiler/output/codegen/helpers/__tests__/TypeGenerationHelper.test.ts +50 -0
  78. package/src/transpiler/output/codegen/resolution/EnumTypeResolver.ts +229 -0
  79. package/src/transpiler/output/codegen/resolution/ScopeResolver.ts +60 -0
  80. package/src/transpiler/output/codegen/resolution/SizeofResolver.ts +177 -0
  81. package/src/transpiler/output/codegen/resolution/__tests__/EnumTypeResolver.test.ts +336 -0
  82. package/src/transpiler/output/codegen/resolution/__tests__/SizeofResolver.test.ts +201 -0
  83. package/src/transpiler/output/codegen/types/IArrayAccessDeps.ts +23 -0
  84. package/src/transpiler/output/codegen/types/IArrayAccessInfo.ts +26 -0
  85. package/src/transpiler/output/codegen/types/IMemberSeparatorDeps.ts +7 -0
  86. package/src/transpiler/output/codegen/utils/CodegenParserUtils.ts +98 -0
  87. package/src/transpiler/output/codegen/utils/ExpressionUnwrapper.ts +22 -22
  88. package/src/transpiler/output/codegen/utils/__tests__/CodegenParserUtils.test.ts +228 -0
  89. package/src/transpiler/types/IFileResult.ts +0 -4
  90. package/src/transpiler/types/IPipelineFile.ts +27 -0
  91. package/src/transpiler/types/IPipelineInput.ts +23 -0
  92. package/src/transpiler/types/TranspilerState.ts +1 -1
  93. package/src/utils/FormatUtils.ts +28 -2
  94. package/src/utils/MapUtils.ts +25 -0
  95. package/src/utils/PostfixAnalysisUtils.ts +48 -0
  96. package/src/utils/__tests__/FormatUtils.test.ts +42 -0
  97. package/src/utils/__tests__/MapUtils.test.ts +85 -0
  98. package/src/utils/constants/OperatorMappings.ts +19 -0
  99. package/src/transpiler/logic/StandaloneContextBuilder.ts +0 -150
  100. package/src/transpiler/logic/__tests__/StandaloneContextBuilder.test.ts +0 -647
  101. package/src/transpiler/output/codegen/types/ITypeResolverDeps.ts +0 -23
  102. package/src/transpiler/output/codegen/types/ITypeValidatorDeps.ts +0 -53
  103. package/src/transpiler/types/ITranspileContext.ts +0 -49
  104. package/src/transpiler/types/ITranspileContribution.ts +0 -32
@@ -0,0 +1,27 @@
1
+ import IDiscoveredFile from "../data/types/IDiscoveredFile";
2
+
3
+ /**
4
+ * A file descriptor for the unified transpilation pipeline.
5
+ *
6
+ * Supports both disk-based files (from run()) and in-memory sources
7
+ * (from transpileSource()). The pipeline reads content via:
8
+ * file.source ?? this.fs.readFile(file.path)
9
+ */
10
+ interface IPipelineFile {
11
+ /** Absolute path to the source file */
12
+ readonly path: string;
13
+
14
+ /** In-memory source content (overrides disk read when set) */
15
+ readonly source?: string;
16
+
17
+ /** The discovered file metadata (type, extension) */
18
+ readonly discoveredFile: IDiscoveredFile;
19
+
20
+ /** When true, collect symbols only — skip code generation */
21
+ readonly symbolOnly?: boolean;
22
+
23
+ /** C-Next includes for transitive enum resolution */
24
+ readonly cnextIncludes?: ReadonlyArray<{ path: string }>;
25
+ }
26
+
27
+ export default IPipelineFile;
@@ -0,0 +1,23 @@
1
+ import IDiscoveredFile from "../data/types/IDiscoveredFile";
2
+ import IPipelineFile from "./IPipelineFile";
3
+
4
+ /**
5
+ * Input to the unified transpilation pipeline (_executePipeline).
6
+ *
7
+ * Both run() and transpileSource() construct this and delegate to the pipeline.
8
+ */
9
+ interface IPipelineInput {
10
+ /** C-Next files to process (in dependency order) */
11
+ readonly cnextFiles: IPipelineFile[];
12
+
13
+ /** C/C++ header files for symbol collection */
14
+ readonly headerFiles: IDiscoveredFile[];
15
+
16
+ /** Whether to write generated output to disk */
17
+ readonly writeOutputToDisk: boolean;
18
+
19
+ /** Skip Stage 4 (symbol conflict check) — standalone mode doesn't need it */
20
+ readonly skipConflictCheck?: boolean;
21
+ }
22
+
23
+ export default IPipelineInput;
@@ -189,7 +189,7 @@ class TranspilerState {
189
189
 
190
190
  /**
191
191
  * Get the processed headers Set (for external APIs that require Set access).
192
- * Issue #592: Used by IncludeResolver.resolveHeadersTransitively() and IStandaloneTranspiler.
192
+ * Issue #592: Used by IncludeResolver.resolveHeadersTransitively().
193
193
  */
194
194
  getProcessedHeadersSet(): Set<string> {
195
195
  return this.processedHeaders;
@@ -20,11 +20,11 @@ class FormatUtils {
20
20
  }
21
21
 
22
22
  /**
23
- * Indent each line of a multi-line string.
23
+ * Indent each line of a multi-line string (skips empty lines).
24
24
  *
25
25
  * @param text - The text to indent (may contain newlines)
26
26
  * @param level - The indentation level
27
- * @returns Text with each line indented
27
+ * @returns Text with each non-empty line indented
28
28
  */
29
29
  static indentLines(text: string, level: number): string {
30
30
  const prefix = FormatUtils.indent(level);
@@ -34,6 +34,21 @@ class FormatUtils {
34
34
  .join("\n");
35
35
  }
36
36
 
37
+ /**
38
+ * Indent ALL lines of a multi-line string (including empty lines).
39
+ *
40
+ * @param text - The text to indent (may contain newlines)
41
+ * @param level - The indentation level
42
+ * @returns Text with every line indented
43
+ */
44
+ static indentAllLines(text: string, level: number): string {
45
+ const prefix = FormatUtils.indent(level);
46
+ return text
47
+ .split("\n")
48
+ .map((line) => prefix + line)
49
+ .join("\n");
50
+ }
51
+
37
52
  /**
38
53
  * Join strings with separator, filtering out empty strings.
39
54
  *
@@ -59,6 +74,17 @@ class FormatUtils {
59
74
  }
60
75
  return `{\n${content}\n}`;
61
76
  }
77
+
78
+ /**
79
+ * Get the appropriate scope separator for C++ vs C/C-Next.
80
+ * C++ uses :: for scope resolution, C/C-Next uses _ (underscore).
81
+ *
82
+ * @param isCppContext - Whether generating C++ code
83
+ * @returns "::" for C++ or "_" for C/C-Next
84
+ */
85
+ static getScopeSeparator(isCppContext: boolean): string {
86
+ return isCppContext ? "::" : "_";
87
+ }
62
88
  }
63
89
 
64
90
  export default FormatUtils;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Map utilities for deep copying and manipulation.
3
+ * Pure functions for working with Map collections.
4
+ */
5
+ class MapUtils {
6
+ /**
7
+ * Deep copy a Map<string, Set<string>>.
8
+ * Creates new Map and new Set instances to ensure complete isolation.
9
+ * Accepts ReadonlyMap/ReadonlySet for flexibility with immutable sources.
10
+ *
11
+ * @param source - The source Map to copy (can be readonly)
12
+ * @returns A new mutable Map with cloned Set values
13
+ */
14
+ static deepCopyStringSetMap(
15
+ source: ReadonlyMap<string, ReadonlySet<string>>,
16
+ ): Map<string, Set<string>> {
17
+ const copy = new Map<string, Set<string>>();
18
+ for (const [key, value] of source) {
19
+ copy.set(key, new Set(value));
20
+ }
21
+ return copy;
22
+ }
23
+ }
24
+
25
+ export default MapUtils;
@@ -0,0 +1,48 @@
1
+ /**
2
+ * PostfixAnalysisUtils - Shared utilities for analyzing postfix target operations
3
+ *
4
+ * Extracts common logic for analyzing assignment targets that may have
5
+ * member access (a.b.c) or subscript access (a[i]).
6
+ */
7
+ import * as Parser from "../transpiler/logic/parser/grammar/CNextParser";
8
+
9
+ /**
10
+ * Result of analyzing postfix target operations.
11
+ */
12
+ interface IPostfixAnalysisResult {
13
+ /** Chain of identifiers from base through member accesses */
14
+ readonly identifiers: string[];
15
+ /** Whether any subscript (array access) operations were found */
16
+ readonly hasSubscript: boolean;
17
+ }
18
+
19
+ /**
20
+ * Analyze postfix target operations to extract identifier chain and detect subscripts.
21
+ *
22
+ * Given an assignment target like `a.b.c[i].d`, this extracts:
23
+ * - identifiers: ["a", "b", "c", "d"]
24
+ * - hasSubscript: true
25
+ *
26
+ * @param baseId - The base identifier (leftmost name)
27
+ * @param postfixOps - Array of postfix operations (member access or subscript)
28
+ * @returns Analysis result with identifiers and subscript detection
29
+ */
30
+ function analyzePostfixOps(
31
+ baseId: string,
32
+ postfixOps: Parser.PostfixTargetOpContext[],
33
+ ): IPostfixAnalysisResult {
34
+ const identifiers: string[] = [baseId];
35
+ let hasSubscript = false;
36
+
37
+ for (const op of postfixOps) {
38
+ if (op.IDENTIFIER()) {
39
+ identifiers.push(op.IDENTIFIER()!.getText());
40
+ } else {
41
+ hasSubscript = true;
42
+ }
43
+ }
44
+
45
+ return { identifiers, hasSubscript };
46
+ }
47
+
48
+ export default analyzePostfixOps;
@@ -51,6 +51,35 @@ describe("FormatUtils.indentLines", () => {
51
51
  });
52
52
  });
53
53
 
54
+ // ========================================================================
55
+ // indentAllLines
56
+ // ========================================================================
57
+ describe("FormatUtils.indentAllLines", () => {
58
+ it("indents single line", () => {
59
+ expect(FormatUtils.indentAllLines("code;", 1)).toBe(" code;");
60
+ });
61
+
62
+ it("indents multiple lines", () => {
63
+ expect(FormatUtils.indentAllLines("line1;\nline2;", 1)).toBe(
64
+ " line1;\n line2;",
65
+ );
66
+ });
67
+
68
+ it("indents empty lines (unlike indentLines)", () => {
69
+ expect(FormatUtils.indentAllLines("line1;\n\nline2;", 1)).toBe(
70
+ " line1;\n \n line2;",
71
+ );
72
+ });
73
+
74
+ it("handles level 0 (no indent)", () => {
75
+ expect(FormatUtils.indentAllLines("code;", 0)).toBe("code;");
76
+ });
77
+
78
+ it("handles deeper indentation", () => {
79
+ expect(FormatUtils.indentAllLines("x = 1;", 2)).toBe(" x = 1;");
80
+ });
81
+ });
82
+
54
83
  // ========================================================================
55
84
  // joinNonEmpty
56
85
  // ========================================================================
@@ -114,3 +143,16 @@ describe("FormatUtils.INDENT", () => {
114
143
  expect(FormatUtils.INDENT.length).toBe(4);
115
144
  });
116
145
  });
146
+
147
+ // ========================================================================
148
+ // getScopeSeparator
149
+ // ========================================================================
150
+ describe("FormatUtils.getScopeSeparator", () => {
151
+ it("returns :: for C++ context", () => {
152
+ expect(FormatUtils.getScopeSeparator(true)).toBe("::");
153
+ });
154
+
155
+ it("returns _ for C/C-Next context", () => {
156
+ expect(FormatUtils.getScopeSeparator(false)).toBe("_");
157
+ });
158
+ });
@@ -0,0 +1,85 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import MapUtils from "../MapUtils.js";
3
+
4
+ describe("MapUtils", () => {
5
+ describe("deepCopyStringSetMap", () => {
6
+ it("should return empty map for empty input", () => {
7
+ const source = new Map<string, Set<string>>();
8
+ const result = MapUtils.deepCopyStringSetMap(source);
9
+
10
+ expect(result.size).toBe(0);
11
+ expect(result).not.toBe(source);
12
+ });
13
+
14
+ it("should deep copy map with single entry", () => {
15
+ const source = new Map<string, Set<string>>([
16
+ ["func1", new Set(["param1", "param2"])],
17
+ ]);
18
+
19
+ const result = MapUtils.deepCopyStringSetMap(source);
20
+
21
+ expect(result.size).toBe(1);
22
+ expect(result.get("func1")).toEqual(new Set(["param1", "param2"]));
23
+ });
24
+
25
+ it("should deep copy map with multiple entries", () => {
26
+ const source = new Map<string, Set<string>>([
27
+ ["func1", new Set(["a", "b"])],
28
+ ["func2", new Set(["c"])],
29
+ ["func3", new Set(["d", "e", "f"])],
30
+ ]);
31
+
32
+ const result = MapUtils.deepCopyStringSetMap(source);
33
+
34
+ expect(result.size).toBe(3);
35
+ expect(result.get("func1")).toEqual(new Set(["a", "b"]));
36
+ expect(result.get("func2")).toEqual(new Set(["c"]));
37
+ expect(result.get("func3")).toEqual(new Set(["d", "e", "f"]));
38
+ });
39
+
40
+ it("should create independent Map instance", () => {
41
+ const source = new Map<string, Set<string>>([
42
+ ["func1", new Set(["param1"])],
43
+ ]);
44
+
45
+ const result = MapUtils.deepCopyStringSetMap(source);
46
+
47
+ // Modify source - should not affect result
48
+ source.set("func2", new Set(["new"]));
49
+ source.delete("func1");
50
+
51
+ expect(result.size).toBe(1);
52
+ expect(result.has("func1")).toBe(true);
53
+ expect(result.has("func2")).toBe(false);
54
+ });
55
+
56
+ it("should create independent Set instances", () => {
57
+ const originalSet = new Set(["param1", "param2"]);
58
+ const source = new Map<string, Set<string>>([["func1", originalSet]]);
59
+
60
+ const result = MapUtils.deepCopyStringSetMap(source);
61
+
62
+ // Modify original Set - should not affect result
63
+ originalSet.add("param3");
64
+ originalSet.delete("param1");
65
+
66
+ const resultSet = result.get("func1");
67
+ expect(resultSet).toBeDefined();
68
+ expect(resultSet!.has("param1")).toBe(true);
69
+ expect(resultSet!.has("param2")).toBe(true);
70
+ expect(resultSet!.has("param3")).toBe(false);
71
+ });
72
+
73
+ it("should handle empty Sets in map", () => {
74
+ const source = new Map<string, Set<string>>([
75
+ ["func1", new Set()],
76
+ ["func2", new Set(["a"])],
77
+ ]);
78
+
79
+ const result = MapUtils.deepCopyStringSetMap(source);
80
+
81
+ expect(result.get("func1")?.size).toBe(0);
82
+ expect(result.get("func2")?.size).toBe(1);
83
+ });
84
+ });
85
+ });
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Operator mapping from C-Next assignment operators to C assignment operators.
3
+ * Used by assignment handling and control flow generation.
4
+ */
5
+ const ASSIGNMENT_OPERATOR_MAP: Readonly<Record<string, string>> = {
6
+ "<-": "=",
7
+ "+<-": "+=",
8
+ "-<-": "-=",
9
+ "*<-": "*=",
10
+ "/<-": "/=",
11
+ "%<-": "%=",
12
+ "&<-": "&=",
13
+ "|<-": "|=",
14
+ "^<-": "^=",
15
+ "<<<-": "<<=",
16
+ ">><-": ">>=",
17
+ };
18
+
19
+ export default ASSIGNMENT_OPERATOR_MAP;
@@ -1,150 +0,0 @@
1
- /**
2
- * StandaloneContextBuilder
3
- * Issue #591: Extracted from Transpiler.transpileSource() to reduce complexity
4
- *
5
- * Handles standalone-mode initialization:
6
- * - Parse C/C++ headers and collect symbols
7
- * - Recursively parse C-Next includes
8
- * - Store header include directives
9
- */
10
-
11
- import IDiscoveredFile from "../data/types/IDiscoveredFile";
12
- import IncludeTreeWalker from "../data/IncludeTreeWalker";
13
- import IncludeResolver from "../data/IncludeResolver";
14
-
15
- /** Inferred type from IncludeResolver.resolve() return type */
16
- type TResolvedIncludes = ReturnType<
17
- InstanceType<typeof IncludeResolver>["resolve"]
18
- >;
19
-
20
- /**
21
- * Interface for the Transpiler methods needed by StandaloneContextBuilder.
22
- * This decouples the builder from the concrete Transpiler class.
23
- */
24
- interface IStandaloneTranspiler {
25
- /** Parse and collect symbols from a C/C++ header file (no recursion, Issue #592) */
26
- collectHeaderSymbols(header: IDiscoveredFile): void;
27
-
28
- /** Parse and collect symbols from a C-Next include file */
29
- collectCNextSymbols(cnxInclude: IDiscoveredFile): void;
30
-
31
- /** Get the configured include directories */
32
- getIncludeDirs(): readonly string[];
33
-
34
- /** Store header include directive for type headers */
35
- setHeaderIncludeDirective(headerPath: string, directive: string): void;
36
-
37
- /** Add a warning message */
38
- addWarning(message: string): void;
39
-
40
- /** Get already-processed header paths (for deduplication) */
41
- getProcessedHeaders(): Set<string>;
42
-
43
- /** Is debug mode enabled? */
44
- isDebugMode(): boolean;
45
- }
46
-
47
- // Interface is not exported - Transpiler uses duck typing
48
-
49
- /**
50
- * Builds standalone context by processing headers and C-Next includes.
51
- *
52
- * In standalone mode (when transpileSource() is called without a context),
53
- * this builder initializes the symbol table by:
54
- * 1. Parsing all C/C++ headers to collect type definitions
55
- * 2. Recursively parsing all C-Next includes for cross-file symbols
56
- * 3. Storing header include directives for generated header files
57
- */
58
- class StandaloneContextBuilder {
59
- /**
60
- * Build the standalone context by processing all includes.
61
- *
62
- * @param transpiler - The transpiler instance (via interface)
63
- * @param resolved - The resolved includes from IncludeResolver
64
- */
65
- static build(
66
- transpiler: IStandaloneTranspiler,
67
- resolved: TResolvedIncludes,
68
- ): void {
69
- // Step 4a: Parse C/C++ headers to populate symbol table
70
- // Issue #592: Use resolveHeadersTransitively for recursive include discovery
71
- StandaloneContextBuilder.processHeaders(transpiler, resolved);
72
-
73
- // Step 4b: Recursively parse C-Next includes for cross-file symbols
74
- StandaloneContextBuilder.processCNextIncludes(
75
- transpiler,
76
- resolved.cnextIncludes,
77
- );
78
- }
79
-
80
- /**
81
- * Process C/C++ headers to collect symbols.
82
- * Issue #592: Uses IncludeResolver.resolveHeadersTransitively() for recursive discovery
83
- */
84
- private static processHeaders(
85
- transpiler: IStandaloneTranspiler,
86
- resolved: TResolvedIncludes,
87
- ): void {
88
- const includeDirs = transpiler.getIncludeDirs();
89
-
90
- // Issue #592: Resolve all headers transitively (including nested includes)
91
- const { headers: allHeaders, warnings: headerWarnings } =
92
- IncludeResolver.resolveHeadersTransitively(
93
- resolved.headers,
94
- [...includeDirs],
95
- {
96
- onDebug: transpiler.isDebugMode()
97
- ? (msg) => console.log(`[DEBUG] ${msg}`)
98
- : undefined,
99
- processedPaths: transpiler.getProcessedHeaders(),
100
- },
101
- );
102
-
103
- // Add any warnings from header resolution
104
- for (const warning of headerWarnings) {
105
- transpiler.addWarning(warning);
106
- }
107
-
108
- // Process all headers (now in dependency order, no recursion needed)
109
- for (const header of allHeaders) {
110
- try {
111
- transpiler.collectHeaderSymbols(header);
112
- // Issue #497: Store the include directive for this header
113
- const directive = resolved.headerIncludeDirectives.get(header.path);
114
- if (directive) {
115
- transpiler.setHeaderIncludeDirective(header.path, directive);
116
- }
117
- } catch (err) {
118
- transpiler.addWarning(
119
- `Failed to process header ${header.path}: ${err}`,
120
- );
121
- }
122
- }
123
- }
124
-
125
- /**
126
- * Recursively process C-Next includes to collect symbols.
127
- * Issue #294: Enables cross-file scope references (e.g., decoder.getSpn() -> decoder_getSpn())
128
- * Issue #465: Recursively process transitive includes for enum info
129
- * Issue #591: Uses shared IncludeTreeWalker to eliminate duplicate traversal code
130
- */
131
- private static processCNextIncludes(
132
- transpiler: IStandaloneTranspiler,
133
- cnextIncludes: IDiscoveredFile[],
134
- ): void {
135
- const includeDirs = transpiler.getIncludeDirs();
136
-
137
- IncludeTreeWalker.walk(cnextIncludes, includeDirs, (file) => {
138
- try {
139
- transpiler.collectCNextSymbols(file);
140
- } catch (err) {
141
- transpiler.addWarning(
142
- `Failed to process C-Next include ${file.path}: ${err}`,
143
- );
144
- return false; // Stop traversing this branch on error
145
- }
146
- });
147
- }
148
- }
149
-
150
- export default StandaloneContextBuilder;