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
@@ -5,7 +5,7 @@
5
5
 
6
6
  import { CommonTokenStream, ParserRuleContext } from "antlr4ng";
7
7
  import * as Parser from "../../logic/parser/grammar/CNextParser";
8
- import SymbolTable from "../../logic/symbols/SymbolTable";
8
+
9
9
  import ESymbolKind from "../../../utils/types/ESymbolKind";
10
10
  import CommentExtractor from "../../logic/analysis/CommentExtractor";
11
11
  import CommentFormatter from "./CommentFormatter";
@@ -67,7 +67,7 @@ import memberAccessChain from "./memberAccessChain";
67
67
  import AssignmentHandlerRegistry from "./assignment/index";
68
68
  import AssignmentClassifier from "./assignment/AssignmentClassifier";
69
69
  import buildAssignmentContext from "./assignment/AssignmentContextBuilder";
70
- import IHandlerDeps from "./assignment/handlers/IHandlerDeps";
70
+ // IHandlerDeps removed - handlers now use CodeGenState.generator directly
71
71
  // Issue #461: LiteralUtils for parsing const values from symbol table
72
72
  import LiteralUtils from "../../../utils/LiteralUtils";
73
73
  // Issue #644: Extracted string length counter for strlen caching optimization
@@ -133,7 +133,10 @@ import TypeGenerationHelper from "./helpers/TypeGenerationHelper";
133
133
  // Phase 5: Cast validation helper for improved testability
134
134
  import CastValidator from "./helpers/CastValidator";
135
135
  // Global state for code generation (simplifies debugging, eliminates DI complexity)
136
- import CodeGenState from "./CodeGenState";
136
+ import CodeGenState from "../../state/CodeGenState";
137
+ // Unified parameter generation (Phase 1)
138
+ import ParameterInputAdapter from "./helpers/ParameterInputAdapter";
139
+ import ParameterSignatureBuilder from "./helpers/ParameterSignatureBuilder";
137
140
  // Extracted resolvers that use CodeGenState
138
141
  import SizeofResolver from "./resolution/SizeofResolver";
139
142
  import EnumTypeResolver from "./resolution/EnumTypeResolver";
@@ -676,7 +679,7 @@ export default class CodeGenerator implements IOrchestrator {
676
679
  currentScope: CodeGenState.currentScope,
677
680
  isCppScopeSymbol: (name) => this.isCppScopeSymbol(name),
678
681
  checkNeedsStructKeyword: (name) =>
679
- CodeGenState.symbolTable?.checkNeedsStructKeyword(name) ?? false,
682
+ CodeGenState.symbolTable.checkNeedsStructKeyword(name),
680
683
  validateCrossScopeVisibility: (scope, member) =>
681
684
  ScopeResolver.validateCrossScopeVisibility(scope, member),
682
685
  });
@@ -802,30 +805,54 @@ export default class CodeGenerator implements IOrchestrator {
802
805
  }
803
806
 
804
807
  // Issue #137: Check for array element access (e.g., names[0], arr[i])
