c-next 0.1.69 → 0.1.70

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 (54) hide show
  1. package/package.json +1 -1
  2. package/src/transpiler/logic/analysis/FunctionCallAnalyzer.ts +240 -204
  3. package/src/transpiler/logic/analysis/PassByValueAnalyzer.ts +693 -0
  4. package/src/transpiler/logic/analysis/__tests__/FunctionCallAnalyzer.test.ts +86 -5
  5. package/src/transpiler/{output/codegen → logic/analysis}/helpers/AssignmentTargetExtractor.ts +1 -1
  6. package/src/transpiler/{output/codegen → logic/analysis}/helpers/ChildStatementCollector.ts +1 -1
  7. package/src/transpiler/{output/codegen → logic/analysis}/helpers/StatementExpressionCollector.ts +1 -1
  8. package/src/transpiler/{output/codegen → logic/analysis}/helpers/__tests__/AssignmentTargetExtractor.test.ts +2 -2
  9. package/src/transpiler/{output/codegen → logic/analysis}/helpers/__tests__/ChildStatementCollector.test.ts +2 -2
  10. package/src/transpiler/{output/codegen → logic/analysis}/helpers/__tests__/StatementExpressionCollector.test.ts +2 -2
  11. package/src/transpiler/output/codegen/CodeGenerator.ts +35 -607
  12. package/src/transpiler/output/codegen/TypeRegistrationUtils.ts +4 -6
  13. package/src/transpiler/output/codegen/TypeResolver.ts +2 -2
  14. package/src/transpiler/output/codegen/TypeValidator.ts +5 -5
  15. package/src/transpiler/output/codegen/__tests__/TypeRegistrationUtils.test.ts +36 -51
  16. package/src/transpiler/output/codegen/__tests__/TypeResolver.test.ts +20 -17
  17. package/src/transpiler/output/codegen/__tests__/TypeValidator.resolution.test.ts +3 -3
  18. package/src/transpiler/output/codegen/__tests__/TypeValidator.test.ts +1 -1
  19. package/src/transpiler/output/codegen/analysis/MemberChainAnalyzer.ts +1 -1
  20. package/src/transpiler/output/codegen/analysis/StringLengthCounter.ts +1 -1
  21. package/src/transpiler/output/codegen/analysis/__tests__/MemberChainAnalyzer.test.ts +9 -9
  22. package/src/transpiler/output/codegen/analysis/__tests__/StringLengthCounter.test.ts +12 -12
  23. package/src/transpiler/output/codegen/assignment/AssignmentClassifier.ts +11 -11
  24. package/src/transpiler/output/codegen/assignment/__tests__/AssignmentClassifier.test.ts +23 -17
  25. package/src/transpiler/output/codegen/assignment/handlers/ArrayHandlers.ts +2 -2
  26. package/src/transpiler/output/codegen/assignment/handlers/BitAccessHandlers.ts +3 -3
  27. package/src/transpiler/output/codegen/assignment/handlers/BitmapHandlers.ts +3 -3
  28. package/src/transpiler/output/codegen/assignment/handlers/SpecialHandlers.ts +4 -4
  29. package/src/transpiler/output/codegen/assignment/handlers/StringHandlers.ts +5 -5
  30. package/src/transpiler/output/codegen/assignment/handlers/__tests__/ArrayHandlers.test.ts +23 -25
  31. package/src/transpiler/output/codegen/assignment/handlers/__tests__/BitAccessHandlers.test.ts +20 -36
  32. package/src/transpiler/output/codegen/assignment/handlers/__tests__/BitmapHandlers.test.ts +18 -18
  33. package/src/transpiler/output/codegen/assignment/handlers/__tests__/SpecialHandlers.test.ts +42 -32
  34. package/src/transpiler/output/codegen/assignment/handlers/__tests__/handlerTestUtils.ts +5 -4
  35. package/src/transpiler/output/codegen/generators/expressions/CallExprGenerator.ts +14 -6
  36. package/src/transpiler/output/codegen/generators/expressions/PostfixExpressionGenerator.ts +19 -16
  37. package/src/transpiler/output/codegen/generators/expressions/__tests__/CallExprGenerator.test.ts +21 -4
  38. package/src/transpiler/output/codegen/generators/expressions/__tests__/PostfixExpressionGenerator.test.ts +15 -2
  39. package/src/transpiler/output/codegen/helpers/ArrayInitHelper.ts +2 -1
  40. package/src/transpiler/output/codegen/helpers/AssignmentExpectedTypeResolver.ts +2 -2
  41. package/src/transpiler/output/codegen/helpers/AssignmentValidator.ts +3 -3
  42. package/src/transpiler/output/codegen/helpers/EnumAssignmentValidator.ts +1 -1
  43. package/src/transpiler/output/codegen/helpers/StringDeclHelper.ts +2 -2
  44. package/src/transpiler/output/codegen/helpers/__tests__/ArrayInitHelper.test.ts +1 -1
  45. package/src/transpiler/output/codegen/helpers/__tests__/AssignmentExpectedTypeResolver.test.ts +7 -7
  46. package/src/transpiler/output/codegen/helpers/__tests__/AssignmentValidator.test.ts +7 -7
  47. package/src/transpiler/output/codegen/helpers/__tests__/EnumAssignmentValidator.test.ts +2 -2
  48. package/src/transpiler/output/codegen/helpers/__tests__/StringDeclHelper.test.ts +4 -4
  49. package/src/transpiler/output/codegen/resolution/EnumTypeResolver.ts +2 -2
  50. package/src/transpiler/output/codegen/resolution/__tests__/EnumTypeResolver.test.ts +5 -5
  51. package/src/transpiler/state/CodeGenState.ts +122 -4
  52. package/src/transpiler/state/__tests__/CodeGenState.test.ts +269 -1
  53. /package/src/transpiler/{output/codegen → logic/analysis}/helpers/TransitiveModificationPropagator.ts +0 -0
  54. /package/src/transpiler/{output/codegen → logic/analysis}/helpers/__tests__/TransitiveModificationPropagator.test.ts +0 -0
