c-next 0.1.65 → 0.1.67

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 (73) hide show
  1. package/package.json +5 -1
  2. package/src/transpiler/Transpiler.ts +49 -42
  3. package/src/transpiler/logic/symbols/cnext/__tests__/TSymbolAdapter.test.ts +129 -0
  4. package/src/transpiler/logic/symbols/cnext/adapters/TSymbolAdapter.ts +27 -3
  5. package/src/transpiler/output/codegen/CodeGenerator.ts +131 -186
  6. package/src/transpiler/output/codegen/TypeResolver.ts +2 -2
  7. package/src/transpiler/output/codegen/TypeValidator.ts +1 -1
  8. package/src/transpiler/output/codegen/__tests__/CodeGenerator.coverage.test.ts +1087 -0
  9. package/src/transpiler/output/codegen/__tests__/CodeGenerator.test.ts +665 -1315
  10. package/src/transpiler/output/codegen/__tests__/TypeResolver.test.ts +1 -1
  11. package/src/transpiler/output/codegen/__tests__/TypeValidator.resolution.test.ts +1 -1
  12. package/src/transpiler/output/codegen/__tests__/TypeValidator.test.ts +1 -1
  13. package/src/transpiler/output/codegen/analysis/MemberChainAnalyzer.ts +1 -1
  14. package/src/transpiler/output/codegen/analysis/StringLengthCounter.ts +1 -1
  15. package/src/transpiler/output/codegen/analysis/__tests__/MemberChainAnalyzer.test.ts +1 -1
  16. package/src/transpiler/output/codegen/analysis/__tests__/StringLengthCounter.test.ts +1 -1
  17. package/src/transpiler/output/codegen/assignment/AssignmentClassifier.ts +1 -1
  18. package/src/transpiler/output/codegen/assignment/__tests__/AssignmentClassifier.test.ts +1 -1
  19. package/src/transpiler/output/codegen/assignment/handlers/AccessPatternHandlers.ts +24 -27
  20. package/src/transpiler/output/codegen/assignment/handlers/ArrayHandlers.ts +25 -18
  21. package/src/transpiler/output/codegen/assignment/handlers/BitAccessHandlers.ts +27 -33
  22. package/src/transpiler/output/codegen/assignment/handlers/BitmapHandlers.ts +39 -42
  23. package/src/transpiler/output/codegen/assignment/handlers/RegisterHandlers.ts +39 -97
  24. package/src/transpiler/output/codegen/assignment/handlers/RegisterUtils.ts +75 -0
  25. package/src/transpiler/output/codegen/assignment/handlers/SimpleHandler.ts +9 -6
  26. package/src/transpiler/output/codegen/assignment/handlers/SpecialHandlers.ts +30 -22
  27. package/src/transpiler/output/codegen/assignment/handlers/StringHandlers.ts +42 -50
  28. package/src/transpiler/output/codegen/assignment/handlers/TAssignmentHandler.ts +6 -5
  29. package/src/transpiler/output/codegen/assignment/handlers/__tests__/AccessPatternHandlers.test.ts +81 -134
  30. package/src/transpiler/output/codegen/assignment/handlers/__tests__/ArrayHandlers.test.ts +85 -124
  31. package/src/transpiler/output/codegen/assignment/handlers/__tests__/BitAccessHandlers.test.ts +82 -124
  32. package/src/transpiler/output/codegen/assignment/handlers/__tests__/BitmapHandlers.test.ts +135 -297
  33. package/src/transpiler/output/codegen/assignment/handlers/__tests__/RegisterHandlers.test.ts +105 -227
  34. package/src/transpiler/output/codegen/assignment/handlers/__tests__/RegisterUtils.test.ts +214 -1
  35. package/src/transpiler/output/codegen/assignment/handlers/__tests__/SpecialHandlers.test.ts +66 -127
  36. package/src/transpiler/output/codegen/assignment/handlers/__tests__/StringHandlers.test.ts +37 -83
  37. package/src/transpiler/output/codegen/assignment/handlers/__tests__/handlerTestUtils.ts +162 -0
  38. package/src/transpiler/output/codegen/generators/expressions/PostfixExpressionGenerator.ts +618 -12
  39. package/src/transpiler/output/codegen/generators/expressions/__tests__/PostfixExpressionGenerator.test.ts +819 -0
  40. package/src/transpiler/output/codegen/helpers/ArrayInitHelper.ts +1 -1
  41. package/src/transpiler/output/codegen/helpers/AssignmentExpectedTypeResolver.ts +1 -1
  42. package/src/transpiler/output/codegen/helpers/AssignmentValidator.ts +1 -1
  43. package/src/transpiler/output/codegen/helpers/CppModeHelper.ts +1 -1
  44. package/src/transpiler/output/codegen/helpers/EnumAssignmentValidator.ts +1 -1
  45. package/src/transpiler/output/codegen/helpers/FloatBitHelper.ts +1 -1
  46. package/src/transpiler/output/codegen/helpers/ParameterInputAdapter.ts +337 -0
  47. package/src/transpiler/output/codegen/helpers/ParameterSignatureBuilder.ts +135 -0
  48. package/src/transpiler/output/codegen/helpers/StringDeclHelper.ts +1 -1
  49. package/src/transpiler/output/codegen/helpers/VariableDeclarationFormatter.ts +118 -0
  50. package/src/transpiler/output/codegen/helpers/__tests__/ArrayInitHelper.test.ts +1 -1
  51. package/src/transpiler/output/codegen/helpers/__tests__/AssignmentExpectedTypeResolver.test.ts +1 -1
  52. package/src/transpiler/output/codegen/helpers/__tests__/AssignmentValidator.test.ts +1 -1
  53. package/src/transpiler/output/codegen/helpers/__tests__/CppModeHelper.test.ts +1 -1
  54. package/src/transpiler/output/codegen/helpers/__tests__/EnumAssignmentValidator.test.ts +1 -1
  55. package/src/transpiler/output/codegen/helpers/__tests__/FloatBitHelper.test.ts +1 -1
  56. package/src/transpiler/output/codegen/helpers/__tests__/ParameterInputAdapter.test.ts +426 -0
  57. package/src/transpiler/output/codegen/helpers/__tests__/ParameterSignatureBuilder.test.ts +315 -0
  58. package/src/transpiler/output/codegen/helpers/__tests__/StringDeclHelper.test.ts +1 -1
  59. package/src/transpiler/output/codegen/helpers/__tests__/VariableDeclarationFormatter.test.ts +333 -0
  60. package/src/transpiler/output/codegen/resolution/EnumTypeResolver.ts +1 -1
  61. package/src/transpiler/output/codegen/resolution/ScopeResolver.ts +1 -1
  62. package/src/transpiler/output/codegen/resolution/SizeofResolver.ts +1 -1
  63. package/src/transpiler/output/codegen/resolution/__tests__/EnumTypeResolver.test.ts +1 -1
  64. package/src/transpiler/output/codegen/resolution/__tests__/SizeofResolver.test.ts +1 -1
  65. package/src/transpiler/output/codegen/types/ICodeGenApi.ts +57 -0
  66. package/src/transpiler/output/codegen/types/IParameterInput.ts +58 -0
  67. package/src/transpiler/output/codegen/types/IVariableFormatInput.ts +51 -0
  68. package/src/transpiler/output/headers/BaseHeaderGenerator.ts +20 -35
  69. package/src/transpiler/output/headers/HeaderGeneratorUtils.ts +21 -48
  70. package/src/transpiler/output/headers/__tests__/HeaderGeneratorUtils.test.ts +0 -64
  71. package/src/transpiler/{output/codegen → state}/CodeGenState.ts +46 -26
  72. package/src/transpiler/{output/codegen → state}/__tests__/CodeGenState.test.ts +12 -2
  73. package/src/transpiler/output/codegen/assignment/handlers/IHandlerDeps.ts +0 -161
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Interface for CodeGenerator methods accessible via CodeGenState.generator.
3
+ *
4
+ * Defines the subset of CodeGenerator methods needed by assignment handlers.
5
+ * Handlers cast CodeGenState.generator to this interface.
6
+ */
7
+ import type TTypeInfo from "./TTypeInfo";
8
+
9
+ interface ICodeGenApi {
10
+ /** Generate C expression from AST context */
11
+ generateExpression(ctx: unknown): string;
12
+
13
+ /** Generate assignment target (lvalue) from AST context */
14
+ generateAssignmentTarget(ctx: unknown): string;
15
+
16
+ /** Try to evaluate expression as compile-time constant */
17
+ tryEvaluateConstant(ctx: unknown): number | undefined;
18
+
19
+ /** Generate atomic read-modify-write operation */
20
+ generateAtomicRMW(
21
+ target: string,
22
+ op: string,
23
+ value: string,
24
+ typeInfo: TTypeInfo,
25
+ ): string;
26
+
27
+ /** Generate float bit write operation (returns null if not applicable) */
28
+ generateFloatBitWrite(
29
+ name: string,
30
+ typeInfo: TTypeInfo,
31
+ bitIndex: string,
32
+ width: string | null,
33
+ value: string,
34
+ ): string | null;
35
+
36
+ /** Validate cross-scope member visibility */
37
+ validateCrossScopeVisibility(scopeName: string, memberName: string): void;
38
+
39
+ /** Analyze member chain for bit access patterns */
40
+ analyzeMemberChainForBitAccess(ctx: unknown): {
41
+ isBitAccess: boolean;
42
+ baseTarget?: string;
43
+ bitIndex?: string;
44
+ baseType?: string;
45
+ };
46
+
47
+ /** Get type info for struct member */
48
+ getMemberTypeInfo(structType: string, fieldName: string): TTypeInfo | null;
49
+
50
+ /** Check if name is a known scope */
51
+ isKnownScope(name: string): boolean;
52
+
53
+ /** Check if name is a known struct */
54
+ isKnownStruct(name: string): boolean;
55
+ }
56
+
57
+ export default ICodeGenApi;
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Normalized parameter input for signature generation
3
+ *
4
+ * This interface serves as the contract between ParameterInputAdapter
5
+ * (which normalizes AST or symbol data) and ParameterSignatureBuilder
6
+ * (which generates the final C/C++ parameter string).
7
+ *
8
+ * All decisions are pre-computed before reaching the builder:
9
+ * - Type classification (callback, string, array, etc.)
10
+ * - Const qualifiers (explicit and auto-inferred)
11
+ * - Pass-by-value vs pass-by-reference
12
+ * - Array dimensions
13
+ */
14
+ interface IParameterInput {
15
+ /** Parameter name */
16
+ name: string;
17
+
18
+ /** Original C-Next type: 'u32', 'string<32>', 'Point', etc. */
19
+ baseType: string;
20
+
21
+ /** Mapped C type: 'uint32_t', 'char', 'Point', etc. */
22
+ mappedType: string;
23
+
24
+ /** Explicit const modifier from source code */
25
+ isConst: boolean;
26
+
27
+ /** Inferred const for unmodified parameters (computed from CodeGenState.modifiedParameters) */
28
+ isAutoConst: boolean;
29
+
30
+ /** Whether this is an array type */
31
+ isArray: boolean;
32
+
33
+ /** Array dimensions as strings: ['10', '20'] or ['33'] for string capacity */
34
+ arrayDimensions?: string[];
35
+
36
+ /** Whether this is a callback type (from CodeGenState.callbackTypes) */
37
+ isCallback: boolean;
38
+
39
+ /** The typedef name for callback types (e.g., 'HandleClickCallback') */
40
+ callbackTypedefName?: string;
41
+
42
+ /** Whether this is a string type (bounded or unbounded) */
43
+ isString: boolean;
44
+
45
+ /** Whether this is an unbounded string (no capacity) */
46
+ isUnboundedString?: boolean;
47
+
48
+ /** String capacity for non-array strings (used for tracking, not output) */
49
+ stringCapacity?: number;
50
+
51
+ /** Whether to use pass-by-value semantics (ISR, float, enum, small primitive) */
52
+ isPassByValue: boolean;
53
+
54
+ /** Whether to use pass-by-reference semantics (known struct or known primitive) */
55
+ isPassByReference: boolean;
56
+ }
57
+
58
+ export default IParameterInput;
@@ -0,0 +1,51 @@
1
+ /**
2
+ * IVariableFormatInput - Normalized input for variable declaration formatting.
3
+ *
4
+ * Phase 2 of unified code generation: Provides a single source of truth for
5
+ * variable declaration string generation, eliminating sync issues between
6
+ * .c/.cpp and .h/.hpp files.
7
+ *
8
+ * Unlike parameters (which have complex pass-by-value/reference semantics),
9
+ * variable declarations focus on:
10
+ * - Modifier ordering (extern, const, volatile)
11
+ * - Type formatting (including string<N> → char[N+1])
12
+ * - Array dimension placement
13
+ */
14
+
15
+ /**
16
+ * Modifier flags for variable declarations.
17
+ * These are resolved before formatting - no CodeGenState access needed.
18
+ */
19
+ interface IVariableModifiers {
20
+ /** Explicit const modifier */
21
+ isConst: boolean;
22
+ /** atomic modifier (maps to volatile in C) */
23
+ isAtomic: boolean;
24
+ /** Explicit volatile modifier */
25
+ isVolatile: boolean;
26
+ /** extern linkage (for headers or top-level const in C++) */
27
+ isExtern: boolean;
28
+ }
29
+
30
+ /**
31
+ * Normalized input for variable declaration formatting.
32
+ * All fields are pre-computed - the formatter is stateless.
33
+ */
34
+ interface IVariableFormatInput {
35
+ /** Variable name */
36
+ name: string;
37
+
38
+ /** Original C-Next type (e.g., 'u32', 'string<32>') */
39
+ cnextType: string;
40
+
41
+ /** Mapped C type (e.g., 'uint32_t', 'char[33]') */
42
+ mappedType: string;
43
+
44
+ /** Pre-resolved modifier flags */
45
+ modifiers: IVariableModifiers;
46
+
47
+ /** Array dimensions as strings (e.g., ['10', '20']) */
48
+ arrayDimensions?: string[];
49
+ }
50
+
51
+ export default IVariableFormatInput;
@@ -12,6 +12,9 @@ import IHeaderOptions from "../codegen/types/IHeaderOptions";
12
12
  import IHeaderTypeInput from "./generators/IHeaderTypeInput";
