c-next 0.1.62 → 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 (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 +817 -1377
  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 +326 -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
@@ -1,7 +1,8 @@
1
- import { describe, it, expect } from "vitest";
1
+ import { describe, it, expect, beforeEach } from "vitest";
2
2
  import AssignmentClassifier from "../AssignmentClassifier";
3
3
  import AssignmentKind from "../AssignmentKind";
4
4
  import IAssignmentContext from "../IAssignmentContext";
5
+ import CodeGenState from "../../CodeGenState";
5
6
  import TTypeInfo from "../../types/TTypeInfo";
6
7
 
7
8
  // ========================================================================
@@ -55,72 +56,46 @@ function createTypeInfo(overrides: Partial<TTypeInfo> = {}): TTypeInfo {
55
56
  }
56
57
 
57
58
  /**
58
- * Create mock classifier dependencies.
59
+ * Helper to set up CodeGenState.symbols with minimal fields.
59
60
  */
60
- function createMockDeps(
61
- overrides: Partial<{
62
- typeRegistry: Map<string, TTypeInfo>;
63
- knownRegisters: Set<string>;
64
- knownScopes: Set<string>;
65
- knownStructs: Set<string>;
66
- bitmapFields: Map<string, Map<string, { offset: number; width: number }>>;
67
- registerMemberTypes: Map<string, string>;
68
- structFields: Map<string, Map<string, string>>;
69
- structFieldArrays: Map<string, Set<string>>;
70
- structFieldDimensions: Map<string, Map<string, readonly number[]>>;
71
- currentScope: string | null;
72
- }> = {},
73
- ) {
74
- const typeRegistry = overrides.typeRegistry ?? new Map();
75
- const knownRegisters = overrides.knownRegisters ?? new Set();
76
- const knownScopes = overrides.knownScopes ?? new Set();
77
- const knownStructs = overrides.knownStructs ?? new Set();
78
- const bitmapFields = overrides.bitmapFields ?? new Map();
79
- const registerMemberTypes = overrides.registerMemberTypes ?? new Map();
80
- const structFields = overrides.structFields ?? new Map();
81
- const structFieldArrays = overrides.structFieldArrays ?? new Map();
82
- const structFieldDimensions = overrides.structFieldDimensions ?? new Map();
83
-
84
- return {
85
- symbols: {
86
- knownScopes,
87
- knownStructs,
88
- knownRegisters,
89
- knownEnums: new Set<string>(),
90
- knownBitmaps: new Set<string>(),
91
- scopeMembers: new Map<string, Set<string>>(),
92
- scopeMemberVisibility: new Map(),
93
- structFields,
94
- structFieldArrays,
95
- structFieldDimensions,
96
- enumMembers: new Map(),
97
- bitmapFields,
98
- bitmapBackingType: new Map(),
99
- bitmapBitWidth: new Map(),
100
- scopedRegisters: new Map(),
101
- registerMemberAccess: new Map(),
102
- registerMemberTypes,
103
- registerBaseAddresses: new Map(),
104
- registerMemberOffsets: new Map(),
105
- registerMemberCTypes: new Map(),
106
- scopeVariableUsage: new Map(),
107
- scopePrivateConstValues: new Map(),
108
- functionReturnTypes: new Map(),
109
- getSingleFunctionForVariable: () => null,
110
- hasPublicSymbols: () => false,
111
- },
112
- typeRegistry,
113
- currentScope: overrides.currentScope ?? null,
114
- isKnownStruct: (name: string) => knownStructs.has(name),
115
- isKnownScope: (name: string) => knownScopes.has(name),
116
- getMemberTypeInfo: (structType: string, memberName: string) => {
117
- const fields = structFields.get(structType);
118
- const fieldType = fields?.get(memberName);
119
- if (fieldType) {
120
- return createTypeInfo({ baseType: fieldType });
121
- }
122
- return null;
123
- },
61
+ function setupSymbols(
62
+ overrides: {
63
+ knownRegisters?: Set<string>;
64
+ knownScopes?: Set<string>;
65
+ knownStructs?: Set<string>;
66
+ bitmapFields?: Map<string, Map<string, { offset: number; width: number }>>;
67
+ registerMemberTypes?: Map<string, string>;
68
+ structFields?: Map<string, Map<string, string>>;
69
+ structFieldArrays?: Map<string, Set<string>>;
70
+ structFieldDimensions?: Map<string, Map<string, readonly number[]>>;
71
+ } = {},
72
+ ): void {
73
+ CodeGenState.symbols = {
74
+ knownScopes: overrides.knownScopes ?? new Set(),
75
+ knownStructs: overrides.knownStructs ?? new Set(),
76
+ knownRegisters: overrides.knownRegisters ?? new Set(),
77
+ knownEnums: new Set<string>(),
78
+ knownBitmaps: new Set<string>(),
79
+ scopeMembers: new Map<string, Set<string>>(),
80
+ scopeMemberVisibility: new Map(),
81
+ structFields: overrides.structFields ?? new Map(),
82
+ structFieldArrays: overrides.structFieldArrays ?? new Map(),
83
+ structFieldDimensions: overrides.structFieldDimensions ?? new Map(),
84
+ enumMembers: new Map(),
85
+ bitmapFields: overrides.bitmapFields ?? new Map(),
86
+ bitmapBackingType: new Map(),
87
+ bitmapBitWidth: new Map(),
88
+ scopedRegisters: new Map(),
89
+ registerMemberAccess: new Map(),
90
+ registerMemberTypes: overrides.registerMemberTypes ?? new Map(),
91
+ registerBaseAddresses: new Map(),
92
+ registerMemberOffsets: new Map(),
93
+ registerMemberCTypes: new Map(),
94
+ scopeVariableUsage: new Map(),
95
+ scopePrivateConstValues: new Map(),
96
+ functionReturnTypes: new Map(),
97
+ getSingleFunctionForVariable: () => null,
98
+ hasPublicSymbols: () => false,
124
99
  };
125
100
  }
126
101
 
@@ -128,29 +103,28 @@ function createMockDeps(
128
103
  // SIMPLE Assignment
129
104
  // ========================================================================
130
105
  describe("AssignmentClassifier - SIMPLE", () => {
131
- it("classifies simple identifier assignment", () => {
132
- const deps = createMockDeps();
133
- const classifier = new AssignmentClassifier(deps);
106
+ beforeEach(() => {
107
+ CodeGenState.reset();
108
+ setupSymbols();
109
+ });
134
110
 
111
+ it("classifies simple identifier assignment", () => {
135
112
  const ctx = createMockContext({
136
113
  identifiers: ["x"],
137
114
  isSimpleIdentifier: true,
138
115
  });
139
116
 
140
- expect(classifier.classify(ctx)).toBe(AssignmentKind.SIMPLE);
117
+ expect(AssignmentClassifier.classify(ctx)).toBe(AssignmentKind.SIMPLE);
141
118
  });
142
119
 
143
120
  it("classifies unknown pattern as SIMPLE fallback", () => {
144
- const deps = createMockDeps();
145
- const classifier = new AssignmentClassifier(deps);
146
-
147
121
  const ctx = createMockContext({
148
122
  identifiers: ["unknown"],
149
123
  hasMemberAccess: true,
150
124
  isSimpleIdentifier: false,
151
125
  });
152
126
 
153
- expect(classifier.classify(ctx)).toBe(AssignmentKind.SIMPLE);
127
+ expect(AssignmentClassifier.classify(ctx)).toBe(AssignmentKind.SIMPLE);
154
128
  });
155
129
  });
156
130
 
@@ -158,19 +132,19 @@ describe("AssignmentClassifier - SIMPLE", () => {
158
132
  // Bitmap Field Assignments
159
133
  // ========================================================================
160
134
  describe("AssignmentClassifier - Bitmap Fields", () => {
135
+ beforeEach(() => {
136
+ CodeGenState.reset();
137
+ });
138
+
161
139
  it("classifies single-bit bitmap field", () => {
162
140
  const bitmapFields = new Map([
163
141
  ["StatusFlags", new Map([["Running", { offset: 0, width: 1 }]])],
164
142
  ]);
165
- const typeRegistry = new Map([
166
- [
167
- "flags",
168
- createTypeInfo({ isBitmap: true, bitmapTypeName: "StatusFlags" }),
169
- ],
170
- ]);
171
-
172
- const deps = createMockDeps({ bitmapFields, typeRegistry });
173
- const classifier = new AssignmentClassifier(deps);
143
+ setupSymbols({ bitmapFields });
144
+ CodeGenState.typeRegistry.set(
145
+ "flags",
146
+ createTypeInfo({ isBitmap: true, bitmapTypeName: "StatusFlags" }),
147
+ );
174
148
 
175
149
  const ctx = createMockContext({
176
150
  identifiers: ["flags", "Running"],
@@ -178,7 +152,7 @@ describe("AssignmentClassifier - Bitmap Fields", () => {
178
152
  isSimpleIdentifier: false,
179
153
  });
180
154
 
181
- expect(classifier.classify(ctx)).toBe(
155
+ expect(AssignmentClassifier.classify(ctx)).toBe(
182
156
  AssignmentKind.BITMAP_FIELD_SINGLE_BIT,
183
157
  );
184
158
  });
@@ -187,15 +161,11 @@ describe("AssignmentClassifier - Bitmap Fields", () => {
187
161
  const bitmapFields = new Map([
188
162
  ["StatusFlags", new Map([["Mode", { offset: 4, width: 4 }]])],
189
163
  ]);
190
- const typeRegistry = new Map([
191
- [
192
- "flags",
193
- createTypeInfo({ isBitmap: true, bitmapTypeName: "StatusFlags" }),
194
- ],
195
- ]);
196
-
197
- const deps = createMockDeps({ bitmapFields, typeRegistry });
198
- const classifier = new AssignmentClassifier(deps);
164
+ setupSymbols({ bitmapFields });
165
+ CodeGenState.typeRegistry.set(
166
+ "flags",
167
+ createTypeInfo({ isBitmap: true, bitmapTypeName: "StatusFlags" }),
168
+ );
199
169
 
200
170
  const ctx = createMockContext({
201
171
  identifiers: ["flags", "Mode"],
@@ -203,7 +173,7 @@ describe("AssignmentClassifier - Bitmap Fields", () => {
203
173
  isSimpleIdentifier: false,
204
174
  });
205
175
 
206
- expect(classifier.classify(ctx)).toBe(
176
+ expect(AssignmentClassifier.classify(ctx)).toBe(
207
177
  AssignmentKind.BITMAP_FIELD_MULTI_BIT,
208
178
  );
209
179
  });
@@ -214,13 +184,7 @@ describe("AssignmentClassifier - Bitmap Fields", () => {
214
184
  ]);
215
185
  const knownRegisters = new Set(["MOTOR"]);
216
186
  const registerMemberTypes = new Map([["MOTOR_CTRL", "ControlBits"]]);
217
-
218
- const deps = createMockDeps({
219
- bitmapFields,
220
- knownRegisters,
221
- registerMemberTypes,
222
- });
223
- const classifier = new AssignmentClassifier(deps);
187
+ setupSymbols({ bitmapFields, knownRegisters, registerMemberTypes });
224
188
 
225
189
  const ctx = createMockContext({
226
190
  identifiers: ["MOTOR", "CTRL", "Enable"],
@@ -228,7 +192,7 @@ describe("AssignmentClassifier - Bitmap Fields", () => {
228
192
  isSimpleIdentifier: false,
229
193
  });
230
194
 
231
- expect(classifier.classify(ctx)).toBe(
195
+ expect(AssignmentClassifier.classify(ctx)).toBe(
232
196
  AssignmentKind.REGISTER_MEMBER_BITMAP_FIELD,
233
197
  );
234
198
  });
@@ -241,17 +205,11 @@ describe("AssignmentClassifier - Bitmap Fields", () => {
241
205
  const structFields = new Map([
242
206
  ["Device", new Map([["flags", "DeviceFlags"]])],
243
207
  ]);
244
- const typeRegistry = new Map([
245
- ["device", createTypeInfo({ baseType: "Device" })],
246
- ]);
247
-
248
- const deps = createMockDeps({
249
- bitmapFields,
250
- knownStructs,
251
- structFields,
252
- typeRegistry,
253
- });
254
- const classifier = new AssignmentClassifier(deps);
208
+ setupSymbols({ bitmapFields, knownStructs, structFields });
209
+ CodeGenState.typeRegistry.set(
210
+ "device",
211
+ createTypeInfo({ baseType: "Device" }),
212
+ );
255
213
 
256
214
  const ctx = createMockContext({
257
215
  identifiers: ["device", "flags", "Active"],
@@ -259,7 +217,7 @@ describe("AssignmentClassifier - Bitmap Fields", () => {
259
217
  isSimpleIdentifier: false,
260
218
  });
261
219
 
262
- expect(classifier.classify(ctx)).toBe(
220
+ expect(AssignmentClassifier.classify(ctx)).toBe(
263
221
  AssignmentKind.STRUCT_MEMBER_BITMAP_FIELD,
264
222
  );
265
223
  });
@@ -269,13 +227,13 @@ describe("AssignmentClassifier - Bitmap Fields", () => {
269
227
  // Integer Bit Access
270
228
  // ========================================================================
271
229
  describe("AssignmentClassifier - Integer Bit Access", () => {
272
- it("classifies single bit access on integer", () => {
273
- const typeRegistry = new Map([
274
- ["flags", createTypeInfo({ baseType: "u8" })],
275
- ]);
230
+ beforeEach(() => {
231
+ CodeGenState.reset();
232
+ setupSymbols();
233
+ });
276
234
 
277
- const deps = createMockDeps({ typeRegistry });
278
- const classifier = new AssignmentClassifier(deps);
235
+ it("classifies single bit access on integer", () => {
236
+ CodeGenState.typeRegistry.set("flags", createTypeInfo({ baseType: "u8" }));
279
237
 
280
238
  const ctx = createMockContext({
281
239
  identifiers: ["flags"],
@@ -284,16 +242,11 @@ describe("AssignmentClassifier - Integer Bit Access", () => {
284
242
  isSimpleIdentifier: false,
285
243
  });
286
244
 
287
- expect(classifier.classify(ctx)).toBe(AssignmentKind.INTEGER_BIT);
245
+ expect(AssignmentClassifier.classify(ctx)).toBe(AssignmentKind.INTEGER_BIT);
288
246
  });
289
247
 
290
248
  it("classifies bit range access on integer", () => {
291
- const typeRegistry = new Map([
292
- ["flags", createTypeInfo({ baseType: "u32" })],
293
- ]);
294
-
295
- const deps = createMockDeps({ typeRegistry });
296
- const classifier = new AssignmentClassifier(deps);
249
+ CodeGenState.typeRegistry.set("flags", createTypeInfo({ baseType: "u32" }));
297
250
 
298
251
  const ctx = createMockContext({
299
252
  identifiers: ["flags"],
@@ -306,7 +259,9 @@ describe("AssignmentClassifier - Integer Bit Access", () => {
306
259
  lastSubscriptExprCount: 2, // bit range has 2 expressions [start, width]
307
260
  });
308
261
 
309
- expect(classifier.classify(ctx)).toBe(AssignmentKind.INTEGER_BIT_RANGE);
262
+ expect(AssignmentClassifier.classify(ctx)).toBe(
263
+ AssignmentKind.INTEGER_BIT_RANGE,
264
+ );
310
265
  });
311
266
  });
312
267
 
@@ -314,19 +269,19 @@ describe("AssignmentClassifier - Integer Bit Access", () => {
314
269
  // Array Assignments
315
270
  // ========================================================================
316
271
  describe("AssignmentClassifier - Array Access", () => {
317
- it("classifies simple array element", () => {
318
- const typeRegistry = new Map([
319
- [
320
- "arr",
321
- createTypeInfo({
322
- isArray: true,
323
- arrayDimensions: [10],
324
- }),
325
- ],
326
- ]);
272
+ beforeEach(() => {
273
+ CodeGenState.reset();
274
+ setupSymbols();
275
+ });
327
276
 
328
- const deps = createMockDeps({ typeRegistry });
329
- const classifier = new AssignmentClassifier(deps);
277
+ it("classifies simple array element", () => {
278
+ CodeGenState.typeRegistry.set(
279
+ "arr",
280
+ createTypeInfo({
281
+ isArray: true,
282
+ arrayDimensions: [10],
283
+ }),
284
+ );
330
285
 
331
286
  const ctx = createMockContext({
332
287
  identifiers: ["arr"],
@@ -335,22 +290,19 @@ describe("AssignmentClassifier - Array Access", () => {
335
290
  isSimpleIdentifier: false,
336
291
  });
337
292
 
338
- expect(classifier.classify(ctx)).toBe(AssignmentKind.ARRAY_ELEMENT);
293
+ expect(AssignmentClassifier.classify(ctx)).toBe(
294
+ AssignmentKind.ARRAY_ELEMENT,
295
+ );
339
296
  });
340
297
 
341
298
  it("classifies array slice", () => {
342
- const typeRegistry = new Map([
343
- [
344
- "buffer",
345
- createTypeInfo({
346
- isArray: true,
347
- arrayDimensions: [100],
348
- }),
349
- ],
350
- ]);
351
-
352
- const deps = createMockDeps({ typeRegistry });
353
- const classifier = new AssignmentClassifier(deps);
299
+ CodeGenState.typeRegistry.set(
300
+ "buffer",
301
+ createTypeInfo({
302
+ isArray: true,
303
+ arrayDimensions: [100],
304
+ }),
305
+ );
354
306
 
355
307
  const ctx = createMockContext({
356
308
  identifiers: ["buffer"],
@@ -363,7 +315,7 @@ describe("AssignmentClassifier - Array Access", () => {
363
315
  lastSubscriptExprCount: 2, // slice has 2 expressions [start, length]
364
316
  });
365
317
 
366
- expect(classifier.classify(ctx)).toBe(AssignmentKind.ARRAY_SLICE);
318
+ expect(AssignmentClassifier.classify(ctx)).toBe(AssignmentKind.ARRAY_SLICE);
367
319
  });
368
320
  });
369
321
 
@@ -371,28 +323,30 @@ describe("AssignmentClassifier - Array Access", () => {
371
323
  // String Assignments
372
324
  // ========================================================================
373
325
  describe("AssignmentClassifier - String Assignments", () => {
374
- it("classifies simple string variable", () => {
375
- const typeRegistry = new Map([
376
- [
377
- "name",
378
- createTypeInfo({
379
- baseType: "string<32>",
380
- isString: true,
381
- stringCapacity: 32,
382
- }),
383
- ],
384
- ]);
326
+ beforeEach(() => {
327
+ CodeGenState.reset();
328
+ setupSymbols();
329
+ });
385
330
 
386
- const deps = createMockDeps({ typeRegistry });
387
- const classifier = new AssignmentClassifier(deps);
331
+ it("classifies simple string variable", () => {
332
+ CodeGenState.typeRegistry.set(
333
+ "name",
334
+ createTypeInfo({
335
+ baseType: "string<32>",
336
+ isString: true,
337
+ stringCapacity: 32,
338
+ }),
339
+ );
388
340
 
389
341
  const ctx = createMockContext({
390
342
  identifiers: ["name"],
391
343
  isSimpleIdentifier: true,
392
- firstIdTypeInfo: typeRegistry.get("name")!,
344
+ firstIdTypeInfo: CodeGenState.typeRegistry.get("name")!,
393
345
  });
394
346
 
395
- expect(classifier.classify(ctx)).toBe(AssignmentKind.STRING_SIMPLE);
347
+ expect(AssignmentClassifier.classify(ctx)).toBe(
348
+ AssignmentKind.STRING_SIMPLE,
349
+ );
396
350
  });
397
351
 
398
352
  it("classifies struct field string", () => {
@@ -400,12 +354,11 @@ describe("AssignmentClassifier - String Assignments", () => {
400
354
  const structFields = new Map([
401
355
  ["Person", new Map([["name", "string<64>"]])],
402
356
  ]);
403
- const typeRegistry = new Map([
404
- ["person", createTypeInfo({ baseType: "Person" })],
405
- ]);
406
-
407
- const deps = createMockDeps({ knownStructs, structFields, typeRegistry });
408
- const classifier = new AssignmentClassifier(deps);
357
+ setupSymbols({ knownStructs, structFields });
358
+ CodeGenState.typeRegistry.set(
359
+ "person",
360
+ createTypeInfo({ baseType: "Person" }),
361
+ );
409
362
 
410
363
  const ctx = createMockContext({
411
364
  identifiers: ["person", "name"],
@@ -413,7 +366,9 @@ describe("AssignmentClassifier - String Assignments", () => {
413
366
  isSimpleIdentifier: false,
414
367
  });
415
368
 
416
- expect(classifier.classify(ctx)).toBe(AssignmentKind.STRING_STRUCT_FIELD);
369
+ expect(AssignmentClassifier.classify(ctx)).toBe(
370
+ AssignmentKind.STRING_STRUCT_FIELD,
371
+ );
417
372
  });
418
373
  });
419
374
 
@@ -421,19 +376,19 @@ describe("AssignmentClassifier - String Assignments", () => {
421
376
  // Special Compound Assignments
422
377
  // ========================================================================
423
378
  describe("AssignmentClassifier - Special Compound", () => {
424
- it("classifies atomic RMW", () => {
425
- const typeRegistry = new Map([
426
- [
427
- "counter",
428
- createTypeInfo({
429
- baseType: "u32",
430
- isAtomic: true,
431
- }),
432
- ],
433
- ]);
379
+ beforeEach(() => {
380
+ CodeGenState.reset();
381
+ setupSymbols();
382
+ });
434
383
 
435
- const deps = createMockDeps({ typeRegistry });
436
- const classifier = new AssignmentClassifier(deps);
384
+ it("classifies atomic RMW", () => {
385
+ CodeGenState.typeRegistry.set(
386
+ "counter",
387
+ createTypeInfo({
388
+ baseType: "u32",
389
+ isAtomic: true,
390
+ }),
391
+ );
437
392
 
438
393
  const ctx = createMockContext({
439
394
  identifiers: ["counter"],
@@ -442,22 +397,17 @@ describe("AssignmentClassifier - Special Compound", () => {
442
397
  cOp: "+=",
443
398
  });
444
399
 
445
- expect(classifier.classify(ctx)).toBe(AssignmentKind.ATOMIC_RMW);
400
+ expect(AssignmentClassifier.classify(ctx)).toBe(AssignmentKind.ATOMIC_RMW);
446
401
  });
447
402
 
448
403
  it("classifies overflow clamp", () => {
449
- const typeRegistry = new Map([
450
- [
451
- "saturated",
452
- createTypeInfo({
453
- baseType: "u8",
454
- overflowBehavior: "clamp",
455
- }),
456
- ],
457
- ]);
458
-
459
- const deps = createMockDeps({ typeRegistry });
460
- const classifier = new AssignmentClassifier(deps);
404
+ CodeGenState.typeRegistry.set(
405
+ "saturated",
406
+ createTypeInfo({
407
+ baseType: "u8",
408
+ overflowBehavior: "clamp",
409
+ }),
410
+ );
461
411
 
462
412
  const ctx = createMockContext({
463
413
  identifiers: ["saturated"],
@@ -466,22 +416,19 @@ describe("AssignmentClassifier - Special Compound", () => {
466
416
  cOp: "+=",
467
417
  });
468
418
 
469
- expect(classifier.classify(ctx)).toBe(AssignmentKind.OVERFLOW_CLAMP);
419
+ expect(AssignmentClassifier.classify(ctx)).toBe(
420
+ AssignmentKind.OVERFLOW_CLAMP,
421
+ );
470
422
  });
471
423
 
472
424
  it("does not classify float as overflow clamp", () => {
473
- const typeRegistry = new Map([
474
- [
475
- "value",
476
- createTypeInfo({
477
- baseType: "f32",
478
- overflowBehavior: "clamp",
479
- }),
480
- ],
481
- ]);
482
-
483
- const deps = createMockDeps({ typeRegistry });
484
- const classifier = new AssignmentClassifier(deps);
425
+ CodeGenState.typeRegistry.set(
426
+ "value",
427
+ createTypeInfo({
428
+ baseType: "f32",
429
+ overflowBehavior: "clamp",
430
+ }),
431
+ );
485
432
 
486
433
  const ctx = createMockContext({
487
434
  identifiers: ["value"],
@@ -491,7 +438,7 @@ describe("AssignmentClassifier - Special Compound", () => {
491
438
  });
492
439
 
493
440
  // Floats use native arithmetic, so not OVERFLOW_CLAMP
494
- expect(classifier.classify(ctx)).toBe(AssignmentKind.SIMPLE);
441
+ expect(AssignmentClassifier.classify(ctx)).toBe(AssignmentKind.SIMPLE);
495
442
  });
496
443
  });
497
444
 
@@ -499,10 +446,13 @@ describe("AssignmentClassifier - Special Compound", () => {
499
446
  // Global/This Prefix Patterns
500
447
  // ========================================================================
501
448
  describe("AssignmentClassifier - Prefix Patterns", () => {
449
+ beforeEach(() => {
450
+ CodeGenState.reset();
451
+ });
452
+
502
453
  it("classifies global.member", () => {
503
454
  const knownScopes = new Set(["Counter"]);
504
- const deps = createMockDeps({ knownScopes });
505
- const classifier = new AssignmentClassifier(deps);
455
+ setupSymbols({ knownScopes });
506
456
 
507
457
  const ctx = createMockContext({
508
458
  identifiers: ["Counter", "value"],
@@ -511,12 +461,13 @@ describe("AssignmentClassifier - Prefix Patterns", () => {
511
461
  isSimpleIdentifier: false,
512
462
  });
513
463
 
514
- expect(classifier.classify(ctx)).toBe(AssignmentKind.GLOBAL_MEMBER);
464
+ expect(AssignmentClassifier.classify(ctx)).toBe(
465
+ AssignmentKind.GLOBAL_MEMBER,
466
+ );
515
467
  });
516
468
 
517
469
  it("classifies global.arr[i]", () => {
518
- const deps = createMockDeps();
519
- const classifier = new AssignmentClassifier(deps);
470
+ setupSymbols();
520
471
 
521
472
  const ctx = createMockContext({
522
473
  identifiers: ["arr"],
@@ -527,12 +478,14 @@ describe("AssignmentClassifier - Prefix Patterns", () => {
527
478
  isSimpleIdentifier: false,
528
479
  });
529
480
 
530
- expect(classifier.classify(ctx)).toBe(AssignmentKind.GLOBAL_ARRAY);
481
+ expect(AssignmentClassifier.classify(ctx)).toBe(
482
+ AssignmentKind.GLOBAL_ARRAY,
483
+ );
531
484
  });
532
485
 
533
486
  it("classifies this.member", () => {
534
- const deps = createMockDeps({ currentScope: "Counter" });
535
- const classifier = new AssignmentClassifier(deps);
487
+ setupSymbols();
488
+ CodeGenState.currentScope = "Counter";
536
489
 
537
490
  const ctx = createMockContext({
538
491
  identifiers: ["count"],
@@ -541,12 +494,12 @@ describe("AssignmentClassifier - Prefix Patterns", () => {
541
494
  isSimpleIdentifier: false,
542
495
  });
543
496
 
544
- expect(classifier.classify(ctx)).toBe(AssignmentKind.THIS_MEMBER);
497
+ expect(AssignmentClassifier.classify(ctx)).toBe(AssignmentKind.THIS_MEMBER);
545
498
  });
546
499
 
547
500
  it("classifies this.arr[i]", () => {
548
- const deps = createMockDeps({ currentScope: "Buffer" });
549
- const classifier = new AssignmentClassifier(deps);
501
+ setupSymbols();
502
+ CodeGenState.currentScope = "Buffer";
550
503
 
551
504
  const ctx = createMockContext({
552
505
  identifiers: ["data"],
@@ -557,7 +510,7 @@ describe("AssignmentClassifier - Prefix Patterns", () => {
557
510
  isSimpleIdentifier: false,
558
511
  });
559
512
 
560
- expect(classifier.classify(ctx)).toBe(AssignmentKind.THIS_ARRAY);
513
+ expect(AssignmentClassifier.classify(ctx)).toBe(AssignmentKind.THIS_ARRAY);
561
514
  });
562
515
  });
563
516
 
@@ -565,10 +518,13 @@ describe("AssignmentClassifier - Prefix Patterns", () => {
565
518
  // Register Bit Access
566
519
  // ========================================================================
567
520
  describe("AssignmentClassifier - Register Bit Access", () => {
521
+ beforeEach(() => {
522
+ CodeGenState.reset();
523
+ });
524
+
568
525
  it("classifies register single bit", () => {
569
526
  const knownRegisters = new Set(["GPIO7"]);
570
- const deps = createMockDeps({ knownRegisters });
571
- const classifier = new AssignmentClassifier(deps);
527
+ setupSymbols({ knownRegisters });
572
528
 
573
529
  const ctx = createMockContext({
574
530
  identifiers: ["GPIO7", "DR_SET"],
@@ -578,13 +534,14 @@ describe("AssignmentClassifier - Register Bit Access", () => {
578
534
  isSimpleIdentifier: false,
579
535
  });
580
536
 
581
- expect(classifier.classify(ctx)).toBe(AssignmentKind.REGISTER_BIT);
537
+ expect(AssignmentClassifier.classify(ctx)).toBe(
538
+ AssignmentKind.REGISTER_BIT,
539
+ );
582
540
  });
583
541
 
584
542
  it("classifies register bit range", () => {
585
543
  const knownRegisters = new Set(["GPIO7"]);
586
- const deps = createMockDeps({ knownRegisters });
587
- const classifier = new AssignmentClassifier(deps);
544
+ setupSymbols({ knownRegisters });
588
545
 
589
546
  const ctx = createMockContext({
590
547
  identifiers: ["GPIO7", "DR_SET"],
@@ -597,18 +554,16 @@ describe("AssignmentClassifier - Register Bit Access", () => {
597
554
  isSimpleIdentifier: false,
598
555
  });
599
556
 
600
- expect(classifier.classify(ctx)).toBe(AssignmentKind.REGISTER_BIT_RANGE);
557
+ expect(AssignmentClassifier.classify(ctx)).toBe(
558
+ AssignmentKind.REGISTER_BIT_RANGE,
559
+ );
601
560
  });
602
561
 
603
562
  it("classifies scoped register bit", () => {
604
563
  const knownScopes = new Set(["Teensy4"]);
605
564
  const knownRegisters = new Set(["Teensy4_GPIO7"]);
606
- const deps = createMockDeps({
607
- knownScopes,
608
- knownRegisters,
609
- currentScope: "Teensy4",
610
- });
611
- const classifier = new AssignmentClassifier(deps);
565
+ setupSymbols({ knownScopes, knownRegisters });
566
+ CodeGenState.currentScope = "Teensy4";
612
567
 
613
568
  const ctx = createMockContext({
614
569
  identifiers: ["GPIO7", "DR_SET"],
@@ -619,7 +574,9 @@ describe("AssignmentClassifier - Register Bit Access", () => {
619
574
  isSimpleIdentifier: false,
620
575
  });
621
576
 
622
- expect(classifier.classify(ctx)).toBe(AssignmentKind.SCOPED_REGISTER_BIT);
577
+ expect(AssignmentClassifier.classify(ctx)).toBe(
578
+ AssignmentKind.SCOPED_REGISTER_BIT,
579
+ );
623
580
  });
624
581
  });
625
582
 
@@ -627,6 +584,10 @@ describe("AssignmentClassifier - Register Bit Access", () => {
627
584
  // Scoped Register Bitmap Field (4-id pattern)
628
585
  // ========================================================================
629
586
  describe("AssignmentClassifier - Scoped Register Bitmap Field", () => {
587
+ beforeEach(() => {
588
+ CodeGenState.reset();
589
+ });
590
+
630
591
  it("classifies Scope.REG.MEMBER.field as SCOPED_REGISTER_MEMBER_BITMAP_FIELD", () => {
631
592
  const bitmapFields = new Map([
632
593
  ["ControlBits", new Map([["Enable", { offset: 0, width: 1 }]])],
@@ -636,14 +597,12 @@ describe("AssignmentClassifier - Scoped Register Bitmap Field", () => {
636
597
  const registerMemberTypes = new Map([
637
598
  ["Teensy4_GPIO7_ICR1", "ControlBits"],
638
599
  ]);
639
-
640
- const deps = createMockDeps({
600
+ setupSymbols({
641
601
  bitmapFields,
642
602
  knownScopes,
643
603
  knownRegisters,
644
604
  registerMemberTypes,
645
605
  });
646
- const classifier = new AssignmentClassifier(deps);
647
606
 
648
607
  const ctx = createMockContext({
649
608
  identifiers: ["Teensy4", "GPIO7", "ICR1", "Enable"],
@@ -651,14 +610,13 @@ describe("AssignmentClassifier - Scoped Register Bitmap Field", () => {
651
610
  isSimpleIdentifier: false,
652
611
  });
653
612
 
654
- expect(classifier.classify(ctx)).toBe(
613
+ expect(AssignmentClassifier.classify(ctx)).toBe(
655
614
  AssignmentKind.SCOPED_REGISTER_MEMBER_BITMAP_FIELD,
656
615
  );
657
616
  });
658
617
 
659
618
  it("returns null for unknown scope in 4-id pattern", () => {
660
- const deps = createMockDeps();
661
- const classifier = new AssignmentClassifier(deps);
619
+ setupSymbols();
662
620
 
663
621
  const ctx = createMockContext({
664
622
  identifiers: ["UnknownScope", "REG", "MEMBER", "field"],
@@ -666,7 +624,7 @@ describe("AssignmentClassifier - Scoped Register Bitmap Field", () => {
666
624
  isSimpleIdentifier: false,
667
625
  });
668
626
 
669
- expect(classifier.classify(ctx)).toBe(AssignmentKind.SIMPLE);
627
+ expect(AssignmentClassifier.classify(ctx)).toBe(AssignmentKind.SIMPLE);
670
628
  });
671
629
  });
672
630
 
@@ -674,24 +632,24 @@ describe("AssignmentClassifier - Scoped Register Bitmap Field", () => {
674
632
  // Bitmap Array Element Field
675
633
  // ========================================================================
676
634
  describe("AssignmentClassifier - Bitmap Array Element Field", () => {
635
+ beforeEach(() => {
636
+ CodeGenState.reset();
637
+ });
638
+
677
639
  it("classifies bitmapArr[i].field as BITMAP_ARRAY_ELEMENT_FIELD", () => {
678
640
  const bitmapFields = new Map([
679
641
  ["StatusFlags", new Map([["Active", { offset: 0, width: 1 }]])],
680
642
  ]);
681
- const typeRegistry = new Map([
682
- [
683
- "flagsArr",
684
- createTypeInfo({
685
- isBitmap: true,
686
- isArray: true,
687
- bitmapTypeName: "StatusFlags",
688
- arrayDimensions: [10],
689
- }),
690
- ],
691
- ]);
692
-
693
- const deps = createMockDeps({ bitmapFields, typeRegistry });
694
- const classifier = new AssignmentClassifier(deps);
643
+ setupSymbols({ bitmapFields });
644
+ CodeGenState.typeRegistry.set(
645
+ "flagsArr",
646
+ createTypeInfo({
647
+ isBitmap: true,
648
+ isArray: true,
649
+ bitmapTypeName: "StatusFlags",
650
+ arrayDimensions: [10],
651
+ }),
652
+ );
695
653
 
696
654
  const ctx = createMockContext({
697
655
  identifiers: ["flagsArr", "Active"],
@@ -701,7 +659,7 @@ describe("AssignmentClassifier - Bitmap Array Element Field", () => {
701
659
  isSimpleIdentifier: false,
702
660
  });
703
661
 
704
- expect(classifier.classify(ctx)).toBe(
662
+ expect(AssignmentClassifier.classify(ctx)).toBe(
705
663
  AssignmentKind.BITMAP_ARRAY_ELEMENT_FIELD,
706
664
  );
707
665
  });
@@ -711,20 +669,20 @@ describe("AssignmentClassifier - Bitmap Array Element Field", () => {
711
669
  // Multi-dim Array with Bit Indexing
712
670
  // ========================================================================
713
671
  describe("AssignmentClassifier - Multi-dim Array Bit Indexing", () => {
714
- it("classifies matrix[i][j][bit] as ARRAY_ELEMENT_BIT", () => {
715
- const typeRegistry = new Map([
716
- [
717
- "matrix",
718
- createTypeInfo({
719
- baseType: "u32",
720
- isArray: true,
721
- arrayDimensions: [4, 4],
722
- }),
723
- ],
724
- ]);
672
+ beforeEach(() => {
673
+ CodeGenState.reset();
674
+ setupSymbols();
675
+ });
725
676
 
726
- const deps = createMockDeps({ typeRegistry });
727
- const classifier = new AssignmentClassifier(deps);
677
+ it("classifies matrix[i][j][bit] as ARRAY_ELEMENT_BIT", () => {
678
+ CodeGenState.typeRegistry.set(
679
+ "matrix",
680
+ createTypeInfo({
681
+ baseType: "u32",
682
+ isArray: true,
683
+ arrayDimensions: [4, 4],
684
+ }),
685
+ );
728
686
 
729
687
  const ctx = createMockContext({
730
688
  identifiers: ["matrix"],
@@ -738,23 +696,20 @@ describe("AssignmentClassifier - Multi-dim Array Bit Indexing", () => {
738
696
  isSimpleIdentifier: false,
739
697
  });
740
698
 
741
- expect(classifier.classify(ctx)).toBe(AssignmentKind.ARRAY_ELEMENT_BIT);
699
+ expect(AssignmentClassifier.classify(ctx)).toBe(
700
+ AssignmentKind.ARRAY_ELEMENT_BIT,
701
+ );
742
702
  });
743
703
 
744
704
  it("classifies matrix[i][j] as MULTI_DIM_ARRAY_ELEMENT", () => {
745
- const typeRegistry = new Map([
746
- [
747
- "matrix",
748
- createTypeInfo({
749
- baseType: "u32",
750
- isArray: true,
751
- arrayDimensions: [4, 4],
752
- }),
753
- ],
754
- ]);
755
-
756
- const deps = createMockDeps({ typeRegistry });
757
- const classifier = new AssignmentClassifier(deps);
705
+ CodeGenState.typeRegistry.set(
706
+ "matrix",
707
+ createTypeInfo({
708
+ baseType: "u32",
709
+ isArray: true,
710
+ arrayDimensions: [4, 4],
711
+ }),
712
+ );
758
713
 
759
714
  const ctx = createMockContext({
760
715
  identifiers: ["matrix"],
@@ -767,7 +722,7 @@ describe("AssignmentClassifier - Multi-dim Array Bit Indexing", () => {
767
722
  isSimpleIdentifier: false,
768
723
  });
769
724
 
770
- expect(classifier.classify(ctx)).toBe(
725
+ expect(AssignmentClassifier.classify(ctx)).toBe(
771
726
  AssignmentKind.MULTI_DIM_ARRAY_ELEMENT,
772
727
  );
773
728
  });
@@ -777,13 +732,14 @@ describe("AssignmentClassifier - Multi-dim Array Bit Indexing", () => {
777
732
  // Scoped Register Bit Range via This Prefix
778
733
  // ========================================================================
779
734
  describe("AssignmentClassifier - Scoped Register Bit Range", () => {
735
+ beforeEach(() => {
736
+ CodeGenState.reset();
737
+ });
738
+
780
739
  it("classifies this.reg[start, width] as SCOPED_REGISTER_BIT_RANGE", () => {
781
740
  const knownRegisters = new Set(["Teensy4_GPIO7"]);
782
- const deps = createMockDeps({
783
- knownRegisters,
784
- currentScope: "Teensy4",
785
- });
786
- const classifier = new AssignmentClassifier(deps);
741
+ setupSymbols({ knownRegisters });
742
+ CodeGenState.currentScope = "Teensy4";
787
743
 
788
744
  const ctx = createMockContext({
789
745
  identifiers: ["GPIO7", "ICR1"],
@@ -800,7 +756,7 @@ describe("AssignmentClassifier - Scoped Register Bit Range", () => {
800
756
  isSimpleIdentifier: false,
801
757
  });
802
758
 
803
- expect(classifier.classify(ctx)).toBe(
759
+ expect(AssignmentClassifier.classify(ctx)).toBe(
804
760
  AssignmentKind.SCOPED_REGISTER_BIT_RANGE,
805
761
  );
806
762
  });
@@ -810,10 +766,13 @@ describe("AssignmentClassifier - Scoped Register Bit Range", () => {
810
766
  // Register Bit Access via classifyMemberWithSubscript (non-scoped, 2+ ids)
811
767
  // ========================================================================
812
768
  describe("AssignmentClassifier - Register Bit via MemberWithSubscript", () => {
769
+ beforeEach(() => {
770
+ CodeGenState.reset();
771
+ });
772
+
813
773
  it("classifies REG.MEMBER[bit] as REGISTER_BIT (non-this, non-global)", () => {
814
774
  const knownRegisters = new Set(["TIMER"]);
815
- const deps = createMockDeps({ knownRegisters });
816
- const classifier = new AssignmentClassifier(deps);
775
+ setupSymbols({ knownRegisters });
817
776
 
818
777
  const ctx = createMockContext({
819
778
  identifiers: ["TIMER", "CTRL"],
@@ -823,13 +782,14 @@ describe("AssignmentClassifier - Register Bit via MemberWithSubscript", () => {
823
782
  isSimpleIdentifier: false,
824
783
  });
825
784
 
826
- expect(classifier.classify(ctx)).toBe(AssignmentKind.REGISTER_BIT);
785
+ expect(AssignmentClassifier.classify(ctx)).toBe(
786
+ AssignmentKind.REGISTER_BIT,
787
+ );
827
788
  });
828
789
 
829
790
  it("classifies REG.MEMBER[start, width] as REGISTER_BIT_RANGE (non-this)", () => {
830
791
  const knownRegisters = new Set(["TIMER"]);
831
- const deps = createMockDeps({ knownRegisters });
832
- const classifier = new AssignmentClassifier(deps);
792
+ setupSymbols({ knownRegisters });
833
793
 
834
794
  const ctx = createMockContext({
835
795
  identifiers: ["TIMER", "CTRL"],
@@ -842,14 +802,15 @@ describe("AssignmentClassifier - Register Bit via MemberWithSubscript", () => {
842
802
  isSimpleIdentifier: false,
843
803
  });
844
804
 
845
- expect(classifier.classify(ctx)).toBe(AssignmentKind.REGISTER_BIT_RANGE);
805
+ expect(AssignmentClassifier.classify(ctx)).toBe(
806
+ AssignmentKind.REGISTER_BIT_RANGE,
807
+ );
846
808
  });
847
809
 
848
810
  it("classifies Scope.REG.MEMBER[bit] as REGISTER_BIT via memberWithSubscript", () => {
849
811
  const knownScopes = new Set(["Teensy4"]);
850
812
  const knownRegisters = new Set(["Teensy4_GPIO7"]);
851
- const deps = createMockDeps({ knownScopes, knownRegisters });
852
- const classifier = new AssignmentClassifier(deps);
813
+ setupSymbols({ knownScopes, knownRegisters });
853
814
 
854
815
  const ctx = createMockContext({
855
816
  identifiers: ["Teensy4", "GPIO7", "DR_SET"],
@@ -859,7 +820,9 @@ describe("AssignmentClassifier - Register Bit via MemberWithSubscript", () => {
859
820
  isSimpleIdentifier: false,
860
821
  });
861
822
 
862
- expect(classifier.classify(ctx)).toBe(AssignmentKind.REGISTER_BIT);
823
+ expect(AssignmentClassifier.classify(ctx)).toBe(
824
+ AssignmentKind.REGISTER_BIT,
825
+ );
863
826
  });
864
827
  });
865
828
 
@@ -867,19 +830,18 @@ describe("AssignmentClassifier - Register Bit via MemberWithSubscript", () => {
867
830
  // This Prefix - Scoped Register Bitmap Field
868
831
  // ========================================================================
869
832
  describe("AssignmentClassifier - This Prefix Register Bitmap", () => {
833
+ beforeEach(() => {
834
+ CodeGenState.reset();
835
+ });
836
+
870
837
  it("classifies this.REG.MEMBER.field as SCOPED_REGISTER_MEMBER_BITMAP_FIELD", () => {
871
838
  const knownRegisters = new Set(["Motor_GPIO7"]);
872
839
  const registerMemberTypes = new Map([["Motor_GPIO7_ICR1", "CtrlBits"]]);
873
840
  const bitmapFields = new Map([
874
841
  ["CtrlBits", new Map([["Enable", { offset: 0, width: 1 }]])],
875
842
  ]);
876
- const deps = createMockDeps({
877
- knownRegisters,
878
- registerMemberTypes,
879
- bitmapFields,
880
- currentScope: "Motor",
881
- });
882
- const classifier = new AssignmentClassifier(deps);
843
+ setupSymbols({ knownRegisters, registerMemberTypes, bitmapFields });
844
+ CodeGenState.currentScope = "Motor";
883
845
 
884
846
  const ctx = createMockContext({
885
847
  identifiers: ["GPIO7", "ICR1", "Enable"],
@@ -888,7 +850,7 @@ describe("AssignmentClassifier - This Prefix Register Bitmap", () => {
888
850
  isSimpleIdentifier: false,
889
851
  });
890
852
 
891
- expect(classifier.classify(ctx)).toBe(
853
+ expect(AssignmentClassifier.classify(ctx)).toBe(
892
854
  AssignmentKind.SCOPED_REGISTER_MEMBER_BITMAP_FIELD,
893
855
  );
894
856
  });
@@ -898,15 +860,18 @@ describe("AssignmentClassifier - This Prefix Register Bitmap", () => {
898
860
  // Member Chain
899
861
  // ========================================================================
900
862
  describe("AssignmentClassifier - Member Chain", () => {
863
+ beforeEach(() => {
864
+ CodeGenState.reset();
865
+ });
866
+
901
867
  it("classifies complex member chain as MEMBER_CHAIN", () => {
902
868
  const knownStructs = new Set(["Config"]);
903
869
  const structFields = new Map([["Config", new Map([["items", "Item"]])]]);
904
- const typeRegistry = new Map([
905
- ["config", createTypeInfo({ baseType: "Config" })],
906
- ]);
907
-
908
- const deps = createMockDeps({ knownStructs, structFields, typeRegistry });
909
- const classifier = new AssignmentClassifier(deps);
870
+ setupSymbols({ knownStructs, structFields });
871
+ CodeGenState.typeRegistry.set(
872
+ "config",
873
+ createTypeInfo({ baseType: "Config" }),
874
+ );
910
875
 
911
876
  const ctx = createMockContext({
912
877
  identifiers: ["config", "items"],
@@ -916,6 +881,8 @@ describe("AssignmentClassifier - Member Chain", () => {
916
881
  isSimpleIdentifier: false,
917
882
  });
918
883
 
919
- expect(classifier.classify(ctx)).toBe(AssignmentKind.MEMBER_CHAIN);
884
+ expect(AssignmentClassifier.classify(ctx)).toBe(
885
+ AssignmentKind.MEMBER_CHAIN,
886
+ );
920
887
  });
921
888
  });