@@ -38,7 +38,7 @@ describe("StringLengthCounter", () => {
38
38
 
39
39
  describe("countExpression", () => {
40
40
  it("counts single .length access on string variable", () => {
41
- CodeGenState.typeRegistry.set("myStr", {
41
+ CodeGenState.setVariableTypeInfo("myStr", {
42
42
  baseType: "char",
43
43
  bitWidth: 8,
44
44
  isArray: false,
@@ -54,7 +54,7 @@ describe("StringLengthCounter", () => {
54
54
  });
55
55
 
56
56
  it("counts multiple .length accesses on same variable", () => {
57
- CodeGenState.typeRegistry.set("str", {
57
+ CodeGenState.setVariableTypeInfo("str", {
58
58
  baseType: "char",
59
59
  bitWidth: 8,
60
60
  isArray: false,
@@ -71,7 +71,7 @@ describe("StringLengthCounter", () => {
71
71
  });
72
72
 
73
73
  it("counts .length accesses on different string variables", () => {
74
- CodeGenState.typeRegistry.set("a", {
74
+ CodeGenState.setVariableTypeInfo("a", {
75
75
  baseType: "char",
76
76
  bitWidth: 8,
77
77
  isArray: false,
@@ -79,7 +79,7 @@ describe("StringLengthCounter", () => {
79
79
  isString: true,
80
80
  stringCapacity: 16,
81
81
  });
82
- CodeGenState.typeRegistry.set("b", {
82
+ CodeGenState.setVariableTypeInfo("b", {
83
83
  baseType: "char",
84
84
  bitWidth: 8,
85
85
  isArray: false,
@@ -96,7 +96,7 @@ describe("StringLengthCounter", () => {
96
96
  });
97
97
 
98
98
  it("ignores .length on non-string variables", () => {
99
- CodeGenState.typeRegistry.set("arr", {
99
+ CodeGenState.setVariableTypeInfo("arr", {
100
100
  baseType: "u8",
101
101
  bitWidth: 8,
102
102
  isArray: true,
@@ -111,7 +111,7 @@ describe("StringLengthCounter", () => {
111
111
  });
112
112
 
113
113
  it("ignores other member accesses", () => {
114
- CodeGenState.typeRegistry.set("obj", {
114
+ CodeGenState.setVariableTypeInfo("obj", {
115
115
  baseType: "MyStruct",
116
116
  bitWidth: 32,
117
117
  isArray: false,
@@ -135,7 +135,7 @@ describe("StringLengthCounter", () => {
135
135
 
136
136
  describe("countBlock", () => {
137
137
  it("counts .length accesses across multiple statements", () => {
138
- CodeGenState.typeRegistry.set("msg", {
138
+ CodeGenState.setVariableTypeInfo("msg", {
139
139
  baseType: "char",
140
140
  bitWidth: 8,
141
141
  isArray: false,
@@ -154,7 +154,7 @@ describe("StringLengthCounter", () => {
154
154
  });
155
155
 
156
156
  it("counts .length in assignment statements", () => {
157
- CodeGenState.typeRegistry.set("text", {
157
+ CodeGenState.setVariableTypeInfo("text", {
158
158
  baseType: "char",
159
159
  bitWidth: 8,
160
160
  isArray: false,
@@ -175,7 +175,7 @@ describe("StringLengthCounter", () => {
175
175
 
176
176
  describe("countBlockInto", () => {
177
177
  it("adds counts to existing map", () => {
178
- CodeGenState.typeRegistry.set("s1", {
178
+ CodeGenState.setVariableTypeInfo("s1", {
179
179
  baseType: "char",
180
180
  bitWidth: 8,
181
181
  isArray: false,
@@ -183,7 +183,7 @@ describe("StringLengthCounter", () => {
183
183
  isString: true,
184
184
  stringCapacity: 32,
185
185
  });
186
- CodeGenState.typeRegistry.set("s2", {
186
+ CodeGenState.setVariableTypeInfo("s2", {
187
187
  baseType: "char",
188
188
  bitWidth: 8,
189
189
  isArray: false,
@@ -209,7 +209,7 @@ describe("StringLengthCounter", () => {
209
209
 
210
210
  describe("nested expressions", () => {
211
211
  it("counts .length in ternary expressions", () => {
212
- CodeGenState.typeRegistry.set("str", {
212
+ CodeGenState.setVariableTypeInfo("str", {
213
213
  baseType: "char",
214
214
  bitWidth: 8,
215
215
  isArray: false,
@@ -225,7 +225,7 @@ describe("StringLengthCounter", () => {
225
225
  });
226
226
 
227
227
  it("counts .length in comparison expressions", () => {
228
- CodeGenState.typeRegistry.set("name", {
228
+ CodeGenState.setVariableTypeInfo("name", {
229
229
  baseType: "char",
230
230
  bitWidth: 8,
231
231
  isArray: false,
@@ -144,7 +144,7 @@ class AssignmentClassifier {
144
144
  varName: string,
145
145
  fieldName: string,
146
146
  ): AssignmentKind | null {
147
- const typeInfo = CodeGenState.typeRegistry.get(varName);
147
+ const typeInfo = CodeGenState.getVariableTypeInfo(varName);
148
148
  if (!typeInfo?.isBitmap || !typeInfo.bitmapTypeName) {
149
149
  return null;
150
150
  }
@@ -189,7 +189,7 @@ class AssignmentClassifier {
189
189
  }
190
190
 
191
191
  // Check if struct member bitmap field: struct.bitmapMember.field
192
- const structTypeInfo = CodeGenState.typeRegistry.get(firstName);
192
+ const structTypeInfo = CodeGenState.getVariableTypeInfo(firstName);
193
193
  if (
194
194
  !structTypeInfo ||
195
195
  !CodeGenState.isKnownStruct(structTypeInfo.baseType)
@@ -270,7 +270,7 @@ class AssignmentClassifier {
270
270
 
271
271
  const ids = ctx.identifiers;
272
272
  const firstId = ids[0];
273
- const typeInfo = CodeGenState.typeRegistry.get(firstId);
273
+ const typeInfo = CodeGenState.getVariableTypeInfo(firstId);
274
274
 
275
275
  // Check for bit range through struct chain: devices[0].control[0, 4]
276
276
  // Detected by last subscript having 2 expressions (start, width)
@@ -494,7 +494,7 @@ class AssignmentClassifier {
494
494
  }
495
495
 
496
496
  const name = ctx.identifiers[0];
497
- const typeInfo = CodeGenState.typeRegistry.get(name) ?? null;
497
+ const typeInfo = CodeGenState.getVariableTypeInfo(name) ?? null;
498
498
 
499
499
  // Use shared classifier for array vs bit access decision
500
500
  // Use lastSubscriptExprCount to distinguish [0][0] (two ops, each 1 expr)
@@ -558,16 +558,16 @@ class AssignmentClassifier {
558
558
  let typeInfo;
559
559
  if (ctx.isSimpleIdentifier) {
560
560
  const id = ctx.identifiers[0];
561
- typeInfo = CodeGenState.typeRegistry.get(id);
561
+ typeInfo = CodeGenState.getVariableTypeInfo(id);
562
562
  } else if (ctx.isSimpleThisAccess && CodeGenState.currentScope) {
563
563
  // this.member pattern: lookup using scoped name
564
564
  const memberName = ctx.identifiers[0];
565
565
  const scopedName = `${CodeGenState.currentScope}_${memberName}`;
566
- typeInfo = CodeGenState.typeRegistry.get(scopedName);
566
+ typeInfo = CodeGenState.getVariableTypeInfo(scopedName);
567
567
  } else if (ctx.isSimpleGlobalAccess) {
568
568
  // global.member pattern: lookup using direct name
569
569
  const memberName = ctx.identifiers[0];
570
- typeInfo = CodeGenState.typeRegistry.get(memberName);
570
+ typeInfo = CodeGenState.getVariableTypeInfo(memberName);
571
571
  } else {
572
572
  return null;
573
573
  }
@@ -604,7 +604,7 @@ class AssignmentClassifier {
604
604
  ): AssignmentKind | null {
605
605
  if (!ctx.isSimpleIdentifier) return null;
606
606
  const id = ctx.identifiers[0];
607
- const typeInfo = CodeGenState.typeRegistry.get(id);
607
+ const typeInfo = CodeGenState.getVariableTypeInfo(id);
608
608
  return AssignmentClassifier.isSimpleStringType(typeInfo)
609
609
  ? AssignmentKind.STRING_SIMPLE
610
610
  : null;
@@ -619,7 +619,7 @@ class AssignmentClassifier {
619
619
  if (!ctx.isSimpleThisAccess || !CodeGenState.currentScope) return null;
620
620
  const memberName = ctx.identifiers[0];
621
621
  const scopedName = `${CodeGenState.currentScope}_${memberName}`;
622
- const typeInfo = CodeGenState.typeRegistry.get(scopedName);
622
+ const typeInfo = CodeGenState.getVariableTypeInfo(scopedName);
623
623
  return AssignmentClassifier.isSimpleStringType(typeInfo)
624
624
  ? AssignmentKind.STRING_THIS_MEMBER
625
625
  : null;
@@ -633,7 +633,7 @@ class AssignmentClassifier {
633
633
  ): AssignmentKind | null {
634
634
  if (!ctx.isSimpleGlobalAccess) return null;
635
635
  const id = ctx.identifiers[0];
636
- const typeInfo = CodeGenState.typeRegistry.get(id);
636
+ const typeInfo = CodeGenState.getVariableTypeInfo(id);
637
637
  return AssignmentClassifier.isSimpleStringType(typeInfo)
638
638
  ? AssignmentKind.STRING_GLOBAL
639
639
  : null;
@@ -644,7 +644,7 @@ class AssignmentClassifier {
644
644
  * Returns the base struct type if valid, null if not a known struct.
645
645
  */
646
646
  private static _resolveStructType(structName: string): string | null {
647
- const structTypeInfo = CodeGenState.typeRegistry.get(structName);
647
+ const structTypeInfo = CodeGenState.getVariableTypeInfo(structName);
648
648
  if (
649
649
  !structTypeInfo ||
650
650
  !CodeGenState.isKnownStruct(structTypeInfo.baseType)
@@ -148,7 +148,7 @@ describe("AssignmentClassifier - Bitmap Fields", () => {
148
148
  ["StatusFlags", new Map([["Running", { offset: 0, width: 1 }]])],
149
149
  ]);
150
150
  setupSymbols({ bitmapFields });
151
- CodeGenState.typeRegistry.set(
151
+ CodeGenState.setVariableTypeInfo(
152
152
  "flags",
153
153
  createTypeInfo({ isBitmap: true, bitmapTypeName: "StatusFlags" }),
154
154
  );
@@ -169,7 +169,7 @@ describe("AssignmentClassifier - Bitmap Fields", () => {
169
169
  ["StatusFlags", new Map([["Mode", { offset: 4, width: 4 }]])],
170
170
  ]);
171
171
  setupSymbols({ bitmapFields });
172
- CodeGenState.typeRegistry.set(
172
+ CodeGenState.setVariableTypeInfo(
173
173
  "flags",
174
174
  createTypeInfo({ isBitmap: true, bitmapTypeName: "StatusFlags" }),
175
175
  );
@@ -213,7 +213,7 @@ describe("AssignmentClassifier - Bitmap Fields", () => {
213
213
  ["Device", new Map([["flags", "DeviceFlags"]])],
214
214
  ]);
215
215
  setupSymbols({ bitmapFields, knownStructs, structFields });
216
- CodeGenState.typeRegistry.set(
216
+ CodeGenState.setVariableTypeInfo(
217
217
  "device",
218
218
  createTypeInfo({ baseType: "Device" }),
219
219
  );
@@ -240,7 +240,10 @@ describe("AssignmentClassifier - Integer Bit Access", () => {
240
240
  });
241
241
 
242
242
  it("classifies single bit access on integer", () => {
243
- CodeGenState.typeRegistry.set("flags", createTypeInfo({ baseType: "u8" }));
243
+ CodeGenState.setVariableTypeInfo(
244
+ "flags",
245
+ createTypeInfo({ baseType: "u8" }),
246
+ );
244
247
 
245
248
  const ctx = createMockContext({
246
249
  identifiers: ["flags"],
@@ -253,7 +256,10 @@ describe("AssignmentClassifier - Integer Bit Access", () => {
253
256
  });
254
257
 
255
258
  it("classifies bit range access on integer", () => {
256
- CodeGenState.typeRegistry.set("flags", createTypeInfo({ baseType: "u32" }));
259
+ CodeGenState.setVariableTypeInfo(
260
+ "flags",
261
+ createTypeInfo({ baseType: "u32" }),
262
+ );
257
263
 
258
264
  const ctx = createMockContext({
259
265
  identifiers: ["flags"],
@@ -282,7 +288,7 @@ describe("AssignmentClassifier - Array Access", () => {
282
288
  });
283
289
 
284
290
  it("classifies simple array element", () => {
285
- CodeGenState.typeRegistry.set(
291
+ CodeGenState.setVariableTypeInfo(
286
292
  "arr",
287
293
  createTypeInfo({
288
294
  isArray: true,
@@ -303,7 +309,7 @@ describe("AssignmentClassifier - Array Access", () => {
303
309
  });
304
310
 
305
311
  it("classifies array slice", () => {
306
- CodeGenState.typeRegistry.set(
312
+ CodeGenState.setVariableTypeInfo(
307
313
  "buffer",
308
314
  createTypeInfo({
309
315
  isArray: true,
@@ -336,7 +342,7 @@ describe("AssignmentClassifier - String Assignments", () => {
336
342
  });
337
343
 
338
344
  it("classifies simple string variable", () => {
339
- CodeGenState.typeRegistry.set(
345
+ CodeGenState.setVariableTypeInfo(
340
346
  "name",
341
347
  createTypeInfo({
342
348
  baseType: "string<32>",
@@ -348,7 +354,7 @@ describe("AssignmentClassifier - String Assignments", () => {
348
354
  const ctx = createMockContext({
349
355
  identifiers: ["name"],
350
356
  isSimpleIdentifier: true,
351
- firstIdTypeInfo: CodeGenState.typeRegistry.get("name")!,
357
+ firstIdTypeInfo: CodeGenState.getVariableTypeInfo("name")!,
352
358
  });
353
359
 
354
360
  expect(AssignmentClassifier.classify(ctx)).toBe(
@@ -362,7 +368,7 @@ describe("AssignmentClassifier - String Assignments", () => {
362
368
  ["Person", new Map([["name", "string<64>"]])],
363
369
  ]);
364
370
  setupSymbols({ knownStructs, structFields });
365
- CodeGenState.typeRegistry.set(
371
+ CodeGenState.setVariableTypeInfo(
366
372
  "person",
367
373
  createTypeInfo({ baseType: "Person" }),
368
374
  );
@@ -389,7 +395,7 @@ describe("AssignmentClassifier - Special Compound", () => {
389
395
  });
390
396
 
391
397
  it("classifies atomic RMW", () => {
392
- CodeGenState.typeRegistry.set(
398
+ CodeGenState.setVariableTypeInfo(
393
399
  "counter",
394
400
  createTypeInfo({
395
401
  baseType: "u32",
@@ -408,7 +414,7 @@ describe("AssignmentClassifier - Special Compound", () => {
408
414
  });
409
415
 
410
416
  it("classifies overflow clamp", () => {
411
- CodeGenState.typeRegistry.set(
417
+ CodeGenState.setVariableTypeInfo(
412
418
  "saturated",
413
419
  createTypeInfo({
414
420
  baseType: "u8",
@@ -429,7 +435,7 @@ describe("AssignmentClassifier - Special Compound", () => {
429
435
  });
430
436
 
431
437
  it("does not classify float as overflow clamp", () => {
432
- CodeGenState.typeRegistry.set(
438
+ CodeGenState.setVariableTypeInfo(
433
439
  "value",
434
440
  createTypeInfo({
435
441
  baseType: "f32",
@@ -648,7 +654,7 @@ describe("AssignmentClassifier - Bitmap Array Element Field", () => {
648
654
  ["StatusFlags", new Map([["Active", { offset: 0, width: 1 }]])],
649
655
  ]);
650
656
  setupSymbols({ bitmapFields });
651
- CodeGenState.typeRegistry.set(
657
+ CodeGenState.setVariableTypeInfo(
652
658
  "flagsArr",
653
659
  createTypeInfo({
654
660
  isBitmap: true,
@@ -682,7 +688,7 @@ describe("AssignmentClassifier - Multi-dim Array Bit Indexing", () => {
682
688
  });
683
689
 
684
690
  it("classifies matrix[i][j][bit] as ARRAY_ELEMENT_BIT", () => {
685
- CodeGenState.typeRegistry.set(
691
+ CodeGenState.setVariableTypeInfo(
686
692
  "matrix",
687
693
  createTypeInfo({
688
694
  baseType: "u32",
@@ -709,7 +715,7 @@ describe("AssignmentClassifier - Multi-dim Array Bit Indexing", () => {
709
715
  });
710
716
 
711
717
  it("classifies matrix[i][j] as MULTI_DIM_ARRAY_ELEMENT", () => {
712
- CodeGenState.typeRegistry.set(
718
+ CodeGenState.setVariableTypeInfo(
713
719
  "matrix",
714
720
  createTypeInfo({
715
721
  baseType: "u32",
@@ -875,7 +881,7 @@ describe("AssignmentClassifier - Member Chain", () => {
875
881
  const knownStructs = new Set(["Config"]);
876
882
  const structFields = new Map([["Config", new Map([["items", "Item"]])]]);
877
883
  setupSymbols({ knownStructs, structFields });
878
- CodeGenState.typeRegistry.set(
884
+ CodeGenState.setVariableTypeInfo(
879
885
  "config",
880
886
  createTypeInfo({ baseType: "Config" }),
881
887
  );
@@ -37,7 +37,7 @@ function handleArrayElement(ctx: IAssignmentContext): string {
37
37
  function handleMultiDimArrayElement(ctx: IAssignmentContext): string {
38
38
  // Use resolvedBaseIdentifier for type lookup (includes scope prefix)
39
39
  // e.g., "ArrayBug_data" instead of "data"
40
- const typeInfo = CodeGenState.typeRegistry.get(ctx.resolvedBaseIdentifier);
40
+ const typeInfo = CodeGenState.getVariableTypeInfo(ctx.resolvedBaseIdentifier);
41
41
 
42
42
  // ADR-036: Compile-time bounds checking for constant indices
43
43
  if (typeInfo?.arrayDimensions) {
@@ -71,7 +71,7 @@ function handleArraySlice(ctx: IAssignmentContext): string {
71
71
 
72
72
  // Use resolvedBaseIdentifier for type lookup (includes scope prefix)
73
73
  const name = ctx.resolvedBaseIdentifier;
74
- const typeInfo = CodeGenState.typeRegistry.get(name);
74
+ const typeInfo = CodeGenState.getVariableTypeInfo(name);
75
75
 
76
76
  // Get line number for error messages
77
77
  const line = ctx.subscripts[0].start?.line ?? 0;
@@ -42,7 +42,7 @@ function handleIntegerBit(ctx: IAssignmentContext): string {
42
42
  // e.g., "ArrayBug_flags" instead of "flags"
43
43
  const name = ctx.resolvedBaseIdentifier;
44
44
  const bitIndex = gen().generateExpression(ctx.subscripts[0]);
45
- const typeInfo = CodeGenState.typeRegistry.get(name);
45
+ const typeInfo = CodeGenState.getVariableTypeInfo(name);
46
46
 
47
47
  // Check for float bit indexing
48
48
  if (typeInfo) {
@@ -79,7 +79,7 @@ function handleIntegerBitRange(ctx: IAssignmentContext): string {
79
79
  const name = ctx.resolvedBaseIdentifier;
80
80
  const start = gen().generateExpression(ctx.subscripts[0]);
81
81
  const width = gen().generateExpression(ctx.subscripts[1]);
82
- const typeInfo = CodeGenState.typeRegistry.get(name);
82
+ const typeInfo = CodeGenState.getVariableTypeInfo(name);
83
83
 
84
84
  // Check for float bit indexing
85
85
  if (typeInfo) {
@@ -138,7 +138,7 @@ function handleArrayElementBit(ctx: IAssignmentContext): string {
138
138
 
139
139
  // Use resolvedBaseIdentifier for type lookup and code generation
140
140
  const arrayName = ctx.resolvedBaseIdentifier;
141
- const typeInfo = CodeGenState.typeRegistry.get(arrayName);
141
+ const typeInfo = CodeGenState.getVariableTypeInfo(arrayName);
142
142
 
143
143
  if (!typeInfo?.arrayDimensions) {
144
144
  // Use raw identifier in error message for clarity
@@ -109,7 +109,7 @@ function generateWriteOnlyBitmapWrite(
109
109
  function handleBitmapFieldSingleBit(ctx: IAssignmentContext): string {
110
110
  const varName = ctx.identifiers[0];
111
111
  const fieldName = ctx.identifiers[1];
112
- const typeInfo = CodeGenState.typeRegistry.get(varName);
112
+ const typeInfo = CodeGenState.getVariableTypeInfo(varName);
113
113
  const bitmapType = typeInfo!.bitmapTypeName!;
114
114
 
115
115
  const fieldInfo = getBitmapFieldInfo(bitmapType, fieldName, ctx);
@@ -130,7 +130,7 @@ function handleBitmapFieldMultiBit(ctx: IAssignmentContext): string {
130
130
  function handleBitmapArrayElementField(ctx: IAssignmentContext): string {
131
131
  const arrayName = ctx.identifiers[0];
132
132
  const fieldName = ctx.identifiers[1];
133
- const typeInfo = CodeGenState.typeRegistry.get(arrayName);
133
+ const typeInfo = CodeGenState.getVariableTypeInfo(arrayName);
134
134
  const bitmapType = typeInfo!.bitmapTypeName!;
135
135
 
136
136
  const fieldInfo = getBitmapFieldInfo(bitmapType, fieldName, ctx);
@@ -148,7 +148,7 @@ function handleStructMemberBitmapField(ctx: IAssignmentContext): string {
148
148
  const memberName = ctx.identifiers[1];
149
149
  const fieldName = ctx.identifiers[2];
150
150
 
151
- const structTypeInfo = CodeGenState.typeRegistry.get(structName);
151
+ const structTypeInfo = CodeGenState.getVariableTypeInfo(structName);
152
152
  const memberInfo = CodeGenState.getMemberTypeInfo(
153
153
  structTypeInfo!.baseType,
154
154
  memberName,
@@ -36,22 +36,22 @@ function getTargetTypeInfo(ctx: IAssignmentContext): {
36
36
 
37
37
  // Simple identifier
38
38
  if (ctx.isSimpleIdentifier) {
39
- return { typeInfo: CodeGenState.typeRegistry.get(id) };
39
+ return { typeInfo: CodeGenState.getVariableTypeInfo(id) };
40
40
  }
41
41
 
42
42
  // this.member: lookup using scoped name
43
43
  if (ctx.isSimpleThisAccess && CodeGenState.currentScope) {
44
44
  const scopedName = `${CodeGenState.currentScope}_${id}`;
45
- return { typeInfo: CodeGenState.typeRegistry.get(scopedName) };
45
+ return { typeInfo: CodeGenState.getVariableTypeInfo(scopedName) };
46
46
  }
47
47
 
48
48
  // global.member: lookup using direct name
49
49
  if (ctx.isSimpleGlobalAccess) {
50
- return { typeInfo: CodeGenState.typeRegistry.get(id) };
50
+ return { typeInfo: CodeGenState.getVariableTypeInfo(id) };
51
51
  }
52
52
 
53
53
  // Fallback to direct lookup
54
- return { typeInfo: CodeGenState.typeRegistry.get(id) };
54
+ return { typeInfo: CodeGenState.getVariableTypeInfo(id) };
55
55
  }
56
56
 
57
57
  /**
@@ -42,7 +42,7 @@ function handleSimpleStringAssignment(ctx: IAssignmentContext): string {
42
42
  validateNotCompound(ctx);
43
43
 
44
44
  const id = ctx.identifiers[0];
45
- const typeInfo = CodeGenState.typeRegistry.get(id);
45
+ const typeInfo = CodeGenState.getVariableTypeInfo(id);
46
46
  const capacity = typeInfo!.stringCapacity!;
47
47
 
48
48
  CodeGenState.needsString = true;
@@ -57,7 +57,7 @@ function handleSimpleStringAssignment(ctx: IAssignmentContext): string {
57
57
  * Shared helper for struct field string handlers.
58
58
  */
59
59
  function getStructFieldType(structName: string, fieldName: string): string {
60
- const structTypeInfo = CodeGenState.typeRegistry.get(structName);
60
+ const structTypeInfo = CodeGenState.getVariableTypeInfo(structName);
61
61
  const structType = structTypeInfo!.baseType;
62
62
  const structFields = CodeGenState.symbols!.structFields.get(structType);
63
63
  return structFields!.get(fieldName)!;
@@ -69,7 +69,7 @@ function getStructFieldType(structName: string, fieldName: string): string {
69
69
  * Shared helper for struct field handlers.
70
70
  */
71
71
  function getStructType(structName: string): string {
72
- const structTypeInfo = CodeGenState.typeRegistry.get(structName);
72
+ const structTypeInfo = CodeGenState.getVariableTypeInfo(structName);
73
73
  return structTypeInfo!.baseType;
74
74
  }
75
75
 
@@ -85,7 +85,7 @@ function handleStringThisMember(ctx: IAssignmentContext): string {
85
85
 
86
86
  const memberName = ctx.identifiers[0];
87
87
  const scopedName = `${CodeGenState.currentScope}_${memberName}`;
88
- const typeInfo = CodeGenState.typeRegistry.get(scopedName);
88
+ const typeInfo = CodeGenState.getVariableTypeInfo(scopedName);
89
89
  const capacity = typeInfo!.stringCapacity!;
90
90
 
91
91
  CodeGenState.needsString = true;
@@ -123,7 +123,7 @@ function handleStringArrayElement(ctx: IAssignmentContext): string {
123
123
  validateNotCompound(ctx);
124
124
 
125
125
  const name = ctx.identifiers[0];
126
- const typeInfo = CodeGenState.typeRegistry.get(name);
126
+ const typeInfo = CodeGenState.getVariableTypeInfo(name);
127
127
  const capacity = typeInfo!.stringCapacity!;
128
128
 
129
129
  CodeGenState.needsString = true;
@@ -183,9 +183,9 @@ describe("ArrayHandlers", () => {
183
183
  });
184
184
 
185
185
  it("performs bounds checking when type info available", () => {
186
- CodeGenState.typeRegistry = new Map([
186
+ HandlerTestUtils.setupMockTypeRegistry([
187
187
  ["matrix", { arrayDimensions: [10, 10], baseType: "i32" }],
188
- ]) as any;
188
+ ]);
189
189
  mockCheckArrayBounds.mockClear();
190
190
  HandlerTestUtils.setupMockGenerator({
191
191
  generateExpression: vi
@@ -242,9 +242,9 @@ describe("ArrayHandlers", () => {
242
242
  arrayHandlers.find(([kind]) => kind === AssignmentKind.ARRAY_SLICE)?.[1];
243
243
 
244
244
  it("generates memcpy for valid slice assignment", () => {
245
- CodeGenState.typeRegistry = new Map([
245
+ HandlerTestUtils.setupMockTypeRegistry([
246
246
  ["buffer", { arrayDimensions: [100], baseType: "u8" }],
247
- ]) as any;
247
+ ]);
248
248
  HandlerTestUtils.setupMockGenerator({
249
249
  tryEvaluateConstant: vi
250
250
  .fn()
@@ -267,7 +267,7 @@ describe("ArrayHandlers", () => {
267
267
  });
268
268
 
269
269
  it("generates memcpy for string slice", () => {
270
- CodeGenState.typeRegistry = new Map([
270
+ HandlerTestUtils.setupMockTypeRegistry([
271
271
  [
272
272
  "str",
273
273
  {
@@ -277,7 +277,7 @@ describe("ArrayHandlers", () => {
277
277
  baseType: "string",
278
278
  },
279
279
  ],
280
- ]) as any;
280
+ ]);
281
281
  HandlerTestUtils.setupMockGenerator({
282
282
  tryEvaluateConstant: vi
283
283
  .fn()
@@ -299,9 +299,9 @@ describe("ArrayHandlers", () => {
299
299
  });
300
300
 
301
301
  it("throws on compound assignment", () => {
302
- CodeGenState.typeRegistry = new Map([
302
+ HandlerTestUtils.setupMockTypeRegistry([
303
303
  ["buffer", { arrayDimensions: [100], baseType: "u8" }],
304
- ]) as any;
304
+ ]);
305
305
  HandlerTestUtils.setupMockGenerator({
306
306
  tryEvaluateConstant: vi
307
307
  .fn()
@@ -323,9 +323,9 @@ describe("ArrayHandlers", () => {
323
323
  });
324
324
 
325
325
  it("throws on multi-dimensional array", () => {
326
- CodeGenState.typeRegistry = new Map([
326
+ HandlerTestUtils.setupMockTypeRegistry([
327
327
  ["matrix", { arrayDimensions: [10, 10], baseType: "u8" }],
328
- ]) as any;
328
+ ]);
329
329
  const ctx = createMockContext({
330
330
  identifiers: ["matrix"],
331
331
  subscripts: [
@@ -340,9 +340,9 @@ describe("ArrayHandlers", () => {
340
340
  });
341
341
 
342
342
  it("throws on non-constant offset", () => {
343
- CodeGenState.typeRegistry = new Map([
343
+ HandlerTestUtils.setupMockTypeRegistry([
344
344
  ["buffer", { arrayDimensions: [100], baseType: "u8" }],
345
- ]) as any;
345
+ ]);
346
346
  HandlerTestUtils.setupMockGenerator({
347
347
  tryEvaluateConstant: vi.fn().mockReturnValue(undefined),
348
348
  });
@@ -359,9 +359,9 @@ describe("ArrayHandlers", () => {
359
359
  });
360
360
 
361
361
  it("throws on non-constant length", () => {
362
- CodeGenState.typeRegistry = new Map([
362
+ HandlerTestUtils.setupMockTypeRegistry([
363
363
  ["buffer", { arrayDimensions: [100], baseType: "u8" }],
364
- ]) as any;
364
+ ]);
365
365
  HandlerTestUtils.setupMockGenerator({
366
366
  tryEvaluateConstant: vi
367
367
  .fn()
@@ -381,9 +381,9 @@ describe("ArrayHandlers", () => {
381
381
  });
382
382
 
383
383
  it("throws on out of bounds access", () => {
384
- CodeGenState.typeRegistry = new Map([
384
+ HandlerTestUtils.setupMockTypeRegistry([
385
385
  ["buffer", { arrayDimensions: [50], baseType: "u8" }],
386
- ]) as any;
386
+ ]);
387
387
  HandlerTestUtils.setupMockGenerator({
388
388
  tryEvaluateConstant: vi
389
389
  .fn()
@@ -404,9 +404,9 @@ describe("ArrayHandlers", () => {
404
404
  });
405
405
 
406
406
  it("throws on negative offset", () => {
407
- CodeGenState.typeRegistry = new Map([
407
+ HandlerTestUtils.setupMockTypeRegistry([
408
408
  ["buffer", { arrayDimensions: [100], baseType: "u8" }],
409
- ]) as any;
409
+ ]);
410
410
  HandlerTestUtils.setupMockGenerator({
411
411
  tryEvaluateConstant: vi
412
412
  .fn()
@@ -427,9 +427,9 @@ describe("ArrayHandlers", () => {
427
427
  });
428
428
 
429
429
  it("throws on zero length", () => {
430
- CodeGenState.typeRegistry = new Map([
430
+ HandlerTestUtils.setupMockTypeRegistry([
431
431
  ["buffer", { arrayDimensions: [100], baseType: "u8" }],
432
- ]) as any;
432
+ ]);
433
433
  HandlerTestUtils.setupMockGenerator({
434
434
  tryEvaluateConstant: vi
435
435
  .fn()
@@ -450,9 +450,9 @@ describe("ArrayHandlers", () => {
450
450
  });
451
451
 
452
452
  it("throws on negative length", () => {
453
- CodeGenState.typeRegistry = new Map([
453
+ HandlerTestUtils.setupMockTypeRegistry([
454
454
  ["buffer", { arrayDimensions: [100], baseType: "u8" }],
455
- ]) as any;
455
+ ]);
456
456
  HandlerTestUtils.setupMockGenerator({
457
457
  tryEvaluateConstant: vi
458
458
  .fn()
@@ -473,9 +473,7 @@ describe("ArrayHandlers", () => {
473
473
  });
474
474
 
475
475
  it("throws when buffer size cannot be determined", () => {
476
- CodeGenState.typeRegistry = new Map([
477
- ["unknown", { baseType: "u8" }],
478
- ]) as any;
476
+ HandlerTestUtils.setupMockTypeRegistry([["unknown", { baseType: "u8" }]]);
479
477
  HandlerTestUtils.setupMockGenerator({
480
478
  tryEvaluateConstant: vi
481
479
  .fn()