13
13
  import typeUtils from "./generators/mapType";
14
14
  import HeaderGeneratorUtils from "./HeaderGeneratorUtils";
15
+ // Unified parameter generation (Phase 1)
16
+ import ParameterInputAdapter from "../codegen/helpers/ParameterInputAdapter";
17
+ import ParameterSignatureBuilder from "../codegen/helpers/ParameterSignatureBuilder";
15
18
 
16
19
  const { mapType } = typeUtils;
17
20
 
@@ -184,41 +187,23 @@ abstract class BaseHeaderGenerator {
184
187
  passByValueSet?: ReadonlySet<string>,
185
188
  allKnownEnums?: ReadonlySet<string>,
186
189
  ): string {
187
- const baseType = mapType(p.type);
188
- const constMod = p.isConst ? "const " : "";
189
- const autoConst = p.isAutoConst ? "const " : "";
190
-
191
- // Array parameters - pass naturally as pointers per C semantics
192
- if (p.isArray && p.arrayDimensions) {
193
- const dims = p.arrayDimensions.map((d) => `[${d}]`).join("");
194
- if (p.type === "string") {
195
- return `${autoConst}${constMod}char* ${p.name}${dims}`;
196
- }
197
- return `${autoConst}${constMod}${baseType} ${p.name}${dims}`;
198
- }
199
-
200
- // ISR is a function pointer typedef - no pointer needed
201
- if (p.type === "ISR") {
202
- return `${constMod}${baseType} ${p.name}`;
203
- }
204
-
205
- // Float types use standard pass-by-value
206
- if (p.type === "f32" || p.type === "f64") {
207
- return `${constMod}${baseType} ${p.name}`;
208
- }
209
-
210
- // Enum types use pass-by-value (like primitives)
211
- if (allKnownEnums?.has(p.type)) {
212
- return `${constMod}${baseType} ${p.name}`;
213
- }
214
-
215
- // Check if parameter should be passed by value
216
- if (passByValueSet?.has(p.name)) {
217
- return `${constMod}${baseType} ${p.name}`;
218
- }
219
-
220
- // Default: pass by reference using subclass-specific semantics
221
- return `${autoConst}${constMod}${baseType}${this.getRefSuffix()} ${p.name}`;
190
+ // Pre-compute pass-by-value (ISR, float, enum, or explicitly marked)
191
+ const isPassByValue =
192
+ p.type === "ISR" ||
193
+ p.type === "f32" ||
194
+ p.type === "f64" ||
195
+ allKnownEnums?.has(p.type) ||
196
+ passByValueSet?.has(p.name) ||
197
+ false;
198
+
199
+ // Build normalized input using adapter
200
+ const input = ParameterInputAdapter.fromSymbol(p, {
201
+ mapType: (t) => mapType(t),
202
+ isPassByValue,
203
+ });
204
+
205
+ // Use shared builder with subclass-specific ref suffix
206
+ return ParameterSignatureBuilder.build(input, this.getRefSuffix());
222
207
  }
