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
@@ -76,9 +76,7 @@ describe("BitAccessHandlers", () => {
76
76
  )?.[1];
77
77
 
78
78
  it("generates single bit read-modify-write", () => {
79
- CodeGenState.typeRegistry = new Map([
80
- ["flags", { baseType: "u32" }],
81
- ]) as any;
79
+ HandlerTestUtils.setupMockTypeRegistry([["flags", { baseType: "u32" }]]);
82
80
  HandlerTestUtils.setupMockGenerator({
83
81
  generateExpression: vi.fn().mockReturnValue("3"),
84
82
  });
@@ -92,9 +90,7 @@ describe("BitAccessHandlers", () => {
92
90
  });
93
91
 
94
92
  it("uses 1ULL for 64-bit types", () => {
95
- CodeGenState.typeRegistry = new Map([
96
- ["flags", { baseType: "u64" }],
97
- ]) as any;
93
+ HandlerTestUtils.setupMockTypeRegistry([["flags", { baseType: "u64" }]]);
98
94
  HandlerTestUtils.setupMockGenerator({
99
95
  generateExpression: vi.fn().mockReturnValue("32"),
100
96
  });
@@ -108,9 +104,7 @@ describe("BitAccessHandlers", () => {
108
104
  });
109
105
 
110
106
  it("uses 1ULL for signed 64-bit types", () => {
111
- CodeGenState.typeRegistry = new Map([
112
- ["flags", { baseType: "i64" }],
113
- ]) as any;
107
+ HandlerTestUtils.setupMockTypeRegistry([["flags", { baseType: "i64" }]]);
114
108
  HandlerTestUtils.setupMockGenerator({
115
109
  generateExpression: vi.fn().mockReturnValue("bit"),
116
110
  });
@@ -123,9 +117,7 @@ describe("BitAccessHandlers", () => {
123
117
  });
124
118
 
125
119
  it("converts true to 1", () => {
126
- CodeGenState.typeRegistry = new Map([
127
- ["flags", { baseType: "u8" }],
128
- ]) as any;
120
+ HandlerTestUtils.setupMockTypeRegistry([["flags", { baseType: "u8" }]]);
129
121
  HandlerTestUtils.setupMockGenerator({
130
122
  generateExpression: vi.fn().mockReturnValue("0"),
131
123
  });
@@ -139,9 +131,7 @@ describe("BitAccessHandlers", () => {
139
131
  });
140
132
 
141
133
  it("converts false to 0", () => {
142
- CodeGenState.typeRegistry = new Map([
143
- ["flags", { baseType: "u8" }],
144
- ]) as any;
134
+ HandlerTestUtils.setupMockTypeRegistry([["flags", { baseType: "u8" }]]);
145
135
  HandlerTestUtils.setupMockGenerator({
146
136
  generateExpression: vi.fn().mockReturnValue("0"),
147
137
  });
@@ -155,7 +145,7 @@ describe("BitAccessHandlers", () => {
155
145
  });
156
146
 
157
147
  it("delegates to float bit write for float types", () => {
158
- CodeGenState.typeRegistry = new Map([["f", { baseType: "f32" }]]) as any;
148
+ HandlerTestUtils.setupMockTypeRegistry([["f", { baseType: "f32" }]]);
159
149
  const generateFloatBitWrite = vi
160
150
  .fn()
161
151
  .mockReturnValue("float_bit_write_result");
@@ -192,9 +182,7 @@ describe("BitAccessHandlers", () => {
192
182
  )?.[1];
193
183
 
194
184
  it("generates bit range read-modify-write", () => {
195
- CodeGenState.typeRegistry = new Map([
196
- ["flags", { baseType: "u32" }],
197
- ]) as any;
185
+ HandlerTestUtils.setupMockTypeRegistry([["flags", { baseType: "u32" }]]);
198
186
  HandlerTestUtils.setupMockGenerator({
199
187
  generateExpression: vi
200
188
  .fn()
@@ -214,9 +202,7 @@ describe("BitAccessHandlers", () => {
214
202
  });
215
203
 
216
204
  it("uses correct mask for bit range", () => {
217
- CodeGenState.typeRegistry = new Map([
218
- ["data", { baseType: "u16" }],
219
- ]) as any;
205
+ HandlerTestUtils.setupMockTypeRegistry([["data", { baseType: "u16" }]]);
220
206
  HandlerTestUtils.setupMockGenerator({
221
207
  generateExpression: vi
222
208
  .fn()
@@ -237,9 +223,7 @@ describe("BitAccessHandlers", () => {
237
223
  });
238
224
 
239
225
  it("uses ULL suffix for 64-bit bit range mask", () => {
240
- CodeGenState.typeRegistry = new Map([
241
- ["flags", { baseType: "u64" }],
242
- ]) as any;
226
+ HandlerTestUtils.setupMockTypeRegistry([["flags", { baseType: "u64" }]]);
243
227
  HandlerTestUtils.setupMockGenerator({
244
228
  generateExpression: vi
245
229
  .fn()
@@ -261,7 +245,7 @@ describe("BitAccessHandlers", () => {
261
245
  });
262
246
 
263
247
  it("delegates to float bit write for float types", () => {
264
- CodeGenState.typeRegistry = new Map([["f", { baseType: "f32" }]]) as any;
248
+ HandlerTestUtils.setupMockTypeRegistry([["f", { baseType: "f32" }]]);
265
249
  const generateFloatBitWrite = vi
266
250
  .fn()
267
251
  .mockReturnValue("float_range_write_result");
@@ -344,9 +328,9 @@ describe("BitAccessHandlers", () => {
344
328
  )?.[1];
345
329
 
346
330
  it("generates array element bit assignment for 1D array", () => {
347
- CodeGenState.typeRegistry = new Map([
331
+ HandlerTestUtils.setupMockTypeRegistry([
348
332
  ["arr", { baseType: "u32", arrayDimensions: [10] }],
349
- ]) as any;
333
+ ]);
350
334
  HandlerTestUtils.setupMockGenerator({
351
335
  generateExpression: vi
352
336
  .fn()
@@ -368,9 +352,9 @@ describe("BitAccessHandlers", () => {
368
352
  });
369
353
 
370
354
  it("generates array element bit assignment for 2D array", () => {
371
- CodeGenState.typeRegistry = new Map([
355
+ HandlerTestUtils.setupMockTypeRegistry([
372
356
  ["matrix", { baseType: "u16", arrayDimensions: [10, 10] }],
373
- ]) as any;
357
+ ]);
374
358
  HandlerTestUtils.setupMockGenerator({
375
359
  generateExpression: vi
376
360
  .fn()
@@ -394,9 +378,9 @@ describe("BitAccessHandlers", () => {
394
378
  });
395
379
 
396
380
  it("uses 1ULL for 64-bit array element", () => {
397
- CodeGenState.typeRegistry = new Map([
381
+ HandlerTestUtils.setupMockTypeRegistry([
398
382
  ["arr", { baseType: "u64", arrayDimensions: [5] }],
399
- ]) as any;
383
+ ]);
400
384
  HandlerTestUtils.setupMockGenerator({
401
385
  generateExpression: vi
402
386
  .fn()
@@ -414,9 +398,9 @@ describe("BitAccessHandlers", () => {
414
398
  });
415
399
 
416
400
  it("throws when variable is not an array", () => {
417
- CodeGenState.typeRegistry = new Map([
401
+ HandlerTestUtils.setupMockTypeRegistry([
418
402
  ["notArray", { baseType: "u32" }],
419
- ]) as any;
403
+ ]);
420
404
  const ctx = createMockContext({
421
405
  identifiers: ["notArray"],
422
406
  });
@@ -425,9 +409,9 @@ describe("BitAccessHandlers", () => {
425
409
  });
426
410
 
427
411
  it("throws on compound assignment", () => {
428
- CodeGenState.typeRegistry = new Map([
412
+ HandlerTestUtils.setupMockTypeRegistry([
429
413
  ["arr", { baseType: "u32", arrayDimensions: [10] }],
430
- ]) as any;
414
+ ]);
431
415
  const ctx = createMockContext({
432
416
  isCompound: true,
433
417
  cnextOp: "+<-",
@@ -89,9 +89,9 @@ describe("BitmapHandlers", () => {
89
89
  )?.[1];
90
90
 
91
91
  it("generates single-bit read-modify-write", () => {
92
- CodeGenState.typeRegistry = new Map([
92
+ HandlerTestUtils.setupMockTypeRegistry([
93
93
  ["flags", { bitmapTypeName: "StatusFlags", baseType: "u8" }],
94
- ]) as any;
94
+ ]);
95
95
  HandlerTestUtils.setupMockSymbols({
96
96
  bitmapFields: new Map([
97
97
  ["StatusFlags", new Map([["Running", { offset: 0, width: 1 }]])],
@@ -107,9 +107,9 @@ describe("BitmapHandlers", () => {
107
107
  });
108
108
 
109
109
  it("generates single-bit write with correct offset", () => {
110
- CodeGenState.typeRegistry = new Map([
110
+ HandlerTestUtils.setupMockTypeRegistry([
111
111
  ["flags", { bitmapTypeName: "StatusFlags", baseType: "u8" }],
112
- ]) as any;
112
+ ]);
113
113
  HandlerTestUtils.setupMockSymbols({
114
114
  bitmapFields: new Map([
115
115
  ["StatusFlags", new Map([["Active", { offset: 3, width: 1 }]])],
@@ -125,9 +125,9 @@ describe("BitmapHandlers", () => {
125
125
  });
126
126
 
127
127
  it("throws on unknown bitmap field", () => {
128
- CodeGenState.typeRegistry = new Map([
128
+ HandlerTestUtils.setupMockTypeRegistry([
129
129
  ["flags", { bitmapTypeName: "StatusFlags", baseType: "u8" }],
130
- ]) as any;
130
+ ]);
131
131
  HandlerTestUtils.setupMockSymbols({
132
132
  bitmapFields: new Map([["StatusFlags", new Map()]]),
133
133
  });
@@ -141,9 +141,9 @@ describe("BitmapHandlers", () => {
141
141
  });
142
142
 
143
143
  it("throws on compound assignment", () => {
144
- CodeGenState.typeRegistry = new Map([
144
+ HandlerTestUtils.setupMockTypeRegistry([
145
145
  ["flags", { bitmapTypeName: "StatusFlags", baseType: "u8" }],
146
- ]) as any;
146
+ ]);
147
147
  HandlerTestUtils.setupMockSymbols({
148
148
  bitmapFields: new Map([
149
149
  ["StatusFlags", new Map([["Running", { offset: 0, width: 1 }]])],
@@ -160,9 +160,9 @@ describe("BitmapHandlers", () => {
160
160
  });
161
161
 
162
162
  it("validates bitmap field literal", () => {
163
- CodeGenState.typeRegistry = new Map([
163
+ HandlerTestUtils.setupMockTypeRegistry([
164
164
  ["flags", { bitmapTypeName: "StatusFlags", baseType: "u8" }],
165
- ]) as any;
165
+ ]);
166
166
  HandlerTestUtils.setupMockSymbols({
167
167
  bitmapFields: new Map([
168
168
  ["StatusFlags", new Map([["Running", { offset: 0, width: 1 }]])],
@@ -188,9 +188,9 @@ describe("BitmapHandlers", () => {
188
188
  )?.[1];
189
189
 
190
190
  it("generates multi-bit read-modify-write with mask", () => {
191
- CodeGenState.typeRegistry = new Map([
191
+ HandlerTestUtils.setupMockTypeRegistry([
192
192
  ["flags", { bitmapTypeName: "StatusFlags", baseType: "u8" }],
193
- ]) as any;
193
+ ]);
194
194
  HandlerTestUtils.setupMockSymbols({
195
195
  bitmapFields: new Map([
196
196
  ["StatusFlags", new Map([["Mode", { offset: 4, width: 3 }]])],
@@ -210,9 +210,9 @@ describe("BitmapHandlers", () => {
210
210
  });
211
211
 
212
212
  it("generates correct mask for 2-bit field", () => {
213
- CodeGenState.typeRegistry = new Map([
213
+ HandlerTestUtils.setupMockTypeRegistry([
214
214
  ["config", { bitmapTypeName: "Config", baseType: "u8" }],
215
- ]) as any;
215
+ ]);
216
216
  HandlerTestUtils.setupMockSymbols({
217
217
  bitmapFields: new Map([
218
218
  ["Config", new Map([["Priority", { offset: 0, width: 2 }]])],
@@ -236,9 +236,9 @@ describe("BitmapHandlers", () => {
236
236
  )?.[1];
237
237
 
238
238
  it("generates array element bitmap field assignment", () => {
239
- CodeGenState.typeRegistry = new Map([
239
+ HandlerTestUtils.setupMockTypeRegistry([
240
240
  ["flagsArray", { bitmapTypeName: "StatusFlags", baseType: "u8" }],
241
- ]) as any;
241
+ ]);
242
242
  HandlerTestUtils.setupMockGenerator({
243
243
  generateExpression: vi.fn().mockReturnValue("i"),
244
244
  });
@@ -266,9 +266,9 @@ describe("BitmapHandlers", () => {
266
266
  )?.[1];
267
267
 
268
268
  it("generates struct member bitmap field assignment", () => {
269
- CodeGenState.typeRegistry = new Map([
269
+ HandlerTestUtils.setupMockTypeRegistry([
270
270
  ["device", { baseType: "Device" }],
271
- ]) as any;
271
+ ]);
272
272
  HandlerTestUtils.setupMockSymbols({
273
273
  bitmapFields: new Map([
274
274
  ["StatusFlags", new Map([["Active", { offset: 2, width: 1 }]])],
@@ -71,9 +71,9 @@ describe("SpecialHandlers", () => {
71
71
  specialHandlers.find(([kind]) => kind === AssignmentKind.ATOMIC_RMW)?.[1];
72
72
 
73
73
  it("delegates to generateAtomicRMW for simple identifier", () => {
74
- CodeGenState.typeRegistry = new Map([
74
+ HandlerTestUtils.setupMockTypeRegistry([
75
75
  ["counter", { baseType: "u32", isAtomic: true }],
76
- ]) as any;
76
+ ]);
77
77
  const generateAtomicRMW = vi.fn().mockReturnValue("LDREX/STREX pattern");
78
78
  const generateAssignmentTarget = vi.fn().mockReturnValue("counter");
79
79
  HandlerTestUtils.setupMockGenerator({
@@ -84,18 +84,23 @@ describe("SpecialHandlers", () => {
84
84
 
85
85
  const result = getHandler()!(ctx);
86
86
 
87
- expect(generateAtomicRMW).toHaveBeenCalledWith("counter", "+=", "1", {
88
- baseType: "u32",
89
- isAtomic: true,
90
- });
87
+ expect(generateAtomicRMW).toHaveBeenCalledWith(
88
+ "counter",
89
+ "+=",
90
+ "1",
91
+ expect.objectContaining({
92
+ baseType: "u32",
93
+ isAtomic: true,
94
+ }),
95
+ );
91
96
  expect(result).toBe("LDREX/STREX pattern");
92
97
  });
93
98
 
94
99
  it("handles this.member atomic variable", () => {
95
100
  CodeGenState.currentScope = "Motor";
96
- CodeGenState.typeRegistry = new Map([
101
+ HandlerTestUtils.setupMockTypeRegistry([
97
102
  ["Motor_count", { baseType: "u32", isAtomic: true }],
98
- ]) as any;
103
+ ]);
99
104
  const generateAtomicRMW = vi.fn().mockReturnValue("atomic result");
100
105
  const generateAssignmentTarget = vi.fn().mockReturnValue("Motor_count");
101
106
  HandlerTestUtils.setupMockGenerator({
@@ -110,17 +115,22 @@ describe("SpecialHandlers", () => {
110
115
 
111
116
  const result = getHandler()!(ctx);
112
117
 
113
- expect(generateAtomicRMW).toHaveBeenCalledWith("Motor_count", "+=", "1", {
114
- baseType: "u32",
115
- isAtomic: true,
116
- });
118
+ expect(generateAtomicRMW).toHaveBeenCalledWith(
119
+ "Motor_count",
120
+ "+=",
121
+ "1",
122
+ expect.objectContaining({
123
+ baseType: "u32",
124
+ isAtomic: true,
125
+ }),
126
+ );
117
127
  expect(result).toBe("atomic result");
118
128
  });
119
129
 
120
130
  it("handles global.member atomic variable", () => {
121
- CodeGenState.typeRegistry = new Map([
131
+ HandlerTestUtils.setupMockTypeRegistry([
122
132
  ["globalCounter", { baseType: "u32", isAtomic: true }],
123
- ]) as any;
133
+ ]);
124
134
  const generateAtomicRMW = vi.fn().mockReturnValue("global atomic result");
125
135
  const generateAssignmentTarget = vi.fn().mockReturnValue("globalCounter");
126
136
  HandlerTestUtils.setupMockGenerator({
@@ -139,9 +149,9 @@ describe("SpecialHandlers", () => {
139
149
  });
140
150
 
141
151
  it("handles subtract operation", () => {
142
- CodeGenState.typeRegistry = new Map([
152
+ HandlerTestUtils.setupMockTypeRegistry([
143
153
  ["counter", { baseType: "u32", isAtomic: true }],
144
- ]) as any;
154
+ ]);
145
155
  const generateAtomicRMW = vi.fn().mockReturnValue("atomic sub");
146
156
  const generateAssignmentTarget = vi.fn().mockReturnValue("counter");
147
157
  HandlerTestUtils.setupMockGenerator({
@@ -171,9 +181,9 @@ describe("SpecialHandlers", () => {
171
181
  )?.[1];
172
182
 
173
183
  it("generates clamp add helper for u8", () => {
174
- CodeGenState.typeRegistry = new Map([
184
+ HandlerTestUtils.setupMockTypeRegistry([
175
185
  ["saturated", { baseType: "u8", overflowBehavior: "clamp" }],
176
- ]) as any;
186
+ ]);
177
187
  const generateAssignmentTarget = vi.fn().mockReturnValue("saturated");
178
188
  HandlerTestUtils.setupMockGenerator({
179
189
  generateAssignmentTarget,
@@ -190,9 +200,9 @@ describe("SpecialHandlers", () => {
190
200
  });
191
201
 
192
202
  it("generates clamp sub helper for u16", () => {
193
- CodeGenState.typeRegistry = new Map([
203
+ HandlerTestUtils.setupMockTypeRegistry([
194
204
  ["value", { baseType: "u16", overflowBehavior: "clamp" }],
195
- ]) as any;
205
+ ]);
196
206
  const generateAssignmentTarget = vi.fn().mockReturnValue("value");
197
207
  HandlerTestUtils.setupMockGenerator({
198
208
  generateAssignmentTarget,
@@ -211,9 +221,9 @@ describe("SpecialHandlers", () => {
211
221
  });
212
222
 
213
223
  it("generates clamp mul helper for u32", () => {
214
- CodeGenState.typeRegistry = new Map([
224
+ HandlerTestUtils.setupMockTypeRegistry([
215
225
  ["result", { baseType: "u32", overflowBehavior: "clamp" }],
216
- ]) as any;
226
+ ]);
217
227
  const generateAssignmentTarget = vi.fn().mockReturnValue("result");
218
228
  HandlerTestUtils.setupMockGenerator({
219
229
  generateAssignmentTarget,
@@ -232,9 +242,9 @@ describe("SpecialHandlers", () => {
232
242
  });
233
243
 
234
244
  it("uses native arithmetic for float types", () => {
235
- CodeGenState.typeRegistry = new Map([
245
+ HandlerTestUtils.setupMockTypeRegistry([
236
246
  ["f", { baseType: "f32", overflowBehavior: "clamp" }],
237
- ]) as any;
247
+ ]);
238
248
  const generateAssignmentTarget = vi.fn().mockReturnValue("f");
239
249
  HandlerTestUtils.setupMockGenerator({
240
250
  generateAssignmentTarget,
@@ -251,9 +261,9 @@ describe("SpecialHandlers", () => {
251
261
  });
252
262
 
253
263
  it("uses native arithmetic for f64 type", () => {
254
- CodeGenState.typeRegistry = new Map([
264
+ HandlerTestUtils.setupMockTypeRegistry([
255
265
  ["d", { baseType: "f64", overflowBehavior: "clamp" }],
256
- ]) as any;
266
+ ]);
257
267
  const generateAssignmentTarget = vi.fn().mockReturnValue("d");
258
268
  HandlerTestUtils.setupMockGenerator({
259
269
  generateAssignmentTarget,
@@ -270,9 +280,9 @@ describe("SpecialHandlers", () => {
270
280
  });
271
281
 
272
282
  it("falls back to native for unsupported operators", () => {
273
- CodeGenState.typeRegistry = new Map([
283
+ HandlerTestUtils.setupMockTypeRegistry([
274
284
  ["value", { baseType: "u32", overflowBehavior: "clamp" }],
275
- ]) as any;
285
+ ]);
276
286
  const generateAssignmentTarget = vi.fn().mockReturnValue("value");
277
287
  HandlerTestUtils.setupMockGenerator({
278
288
  generateAssignmentTarget,
@@ -292,9 +302,9 @@ describe("SpecialHandlers", () => {
292
302
 
293
303
  it("handles this.member with clamp", () => {
294
304
  CodeGenState.currentScope = "Motor";
295
- CodeGenState.typeRegistry = new Map([
305
+ HandlerTestUtils.setupMockTypeRegistry([
296
306
  ["Motor_speed", { baseType: "u8", overflowBehavior: "clamp" }],
297
- ]) as any;
307
+ ]);
298
308
  const generateAssignmentTarget = vi.fn().mockReturnValue("Motor_speed");
299
309
  HandlerTestUtils.setupMockGenerator({
300
310
  generateAssignmentTarget,
@@ -313,9 +323,9 @@ describe("SpecialHandlers", () => {
313
323
  });
314
324
 
315
325
  it("handles global.member with clamp", () => {
316
- CodeGenState.typeRegistry = new Map([
326
+ HandlerTestUtils.setupMockTypeRegistry([
317
327
  ["globalValue", { baseType: "i16", overflowBehavior: "clamp" }],
318
- ]) as any;
328
+ ]);
319
329
  const generateAssignmentTarget = vi.fn().mockReturnValue("globalValue");
320
330
  HandlerTestUtils.setupMockGenerator({
321
331
  generateAssignmentTarget,
@@ -141,15 +141,16 @@ function createTypeInfo(overrides: Partial<TTypeInfo> = {}): TTypeInfo {
141
141
  }
142
142
 
143
143
  /**
144
- * Set up CodeGenState.typeRegistry with typed entries.
144
+ * Set up CodeGenState type registry with typed entries.
145
145
  * Entries only need to specify the fields relevant to the test.
146
+ * Uses setVariableTypeInfo to properly populate the registry.
146
147
  */
147
148
  function setupMockTypeRegistry(
148
149
  entries: Array<[string, Partial<TTypeInfo>]>,
149
150
  ): void {
150
- CodeGenState.typeRegistry = new Map(
151
- entries.map(([name, partial]) => [name, createTypeInfo(partial)]),
152
- );
151
+ for (const [name, partial] of entries) {
152
+ CodeGenState.setVariableTypeInfo(name, createTypeInfo(partial));
153
+ }
153
154
  }
154
155
 
155
156
  export default class HandlerTestUtils {
@@ -17,6 +17,7 @@ import IGeneratorInput from "../IGeneratorInput";
17
17
  import IGeneratorState from "../IGeneratorState";
18
18
  import IOrchestrator from "../IOrchestrator";
19
19
  import CallExprUtils from "./CallExprUtils";
20
+ import CodeGenState from "../../../../state/CodeGenState";
20
21
 
21
22
  /**
22
23
  * Issue #304: Wrap argument with static_cast if it's a C++ enum class
@@ -80,7 +81,7 @@ const _generateCFunctionArg = (
80
81
  // Issue #322: If getExpressionType returns null (e.g., for this.member),
81
82
  // fall back to looking up the generated code in the type registry
82
83
  if (!argType && !argCode.startsWith("&")) {
83
- const typeInfo = input.typeRegistry.get(argCode);
84
+ const typeInfo = CodeGenState.getVariableTypeInfo(argCode);
84
85
  if (typeInfo) {
85
86
  argType = typeInfo.baseType;
86
87
  }
@@ -119,8 +120,15 @@ const _shouldPassByValue = (
119
120
  funcExpr,
120
121
  idx,
121
122
  );
122
- const isSmallPrimitive =
123
- isCrossFile && CallExprUtils.isSmallPrimitiveType(targetParam.baseType);
123
+
124
+ // Issue #786: For cross-file calls, check if parameter is a known primitive type.
125
+ // Known primitives (u8-u64, i8-i64, bool) should always be pass-by-value.
126
+ // This handles the case where local passByValueParams isn't populated for cross-file functions.
127
+ const isCrossFilePrimitive =
128
+ isCrossFile &&
129
+ CallExprUtils.isKnownPrimitiveType(targetParam.baseType) &&
130
+ !orchestrator.isStructType(targetParam.baseType) &&
131
+ !CallExprUtils.isStringType(targetParam.baseType);
124
132
 
125
133
  // Issue #551: Unknown types (external enums, typedefs) use pass-by-value
126
134
  const isUnknownType =
@@ -129,13 +137,13 @@ const _shouldPassByValue = (
129
137
  !CallExprUtils.isStringType(targetParam.baseType) &&
130
138
  !isFloatParam &&
131
139
  !isEnumParam &&
132
- !isSmallPrimitive;
140
+ !isCrossFilePrimitive;
133
141
 
134
142
  return (
135
143
  isFloatParam ||
136
144
  isEnumParam ||
137
145
  isPrimitivePassByValue ||
138
- isSmallPrimitive ||
146
+ isCrossFilePrimitive ||
139
147
  isUnknownType
140
148
  );
141
149
  };
@@ -259,7 +267,7 @@ const generateSafeDivMod = (
259
267
  }
260
268
 
261
269
  // Look up the type of the output parameter
262
- const typeInfo = input.typeRegistry.get(outputArgId);
270
+ const typeInfo = CodeGenState.getVariableTypeInfo(outputArgId);
263
271
  if (!typeInfo) {
264
272
  throw new Error(
265
273
  `Cannot determine type of output parameter '${outputArgId}' for ${funcName}`,
@@ -27,6 +27,7 @@ import SubscriptClassifier from "../../subscript/SubscriptClassifier";
27
27
  import TYPE_WIDTH from "../../types/TYPE_WIDTH";
28
28
  import C_TYPE_WIDTH from "../../types/C_TYPE_WIDTH";
29
29
  import TTypeInfo from "../../types/TTypeInfo";
30
+ import CodeGenState from "../../../../state/CodeGenState";
30
31
 
31
32
  // ========================================================================
32
33
  // Tracking State
@@ -67,7 +68,7 @@ const initializeTrackingState = (
67
68
  : false;
68
69
 
69
70
  const primaryBaseType = rootIdentifier
70
- ? input.typeRegistry.get(rootIdentifier)?.baseType
71
+ ? CodeGenState.getVariableTypeInfo(rootIdentifier)?.baseType
71
72
  : undefined;
72
73
  const currentStructType =
73
74
  primaryBaseType && orchestrator.isKnownStruct(primaryBaseType)
@@ -162,7 +163,7 @@ const generatePostfixExpression = (
162
163
  }
163
164
 
164
165
  const primaryTypeInfo = rootIdentifier
165
- ? input.typeRegistry.get(rootIdentifier)
166
+ ? CodeGenState.getVariableTypeInfo(rootIdentifier)
166
167
  : undefined;
167
168
 
168
169
  const tracking = initializeTrackingState(
@@ -364,7 +365,7 @@ const handleGlobalPrefix = (
364
365
  }
365
366
 
366
367
  // Issue #612: Set currentStructType for global struct variables
367
- const globalTypeInfo = input.typeRegistry.get(memberName);
368
+ const globalTypeInfo = CodeGenState.getVariableTypeInfo(memberName);
368
369
  if (globalTypeInfo && orchestrator.isKnownStruct(globalTypeInfo.baseType)) {
369
370
  tracking.currentStructType = globalTypeInfo.baseType;
370
371
  }
@@ -396,7 +397,7 @@ const handleThisScopeLength = (
396
397
 
397
398
  tracking.result = `${state.currentScope}_${memberName}`;
398
399
  tracking.resolvedIdentifier = tracking.result;
399
- const resolvedTypeInfo = input.typeRegistry.get(tracking.result);
400
+ const resolvedTypeInfo = CodeGenState.getVariableTypeInfo(tracking.result);
400
401
  if (
401
402
  resolvedTypeInfo &&
402
403
  orchestrator.isKnownStruct(resolvedTypeInfo.baseType)
@@ -422,7 +423,9 @@ const resolveStringTypeInfo = (
422
423
  orchestrator: IOrchestrator,
423
424
  ): TTypeInfo | undefined => {
424
425
  const identifier = tracking.resolvedIdentifier ?? rootIdentifier;
425
- const typeInfo = identifier ? input.typeRegistry.get(identifier) : undefined;
426
+ const typeInfo = identifier
427
+ ? CodeGenState.getVariableTypeInfo(identifier)
428
+ : undefined;
426
429
  if (typeInfo?.isString) {
427
430
  return typeInfo;
428
431
  }
@@ -650,7 +653,7 @@ const generateLengthProperty = (
650
653
 
651
654
  // Fall back to checking the current resolved identifier's type
652
655
  const typeInfo = ctx.resolvedIdentifier
653
- ? input.typeRegistry.get(ctx.resolvedIdentifier)
656
+ ? CodeGenState.getVariableTypeInfo(ctx.resolvedIdentifier)
654
657
  : undefined;
655
658
 
656
659
  if (!typeInfo) {
@@ -931,7 +934,7 @@ const generateBitLengthProperty = (
931
934
 
932
935
  // Get type info for the resolved identifier
933
936
  const typeInfo = ctx.resolvedIdentifier
934
- ? input.typeRegistry.get(ctx.resolvedIdentifier)
937
+ ? CodeGenState.getVariableTypeInfo(ctx.resolvedIdentifier)
935
938
  : undefined;
936
939
 
937
940
  if (!typeInfo) {
@@ -1185,7 +1188,7 @@ const generateByteLengthProperty = (
1185
1188
 
1186
1189
  // Get type info for the resolved identifier
1187
1190
  const typeInfo = ctx.resolvedIdentifier
1188
- ? input.typeRegistry.get(ctx.resolvedIdentifier)
1191
+ ? CodeGenState.getVariableTypeInfo(ctx.resolvedIdentifier)
1189
1192
  : undefined;
1190
1193
 
1191
1194
  if (!typeInfo) {
@@ -1251,10 +1254,10 @@ const generateStructFieldElementCount = (
1251
1254
  */
1252
1255
  const generateTypeInfoElementCount = (
1253
1256
  ctx: IExplicitLengthContext,
1254
- input: IGeneratorInput,
1257
+ _input: IGeneratorInput,
1255
1258
  ): string => {
1256
1259
  const typeInfo = ctx.resolvedIdentifier
1257
- ? input.typeRegistry.get(ctx.resolvedIdentifier)
1260
+ ? CodeGenState.getVariableTypeInfo(ctx.resolvedIdentifier)
1258
1261
  : undefined;
1259
1262
 
1260
1263
  if (!typeInfo) {
@@ -1350,7 +1353,7 @@ const generateCharCountProperty = (
1350
1353
 
1351
1354
  // Get type info
1352
1355
  const typeInfo = ctx.resolvedIdentifier
1353
- ? input.typeRegistry.get(ctx.resolvedIdentifier)
1356
+ ? CodeGenState.getVariableTypeInfo(ctx.resolvedIdentifier)
1354
1357
  : undefined;
1355
1358
 
1356
1359
  if (!typeInfo) {
@@ -1484,7 +1487,7 @@ const tryBitmapFieldAccess = (
1484
1487
  if (!ctx.rootIdentifier) {
1485
1488
  return null;
1486
1489
  }
1487
- const typeInfo = input.typeRegistry.get(ctx.rootIdentifier);
1490
+ const typeInfo = CodeGenState.getVariableTypeInfo(ctx.rootIdentifier);
1488
1491
  if (!typeInfo?.isBitmap || !typeInfo.bitmapTypeName) {
1489
1492
  return null;
1490
1493
  }
@@ -1525,7 +1528,7 @@ const tryScopeMemberAccess = (
1525
1528
  output.result = fullName;
1526
1529
  output.resolvedIdentifier = fullName;
1527
1530
  if (!input.symbols!.knownEnums.has(fullName)) {
1528
- const resolvedTypeInfo = input.typeRegistry.get(fullName);
1531
+ const resolvedTypeInfo = CodeGenState.getVariableTypeInfo(fullName);
1529
1532
  if (
1530
1533
  resolvedTypeInfo &&
1531
1534
  orchestrator.isKnownStruct(resolvedTypeInfo.baseType)
@@ -1569,7 +1572,7 @@ const tryKnownScopeAccess = (
1569
1572
  const output = initializeMemberOutput(ctx);
1570
1573
  output.result = `${ctx.result}${orchestrator.getScopeSeparator(ctx.isCppAccessChain)}${ctx.memberName}`;
1571
1574
  output.resolvedIdentifier = output.result;
1572
- const resolvedTypeInfo = input.typeRegistry.get(output.result);
1575
+ const resolvedTypeInfo = CodeGenState.getVariableTypeInfo(output.result);
1573
1576
  if (
1574
1577
  resolvedTypeInfo &&
1575
1578
  orchestrator.isKnownStruct(resolvedTypeInfo.baseType)
@@ -1920,11 +1923,11 @@ const checkRegisterAccess = (
1920
1923
  */
1921
1924
  const getIdentifierTypeInfo = (
1922
1925
  ctx: ISubscriptAccessContext,
1923
- input: IGeneratorInput,
1926
+ _input: IGeneratorInput,
1924
1927
  ): TTypeInfo | undefined => {
1925
1928
  const identifierToCheck = ctx.resolvedIdentifier || ctx.rootIdentifier;
1926
1929
  return identifierToCheck
1927
- ? input.typeRegistry.get(identifierToCheck)
1930
+ ? CodeGenState.getVariableTypeInfo(identifierToCheck)
1928
1931
  : undefined;
1929
1932
  };
1930
1933