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
|
@@ -38,7 +38,7 @@ describe("StringLengthCounter", () => {
|
|
|
38
38
|
|
|
39
39
|
describe("countExpression", () => {
|
|
40
40
|
it("counts single .length access on string variable", () => {
|
|
41
|
-
CodeGenState.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
50
|
+
return { typeInfo: CodeGenState.getVariableTypeInfo(id) };
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
// Fallback to direct lookup
|
|
54
|
-
return { typeInfo: CodeGenState.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
186
|
+
HandlerTestUtils.setupMockTypeRegistry([
|
|
187
187
|
["matrix", { arrayDimensions: [10, 10], baseType: "i32" }],
|
|
188
|
-
])
|
|
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
|
-
|
|
245
|
+
HandlerTestUtils.setupMockTypeRegistry([
|
|
246
246
|
["buffer", { arrayDimensions: [100], baseType: "u8" }],
|
|
247
|
-
])
|
|
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
|
-
|
|
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
|
-
])
|
|
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
|
-
|
|
302
|
+
HandlerTestUtils.setupMockTypeRegistry([
|
|
303
303
|
["buffer", { arrayDimensions: [100], baseType: "u8" }],
|
|
304
|
-
])
|
|
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
|
-
|
|
326
|
+
HandlerTestUtils.setupMockTypeRegistry([
|
|
327
327
|
["matrix", { arrayDimensions: [10, 10], baseType: "u8" }],
|
|
328
|
-
])
|
|
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
|
-
|
|
343
|
+
HandlerTestUtils.setupMockTypeRegistry([
|
|
344
344
|
["buffer", { arrayDimensions: [100], baseType: "u8" }],
|
|
345
|
-
])
|
|
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
|
-
|
|
362
|
+
HandlerTestUtils.setupMockTypeRegistry([
|
|
363
363
|
["buffer", { arrayDimensions: [100], baseType: "u8" }],
|
|
364
|
-
])
|
|
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
|
-
|
|
384
|
+
HandlerTestUtils.setupMockTypeRegistry([
|
|
385
385
|
["buffer", { arrayDimensions: [50], baseType: "u8" }],
|
|
386
|
-
])
|
|
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
|
-
|
|
407
|
+
HandlerTestUtils.setupMockTypeRegistry([
|
|
408
408
|
["buffer", { arrayDimensions: [100], baseType: "u8" }],
|
|
409
|
-
])
|
|
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
|
-
|
|
430
|
+
HandlerTestUtils.setupMockTypeRegistry([
|
|
431
431
|
["buffer", { arrayDimensions: [100], baseType: "u8" }],
|
|
432
|
-
])
|
|
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
|
-
|
|
453
|
+
HandlerTestUtils.setupMockTypeRegistry([
|
|
454
454
|
["buffer", { arrayDimensions: [100], baseType: "u8" }],
|
|
455
|
-
])
|
|
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
|
-
|
|
477
|
-
["unknown", { baseType: "u8" }],
|
|
478
|
-
]) as any;
|
|
476
|
+
HandlerTestUtils.setupMockTypeRegistry([["unknown", { baseType: "u8" }]]);
|
|
479
477
|
HandlerTestUtils.setupMockGenerator({
|
|
480
478
|
tryEvaluateConstant: vi
|
|
481
479
|
.fn()
|