223
208
  }
224
209
 
@@ -16,6 +16,8 @@ import IHeaderTypeInput from "./generators/IHeaderTypeInput";
16
16
  import generateEnumHeader from "./generators/generateEnumHeader";
17
17
  import generateStructHeader from "./generators/generateStructHeader";
18
18
  import generateBitmapHeader from "./generators/generateBitmapHeader";
19
+ import VariableDeclarationFormatter from "../codegen/helpers/VariableDeclarationFormatter";
20
+ import type IVariableFormatInput from "../codegen/types/IVariableFormatInput";
19
21
 
20
22
  const { mapType, isBuiltInType } = typeUtils;
21
23
 
@@ -202,39 +204,6 @@ class HeaderGeneratorUtils {
202
204
  );
203
205
  }
204
206
 
205
- /**
206
- * Format a variable declaration with proper C syntax
207
- *
208
- * In C, array dimensions follow the variable name, not the type:
209
- * char greeting[33]; // Correct
210
- * char[33] greeting; // Wrong
211
- *
212
- * Handles types that include embedded dimensions (like char[33] from
213
- * mapType("string<32>")) and places them correctly after the variable name.
214
- */
215
- static formatVariableDeclaration(
216
- cnextType: string,
217
- name: string,
218
- additionalDims: string,
219
- constPrefix: string,
220
- volatilePrefix: string = "",
221
- ): string {
222
- const cType = mapType(cnextType);
223
-
224
- // Check if the mapped type has embedded array dimensions (e.g., char[33])
225
- // This happens for string<N> types which map to char[N+1]
226
- const embeddedMatch = /^(\w+)\[(\d+)\]$/.exec(cType);
227
- if (embeddedMatch) {
228
- const baseType = embeddedMatch[1];
229
- const embeddedDim = embeddedMatch[2];
230
- // Format: volatile const char name[additionalDims][embeddedDim]
231
- return `${volatilePrefix}${constPrefix}${baseType} ${name}${additionalDims}[${embeddedDim}]`;
232
- }
233
-
234
- // No embedded dimensions - standard format
235
- return `${volatilePrefix}${constPrefix}${cType} ${name}${additionalDims}`;
236
- }
237
-
238
207
  /**
239
208
  * Build headers to include from external type header mappings
240
209
  */