808
+ return this._isArrayAccessStringExpression(text);
809
+ }
810
+
811
+ /**
812
+ * Check if array access expression evaluates to a string.
813
+ * Extracted from isStringExpression to reduce cognitive complexity.
814
+ */
815
+ private _isArrayAccessStringExpression(text: string): boolean {
805
816
  // Pattern: identifier[expression] or identifier[expression][expression]...
806
817
  // BUT NOT if accessing .length/.capacity/.size (those return numbers, not strings)
807
818
  const arrayAccessMatch = /^([a-zA-Z_]\w*)\[/.exec(text);
808
- if (arrayAccessMatch) {
809
- // ADR-045: String properties return numeric values, not strings
810
- if (
811
- text.endsWith(".length") ||
812
- text.endsWith(".capacity") ||
813
- text.endsWith(".size")
814
- ) {
815
- return false;
816
- }
817
- const arrayName = arrayAccessMatch[1];
818
- const typeInfo = CodeGenState.typeRegistry.get(arrayName);
819
- // Check if base type is a string type
820
- if (
821
- typeInfo?.isString ||
822
- (typeInfo?.baseType && TypeCheckUtils.isString(typeInfo.baseType))
823
- ) {
824
- return true;
825
- }
819
+ if (!arrayAccessMatch) {
820
+ return false;
826
821
  }
827
822
 
828
- return false;
823
+ // ADR-045: String properties return numeric values, not strings
824
+ if (
825
+ text.endsWith(".length") ||
826
+ text.endsWith(".capacity") ||
827
+ text.endsWith(".size")
828
+ ) {
829
+ return false;
830
+ }
831
+
832
+ const arrayName = arrayAccessMatch[1];
833
+ const typeInfo = CodeGenState.typeRegistry.get(arrayName);
834
+ if (!typeInfo) {
835
+ return false;
836
+ }
837
+
838
+ // Check if it's an ARRAY OF STRINGS (not a single string being indexed)
839
+ // A single string<50> has arrayDimensions=[51] (just the char buffer)
840
+ // An array of strings string<50>[10] has arrayDimensions=[10, 51]
841
+ // Single string indexing (e.g., userName[i]) returns a char, not a string
842
+ // Array of strings indexing (e.g., names[0]) returns a string
843
+ if (typeInfo.isString) {
844
+ // For strings, only treat as string expression if it's an array of strings
845
+ // (arrayDimensions.length > 1 means it's string<N>[M], not just string<N>)
846
+ const dims = typeInfo.arrayDimensions;
847
+ return Array.isArray(dims) && dims.length > 1;
848
+ }
849
+
850
+ // Non-string array with string base type
851
+ return Boolean(
852
+ typeInfo.isArray &&
853
+ typeInfo.baseType &&
854
+ TypeCheckUtils.isString(typeInfo.baseType),
855
+ );
829
856
  }
830
857
 
831
858
  /**
@@ -1505,7 +1532,9 @@ export default class CodeGenerator implements IOrchestrator {
1505
1532
  return `${constMod}${p.type} ${p.name}${p.arrayDims}`;
1506
1533
  } else if (p.isPointer) {
1507
1534
  // ADR-006: Non-array, non-callback parameters become pointers
1508
- return `${constMod}${p.type}*`;
1535
+ // In C++ mode, use reference (&) instead of pointer (*)
1536
+ const ptrOrRef = this.isCppMode() ? "&" : "*";
1537
+ return `${constMod}${p.type}${ptrOrRef}`;
1509
1538
  } else {
1510
1539
  // ADR-029: Callback parameters are already function pointers
1511
1540
  return `${p.type}`;
@@ -2088,13 +2117,11 @@ export default class CodeGenerator implements IOrchestrator {
2088
2117
  /**
2089
2118
  * Generate C code from a C-Next program
2090
2119
  * @param tree The parsed C-Next program
2091
- * @param symbolTable Optional symbol table for cross-language interop
2092
2120
  * @param tokenStream Optional token stream for comment preservation (ADR-043)
2093
2121
  * @param options Optional code generator options (e.g., debugMode)
2094
2122
  */
2095
2123
  generate(
2096
2124
  tree: Parser.ProgramContext,
2097
- symbolTable?: SymbolTable,
2098
2125
  tokenStream?: CommonTokenStream,
2099
2126
  options?: ICodeGeneratorOptions,
2100
2127
  ): string {
@@ -2116,9 +2143,6 @@ export default class CodeGenerator implements IOrchestrator {
2116
2143
  // Initialize options and configuration (after reset)
2117
2144
  this.initializeGenerateOptions(options, tokenStream);
2118
2145
 
2119
- // Store symbol table for function lookup (after reset)
2120
- CodeGenState.symbolTable = symbolTable ?? null;
2121
-
2122
2146
  // ADR-055: Use pre-collected symbolInfo from Pipeline (TSymbolInfoAdapter)
2123
2147
  if (!options?.symbolInfo) {
2124
2148
  throw new Error(
@@ -2169,6 +2193,9 @@ export default class CodeGenerator implements IOrchestrator {
2169
2193
  // Reset global state first
2170
2194
  CodeGenState.reset(targetCapabilities);
2171
2195
 
2196
+ // Set generator reference for handlers to use
2197
+ CodeGenState.generator = this;
2198
+
2172
2199
  // Reset local context (will gradually migrate to CodeGenState)
2173
2200
  this.context = CodeGenerator.createDefaultContext(targetCapabilities);
2174
2201
 
@@ -2373,9 +2400,13 @@ export default class CodeGenerator implements IOrchestrator {
2373
2400
  */
2374
2401
  private addGeneratedHelpers(output: string[]): void {
2375
2402
  if (CodeGenState.needsFloatStaticAssert) {
2403
+ // Use static_assert for C++ (standard), _Static_assert for C11
2404
+ const assertKeyword = this.isCppMode()
2405
+ ? "static_assert"
2406
+ : "_Static_assert";
2376
2407
  output.push(
2377
- '_Static_assert(sizeof(float) == 4, "Float bit indexing requires 32-bit float");',
2378
- '_Static_assert(sizeof(double) == 8, "Float bit indexing requires 64-bit double");',
2408
+ `${assertKeyword}(sizeof(float) == 4, "Float bit indexing requires 32-bit float");`,
2409
+ `${assertKeyword}(sizeof(double) == 8, "Float bit indexing requires 64-bit double");`,
2379
2410
  "",
2380
2411
  );
2381
2412
  }
@@ -5273,16 +5304,47 @@ export default class CodeGenerator implements IOrchestrator {
5273
5304
  }
5274
5305
 
5275
5306
  private generateParameter(ctx: Parser.ParameterContext): string {
5276
- const constMod = ctx.constModifier() ? "const " : "";
5277
5307
  const typeName = this.getTypeName(ctx.type());
5278
5308
  const name = ctx.IDENTIFIER().getText();
5279
- const dims = ctx.arrayDimension();
5280
5309
 
5281
- // Reject ALL C-style array parameters - require C-Next style (dimensions in type)
5282
- // C-style: u8 data[8], u8 data[4][4], u8 data[]
5283
- // C-Next: u8[8] data, u8[4][4] data, u8[] data
5310
+ // Validate: Reject C-style array parameters
5311
+ this._validateCStyleArrayParam(ctx, typeName, name);
5312
+
5313
+ // Validate: Reject unbounded array dimensions
5314
+ this._validateUnboundedArrayParam(ctx);
5315
+
5316
+ // Pre-compute CodeGenState-dependent values
5317
+ const isModified = this._isCurrentParameterModified(name);
5318
+ const isPassByValue = this._isPassByValueType(typeName, name);
5319
+
5320
+ // Build normalized input using adapter
5321
+ const input = ParameterInputAdapter.fromAST(ctx, {
5322
+ getTypeName: (t) => this.getTypeName(t),
5323
+ generateType: (t) => this.generateType(t),
5324
+ generateExpression: (e) => this.generateExpression(e),
5325
+ callbackTypes: CodeGenState.callbackTypes,
5326
+ isKnownStruct: (t) => this.isKnownStruct(t),
5327
+ typeMap: TYPE_MAP,
5328
+ isModified,
5329
+ isPassByValue,
5330
+ });
5331
+
5332
+ // Use shared builder with C/C++ mode
5333
+ return ParameterSignatureBuilder.build(input, CppModeHelper.refOrPtr());
5334
+ }
5335
+
5336
+ /**
5337
+ * Validate: Reject C-style array parameters
5338
+ * C-style: u8 data[8], u8 data[4][4], u8 data[]
5339
+ * C-Next: u8[8] data, u8[4][4] data, u8[] data
5340
+ */
5341
+ private _validateCStyleArrayParam(
5342
+ ctx: Parser.ParameterContext,
5343
+ typeName: string,
5344
+ name: string,
5345
+ ): void {
5346
+ const dims = ctx.arrayDimension();
5284
5347
  if (dims.length > 0) {
5285
- const baseType = typeName;
5286
5348
  const dimensions = dims
5287
5349
  .map((dim) => `[${dim.expression()?.getText() ?? ""}]`)
5288
5350
  .join("");
@@ -5290,73 +5352,28 @@ export default class CodeGenerator implements IOrchestrator {
5290
5352
  const col = ctx.start?.column ?? 0;
5291
5353
  throw new Error(
5292
5354
  `${line}:${col} C-style array parameter is not allowed. ` +
5293
- `Use '${baseType}${dimensions} ${name}' instead of '${baseType} ${name}${dimensions}'`,
5355
+ `Use '${typeName}${dimensions} ${name}' instead of '${typeName} ${name}${dimensions}'`,
5294
5356
  );
5295
5357
  }
5358
+ }
5296
5359
 
5297
- // ADR-029: Check if this is a callback type parameter
5298
- if (CodeGenState.callbackTypes.has(typeName)) {
5299
- const callbackInfo = CodeGenState.callbackTypes.get(typeName)!;
5300
- return `${callbackInfo.typedefName} ${name}`;
5301
- }
5302
-
5303
- const type = this.generateType(ctx.type());
5304
-
5305
- // Handle C-Next style array type in parameter (e.g., u8[8] param, u8[4][4] param, string<32>[5] param)
5360
+ /**
5361
+ * Validate: Reject unbounded array dimensions for memory safety
5362
+ */
5363
+ private _validateUnboundedArrayParam(ctx: Parser.ParameterContext): void {
5306
5364
  const arrayTypeCtx = ctx.type().arrayType();
5307
- if (arrayTypeCtx) {
5308
- // Check for unbounded dimensions - reject for memory safety
5309
- const allDims = arrayTypeCtx.arrayTypeDimension();
5310
- const hasUnboundedDim = allDims.some((d) => !d.expression());
5311
- if (hasUnboundedDim) {
5312
- const line = ctx.start?.line ?? 0;
5313
- const col = ctx.start?.column ?? 0;
5314
- throw new Error(
5315
- `${line}:${col} Unbounded array parameters are not allowed. ` +
5316
- `All dimensions must have explicit sizes for memory safety.`,
5317
- );
5318
- }
5365
+ if (!arrayTypeCtx) return;
5319
5366
 
5320
- let dims = allDims
5321
- .map((d) => {
5322
- const expr = d.expression();
5323
- return expr ? `[${this.generateExpression(expr)}]` : "[]";
5324
- })
5325
- .join("");
5326
- // For string arrays, add the string capacity dimension (string<32>[5] -> char[5][33])
5327
- if (arrayTypeCtx.stringType()) {
5328
- const stringCtx = arrayTypeCtx.stringType()!;
5329
- const intLiteral = stringCtx.INTEGER_LITERAL();
5330
- if (intLiteral) {
5331
- const capacity = Number.parseInt(intLiteral.getText(), 10);
5332
- dims += `[${capacity + 1}]`;
5333
- }
5334
- }
5335
- const wasModified = this._isCurrentParameterModified(name);
5336
- const autoConst = !wasModified && !constMod ? "const " : "";
5337
- return `${autoConst}${constMod}${type} ${name}${dims}`;
5338
- }
5339
-
5340
- // Pass-by-value types
5341
- if (this._isPassByValueType(typeName, name)) {
5342
- return `${constMod}${type} ${name}`;
5367
+ const allDims = arrayTypeCtx.arrayTypeDimension();
5368
+ const hasUnboundedDim = allDims.some((d) => !d.expression());
5369
+ if (hasUnboundedDim) {
5370
+ const line = ctx.start?.line ?? 0;
5371
+ const col = ctx.start?.column ?? 0;
5372
+ throw new Error(
5373
+ `${line}:${col} Unbounded array parameters are not allowed. ` +
5374
+ `All dimensions must have explicit sizes for memory safety.`,
5375
+ );
5343
5376
  }
5344
-
5345
- // Non-array string parameters
5346
- const stringResult = this._tryGenerateStringParam(
5347
- ctx,
5348
- constMod,
5349
- name,
5350
- dims,
5351
- );
5352
- if (stringResult) return stringResult;
5353
-
5354
- // Pass-by-reference types
5355
- const refResult = this._tryGenerateRefParam(constMod, type, typeName, name);
5356
- if (refResult) return refResult;
5357
-
5358
- // Unknown types use pass-by-value (standard C semantics)
5359
- return `${constMod}${type} ${name}`;
5360
5377
  }
5361
5378
 
5362
5379
  /**
@@ -5366,7 +5383,7 @@ export default class CodeGenerator implements IOrchestrator {
5366
5383
  // ISR, float, enum types
5367
5384
  if (typeName === "ISR") return true;
5368
5385
  if (this._isFloatType(typeName)) return true;
5369
- if (CodeGenState.symbols!.knownEnums.has(typeName)) return true;
5386
+ if (CodeGenState.symbols?.knownEnums.has(typeName)) return true;
5370
5387
 
5371
5388
  // Small unmodified primitives
5372
5389
  if (
@@ -5379,43 +5396,6 @@ export default class CodeGenerator implements IOrchestrator {
5379
5396
  return false;
5380
5397
  }
5381
5398
 
5382
- /**
5383
- * Try to generate non-array string parameter: string<N> -> char*
5384
- */
5385
- private _tryGenerateStringParam(
5386
- ctx: Parser.ParameterContext,
5387
- constMod: string,
5388
- name: string,
5389
- dims: Parser.ArrayDimensionContext[],
5390
- ): string | null {
5391
- if (!ctx.type().stringType() || dims.length !== 0) {
5392
- return null;
5393
- }
5394
-
5395
- const wasModified = this._isCurrentParameterModified(name);
5396
- const autoConst = !wasModified && !constMod ? "const " : "";
5397
- return `${autoConst}${constMod}char* ${name}`;
5398
- }
5399
-
5400
- /**
5401
- * Try to generate pass-by-reference parameter for known types
5402
- */
5403
- private _tryGenerateRefParam(
5404
- constMod: string,
5405
- type: string,
5406
- typeName: string,
5407
- name: string,
5408
- ): string | null {
5409
- if (!this.isKnownStruct(typeName) && !this._isKnownPrimitive(typeName)) {
5410
- return null;
5411
- }
5412
-
5413
- const wasModified = this._isCurrentParameterModified(name);
5414
- const autoConst = !wasModified && !constMod ? "const " : "";
5415
- const refOrPtr = CppModeHelper.refOrPtr();
5416
- return `${autoConst}${constMod}${type}${refOrPtr} ${name}`;
5417
- }
5418
-
5419
5399
  // ========================================================================
5420
5400
  // Variables
5421
5401
  // ========================================================================
@@ -6044,54 +6024,14 @@ export default class CodeGenerator implements IOrchestrator {
6044
6024
  // Issue #644: _generateBitMask removed, now delegating to BitUtils.generateMask
6045
6025
  // ========================================================================
6046
6026
 
6047
- // ADR-109: Build handler dependencies for assignment dispatch
6048
- private buildHandlerDeps(): IHandlerDeps {
6049
- return {
6050
- symbols: CodeGenState.symbols!,
6051
- typeRegistry: CodeGenState.typeRegistry,
6052
- currentScope: CodeGenState.currentScope,
6053
- currentParameters: CodeGenState.currentParameters,
6054
- targetCapabilities: CodeGenState.targetCapabilities,
6055
- generateExpression: (ctx) => this.generateExpression(ctx),
6056
- tryEvaluateConstant: (ctx) => this.tryEvaluateConstant(ctx),
6057
- generateAssignmentTarget: (ctx) => this.generateAssignmentTarget(ctx),
6058
- isKnownStruct: (name) => this.isKnownStruct(name),
6059
- isKnownScope: (name) => this.isKnownScope(name),
6060
- getMemberTypeInfo: (structType, memberName) =>
6061
- this.getMemberTypeInfo(structType, memberName),
6062
- validateBitmapFieldLiteral: (expr, width, fieldName) =>
6063
- TypeValidator.validateBitmapFieldLiteral(expr, width, fieldName),
6064
- validateCrossScopeVisibility: (scopeName, memberName) =>
6065
- this.validateCrossScopeVisibility(scopeName, memberName),
6066
- checkArrayBounds: (arrayName, dimensions, indexExprs, line) =>
6067
- TypeValidator.checkArrayBounds(
6068
- arrayName,
6069
- [...dimensions],
6070
- [...indexExprs],
6071
- line,
6072
- (expr) => this.tryEvaluateConstant(expr),
6073
- ),
6074
- analyzeMemberChainForBitAccess: (targetCtx) =>
6075
- this.analyzeMemberChainForBitAccess(targetCtx),
6076
- generateFloatBitWrite: (name, typeInfo, bitIndex, width, value) =>
6077
- this.generateFloatBitWrite(name, typeInfo, bitIndex, width, value),
6078
- foldBooleanToInt: (expr) => this.foldBooleanToInt(expr),
6079
- markNeedsString: () => {
6080
- this.requireInclude("string");
6081
- },
6082
- markClampOpUsed: (op, typeName) => this.markClampOpUsed(op, typeName),
6083
- generateAtomicRMW: (target, cOp, value, typeInfo) =>
6084
- this.generateAtomicRMW(target, cOp, value, typeInfo),
6085
- };
6086
- }
6027
+ // ADR-109: buildHandlerDeps removed - handlers now use CodeGenState.generator directly
6087
6028
 
6088
6029
  /**
6089
6030
  * Analyze a member chain target to detect bit access at the end.
6090
6031
  * Issue #644: Delegates to MemberChainAnalyzer.
6091
6032
  */
6092
- private analyzeMemberChainForBitAccess(
6093
- targetCtx: Parser.AssignmentTargetContext,
6094
- ): {
6033
+ /** Public for handler access via CodeGenState.generator */
6034
+ analyzeMemberChainForBitAccess(targetCtx: Parser.AssignmentTargetContext): {
6095
6035
  isBitAccess: boolean;
6096
6036
  baseTarget?: string;
6097
6037
  bitIndex?: string;
@@ -6107,7 +6047,8 @@ export default class CodeGenerator implements IOrchestrator {
6107
6047
  * Generate float bit write using shadow variable + memcpy.
6108
6048
  * Issue #644: Delegates to FloatBitHelper.
6109
6049
  */
6110
- private generateFloatBitWrite(
6050
+ /** Public for handler access via CodeGenState.generator */
6051
+ generateFloatBitWrite(
6111
6052
  name: string,
6112
6053
  typeInfo: TTypeInfo,
6113
6054
  bitIndex: string,
@@ -6180,17 +6121,18 @@ export default class CodeGenerator implements IOrchestrator {
6180
6121
  typeRegistry: CodeGenState.typeRegistry,
6181
6122
  generateExpression: () => value,
6182
6123
  });
6183
- const handlerDeps = this.buildHandlerDeps();
6124
+ // ADR-109: Handlers access CodeGenState directly, no deps needed
6184
6125
  const assignmentKind = AssignmentClassifier.classify(assignCtx);
6185
6126
  const handler = AssignmentHandlerRegistry.getHandler(assignmentKind);
6186
- return handler(assignCtx, handlerDeps);
6127
+ return handler(assignCtx);
6187
6128
  }
6188
6129
 
6189
6130
  /**
6190
6131
  * ADR-049: Generate atomic Read-Modify-Write operation
6191
6132
  * Uses LDREX/STREX on platforms that support it, otherwise PRIMASK
6192
6133
  */
6193
- private generateAtomicRMW(
6134
+ /** Public for handler access via CodeGenState.generator */
6135
+ generateAtomicRMW(
6194
6136
  target: string,
6195
6137
  cOp: string,
6196
6138
  value: string,
@@ -6440,7 +6382,7 @@ export default class CodeGenerator implements IOrchestrator {
6440
6382
  return null;
6441
6383
  }
6442
6384
 
6443
- // No expected enum type - search all enums but error on ambiguity
6385
+ // No expected enum type - bare enum members are not allowed without context
6444
6386
  const matchingEnums: string[] = [];
6445
6387
  for (const [enumName, members] of CodeGenState.symbols!.enumMembers) {
6446
6388
  if (members.has(id)) {
@@ -6449,11 +6391,14 @@ export default class CodeGenerator implements IOrchestrator {
6449
6391
  }
6450
6392
 
6451
6393
  if (matchingEnums.length === 1) {
6452
- return `${matchingEnums[0]}${this.getScopeSeparator(false)}${id}`;
6394
+ throw new Error(
6395
+ `error[E0424]: '${id}' is not defined; did you mean '${matchingEnums[0]}.${id}'?`,
6396
+ );
6453
6397
  }
6454
6398
  if (matchingEnums.length > 1) {
6399
+ const suggestions = matchingEnums.map((e) => `'${e}.${id}'`).join(" or ");
6455
6400
  throw new Error(
6456
- `Error: Ambiguous enum member '${id}' exists in multiple enums: ${matchingEnums.join(", ")}. Use qualified access (e.g., ${matchingEnums[0]}.${id})`,
6401
+ `error[E0424]: '${id}' is not defined; did you mean ${suggestions}?`,
6457
6402
  );
6458
6403
  }
6459
6404
 
@@ -3,7 +3,7 @@
3
3
  * Static class that reads from CodeGenState directly.
4
4
  */
5
5
  import * as Parser from "../../logic/parser/grammar/CNextParser";
6
- import CodeGenState from "./CodeGenState";
6
+ import CodeGenState from "../../state/CodeGenState";
7
7
  import INTEGER_TYPES from "./types/INTEGER_TYPES";
8
8
  import FLOAT_TYPES from "./types/FLOAT_TYPES";
9
9
  import SIGNED_TYPES from "./types/SIGNED_TYPES";
@@ -73,7 +73,7 @@ class TypeResolver {
73
73
  if (CodeGenState.symbols?.knownBitmaps.has(typeName)) {
74
74
  return true;
75
75
  }
76
- if (CodeGenState.symbolTable?.getStructFields(typeName)) {
76
+ if (CodeGenState.symbolTable.getStructFields(typeName)) {
77
77
  return true;
78
78
  }
79
79
  return false;
@@ -6,7 +6,7 @@
6
6
  import { existsSync } from "node:fs";
7
7
  import { dirname, resolve, join } from "node:path";
8
8
  import * as Parser from "../../logic/parser/grammar/CNextParser";
9
- import CodeGenState from "./CodeGenState";
9
+ import CodeGenState from "../../state/CodeGenState";
10
10
  import TypeResolver from "./TypeResolver";
11
11
  import ExpressionUtils from "../../../utils/ExpressionUtils";
12
12
  // SonarCloud S3776: Extracted literal parsing to reduce complexity