c-next 0.1.62 → 0.1.64

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 (55) hide show
  1. package/README.md +86 -63
  2. package/package.json +1 -1
  3. package/src/transpiler/Transpiler.ts +3 -2
  4. package/src/transpiler/__tests__/DualCodePaths.test.ts +1 -1
  5. package/src/transpiler/__tests__/Transpiler.coverage.test.ts +1 -1
  6. package/src/transpiler/__tests__/Transpiler.test.ts +0 -23
  7. package/src/transpiler/logic/symbols/cnext/collectors/StructCollector.ts +156 -70
  8. package/src/transpiler/logic/symbols/cnext/collectors/VariableCollector.ts +31 -6
  9. package/src/transpiler/logic/symbols/cnext/utils/TypeUtils.ts +43 -11
  10. package/src/transpiler/output/codegen/CodeGenState.ts +811 -0
  11. package/src/transpiler/output/codegen/CodeGenerator.ts +848 -1382
  12. package/src/transpiler/output/codegen/TypeResolver.ts +193 -149
  13. package/src/transpiler/output/codegen/TypeValidator.ts +148 -370
  14. package/src/transpiler/output/codegen/__tests__/CodeGenState.test.ts +446 -0
  15. package/src/transpiler/output/codegen/__tests__/CodeGenerator.test.ts +462 -60
  16. package/src/transpiler/output/codegen/__tests__/TrackVariableTypeHelpers.test.ts +1 -1
  17. package/src/transpiler/output/codegen/__tests__/TypeResolver.test.ts +435 -196
  18. package/src/transpiler/output/codegen/__tests__/TypeValidator.resolution.test.ts +51 -67
  19. package/src/transpiler/output/codegen/__tests__/TypeValidator.test.ts +495 -471
  20. package/src/transpiler/output/codegen/analysis/MemberChainAnalyzer.ts +39 -43
  21. package/src/transpiler/output/codegen/analysis/StringLengthCounter.ts +52 -55
  22. package/src/transpiler/output/codegen/analysis/__tests__/MemberChainAnalyzer.test.ts +122 -62
  23. package/src/transpiler/output/codegen/analysis/__tests__/StringLengthCounter.test.ts +101 -144
  24. package/src/transpiler/output/codegen/assignment/AssignmentClassifier.ts +143 -126
  25. package/src/transpiler/output/codegen/assignment/__tests__/AssignmentClassifier.test.ts +287 -320
  26. package/src/transpiler/output/codegen/generators/GeneratorRegistry.ts +12 -0
  27. package/src/transpiler/output/codegen/generators/__tests__/GeneratorRegistry.test.ts +28 -1
  28. package/src/transpiler/output/codegen/generators/declarationGenerators/ArrayDimensionUtils.ts +67 -0
  29. package/src/transpiler/output/codegen/generators/declarationGenerators/ScopeGenerator.ts +121 -51
  30. package/src/transpiler/output/codegen/generators/declarationGenerators/StructGenerator.ts +100 -23
  31. package/src/transpiler/output/codegen/generators/declarationGenerators/__tests__/ArrayDimensionUtils.test.ts +125 -0
  32. package/src/transpiler/output/codegen/generators/declarationGenerators/__tests__/ScopeGenerator.test.ts +157 -4
  33. package/src/transpiler/output/codegen/generators/support/HelperGenerator.ts +23 -22
  34. package/src/transpiler/output/codegen/helpers/ArrayInitHelper.ts +54 -61
  35. package/src/transpiler/output/codegen/helpers/AssignmentExpectedTypeResolver.ts +21 -30
  36. package/src/transpiler/output/codegen/helpers/AssignmentValidator.ts +56 -53
  37. package/src/transpiler/output/codegen/helpers/CppModeHelper.ts +22 -30
  38. package/src/transpiler/output/codegen/helpers/EnumAssignmentValidator.ts +108 -50
  39. package/src/transpiler/output/codegen/helpers/FloatBitHelper.ts +16 -31
  40. package/src/transpiler/output/codegen/helpers/StringDeclHelper.ts +103 -96
  41. package/src/transpiler/output/codegen/helpers/TypeGenerationHelper.ts +9 -0
  42. package/src/transpiler/output/codegen/helpers/__tests__/ArrayInitHelper.test.ts +58 -103
  43. package/src/transpiler/output/codegen/helpers/__tests__/AssignmentExpectedTypeResolver.test.ts +97 -40
  44. package/src/transpiler/output/codegen/helpers/__tests__/AssignmentValidator.test.ts +223 -128
  45. package/src/transpiler/output/codegen/helpers/__tests__/CppModeHelper.test.ts +68 -41
  46. package/src/transpiler/output/codegen/helpers/__tests__/EnumAssignmentValidator.test.ts +198 -47
  47. package/src/transpiler/output/codegen/helpers/__tests__/FloatBitHelper.test.ts +39 -37
  48. package/src/transpiler/output/codegen/helpers/__tests__/StringDeclHelper.test.ts +191 -453
  49. package/src/transpiler/output/codegen/resolution/EnumTypeResolver.ts +229 -0
  50. package/src/transpiler/output/codegen/resolution/ScopeResolver.ts +60 -0
  51. package/src/transpiler/output/codegen/resolution/SizeofResolver.ts +177 -0
  52. package/src/transpiler/output/codegen/resolution/__tests__/EnumTypeResolver.test.ts +336 -0
  53. package/src/transpiler/output/codegen/resolution/__tests__/SizeofResolver.test.ts +201 -0
  54. package/src/transpiler/output/codegen/types/ITypeResolverDeps.ts +0 -23
  55. package/src/transpiler/output/codegen/types/ITypeValidatorDeps.ts +0 -53
