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