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.
- package/package.json +1 -1
- package/src/transpiler/logic/analysis/FunctionCallAnalyzer.ts +240 -204
- package/src/transpiler/logic/analysis/PassByValueAnalyzer.ts +693 -0
- package/src/transpiler/logic/analysis/__tests__/FunctionCallAnalyzer.test.ts +86 -5
- package/src/transpiler/{output/codegen → logic/analysis}/helpers/AssignmentTargetExtractor.ts +1 -1
- package/src/transpiler/{output/codegen → logic/analysis}/helpers/ChildStatementCollector.ts +1 -1
- package/src/transpiler/{output/codegen → logic/analysis}/helpers/StatementExpressionCollector.ts +1 -1
- package/src/transpiler/{output/codegen → logic/analysis}/helpers/__tests__/AssignmentTargetExtractor.test.ts +2 -2
- package/src/transpiler/{output/codegen → logic/analysis}/helpers/__tests__/ChildStatementCollector.test.ts +2 -2
- package/src/transpiler/{output/codegen → logic/analysis}/helpers/__tests__/StatementExpressionCollector.test.ts +2 -2
- package/src/transpiler/output/codegen/CodeGenerator.ts +35 -607
- package/src/transpiler/output/codegen/TypeRegistrationUtils.ts +4 -6
- package/src/transpiler/output/codegen/TypeResolver.ts +2 -2
- package/src/transpiler/output/codegen/TypeValidator.ts +5 -5
- package/src/transpiler/output/codegen/__tests__/TypeRegistrationUtils.test.ts +36 -51
- package/src/transpiler/output/codegen/__tests__/TypeResolver.test.ts +20 -17
- package/src/transpiler/output/codegen/__tests__/TypeValidator.resolution.test.ts +3 -3
- package/src/transpiler/output/codegen/__tests__/TypeValidator.test.ts +1 -1
- package/src/transpiler/output/codegen/analysis/MemberChainAnalyzer.ts +1 -1
- package/src/transpiler/output/codegen/analysis/StringLengthCounter.ts +1 -1
- package/src/transpiler/output/codegen/analysis/__tests__/MemberChainAnalyzer.test.ts +9 -9
- package/src/transpiler/output/codegen/analysis/__tests__/StringLengthCounter.test.ts +12 -12
- package/src/transpiler/output/codegen/assignment/AssignmentClassifier.ts +11 -11
- package/src/transpiler/output/codegen/assignment/__tests__/AssignmentClassifier.test.ts +23 -17
- package/src/transpiler/output/codegen/assignment/handlers/ArrayHandlers.ts +2 -2
- package/src/transpiler/output/codegen/assignment/handlers/BitAccessHandlers.ts +3 -3
- package/src/transpiler/output/codegen/assignment/handlers/BitmapHandlers.ts +3 -3
- package/src/transpiler/output/codegen/assignment/handlers/SpecialHandlers.ts +4 -4
- package/src/transpiler/output/codegen/assignment/handlers/StringHandlers.ts +5 -5
- package/src/transpiler/output/codegen/assignment/handlers/__tests__/ArrayHandlers.test.ts +23 -25
- package/src/transpiler/output/codegen/assignment/handlers/__tests__/BitAccessHandlers.test.ts +20 -36
- package/src/transpiler/output/codegen/assignment/handlers/__tests__/BitmapHandlers.test.ts +18 -18
- package/src/transpiler/output/codegen/assignment/handlers/__tests__/SpecialHandlers.test.ts +42 -32
- package/src/transpiler/output/codegen/assignment/handlers/__tests__/handlerTestUtils.ts +5 -4
- package/src/transpiler/output/codegen/generators/expressions/CallExprGenerator.ts +14 -6
- package/src/transpiler/output/codegen/generators/expressions/PostfixExpressionGenerator.ts +19 -16
- package/src/transpiler/output/codegen/generators/expressions/__tests__/CallExprGenerator.test.ts +21 -4
- package/src/transpiler/output/codegen/generators/expressions/__tests__/PostfixExpressionGenerator.test.ts +15 -2
- package/src/transpiler/output/codegen/helpers/ArrayInitHelper.ts +2 -1
- package/src/transpiler/output/codegen/helpers/AssignmentExpectedTypeResolver.ts +2 -2
- package/src/transpiler/output/codegen/helpers/AssignmentValidator.ts +3 -3
- package/src/transpiler/output/codegen/helpers/EnumAssignmentValidator.ts +1 -1
- package/src/transpiler/output/codegen/helpers/StringDeclHelper.ts +2 -2
- package/src/transpiler/output/codegen/helpers/__tests__/ArrayInitHelper.test.ts +1 -1
- package/src/transpiler/output/codegen/helpers/__tests__/AssignmentExpectedTypeResolver.test.ts +7 -7
- package/src/transpiler/output/codegen/helpers/__tests__/AssignmentValidator.test.ts +7 -7
- package/src/transpiler/output/codegen/helpers/__tests__/EnumAssignmentValidator.test.ts +2 -2
- package/src/transpiler/output/codegen/helpers/__tests__/StringDeclHelper.test.ts +4 -4
- package/src/transpiler/output/codegen/resolution/EnumTypeResolver.ts +2 -2
- package/src/transpiler/output/codegen/resolution/__tests__/EnumTypeResolver.test.ts +5 -5
- package/src/transpiler/state/CodeGenState.ts +122 -4
- package/src/transpiler/state/__tests__/CodeGenState.test.ts +269 -1
- /package/src/transpiler/{output/codegen → logic/analysis}/helpers/TransitiveModificationPropagator.ts +0 -0
- /package/src/transpiler/{output/codegen → logic/analysis}/helpers/__tests__/TransitiveModificationPropagator.test.ts +0 -0
package/src/transpiler/output/codegen/assignment/handlers/__tests__/BitAccessHandlers.test.ts
CHANGED
|
@@ -76,9 +76,7 @@ describe("BitAccessHandlers", () => {
|
|
|
76
76
|
)?.[1];
|
|
77
77
|
|
|
78
78
|
it("generates single bit read-modify-write", () => {
|
|
79
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
331
|
+
HandlerTestUtils.setupMockTypeRegistry([
|
|
348
332
|
["arr", { baseType: "u32", arrayDimensions: [10] }],
|
|
349
|
-
])
|
|
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
|
-
|
|
355
|
+
HandlerTestUtils.setupMockTypeRegistry([
|
|
372
356
|
["matrix", { baseType: "u16", arrayDimensions: [10, 10] }],
|
|
373
|
-
])
|
|
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
|
-
|
|
381
|
+
HandlerTestUtils.setupMockTypeRegistry([
|
|
398
382
|
["arr", { baseType: "u64", arrayDimensions: [5] }],
|
|
399
|
-
])
|
|
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
|
-
|
|
401
|
+
HandlerTestUtils.setupMockTypeRegistry([
|
|
418
402
|
["notArray", { baseType: "u32" }],
|
|
419
|
-
])
|
|
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
|
-
|
|
412
|
+
HandlerTestUtils.setupMockTypeRegistry([
|
|
429
413
|
["arr", { baseType: "u32", arrayDimensions: [10] }],
|
|
430
|
-
])
|
|
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
|
-
|
|
92
|
+
HandlerTestUtils.setupMockTypeRegistry([
|
|
93
93
|
["flags", { bitmapTypeName: "StatusFlags", baseType: "u8" }],
|
|
94
|
-
])
|
|
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
|
-
|
|
110
|
+
HandlerTestUtils.setupMockTypeRegistry([
|
|
111
111
|
["flags", { bitmapTypeName: "StatusFlags", baseType: "u8" }],
|
|
112
|
-
])
|
|
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
|
-
|
|
128
|
+
HandlerTestUtils.setupMockTypeRegistry([
|
|
129
129
|
["flags", { bitmapTypeName: "StatusFlags", baseType: "u8" }],
|
|
130
|
-
])
|
|
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
|
-
|
|
144
|
+
HandlerTestUtils.setupMockTypeRegistry([
|
|
145
145
|
["flags", { bitmapTypeName: "StatusFlags", baseType: "u8" }],
|
|
146
|
-
])
|
|
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
|
-
|
|
163
|
+
HandlerTestUtils.setupMockTypeRegistry([
|
|
164
164
|
["flags", { bitmapTypeName: "StatusFlags", baseType: "u8" }],
|
|
165
|
-
])
|
|
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
|
-
|
|
191
|
+
HandlerTestUtils.setupMockTypeRegistry([
|
|
192
192
|
["flags", { bitmapTypeName: "StatusFlags", baseType: "u8" }],
|
|
193
|
-
])
|
|
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
|
-
|
|
213
|
+
HandlerTestUtils.setupMockTypeRegistry([
|
|
214
214
|
["config", { bitmapTypeName: "Config", baseType: "u8" }],
|
|
215
|
-
])
|
|
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
|
-
|
|
239
|
+
HandlerTestUtils.setupMockTypeRegistry([
|
|
240
240
|
["flagsArray", { bitmapTypeName: "StatusFlags", baseType: "u8" }],
|
|
241
|
-
])
|
|
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
|
-
|
|
269
|
+
HandlerTestUtils.setupMockTypeRegistry([
|
|
270
270
|
["device", { baseType: "Device" }],
|
|
271
|
-
])
|
|
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
|
-
|
|
74
|
+
HandlerTestUtils.setupMockTypeRegistry([
|
|
75
75
|
["counter", { baseType: "u32", isAtomic: true }],
|
|
76
|
-
])
|
|
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(
|
|
88
|
-
|
|
89
|
-
|
|
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
|
-
|
|
101
|
+
HandlerTestUtils.setupMockTypeRegistry([
|
|
97
102
|
["Motor_count", { baseType: "u32", isAtomic: true }],
|
|
98
|
-
])
|
|
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(
|
|
114
|
-
|
|
115
|
-
|
|
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
|
-
|
|
131
|
+
HandlerTestUtils.setupMockTypeRegistry([
|
|
122
132
|
["globalCounter", { baseType: "u32", isAtomic: true }],
|
|
123
|
-
])
|
|
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
|
-
|
|
152
|
+
HandlerTestUtils.setupMockTypeRegistry([
|
|
143
153
|
["counter", { baseType: "u32", isAtomic: true }],
|
|
144
|
-
])
|
|
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
|
-
|
|
184
|
+
HandlerTestUtils.setupMockTypeRegistry([
|
|
175
185
|
["saturated", { baseType: "u8", overflowBehavior: "clamp" }],
|
|
176
|
-
])
|
|
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
|
-
|
|
203
|
+
HandlerTestUtils.setupMockTypeRegistry([
|
|
194
204
|
["value", { baseType: "u16", overflowBehavior: "clamp" }],
|
|
195
|
-
])
|
|
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
|
-
|
|
224
|
+
HandlerTestUtils.setupMockTypeRegistry([
|
|
215
225
|
["result", { baseType: "u32", overflowBehavior: "clamp" }],
|
|
216
|
-
])
|
|
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
|
-
|
|
245
|
+
HandlerTestUtils.setupMockTypeRegistry([
|
|
236
246
|
["f", { baseType: "f32", overflowBehavior: "clamp" }],
|
|
237
|
-
])
|
|
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
|
-
|
|
264
|
+
HandlerTestUtils.setupMockTypeRegistry([
|
|
255
265
|
["d", { baseType: "f64", overflowBehavior: "clamp" }],
|
|
256
|
-
])
|
|
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
|
-
|
|
283
|
+
HandlerTestUtils.setupMockTypeRegistry([
|
|
274
284
|
["value", { baseType: "u32", overflowBehavior: "clamp" }],
|
|
275
|
-
])
|
|
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
|
-
|
|
305
|
+
HandlerTestUtils.setupMockTypeRegistry([
|
|
296
306
|
["Motor_speed", { baseType: "u8", overflowBehavior: "clamp" }],
|
|
297
|
-
])
|
|
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
|
-
|
|
326
|
+
HandlerTestUtils.setupMockTypeRegistry([
|
|
317
327
|
["globalValue", { baseType: "i16", overflowBehavior: "clamp" }],
|
|
318
|
-
])
|
|
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
|
|
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
|
-
|
|
151
|
-
|
|
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 =
|
|
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
|
-
|
|
123
|
-
|
|
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
|
-
!
|
|
140
|
+
!isCrossFilePrimitive;
|
|
133
141
|
|
|
134
142
|
return (
|
|
135
143
|
isFloatParam ||
|
|
136
144
|
isEnumParam ||
|
|
137
145
|
isPrimitivePassByValue ||
|
|
138
|
-
|
|
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 =
|
|
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
|
-
?
|
|
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
|
-
?
|
|
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 =
|
|
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 =
|
|
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
|
|
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
|
-
?
|
|
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
|
-
?
|
|
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
|
-
?
|
|
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
|
-
|
|
1257
|
+
_input: IGeneratorInput,
|
|
1255
1258
|
): string => {
|
|
1256
1259
|
const typeInfo = ctx.resolvedIdentifier
|
|
1257
|
-
?
|
|
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
|
-
?
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
1926
|
+
_input: IGeneratorInput,
|
|
1924
1927
|
): TTypeInfo | undefined => {
|
|
1925
1928
|
const identifierToCheck = ctx.resolvedIdentifier || ctx.rootIdentifier;
|
|
1926
1929
|
return identifierToCheck
|
|
1927
|
-
?
|
|
1930
|
+
? CodeGenState.getVariableTypeInfo(identifierToCheck)
|
|
1928
1931
|
: undefined;
|
|
1929
1932
|
};
|
|
1930
1933
|
|