@@ -3,22 +3,14 @@
3
3
  *
4
4
  * Issue #644: Tests for the extracted member chain analyzer.
5
5
  * Updated to use unified postfixTargetOp grammar after consolidation.
6
+ * Migrated to use CodeGenState instead of constructor DI.
6
7
  */
7
8
 
8
- import { describe, it, expect, beforeEach, vi } from "vitest";
9
+ import { describe, it, expect, beforeEach } from "vitest";
9
10
  import MemberChainAnalyzer from "../MemberChainAnalyzer.js";
10
- import type TTypeInfo from "../../types/TTypeInfo.js";
11
+ import CodeGenState from "../../CodeGenState.js";
11
12
  import type * as Parser from "../../../../logic/parser/grammar/CNextParser.js";
12
13
 
13
- /** Test-local copy of IMemberChainAnalyzerDeps interface */
14
- interface IMemberChainAnalyzerDeps {
15
- typeRegistry: ReadonlyMap<string, TTypeInfo>;
16
- structFields: ReadonlyMap<string, ReadonlyMap<string, string>>;
17
- structFieldArrays: ReadonlyMap<string, ReadonlySet<string>>;
18
- isKnownStruct: (name: string) => boolean;
19
- generateExpression: (ctx: Parser.ExpressionContext) => string;
20
- }
21
-
22
14
  /** Mock type for PostfixTargetOpContext */
23
15
  interface IMockPostfixOp {
24
16
  IDENTIFIER: () => { getText: () => string } | null;
@@ -65,47 +57,89 @@ function createTargetCtx(baseId: string | null, postfixOps: IMockPostfixOp[]) {
65
57
  } as unknown as Parser.AssignmentTargetContext;
66
58
  }
67
59
 
