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
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* qualifiedType, userType) that each had identical enum/bitmap handling.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import
|
|
9
|
+
import CodeGenState from "../../state/CodeGenState";
|
|
10
10
|
import TOverflowBehavior from "./types/TOverflowBehavior";
|
|
11
11
|
|
|
12
12
|
/**
|
|
@@ -40,7 +40,6 @@ class TypeRegistrationUtils {
|
|
|
40
40
|
* Returns true if the type was a known enum and was registered.
|
|
41
41
|
*/
|
|
42
42
|
static tryRegisterEnumType(
|
|
43
|
-
typeRegistry: Map<string, TTypeInfo>,
|
|
44
43
|
symbols: ITypeSymbols,
|
|
45
44
|
options: ITypeRegistrationOptions,
|
|
46
45
|
): boolean {
|
|
@@ -48,7 +47,7 @@ class TypeRegistrationUtils {
|
|
|
48
47
|
return false;
|
|
49
48
|
}
|
|
50
49
|
|
|
51
|
-
|
|
50
|
+
CodeGenState.setVariableTypeInfo(options.name, {
|
|
52
51
|
baseType: options.baseType,
|
|
53
52
|
bitWidth: 0,
|
|
54
53
|
isArray: false,
|
|
@@ -69,7 +68,6 @@ class TypeRegistrationUtils {
|
|
|
69
68
|
* Handles both array and non-array bitmap types.
|
|
70
69
|
*/
|
|
71
70
|
static tryRegisterBitmapType(
|
|
72
|
-
typeRegistry: Map<string, TTypeInfo>,
|
|
73
71
|
symbols: ITypeSymbols,
|
|
74
72
|
options: ITypeRegistrationOptions,
|
|
75
73
|
arrayDimensions: number[] | undefined,
|
|
@@ -82,7 +80,7 @@ class TypeRegistrationUtils {
|
|
|
82
80
|
|
|
83
81
|
if (arrayDimensions && arrayDimensions.length > 0) {
|
|
84
82
|
// Bitmap array
|
|
85
|
-
|
|
83
|
+
CodeGenState.setVariableTypeInfo(options.name, {
|
|
86
84
|
baseType: options.baseType,
|
|
87
85
|
bitWidth,
|
|
88
86
|
isArray: true,
|
|
@@ -95,7 +93,7 @@ class TypeRegistrationUtils {
|
|
|
95
93
|
});
|
|
96
94
|
} else {
|
|
97
95
|
// Non-array bitmap
|
|
98
|
-
|
|
96
|
+
CodeGenState.setVariableTypeInfo(options.name, {
|
|
99
97
|
baseType: options.baseType,
|
|
100
98
|
bitWidth,
|
|
101
99
|
isArray: false,
|
|
@@ -303,7 +303,7 @@ class TypeResolver {
|
|
|
303
303
|
* Look up a variable name in the type registry and return a SuffixResult.
|
|
304
304
|
*/
|
|
305
305
|
private static resolveRegistryLookup(name: string): SuffixResult {
|
|
306
|
-
const typeInfo = CodeGenState.
|
|
306
|
+
const typeInfo = CodeGenState.getVariableTypeInfo(name);
|
|
307
307
|
if (typeInfo) {
|
|
308
308
|
return {
|
|
309
309
|
stop: false,
|
|
@@ -356,7 +356,7 @@ class TypeResolver {
|
|
|
356
356
|
if (id) {
|
|
357
357
|
const name = id.getText();
|
|
358
358
|
const scopedName = CodeGenState.resolveIdentifier(name);
|
|
359
|
-
const typeInfo = CodeGenState.
|
|
359
|
+
const typeInfo = CodeGenState.getVariableTypeInfo(scopedName);
|
|
360
360
|
if (typeInfo) {
|
|
361
361
|
return { baseType: typeInfo.baseType, isArray: typeInfo.isArray };
|
|
362
362
|
}
|
|
@@ -291,7 +291,7 @@ class TypeValidator {
|
|
|
291
291
|
|
|
292
292
|
const scopedName = CodeGenState.resolveIdentifier(identifier);
|
|
293
293
|
|
|
294
|
-
const typeInfo = CodeGenState.
|
|
294
|
+
const typeInfo = CodeGenState.getVariableTypeInfo(scopedName);
|
|
295
295
|
if (typeInfo?.isConst) {
|
|
296
296
|
return `cannot assign to const variable '${identifier}'`;
|
|
297
297
|
}
|
|
@@ -305,7 +305,7 @@ class TypeValidator {
|
|
|
305
305
|
return true;
|
|
306
306
|
}
|
|
307
307
|
|
|
308
|
-
const typeInfo = CodeGenState.
|
|
308
|
+
const typeInfo = CodeGenState.getVariableTypeInfo(identifier);
|
|
309
309
|
if (typeInfo?.isConst) {
|
|
310
310
|
return true;
|
|
311
311
|
}
|
|
@@ -366,7 +366,7 @@ class TypeValidator {
|
|
|
366
366
|
);
|
|
367
367
|
}
|
|
368
368
|
|
|
369
|
-
const typeInfo = CodeGenState.
|
|
369
|
+
const typeInfo = CodeGenState.getVariableTypeInfo(identifier);
|
|
370
370
|
if (typeInfo && !identifier.includes("_")) {
|
|
371
371
|
throw new Error(
|
|
372
372
|
`Error: Use 'global.${identifier}' to access global variable '${identifier}' inside scope '${currentScope}'`,
|
|
@@ -428,7 +428,7 @@ class TypeValidator {
|
|
|
428
428
|
currentScope: string | null,
|
|
429
429
|
isKnownStruct: (name: string) => boolean,
|
|
430
430
|
): boolean {
|
|
431
|
-
const typeInfo = CodeGenState.
|
|
431
|
+
const typeInfo = CodeGenState.getVariableTypeInfo(identifier);
|
|
432
432
|
if (typeInfo && !identifier.includes("_")) {
|
|
433
433
|
return true;
|
|
434
434
|
}
|
|
@@ -790,7 +790,7 @@ class TypeValidator {
|
|
|
790
790
|
return true;
|
|
791
791
|
}
|
|
792
792
|
|
|
793
|
-
const typeInfo = CodeGenState.
|
|
793
|
+
const typeInfo = CodeGenState.getVariableTypeInfo(text);
|
|
794
794
|
if (typeInfo?.baseType === "bool") {
|
|
795
795
|
return true;
|
|
796
796
|
}
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
* Tests the extracted enum/bitmap type registration helpers.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { describe, expect, it } from "vitest";
|
|
6
|
+
import { beforeEach, describe, expect, it } from "vitest";
|
|
7
7
|
import TypeRegistrationUtils from "../TypeRegistrationUtils";
|
|
8
|
-
import
|
|
8
|
+
import CodeGenState from "../../../state/CodeGenState";
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Create mock symbols for testing
|
|
@@ -20,49 +20,43 @@ function createMockSymbols(overrides: Record<string, unknown> = {}) {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
describe("TypeRegistrationUtils", () => {
|
|
23
|
+
beforeEach(() => {
|
|
24
|
+
CodeGenState.reset();
|
|
25
|
+
});
|
|
26
|
+
|
|
23
27
|
describe("tryRegisterEnumType", () => {
|
|
24
28
|
it("returns false if type is not a known enum", () => {
|
|
25
|
-
const typeRegistry = new Map<string, TTypeInfo>();
|
|
26
29
|
const symbols = createMockSymbols();
|
|
27
30
|
|
|
28
|
-
const result = TypeRegistrationUtils.tryRegisterEnumType(
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
overflowBehavior: "clamp",
|
|
36
|
-
isAtomic: false,
|
|
37
|
-
},
|
|
38
|
-
);
|
|
31
|
+
const result = TypeRegistrationUtils.tryRegisterEnumType(symbols, {
|
|
32
|
+
name: "myVar",
|
|
33
|
+
baseType: "UnknownType",
|
|
34
|
+
isConst: false,
|
|
35
|
+
overflowBehavior: "clamp",
|
|
36
|
+
isAtomic: false,
|
|
37
|
+
});
|
|
39
38
|
|
|
40
39
|
expect(result).toBe(false);
|
|
41
|
-
expect(
|
|
40
|
+
expect(CodeGenState.getVariableTypeInfo("myVar")).toBeUndefined();
|
|
42
41
|
});
|
|
43
42
|
|
|
44
43
|
it("registers enum type and returns true", () => {
|
|
45
|
-
const typeRegistry = new Map<string, TTypeInfo>();
|
|
46
44
|
const symbols = createMockSymbols({
|
|
47
45
|
knownEnums: new Set(["MyEnum"]),
|
|
48
46
|
});
|
|
49
47
|
|
|
50
|
-
const result = TypeRegistrationUtils.tryRegisterEnumType(
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
overflowBehavior: "clamp",
|
|
58
|
-
isAtomic: false,
|
|
59
|
-
},
|
|
60
|
-
);
|
|
48
|
+
const result = TypeRegistrationUtils.tryRegisterEnumType(symbols, {
|
|
49
|
+
name: "myVar",
|
|
50
|
+
baseType: "MyEnum",
|
|
51
|
+
isConst: false,
|
|
52
|
+
overflowBehavior: "clamp",
|
|
53
|
+
isAtomic: false,
|
|
54
|
+
});
|
|
61
55
|
|
|
62
56
|
expect(result).toBe(true);
|
|
63
|
-
expect(
|
|
57
|
+
expect(CodeGenState.hasVariableTypeInfo("myVar")).toBe(true);
|
|
64
58
|
|
|
65
|
-
const info =
|
|
59
|
+
const info = CodeGenState.getVariableTypeInfo("myVar")!;
|
|
66
60
|
expect(info.baseType).toBe("MyEnum");
|
|
67
61
|
expect(info.isEnum).toBe(true);
|
|
68
62
|
expect(info.enumTypeName).toBe("MyEnum");
|
|
@@ -70,12 +64,11 @@ describe("TypeRegistrationUtils", () => {
|
|
|
70
64
|
});
|
|
71
65
|
|
|
72
66
|
it("respects isConst flag", () => {
|
|
73
|
-
const typeRegistry = new Map<string, TTypeInfo>();
|
|
74
67
|
const symbols = createMockSymbols({
|
|
75
68
|
knownEnums: new Set(["MyEnum"]),
|
|
76
69
|
});
|
|
77
70
|
|
|
78
|
-
TypeRegistrationUtils.tryRegisterEnumType(
|
|
71
|
+
TypeRegistrationUtils.tryRegisterEnumType(symbols, {
|
|
79
72
|
name: "myVar",
|
|
80
73
|
baseType: "MyEnum",
|
|
81
74
|
isConst: true,
|
|
@@ -83,16 +76,15 @@ describe("TypeRegistrationUtils", () => {
|
|
|
83
76
|
isAtomic: false,
|
|
84
77
|
});
|
|
85
78
|
|
|
86
|
-
expect(
|
|
79
|
+
expect(CodeGenState.getVariableTypeInfo("myVar")!.isConst).toBe(true);
|
|
87
80
|
});
|
|
88
81
|
|
|
89
82
|
it("respects overflowBehavior", () => {
|
|
90
|
-
const typeRegistry = new Map<string, TTypeInfo>();
|
|
91
83
|
const symbols = createMockSymbols({
|
|
92
84
|
knownEnums: new Set(["MyEnum"]),
|
|
93
85
|
});
|
|
94
86
|
|
|
95
|
-
TypeRegistrationUtils.tryRegisterEnumType(
|
|
87
|
+
TypeRegistrationUtils.tryRegisterEnumType(symbols, {
|
|
96
88
|
name: "myVar",
|
|
97
89
|
baseType: "MyEnum",
|
|
98
90
|
isConst: false,
|
|
@@ -100,16 +92,17 @@ describe("TypeRegistrationUtils", () => {
|
|
|
100
92
|
isAtomic: false,
|
|
101
93
|
});
|
|
102
94
|
|
|
103
|
-
expect(
|
|
95
|
+
expect(CodeGenState.getVariableTypeInfo("myVar")!.overflowBehavior).toBe(
|
|
96
|
+
"wrap",
|
|
97
|
+
);
|
|
104
98
|
});
|
|
105
99
|
|
|
106
100
|
it("respects isAtomic flag", () => {
|
|
107
|
-
const typeRegistry = new Map<string, TTypeInfo>();
|
|
108
101
|
const symbols = createMockSymbols({
|
|
109
102
|
knownEnums: new Set(["MyEnum"]),
|
|
110
103
|
});
|
|
111
104
|
|
|
112
|
-
TypeRegistrationUtils.tryRegisterEnumType(
|
|
105
|
+
TypeRegistrationUtils.tryRegisterEnumType(symbols, {
|
|
113
106
|
name: "myVar",
|
|
114
107
|
baseType: "MyEnum",
|
|
115
108
|
isConst: false,
|
|
@@ -117,17 +110,15 @@ describe("TypeRegistrationUtils", () => {
|
|
|
117
110
|
isAtomic: true,
|
|
118
111
|
});
|
|
119
112
|
|
|
120
|
-
expect(
|
|
113
|
+
expect(CodeGenState.getVariableTypeInfo("myVar")!.isAtomic).toBe(true);
|
|
121
114
|
});
|
|
122
115
|
});
|
|
123
116
|
|
|
124
117
|
describe("tryRegisterBitmapType", () => {
|
|
125
118
|
it("returns false if type is not a known bitmap", () => {
|
|
126
|
-
const typeRegistry = new Map<string, TTypeInfo>();
|
|
127
119
|
const symbols = createMockSymbols();
|
|
128
120
|
|
|
129
121
|
const result = TypeRegistrationUtils.tryRegisterBitmapType(
|
|
130
|
-
typeRegistry,
|
|
131
122
|
symbols,
|
|
132
123
|
{
|
|
133
124
|
name: "myVar",
|
|
@@ -140,18 +131,16 @@ describe("TypeRegistrationUtils", () => {
|
|
|
140
131
|
);
|
|
141
132
|
|
|
142
133
|
expect(result).toBe(false);
|
|
143
|
-
expect(
|
|
134
|
+
expect(CodeGenState.getVariableTypeInfo("myVar")).toBeUndefined();
|
|
144
135
|
});
|
|
145
136
|
|
|
146
137
|
it("registers non-array bitmap type", () => {
|
|
147
|
-
const typeRegistry = new Map<string, TTypeInfo>();
|
|
148
138
|
const symbols = createMockSymbols({
|
|
149
139
|
knownBitmaps: new Set(["MyFlags"]),
|
|
150
140
|
bitmapBitWidth: new Map([["MyFlags", 8]]),
|
|
151
141
|
});
|
|
152
142
|
|
|
153
143
|
const result = TypeRegistrationUtils.tryRegisterBitmapType(
|
|
154
|
-
typeRegistry,
|
|
155
144
|
symbols,
|
|
156
145
|
{
|
|
157
146
|
name: "flags",
|
|
@@ -164,9 +153,9 @@ describe("TypeRegistrationUtils", () => {
|
|
|
164
153
|
);
|
|
165
154
|
|
|
166
155
|
expect(result).toBe(true);
|
|
167
|
-
expect(
|
|
156
|
+
expect(CodeGenState.hasVariableTypeInfo("flags")).toBe(true);
|
|
168
157
|
|
|
169
|
-
const info =
|
|
158
|
+
const info = CodeGenState.getVariableTypeInfo("flags")!;
|
|
170
159
|
expect(info.baseType).toBe("MyFlags");
|
|
171
160
|
expect(info.isBitmap).toBe(true);
|
|
172
161
|
expect(info.bitmapTypeName).toBe("MyFlags");
|
|
@@ -175,14 +164,12 @@ describe("TypeRegistrationUtils", () => {
|
|
|
175
164
|
});
|
|
176
165
|
|
|
177
166
|
it("registers bitmap array type with dimensions", () => {
|
|
178
|
-
const typeRegistry = new Map<string, TTypeInfo>();
|
|
179
167
|
const symbols = createMockSymbols({
|
|
180
168
|
knownBitmaps: new Set(["MyFlags"]),
|
|
181
169
|
bitmapBitWidth: new Map([["MyFlags", 16]]),
|
|
182
170
|
});
|
|
183
171
|
|
|
184
172
|
const result = TypeRegistrationUtils.tryRegisterBitmapType(
|
|
185
|
-
typeRegistry,
|
|
186
173
|
symbols,
|
|
187
174
|
{
|
|
188
175
|
name: "flagsArray",
|
|
@@ -196,21 +183,19 @@ describe("TypeRegistrationUtils", () => {
|
|
|
196
183
|
|
|
197
184
|
expect(result).toBe(true);
|
|
198
185
|
|
|
199
|
-
const info =
|
|
186
|
+
const info = CodeGenState.getVariableTypeInfo("flagsArray")!;
|
|
200
187
|
expect(info.isArray).toBe(true);
|
|
201
188
|
expect(info.arrayDimensions).toEqual([10, 5]);
|
|
202
189
|
expect(info.bitWidth).toBe(16);
|
|
203
190
|
});
|
|
204
191
|
|
|
205
192
|
it("defaults bitWidth to 0 if not found", () => {
|
|
206
|
-
const typeRegistry = new Map<string, TTypeInfo>();
|
|
207
193
|
const symbols = createMockSymbols({
|
|
208
194
|
knownBitmaps: new Set(["MyFlags"]),
|
|
209
195
|
// No bitWidth entry
|
|
210
196
|
});
|
|
211
197
|
|
|
212
198
|
TypeRegistrationUtils.tryRegisterBitmapType(
|
|
213
|
-
typeRegistry,
|
|
214
199
|
symbols,
|
|
215
200
|
{
|
|
216
201
|
name: "flags",
|
|
@@ -222,7 +207,7 @@ describe("TypeRegistrationUtils", () => {
|
|
|
222
207
|
undefined,
|
|
223
208
|
);
|
|
224
209
|
|
|
225
|
-
expect(
|
|
210
|
+
expect(CodeGenState.getVariableTypeInfo("flags")!.bitWidth).toBe(0);
|
|
226
211
|
});
|
|
227
212
|
});
|
|
228
213
|
});
|
|
@@ -10,15 +10,18 @@ import TTypeInfo from "../types/TTypeInfo";
|
|
|
10
10
|
|
|
11
11
|
describe("TypeResolver", () => {
|
|
12
12
|
let symbolTable: SymbolTable;
|
|
13
|
-
let typeRegistry: Map<string, TTypeInfo>;
|
|
14
13
|
|
|
15
14
|
beforeEach(() => {
|
|
16
15
|
CodeGenState.reset();
|
|
17
16
|
symbolTable = new SymbolTable();
|
|
18
|
-
typeRegistry = CodeGenState.typeRegistry;
|
|
19
17
|
CodeGenState.symbolTable = symbolTable;
|
|
20
18
|
});
|
|
21
19
|
|
|
20
|
+
/** Helper function to set type info in the registry */
|
|
21
|
+
function setTypeInfo(name: string, info: TTypeInfo): void {
|
|
22
|
+
CodeGenState.setVariableTypeInfo(name, info);
|
|
23
|
+
}
|
|
24
|
+
|
|
22
25
|
// ========================================================================
|
|
23
26
|
// Type Classification Methods
|
|
24
27
|
// ========================================================================
|
|
@@ -400,7 +403,7 @@ describe("TypeResolver", () => {
|
|
|
400
403
|
};
|
|
401
404
|
|
|
402
405
|
it("should return type for identifier in registry", () => {
|
|
403
|
-
|
|
406
|
+
setTypeInfo("myVar", {
|
|
404
407
|
baseType: "u32",
|
|
405
408
|
bitWidth: 32,
|
|
406
409
|
isArray: false,
|
|
@@ -612,7 +615,7 @@ describe("TypeResolver", () => {
|
|
|
612
615
|
});
|
|
613
616
|
|
|
614
617
|
it("should return type from simple identifier", () => {
|
|
615
|
-
|
|
618
|
+
setTypeInfo("counter", {
|
|
616
619
|
baseType: "u32",
|
|
617
620
|
bitWidth: 32,
|
|
618
621
|
isArray: false,
|
|
@@ -651,7 +654,7 @@ describe("TypeResolver", () => {
|
|
|
651
654
|
});
|
|
652
655
|
|
|
653
656
|
it("should return member type for struct member access", () => {
|
|
654
|
-
|
|
657
|
+
setTypeInfo("point", {
|
|
655
658
|
baseType: "Point",
|
|
656
659
|
bitWidth: 0,
|
|
657
660
|
isArray: false,
|
|
@@ -675,7 +678,7 @@ describe("TypeResolver", () => {
|
|
|
675
678
|
});
|
|
676
679
|
|
|
677
680
|
it("should return null for unknown member", () => {
|
|
678
|
-
|
|
681
|
+
setTypeInfo("point", {
|
|
679
682
|
baseType: "Point",
|
|
680
683
|
bitWidth: 0,
|
|
681
684
|
isArray: false,
|
|
@@ -699,7 +702,7 @@ describe("TypeResolver", () => {
|
|
|
699
702
|
});
|
|
700
703
|
|
|
701
704
|
it("should return null for range bit indexing", () => {
|
|
702
|
-
|
|
705
|
+
setTypeInfo("flags", {
|
|
703
706
|
baseType: "u32",
|
|
704
707
|
bitWidth: 32,
|
|
705
708
|
isArray: false,
|
|
@@ -722,7 +725,7 @@ describe("TypeResolver", () => {
|
|
|
722
725
|
});
|
|
723
726
|
|
|
724
727
|
it("should return bool for single bit indexing on integer", () => {
|
|
725
|
-
|
|
728
|
+
setTypeInfo("flags", {
|
|
726
729
|
baseType: "u32",
|
|
727
730
|
bitWidth: 32,
|
|
728
731
|
isArray: false,
|
|
@@ -745,7 +748,7 @@ describe("TypeResolver", () => {
|
|
|
745
748
|
});
|
|
746
749
|
|
|
747
750
|
it("should return element type for struct array member indexing", () => {
|
|
748
|
-
|
|
751
|
+
setTypeInfo("data", {
|
|
749
752
|
baseType: "Data",
|
|
750
753
|
bitWidth: 0,
|
|
751
754
|
isArray: false,
|
|
@@ -774,7 +777,7 @@ describe("TypeResolver", () => {
|
|
|
774
777
|
});
|
|
775
778
|
|
|
776
779
|
it("should return element type for direct array variable indexing", () => {
|
|
777
|
-
|
|
780
|
+
setTypeInfo("arr", {
|
|
778
781
|
baseType: "u8",
|
|
779
782
|
bitWidth: 8,
|
|
780
783
|
isArray: true,
|
|
@@ -798,7 +801,7 @@ describe("TypeResolver", () => {
|
|
|
798
801
|
});
|
|
799
802
|
|
|
800
803
|
it("should return bool for bit indexing on plain integer variable", () => {
|
|
801
|
-
|
|
804
|
+
setTypeInfo("val", {
|
|
802
805
|
baseType: "u8",
|
|
803
806
|
bitWidth: 8,
|
|
804
807
|
isArray: false,
|
|
@@ -828,7 +831,7 @@ describe("TypeResolver", () => {
|
|
|
828
831
|
|
|
829
832
|
describe("getPostfixExpressionType with global/this", () => {
|
|
830
833
|
it("should resolve global.structVar.field type", () => {
|
|
831
|
-
|
|
834
|
+
setTypeInfo("config", {
|
|
832
835
|
baseType: "TConfig",
|
|
833
836
|
bitWidth: 0,
|
|
834
837
|
isArray: false,
|
|
@@ -858,7 +861,7 @@ describe("TypeResolver", () => {
|
|
|
858
861
|
});
|
|
859
862
|
|
|
860
863
|
it("should resolve global.arrayVar[0] element type", () => {
|
|
861
|
-
|
|
864
|
+
setTypeInfo("inputs", {
|
|
862
865
|
baseType: "TInput",
|
|
863
866
|
bitWidth: 0,
|
|
864
867
|
isArray: true,
|
|
@@ -888,7 +891,7 @@ describe("TypeResolver", () => {
|
|
|
888
891
|
|
|
889
892
|
it("should resolve this.scopeVar type", () => {
|
|
890
893
|
CodeGenState.currentScope = "Motor";
|
|
891
|
-
|
|
894
|
+
setTypeInfo("Motor_speed", {
|
|
892
895
|
baseType: "u32",
|
|
893
896
|
bitWidth: 32,
|
|
894
897
|
isArray: false,
|
|
@@ -951,7 +954,7 @@ describe("TypeResolver", () => {
|
|
|
951
954
|
});
|
|
952
955
|
|
|
953
956
|
it("should resolve global.struct.enumField for enum type", () => {
|
|
954
|
-
|
|
957
|
+
setTypeInfo("input", {
|
|
955
958
|
baseType: "TInput",
|
|
956
959
|
bitWidth: 0,
|
|
957
960
|
isArray: false,
|
|
@@ -987,7 +990,7 @@ describe("TypeResolver", () => {
|
|
|
987
990
|
|
|
988
991
|
describe("getUnaryExpressionType", () => {
|
|
989
992
|
it("should return type from postfix expression", () => {
|
|
990
|
-
|
|
993
|
+
setTypeInfo("value", {
|
|
991
994
|
baseType: "i32",
|
|
992
995
|
bitWidth: 32,
|
|
993
996
|
isArray: false,
|
|
@@ -1020,7 +1023,7 @@ describe("TypeResolver", () => {
|
|
|
1020
1023
|
});
|
|
1021
1024
|
|
|
1022
1025
|
it("should recurse through unary expression chain", () => {
|
|
1023
|
-
|
|
1026
|
+
setTypeInfo("x", {
|
|
1024
1027
|
baseType: "i32",
|
|
1025
1028
|
bitWidth: 32,
|
|
1026
1029
|
isArray: false,
|
|
@@ -39,13 +39,13 @@ describe("TypeValidator.resolveBareIdentifier", () => {
|
|
|
39
39
|
beforeEach(() => {
|
|
40
40
|
CodeGenState.reset();
|
|
41
41
|
CodeGenState.setScopeMembers("Motor", new Set(["speed", "maxSpeed"]));
|
|
42
|
-
CodeGenState.
|
|
42
|
+
CodeGenState.setVariableTypeInfo("globalCounter", {
|
|
43
43
|
baseType: "u32",
|
|
44
44
|
bitWidth: 32,
|
|
45
45
|
isArray: false,
|
|
46
46
|
isConst: false,
|
|
47
47
|
});
|
|
48
|
-
CodeGenState.
|
|
48
|
+
CodeGenState.setVariableTypeInfo("Motor_speed", {
|
|
49
49
|
baseType: "u32",
|
|
50
50
|
bitWidth: 32,
|
|
51
51
|
isArray: false,
|
|
@@ -146,7 +146,7 @@ describe("TypeValidator.resolveBareIdentifier", () => {
|
|
|
146
146
|
describe("resolveForMemberAccess", () => {
|
|
147
147
|
it("prefers scope name over global variable for member access", () => {
|
|
148
148
|
// Setup: global variable 'LED' exists AND scope 'LED' exists
|
|
149
|
-
CodeGenState.
|
|
149
|
+
CodeGenState.setVariableTypeInfo("LED", {
|
|
150
150
|
baseType: "u8",
|
|
151
151
|
bitWidth: 8,
|
|
152
152
|
isArray: false,
|
|
@@ -74,7 +74,7 @@ function setupState(options: SetupStateOptions = {}): void {
|
|
|
74
74
|
}
|
|
75
75
|
if (options.typeRegistry) {
|
|
76
76
|
for (const [k, v] of options.typeRegistry) {
|
|
77
|
-
CodeGenState.
|
|
77
|
+
CodeGenState.setVariableTypeInfo(k, v);
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
80
|
if (options.callbackTypes) {
|
|
@@ -127,7 +127,7 @@ class MemberChainAnalyzer {
|
|
|
127
127
|
ops: Parser.PostfixTargetOpContext[],
|
|
128
128
|
_subscriptsSoFar: number,
|
|
129
129
|
): { type: string; isArray: boolean } | undefined {
|
|
130
|
-
const baseTypeInfo = CodeGenState.
|
|
130
|
+
const baseTypeInfo = CodeGenState.getVariableTypeInfo(baseId);
|
|
131
131
|
if (!baseTypeInfo) {
|
|
132
132
|
return undefined;
|
|
133
133
|
}
|
|
@@ -193,7 +193,7 @@ class StringLengthCounter {
|
|
|
193
193
|
const memberName = op.IDENTIFIER()?.getText();
|
|
194
194
|
if (memberName === "length") {
|
|
195
195
|
// Check if this is a string type
|
|
196
|
-
const typeInfo = CodeGenState.
|
|
196
|
+
const typeInfo = CodeGenState.getVariableTypeInfo(primaryId);
|
|
197
197
|
if (typeInfo?.isString) {
|
|
198
198
|
const currentCount = counts.get(primaryId) || 0;
|
|
199
199
|
counts.set(primaryId, currentCount + 1);
|
|
@@ -139,7 +139,7 @@ describe("MemberChainAnalyzer", () => {
|
|
|
139
139
|
|
|
140
140
|
it("returns isBitAccess false when last op is member access", () => {
|
|
141
141
|
// point.flags (no subscript at end)
|
|
142
|
-
CodeGenState.
|
|
142
|
+
CodeGenState.setVariableTypeInfo("point", {
|
|
143
143
|
baseType: "Point",
|
|
144
144
|
bitWidth: 0,
|
|
145
145
|
isArray: false,
|
|
@@ -159,7 +159,7 @@ describe("MemberChainAnalyzer", () => {
|
|
|
159
159
|
|
|
160
160
|
it("returns isBitAccess false when last subscript has 2 expressions (bit range)", () => {
|
|
161
161
|
// flags[0, 8] - bit range, not single bit access
|
|
162
|
-
CodeGenState.
|
|
162
|
+
CodeGenState.setVariableTypeInfo("flags", {
|
|
163
163
|
baseType: "u32",
|
|
164
164
|
bitWidth: 32,
|
|
165
165
|
isArray: false,
|
|
@@ -180,7 +180,7 @@ describe("MemberChainAnalyzer", () => {
|
|
|
180
180
|
pointFields.set("flags", "u8");
|
|
181
181
|
setupStructFields("Point", pointFields);
|
|
182
182
|
|
|
183
|
-
CodeGenState.
|
|
183
|
+
CodeGenState.setVariableTypeInfo("point", {
|
|
184
184
|
baseType: "Point",
|
|
185
185
|
bitWidth: 0,
|
|
186
186
|
isArray: false,
|
|
@@ -209,7 +209,7 @@ describe("MemberChainAnalyzer", () => {
|
|
|
209
209
|
gridFields.set("items", "u8");
|
|
210
210
|
setupStructFields("Grid", gridFields, new Set(["items"]));
|
|
211
211
|
|
|
212
|
-
CodeGenState.
|
|
212
|
+
CodeGenState.setVariableTypeInfo("grid", {
|
|
213
213
|
baseType: "Grid",
|
|
214
214
|
bitWidth: 0,
|
|
215
215
|
isArray: false,
|
|
@@ -236,7 +236,7 @@ describe("MemberChainAnalyzer", () => {
|
|
|
236
236
|
pointFields.set("name", "string");
|
|
237
237
|
setupStructFields("Point", pointFields);
|
|
238
238
|
|
|
239
|
-
CodeGenState.
|
|
239
|
+
CodeGenState.setVariableTypeInfo("point", {
|
|
240
240
|
baseType: "Point",
|
|
241
241
|
bitWidth: 0,
|
|
242
242
|
isArray: false,
|
|
@@ -263,7 +263,7 @@ describe("MemberChainAnalyzer", () => {
|
|
|
263
263
|
deviceFields.set("flags", "u8");
|
|
264
264
|
setupStructFields("Device", deviceFields);
|
|
265
265
|
|
|
266
|
-
CodeGenState.
|
|
266
|
+
CodeGenState.setVariableTypeInfo("devices", {
|
|
267
267
|
baseType: "Device",
|
|
268
268
|
bitWidth: 0,
|
|
269
269
|
isArray: true,
|
|
@@ -290,7 +290,7 @@ describe("MemberChainAnalyzer", () => {
|
|
|
290
290
|
|
|
291
291
|
it("returns false for 2D array element: matrix[0][1]", () => {
|
|
292
292
|
// matrix[0][1] is array access, not bit access
|
|
293
|
-
CodeGenState.
|
|
293
|
+
CodeGenState.setVariableTypeInfo("matrix", {
|
|
294
294
|
baseType: "u8",
|
|
295
295
|
bitWidth: 8,
|
|
296
296
|
isArray: true,
|
|
@@ -315,7 +315,7 @@ describe("MemberChainAnalyzer", () => {
|
|
|
315
315
|
it("detects bit access on 2D array element: matrix[0][1][3]", () => {
|
|
316
316
|
// matrix[0][1][3] where matrix is u8[4][4]
|
|
317
317
|
// The third subscript [3] is bit access on the u8 element
|
|
318
|
-
CodeGenState.
|
|
318
|
+
CodeGenState.setVariableTypeInfo("matrix", {
|
|
319
319
|
baseType: "u8",
|
|
320
320
|
bitWidth: 8,
|
|
321
321
|
isArray: true,
|
|
@@ -357,7 +357,7 @@ describe("MemberChainAnalyzer", () => {
|
|
|
357
357
|
|
|
358
358
|
it("returns false for member access on non-struct", () => {
|
|
359
359
|
// x.field[0] where x is a primitive
|
|
360
|
-
CodeGenState.
|
|
360
|
+
CodeGenState.setVariableTypeInfo("x", {
|
|
361
361
|
baseType: "u32",
|
|
362
362
|
bitWidth: 32,
|
|
363
363
|
isArray: false,
|