c-next 0.1.64 → 0.1.66

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 (33) hide show
  1. package/grammar/CNext.g4 +9 -2
  2. package/package.json +5 -1
  3. package/src/transpiler/logic/parser/grammar/CNext.interp +2 -1
  4. package/src/transpiler/logic/parser/grammar/CNextListener.ts +11 -0
  5. package/src/transpiler/logic/parser/grammar/CNextParser.ts +992 -870
  6. package/src/transpiler/logic/parser/grammar/CNextVisitor.ts +7 -0
  7. package/src/transpiler/logic/symbols/cnext/__tests__/FunctionCollector.test.ts +6 -6
  8. package/src/transpiler/logic/symbols/cnext/__tests__/TSymbolAdapter.test.ts +179 -0
  9. package/src/transpiler/logic/symbols/cnext/__tests__/VariableCollector.test.ts +55 -0
  10. package/src/transpiler/logic/symbols/cnext/adapters/TSymbolAdapter.ts +76 -8
  11. package/src/transpiler/logic/symbols/cnext/collectors/FunctionCollector.ts +9 -10
  12. package/src/transpiler/logic/symbols/cnext/collectors/StructCollector.ts +7 -1
  13. package/src/transpiler/logic/symbols/cnext/collectors/VariableCollector.ts +33 -14
  14. package/src/transpiler/output/codegen/CodeGenerator.ts +243 -166
  15. package/src/transpiler/output/codegen/__tests__/CodeGenerator.coverage.test.ts +1086 -0
  16. package/src/transpiler/output/codegen/__tests__/CodeGenerator.test.ts +254 -22
  17. package/src/transpiler/output/codegen/generators/declarationGenerators/ArrayDimensionUtils.ts +17 -9
  18. package/src/transpiler/output/codegen/generators/declarationGenerators/__tests__/ArrayDimensionUtils.test.ts +5 -3
  19. package/src/transpiler/output/codegen/generators/declarationGenerators/__tests__/ScopeGenerator.test.ts +12 -7
  20. package/src/transpiler/output/codegen/generators/expressions/PostfixExpressionGenerator.ts +624 -12
  21. package/src/transpiler/output/codegen/generators/expressions/__tests__/PostfixExpressionGenerator.test.ts +819 -0
  22. package/src/transpiler/output/codegen/helpers/ParameterInputAdapter.ts +337 -0
  23. package/src/transpiler/output/codegen/helpers/ParameterSignatureBuilder.ts +135 -0
  24. package/src/transpiler/output/codegen/helpers/TypeGenerationHelper.ts +4 -0
  25. package/src/transpiler/output/codegen/helpers/VariableDeclarationFormatter.ts +118 -0
  26. package/src/transpiler/output/codegen/helpers/__tests__/ParameterInputAdapter.test.ts +426 -0
  27. package/src/transpiler/output/codegen/helpers/__tests__/ParameterSignatureBuilder.test.ts +315 -0
  28. package/src/transpiler/output/codegen/helpers/__tests__/VariableDeclarationFormatter.test.ts +333 -0
  29. package/src/transpiler/output/codegen/types/IParameterInput.ts +58 -0
  30. package/src/transpiler/output/codegen/types/IVariableFormatInput.ts +51 -0
  31. package/src/transpiler/output/headers/BaseHeaderGenerator.ts +20 -35
  32. package/src/transpiler/output/headers/HeaderGeneratorUtils.ts +21 -48
  33. package/src/transpiler/output/headers/__tests__/HeaderGeneratorUtils.test.ts +0 -64
@@ -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 = {