68
- describe("MemberChainAnalyzer", () => {
69
- let typeRegistry: Map<string, TTypeInfo>;
70
- let structFields: Map<string, Map<string, string>>;
71
- let structFieldArrays: Map<string, Set<string>>;
72
- let deps: IMemberChainAnalyzerDeps;
73
- let analyzer: MemberChainAnalyzer;
60
+ /**
61
+ * Mock generateExpression callback - just returns getText() of the context
62
+ */
63
+ function mockGenerateExpression(ctx: Parser.ExpressionContext): string {
64
+ return (ctx as unknown as { getText(): string }).getText();
65
+ }
74
66
 
67
+ describe("MemberChainAnalyzer", () => {
75
68
  beforeEach(() => {
76
- typeRegistry = new Map();
77
- structFields = new Map();
78
- structFieldArrays = new Map();
79
-
80
- deps = {
81
- typeRegistry,
82
- structFields,
83
- structFieldArrays,
84
- isKnownStruct: vi.fn((name) => structFields.has(name)),
85
- generateExpression: vi.fn((ctx) =>
86
- (ctx as { getText(): string }).getText(),
87
- ),
88
- };
89
-
90
- analyzer = new MemberChainAnalyzer(deps);
69
+ CodeGenState.reset();
91
70
  });
92
71
 
72
+ /**
73
+ * Helper to set up struct fields in CodeGenState.symbols
74
+ */
75
+ function setupStructFields(
76
+ structName: string,
77
+ fields: Map<string, string>,
78
+ arrayFields: Set<string> = new Set(),
79
+ ): void {
80
+ // Initialize symbols if not set
81
+ if (!CodeGenState.symbols) {
82
+ CodeGenState.symbols = {
83
+ knownStructs: new Set(),
84
+ knownScopes: new Set(),
85
+ knownEnums: new Set(),
86
+ knownBitmaps: new Set(),
87
+ knownRegisters: new Set(),
88
+ structFields: new Map(),
89
+ structFieldArrays: new Map(),
90
+ structFieldDimensions: new Map(),
91
+ enumMembers: new Map(),
92
+ bitmapFields: new Map(),
93
+ bitmapBackingType: new Map(),
94
+ bitmapBitWidth: new Map(),
95
+ scopeMembers: new Map(),
96
+ scopeMemberVisibility: new Map(),
97
+ scopedRegisters: new Map(),
98
+ registerMemberAccess: new Map(),
99
+ registerMemberTypes: new Map(),
100
+ registerBaseAddresses: new Map(),
101
+ registerMemberOffsets: new Map(),
102
+ registerMemberCTypes: new Map(),
103
+ scopeVariableUsage: new Map(),
104
+ scopePrivateConstValues: new Map(),
105
+ functionReturnTypes: new Map(),
106
+ getSingleFunctionForVariable: () => null,
107
+ hasPublicSymbols: () => false,
108
+ };
109
+ }
110
+ (CodeGenState.symbols.knownStructs as Set<string>).add(structName);
111
+ (CodeGenState.symbols.structFields as Map<string, Map<string, string>>).set(
112
+ structName,
113
+ fields,
114
+ );
115
+ (CodeGenState.symbols.structFieldArrays as Map<string, Set<string>>).set(
116
+ structName,
117
+ arrayFields,
118
+ );
119
+ }
120
+
93
121
  describe("analyze", () => {
94
122
  it("returns isBitAccess false when no base identifier", () => {
95
123
  const targetCtx = createTargetCtx(null, []);
96
- const result = analyzer.analyze(targetCtx);
124
+ const result = MemberChainAnalyzer.analyze(
125
+ targetCtx,
126
+ mockGenerateExpression,
127
+ );
97
128
  expect(result.isBitAccess).toBe(false);
98
129
  });
99
130
 
100
131
  it("returns isBitAccess false when no postfix operations", () => {
101
132
  const targetCtx = createTargetCtx("x", []);
102
- const result = analyzer.analyze(targetCtx);
133
+ const result = MemberChainAnalyzer.analyze(
134
+ targetCtx,
135
+ mockGenerateExpression,
136
+ );
103
137
  expect(result.isBitAccess).toBe(false);
104
138
  });
105
139
 
106
140
  it("returns isBitAccess false when last op is member access", () => {
107
141
  // point.flags (no subscript at end)
108
- typeRegistry.set("point", {
142
+ CodeGenState.typeRegistry.set("point", {
109
143
  baseType: "Point",
110
144
  bitWidth: 0,
111
145
  isArray: false,
@@ -113,16 +147,19 @@ describe("MemberChainAnalyzer", () => {
113
147
  });
114
148
  const pointFields = new Map<string, string>();
115
149
  pointFields.set("flags", "u8");
116
- structFields.set("Point", pointFields);
150
+ setupStructFields("Point", pointFields);
117
151
 
118
152
  const targetCtx = createTargetCtx("point", [createMemberOp("flags")]);
119
- const result = analyzer.analyze(targetCtx);
153
+ const result = MemberChainAnalyzer.analyze(
154
+ targetCtx,
155
+ mockGenerateExpression,
156
+ );
120
157
  expect(result.isBitAccess).toBe(false);
121
158
  });
122
159
 
123
160
  it("returns isBitAccess false when last subscript has 2 expressions (bit range)", () => {
124
161
  // flags[0, 8] - bit range, not single bit access
125
- typeRegistry.set("flags", {
162
+ CodeGenState.typeRegistry.set("flags", {
126
163
  baseType: "u32",
127
164
  bitWidth: 32,
128
165
  isArray: false,
@@ -130,7 +167,10 @@ describe("MemberChainAnalyzer", () => {
130
167
  });
131
168
 
132
169
  const targetCtx = createTargetCtx("flags", [createBitRangeOp("0", "8")]);
133
- const result = analyzer.analyze(targetCtx);
170
+ const result = MemberChainAnalyzer.analyze(
171
+ targetCtx,
172
+ mockGenerateExpression,
173
+ );
134
174
  expect(result.isBitAccess).toBe(false);
135
175
  });
136
176
 
@@ -138,10 +178,9 @@ describe("MemberChainAnalyzer", () => {
138
178
  // Setup: struct Point { u8 flags; }
139
179
  const pointFields = new Map<string, string>();
140
180
  pointFields.set("flags", "u8");
141
- structFields.set("Point", pointFields);
142
- structFieldArrays.set("Point", new Set());
181
+ setupStructFields("Point", pointFields);
143
182
 
144
- typeRegistry.set("point", {
183
+ CodeGenState.typeRegistry.set("point", {
145
184
  baseType: "Point",
146
185
  bitWidth: 0,
147
186
  isArray: false,
@@ -153,7 +192,10 @@ describe("MemberChainAnalyzer", () => {
153
192
  createSubscriptOp("3"),
154
193
  ]);
155
194
 
156
- const result = analyzer.analyze(targetCtx);
195
+ const result = MemberChainAnalyzer.analyze(
196
+ targetCtx,
197
+ mockGenerateExpression,
198
+ );
157
199
 
158
200
  expect(result.isBitAccess).toBe(true);
159
201
  expect(result.baseTarget).toBe("point.flags");
@@ -165,10 +207,9 @@ describe("MemberChainAnalyzer", () => {
165
207
  // Setup: struct Grid { u8 items[10]; }
166
208
  const gridFields = new Map<string, string>();
167
209
  gridFields.set("items", "u8");
168
- structFields.set("Grid", gridFields);
169
- structFieldArrays.set("Grid", new Set(["items"]));
210
+ setupStructFields("Grid", gridFields, new Set(["items"]));
170
211
 
171
- typeRegistry.set("grid", {
212
+ CodeGenState.typeRegistry.set("grid", {
172
213
  baseType: "Grid",
173
214
  bitWidth: 0,
174
215
  isArray: false,
@@ -180,7 +221,10 @@ describe("MemberChainAnalyzer", () => {
180
221
  createSubscriptOp("0"),
181
222
  ]);
182
223
 
183
- const result = analyzer.analyze(targetCtx);
224
+ const result = MemberChainAnalyzer.analyze(
225
+ targetCtx,
226
+ mockGenerateExpression,
227
+ );
184
228
 
185
229
  // items is an array, so [0] is array access, not bit access
186
230
  expect(result.isBitAccess).toBe(false);
@@ -190,10 +234,9 @@ describe("MemberChainAnalyzer", () => {
190
234
  // Setup: struct Point { string name; }
191
235
  const pointFields = new Map<string, string>();
192
236
  pointFields.set("name", "string");
193
- structFields.set("Point", pointFields);
194
- structFieldArrays.set("Point", new Set());
237
+ setupStructFields("Point", pointFields);
195
238
 
196
- typeRegistry.set("point", {
239
+ CodeGenState.typeRegistry.set("point", {
197
240
  baseType: "Point",
198
241
  bitWidth: 0,
199
242
  isArray: false,
@@ -205,7 +248,10 @@ describe("MemberChainAnalyzer", () => {
205
248
  createSubscriptOp("0"),
206
249
  ]);
207
250
 
208
- const result = analyzer.analyze(targetCtx);
251
+ const result = MemberChainAnalyzer.analyze(
252
+ targetCtx,
253
+ mockGenerateExpression,
254
+ );
209
255
 
210
256
  // name is a string, not an integer, so no bit access
211
257
  expect(result.isBitAccess).toBe(false);
@@ -215,10 +261,9 @@ describe("MemberChainAnalyzer", () => {
215
261
  // Setup: struct Device { u8 flags; }, Device devices[4];
216
262
  const deviceFields = new Map<string, string>();
217
263
  deviceFields.set("flags", "u8");
218
- structFields.set("Device", deviceFields);
219
- structFieldArrays.set("Device", new Set());
264
+ setupStructFields("Device", deviceFields);
220
265
 
221
- typeRegistry.set("devices", {
266
+ CodeGenState.typeRegistry.set("devices", {
222
267
  baseType: "Device",
223
268
  bitWidth: 0,
224
269
  isArray: true,
@@ -232,7 +277,10 @@ describe("MemberChainAnalyzer", () => {
232
277
  createSubscriptOp("7"),
233
278
  ]);
234
279
 
235
- const result = analyzer.analyze(targetCtx);
280
+ const result = MemberChainAnalyzer.analyze(
281
+ targetCtx,
282
+ mockGenerateExpression,
283
+ );
236
284
 
237
285
  expect(result.isBitAccess).toBe(true);
238
286
  expect(result.baseTarget).toBe("devices[0].flags");
@@ -242,7 +290,7 @@ describe("MemberChainAnalyzer", () => {
242
290
 
243
291
  it("returns false for 2D array element: matrix[0][1]", () => {
244
292
  // matrix[0][1] is array access, not bit access
245
- typeRegistry.set("matrix", {
293
+ CodeGenState.typeRegistry.set("matrix", {
246
294
  baseType: "u8",
247
295
  bitWidth: 8,
248
296
  isArray: true,
@@ -255,7 +303,10 @@ describe("MemberChainAnalyzer", () => {
255
303
  createSubscriptOp("1"),
256
304
  ]);
257
305
 
258
- const result = analyzer.analyze(targetCtx);
306
+ const result = MemberChainAnalyzer.analyze(
307
+ targetCtx,
308
+ mockGenerateExpression,
309
+ );
259
310
 
260
311
  // This is 2D array access, not bit access
261
312
  expect(result.isBitAccess).toBe(false);
@@ -264,7 +315,7 @@ describe("MemberChainAnalyzer", () => {
264
315
  it("detects bit access on 2D array element: matrix[0][1][3]", () => {
265
316
  // matrix[0][1][3] where matrix is u8[4][4]
266
317
  // The third subscript [3] is bit access on the u8 element
267
- typeRegistry.set("matrix", {
318
+ CodeGenState.typeRegistry.set("matrix", {
268
319
  baseType: "u8",
269
320
  bitWidth: 8,
270
321
  isArray: true,
@@ -278,7 +329,10 @@ describe("MemberChainAnalyzer", () => {
278
329
  createSubscriptOp("3"),
279
330
  ]);
280
331
 
281
- const result = analyzer.analyze(targetCtx);
332
+ const result = MemberChainAnalyzer.analyze(
333
+ targetCtx,
334
+ mockGenerateExpression,
335
+ );
282
336
 
283
337
  expect(result.isBitAccess).toBe(true);
284
338
  expect(result.baseTarget).toBe("matrix[0][1]");
@@ -293,14 +347,17 @@ describe("MemberChainAnalyzer", () => {
293
347
  createSubscriptOp("0"),
294
348
  ]);
295
349
 
296
- const result = analyzer.analyze(targetCtx);
350
+ const result = MemberChainAnalyzer.analyze(
351
+ targetCtx,
352
+ mockGenerateExpression,
353
+ );
297
354
 
298
355
  expect(result.isBitAccess).toBe(false);
299
356
  });
300
357
 
301
358
  it("returns false for member access on non-struct", () => {
302
359
  // x.field[0] where x is a primitive
303
- typeRegistry.set("x", {
360
+ CodeGenState.typeRegistry.set("x", {
304
361
  baseType: "u32",
305
362
  bitWidth: 32,
306
363
  isArray: false,
@@ -312,7 +369,10 @@ describe("MemberChainAnalyzer", () => {
312
369
  createSubscriptOp("0"),
313
370
  ]);
314
371
 
315
- const result = analyzer.analyze(targetCtx);
372
+ const result = MemberChainAnalyzer.analyze(
373
+ targetCtx,
374
+ mockGenerateExpression,
375
+ );
316
376
 
317
377
  expect(result.isBitAccess).toBe(false);
318
378
  });