@@ -460,6 +429,8 @@ class HeaderGeneratorUtils {
460
429
 
461
430
  /**
462
431
  * Generate extern variable declarations section
432
+ *
433
+ * Uses VariableDeclarationFormatter for consistent formatting with CodeGenerator.
463
434
  */
464
435
  static generateVariableSection(variables: ISymbol[]): string[] {
465
436
  if (variables.length === 0) {
@@ -468,21 +439,23 @@ class HeaderGeneratorUtils {
468
439
 
469
440
  const lines: string[] = ["/* External variables */"];
470
441
  for (const sym of variables) {
471
- const constPrefix = sym.isConst ? "const " : "";
472
- const volatilePrefix = sym.isAtomic ? "volatile " : "";
473
- const arrayDims =
474
- sym.isArray && sym.arrayDimensions
475
- ? sym.arrayDimensions.map((d) => `[${d}]`).join("")
476
- : "";
477
-
478
- const declaration = HeaderGeneratorUtils.formatVariableDeclaration(
479
- sym.type || "int",
480
- sym.name,
481
- arrayDims,
482
- constPrefix,
483
- volatilePrefix,
484
- );
485
- lines.push(`extern ${declaration};`);
442
+ // Build normalized input for the unified formatter
443
+ const input: IVariableFormatInput = {
444
+ name: sym.name,
445
+ cnextType: sym.type || "int",
446
+ mappedType: mapType(sym.type || "int"),
447
+ modifiers: {
448
+ isConst: sym.isConst ?? false,
449
+ isAtomic: sym.isAtomic ?? false,
450
+ isVolatile: false, // C-Next uses atomic, not volatile directly
451
+ isExtern: true, // Headers always use extern
452
+ },
453
+ arrayDimensions:
454
+ sym.isArray && sym.arrayDimensions ? sym.arrayDimensions : undefined,
455
+ };
456
+
457
+ const declaration = VariableDeclarationFormatter.format(input);
458
+ lines.push(`${declaration};`);
486
459
  }
487
460
  lines.push("");
488
461
  return lines;
@@ -181,70 +181,6 @@ describe("HeaderGeneratorUtils", () => {
181
181
  });
182
182
  });
183
183
 
184
- describe("formatVariableDeclaration", () => {
185
- it("formats simple declaration", () => {
186
- expect(
187
- HeaderGeneratorUtils.formatVariableDeclaration("u32", "count", "", ""),
188
- ).toBe("uint32_t count");
189
- });
190
-
191
- it("formats declaration with const", () => {
192
- expect(
193
- HeaderGeneratorUtils.formatVariableDeclaration(
194
- "u32",
195
- "count",
196
- "",
197
- "const ",
198
- ),
199
- ).toBe("const uint32_t count");
200
- });
201
-
202
- it("formats declaration with volatile", () => {
203
- expect(
204
- HeaderGeneratorUtils.formatVariableDeclaration(
205
- "u32",
206
- "count",
207
- "",
208
- "",
209
- "volatile ",
210
- ),
211
- ).toBe("volatile uint32_t count");
212
- });
213
-
214
- it("formats declaration with array dimensions", () => {
215
- expect(
216
- HeaderGeneratorUtils.formatVariableDeclaration(
217
- "u32",
218
- "values",
219
- "[10]",
220
- "",
221
- ),
222
- ).toBe("uint32_t values[10]");
223
- });
224
-
225
- it("formats string<N> type with embedded dimension", () => {
226
- expect(
227
- HeaderGeneratorUtils.formatVariableDeclaration(
228
- "string<32>",
229
- "name",
230
- "",
231
- "",
232
- ),
233
- ).toBe("char name[33]");
234
- });
235
-
236
- it("formats string<N> array with additional dimensions", () => {
237
- expect(
238
- HeaderGeneratorUtils.formatVariableDeclaration(
239
- "string<16>",
240
- "labels",
241
- "[3]",
242
- "",
243
- ),
244
- ).toBe("char labels[3][17]");
245
- });
246
- });
247
-
248
184
  describe("getLocalTypeNames", () => {
249
185
  it("extracts local type names from grouped symbols", () => {
250
186
  const groups = {
@@ -5,26 +5,31 @@
5
5
  * Eliminates dependency injection complexity and makes debugging easier.
6
6
  *
7
7
  * Usage:
8
- * import CodeGenState from "./CodeGenState";
8
+ * import CodeGenState from "../state/CodeGenState";
9
9
  * const type = CodeGenState.typeRegistry.get(name);
10
10
  * if (CodeGenState.isKnownStruct(name)) { ... }
11
11
  *
12
12
  * Lifecycle:
13
13
  * 1. CodeGenerator.generate() calls CodeGenState.reset()
14
- * 2. CodeGenerator populates state during initialization
14
+ * 2. CodeGenerator sets CodeGenState.generator = this
15
15
  * 3. All generators/helpers read from CodeGenState directly
16
16
  * 4. State persists for the duration of one generate() call
17
+ *
18
+ * SymbolTable ownership:
19
+ * CodeGenState owns the single SymbolTable instance. It persists across
20
+ * reset() calls (which are per-file). The Transpiler clears it via
21
+ * CodeGenState.symbolTable.clear() at the start of each run().
17
22
  */
18
23
 
19
- import SymbolTable from "../../logic/symbols/SymbolTable";
20
- import ICodeGenSymbols from "../../types/ICodeGenSymbols";
21
- import TTypeInfo from "./types/TTypeInfo";
22
- import TParameterInfo from "./types/TParameterInfo";
23
- import IFunctionSignature from "./types/IFunctionSignature";
24
- import ICallbackTypeInfo from "./types/ICallbackTypeInfo";
25
- import ITargetCapabilities from "./types/ITargetCapabilities";
26
- import TOverflowBehavior from "./types/TOverflowBehavior";
27
- import TYPE_WIDTH from "./types/TYPE_WIDTH";
24
+ import SymbolTable from "../logic/symbols/SymbolTable";
25
+ import ICodeGenSymbols from "../types/ICodeGenSymbols";
26
+ import TTypeInfo from "../output/codegen/types/TTypeInfo";
27
+ import TParameterInfo from "../output/codegen/types/TParameterInfo";
28
+ import IFunctionSignature from "../output/codegen/types/IFunctionSignature";
29
+ import ICallbackTypeInfo from "../output/codegen/types/ICallbackTypeInfo";
30
+ import ITargetCapabilities from "../output/codegen/types/ITargetCapabilities";
31
+ import TOverflowBehavior from "../output/codegen/types/TOverflowBehavior";
32
+ import TYPE_WIDTH from "../output/codegen/types/TYPE_WIDTH";
28
33
 
29
34
  /**
30
35
  * Default target capabilities (safe fallback)
@@ -62,6 +67,16 @@ interface ICallGraphEntry {
62
67
  * during code generation.
63
68
  */
64
69
  export default class CodeGenState {
70
+ // ===========================================================================
71
+ // GENERATOR REFERENCE (for handler access)
72
+ // ===========================================================================
73
+
74
+ /**
75
+ * Reference to the CodeGenerator instance for handlers to call methods.
76
+ * Typed as unknown to avoid circular dependencies - handlers cast as needed.
77
+ */
78
+ static generator: unknown = null;
79
+
65
80
  // ===========================================================================
66
81
  // SYMBOL DATA (read-only after initialization)
67
82
  // ===========================================================================
@@ -69,8 +84,11 @@ export default class CodeGenState {
69
84
  /** ADR-055: Pre-collected symbol info from CNextResolver + TSymbolInfoAdapter */
70
85
  static symbols: ICodeGenSymbols | null = null;
71
86
 
72
- /** External symbol table for cross-language interop (C headers) */
73
- static symbolTable: SymbolTable | null = null;
87
+ /** External symbol table for cross-language interop (C headers).
88
+ * Owned by CodeGenState; persists across per-file reset() calls.
89
+ * Cleared via symbolTable.clear() at the start of each Transpiler run.
90
+ */
91
+ static symbolTable: SymbolTable = new SymbolTable();
74
92
 
75
93
  // ===========================================================================
76
94
  // TYPE TRACKING
@@ -277,9 +295,13 @@ export default class CodeGenState {
277
295
  * Called at the start of CodeGenerator.generate()
278
296
  */
279
297
  static reset(targetCapabilities?: ITargetCapabilities): void {
298
+ // Generator reference
299
+ this.generator = null;
300
+
280
301
  // Symbol data
281
302
  this.symbols = null;
282
- this.symbolTable = null;
303
+ // Note: symbolTable is NOT reset here — it persists across per-file generates.
304
+ // It is cleared via symbolTable.clear() at the start of each Transpiler run.
283
305
 
284
306
  // Type tracking
285
307
  this.typeRegistry = new Map();
@@ -388,7 +410,7 @@ export default class CodeGenState {
388
410
  static isKnownStruct(name: string): boolean {
389
411
  if (this.symbols?.knownStructs.has(name)) return true;
390
412
  if (this.symbols?.knownBitmaps.has(name)) return true;
391
- if (this.symbolTable?.getStructFields?.(name)) return true;
413
+ if (this.symbolTable.getStructFields(name)) return true;
392
414
  return false;
393
415
  }
394
416
 
@@ -553,17 +575,15 @@ export default class CodeGenState {
553
575
  fieldName: string,
554
576
  ): { type: string; dimensions?: (number | string)[] } | null {
555
577
  // First check SymbolTable (C header structs)
556
- if (this.symbolTable) {
557
- const fieldInfo = this.symbolTable.getStructFieldInfo(
558
- structType,
559
- fieldName,
560
- );
561
- if (fieldInfo) {
562
- return {
563
- type: fieldInfo.type,
564
- dimensions: fieldInfo.arrayDimensions,
565
- };
566
- }
578
+ const fieldInfo = this.symbolTable.getStructFieldInfo(
579
+ structType,
580
+ fieldName,
581
+ );
582
+ if (fieldInfo) {
583
+ return {
584
+ type: fieldInfo.type,
585
+ dimensions: fieldInfo.arrayDimensions,
586
+ };
567
587
  }
568
588
 
569
589
  // Fall back to local C-Next struct fields
@@ -4,8 +4,8 @@
4
4
 
5
5
  import { describe, it, expect, beforeEach } from "vitest";
6
6
  import CodeGenState from "../CodeGenState";
7
- import TTypeInfo from "../types/TTypeInfo";
8
- import ICodeGenSymbols from "../../../types/ICodeGenSymbols";
7
+ import TTypeInfo from "../../output/codegen/types/TTypeInfo";
8
+ import ICodeGenSymbols from "../../types/ICodeGenSymbols";
9
9
 
10
10
  /**
11
11
  * Create a minimal mock ICodeGenSymbols with default empty collections.
@@ -76,6 +76,16 @@ describe("CodeGenState", () => {
76
76
  expect(CodeGenState.indentLevel).toBe(0);
77
77
  });
78
78
 
79
+ it("resets generator reference", () => {
80
+ // Simulate having a generator set
81
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
82
+ CodeGenState.generator = {} as any;
83
+
84
+ CodeGenState.reset();
85
+
86
+ expect(CodeGenState.generator).toBeNull();
87
+ });
88
+
79
89
  it("accepts custom target capabilities", () => {
80
90
  const customTarget = {
81
91
  hasFPU: true,