c-next 0.1.62 → 0.1.63
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/README.md +86 -63
- package/package.json +1 -1
- package/src/transpiler/Transpiler.ts +3 -2
- package/src/transpiler/__tests__/DualCodePaths.test.ts +1 -1
- package/src/transpiler/__tests__/Transpiler.coverage.test.ts +1 -1
- package/src/transpiler/__tests__/Transpiler.test.ts +0 -23
- package/src/transpiler/logic/symbols/cnext/collectors/StructCollector.ts +156 -70
- package/src/transpiler/logic/symbols/cnext/collectors/VariableCollector.ts +31 -6
- package/src/transpiler/logic/symbols/cnext/utils/TypeUtils.ts +43 -11
- package/src/transpiler/output/codegen/CodeGenState.ts +811 -0
- package/src/transpiler/output/codegen/CodeGenerator.ts +817 -1377
- package/src/transpiler/output/codegen/TypeResolver.ts +193 -149
- package/src/transpiler/output/codegen/TypeValidator.ts +148 -370
- package/src/transpiler/output/codegen/__tests__/CodeGenState.test.ts +446 -0
- package/src/transpiler/output/codegen/__tests__/CodeGenerator.test.ts +326 -60
- package/src/transpiler/output/codegen/__tests__/TrackVariableTypeHelpers.test.ts +1 -1
- package/src/transpiler/output/codegen/__tests__/TypeResolver.test.ts +435 -196
- package/src/transpiler/output/codegen/__tests__/TypeValidator.resolution.test.ts +51 -67
- package/src/transpiler/output/codegen/__tests__/TypeValidator.test.ts +495 -471
- package/src/transpiler/output/codegen/analysis/MemberChainAnalyzer.ts +39 -43
- package/src/transpiler/output/codegen/analysis/StringLengthCounter.ts +52 -55
- package/src/transpiler/output/codegen/analysis/__tests__/MemberChainAnalyzer.test.ts +122 -62
- package/src/transpiler/output/codegen/analysis/__tests__/StringLengthCounter.test.ts +101 -144
- package/src/transpiler/output/codegen/assignment/AssignmentClassifier.ts +143 -126
- package/src/transpiler/output/codegen/assignment/__tests__/AssignmentClassifier.test.ts +287 -320
- package/src/transpiler/output/codegen/generators/GeneratorRegistry.ts +12 -0
- package/src/transpiler/output/codegen/generators/__tests__/GeneratorRegistry.test.ts +28 -1
- package/src/transpiler/output/codegen/generators/declarationGenerators/ArrayDimensionUtils.ts +67 -0
- package/src/transpiler/output/codegen/generators/declarationGenerators/ScopeGenerator.ts +121 -51
- package/src/transpiler/output/codegen/generators/declarationGenerators/StructGenerator.ts +100 -23
- package/src/transpiler/output/codegen/generators/declarationGenerators/__tests__/ArrayDimensionUtils.test.ts +125 -0
- package/src/transpiler/output/codegen/generators/declarationGenerators/__tests__/ScopeGenerator.test.ts +157 -4
- package/src/transpiler/output/codegen/generators/support/HelperGenerator.ts +23 -22
- package/src/transpiler/output/codegen/helpers/ArrayInitHelper.ts +54 -61
- package/src/transpiler/output/codegen/helpers/AssignmentExpectedTypeResolver.ts +21 -30
- package/src/transpiler/output/codegen/helpers/AssignmentValidator.ts +56 -53
- package/src/transpiler/output/codegen/helpers/CppModeHelper.ts +22 -30
- package/src/transpiler/output/codegen/helpers/EnumAssignmentValidator.ts +108 -50
- package/src/transpiler/output/codegen/helpers/FloatBitHelper.ts +16 -31
- package/src/transpiler/output/codegen/helpers/StringDeclHelper.ts +103 -96
- package/src/transpiler/output/codegen/helpers/TypeGenerationHelper.ts +9 -0
- package/src/transpiler/output/codegen/helpers/__tests__/ArrayInitHelper.test.ts +58 -103
- package/src/transpiler/output/codegen/helpers/__tests__/AssignmentExpectedTypeResolver.test.ts +97 -40
- package/src/transpiler/output/codegen/helpers/__tests__/AssignmentValidator.test.ts +223 -128
- package/src/transpiler/output/codegen/helpers/__tests__/CppModeHelper.test.ts +68 -41
- package/src/transpiler/output/codegen/helpers/__tests__/EnumAssignmentValidator.test.ts +198 -47
- package/src/transpiler/output/codegen/helpers/__tests__/FloatBitHelper.test.ts +39 -37
- package/src/transpiler/output/codegen/helpers/__tests__/StringDeclHelper.test.ts +191 -453
- package/src/transpiler/output/codegen/resolution/EnumTypeResolver.ts +229 -0
- package/src/transpiler/output/codegen/resolution/ScopeResolver.ts +60 -0
- package/src/transpiler/output/codegen/resolution/SizeofResolver.ts +177 -0
- package/src/transpiler/output/codegen/resolution/__tests__/EnumTypeResolver.test.ts +336 -0
- package/src/transpiler/output/codegen/resolution/__tests__/SizeofResolver.test.ts +201 -0
- package/src/transpiler/output/codegen/types/ITypeResolverDeps.ts +0 -23
- package/src/transpiler/output/codegen/types/ITypeValidatorDeps.ts +0 -53
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
2
2
|
import AssignmentValidator from "../AssignmentValidator.js";
|
|
3
|
+
import TypeValidator from "../../TypeValidator.js";
|
|
4
|
+
import EnumAssignmentValidator from "../EnumAssignmentValidator.js";
|
|
3
5
|
import CNextSourceParser from "../../../../logic/parser/CNextSourceParser.js";
|
|
6
|
+
import CodeGenState from "../../CodeGenState.js";
|
|
4
7
|
|
|
5
8
|
/**
|
|
6
9
|
* Create a mock assignment target context by parsing a minimal assignment statement.
|
|
@@ -19,96 +22,126 @@ function parseAssignment(target: string) {
|
|
|
19
22
|
};
|
|
20
23
|
}
|
|
21
24
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
25
|
+
/**
|
|
26
|
+
* Default callbacks for testing.
|
|
27
|
+
*/
|
|
28
|
+
const defaultCallbacks = {
|
|
29
|
+
getExpressionType: () => null,
|
|
30
|
+
tryEvaluateConstant: () => undefined,
|
|
31
|
+
isCallbackTypeUsedAsFieldType: () => false,
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Helper to set up CodeGenState.symbols with minimal fields.
|
|
36
|
+
*/
|
|
37
|
+
function setupSymbols(
|
|
38
|
+
overrides: {
|
|
39
|
+
registerMemberAccess?: Map<string, string>;
|
|
40
|
+
} = {},
|
|
41
|
+
): void {
|
|
42
|
+
CodeGenState.symbols = {
|
|
43
|
+
knownScopes: new Set(),
|
|
44
|
+
knownStructs: new Set(),
|
|
45
|
+
knownRegisters: new Set(),
|
|
46
|
+
knownEnums: new Set(),
|
|
47
|
+
knownBitmaps: new Set(),
|
|
48
|
+
scopeMembers: new Map(),
|
|
49
|
+
scopeMemberVisibility: new Map(),
|
|
50
|
+
structFields: new Map(),
|
|
51
|
+
structFieldArrays: new Map(),
|
|
52
|
+
structFieldDimensions: new Map(),
|
|
53
|
+
enumMembers: new Map(),
|
|
54
|
+
bitmapFields: new Map(),
|
|
55
|
+
bitmapBackingType: new Map(),
|
|
56
|
+
bitmapBitWidth: new Map(),
|
|
57
|
+
scopedRegisters: new Map(),
|
|
58
|
+
registerMemberAccess: overrides.registerMemberAccess ?? new Map(),
|
|
59
|
+
registerMemberTypes: new Map(),
|
|
60
|
+
registerBaseAddresses: new Map(),
|
|
61
|
+
registerMemberOffsets: new Map(),
|
|
62
|
+
registerMemberCTypes: new Map(),
|
|
63
|
+
scopeVariableUsage: new Map(),
|
|
64
|
+
scopePrivateConstValues: new Map(),
|
|
65
|
+
functionReturnTypes: new Map(),
|
|
66
|
+
getSingleFunctionForVariable: () => null,
|
|
67
|
+
hasPublicSymbols: () => false,
|
|
31
68
|
};
|
|
32
|
-
|
|
33
|
-
string,
|
|
34
|
-
{
|
|
35
|
-
baseType: string;
|
|
36
|
-
bitWidth: number;
|
|
37
|
-
isArray: boolean;
|
|
38
|
-
isConst: boolean;
|
|
39
|
-
isEnum?: boolean;
|
|
40
|
-
enumTypeName?: string;
|
|
41
|
-
arrayDimensions?: number[];
|
|
42
|
-
}
|
|
43
|
-
>;
|
|
44
|
-
let floatShadowCurrent: Set<string>;
|
|
45
|
-
let registerMemberAccess: Map<string, string>;
|
|
46
|
-
let callbackFieldTypes: Map<string, string>;
|
|
47
|
-
let validator: AssignmentValidator;
|
|
69
|
+
}
|
|
48
70
|
|
|
71
|
+
describe("AssignmentValidator", () => {
|
|
49
72
|
beforeEach(() => {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
registerMemberAccess,
|
|
70
|
-
callbackFieldTypes,
|
|
71
|
-
isKnownStruct: () => false,
|
|
72
|
-
isIntegerType: (t) => t.startsWith("u") || t.startsWith("i"),
|
|
73
|
-
getExpressionType: () => null,
|
|
74
|
-
tryEvaluateConstant: () => undefined,
|
|
75
|
-
isCallbackTypeUsedAsFieldType: () => false,
|
|
76
|
-
});
|
|
73
|
+
vi.spyOn(TypeValidator, "checkConstAssignment").mockReturnValue(null);
|
|
74
|
+
vi.spyOn(TypeValidator, "checkArrayBounds").mockImplementation(() => {});
|
|
75
|
+
vi.spyOn(TypeValidator, "validateIntegerAssignment").mockImplementation(
|
|
76
|
+
() => {},
|
|
77
|
+
);
|
|
78
|
+
vi.spyOn(TypeValidator, "validateCallbackAssignment").mockImplementation(
|
|
79
|
+
() => {},
|
|
80
|
+
);
|
|
81
|
+
vi.spyOn(
|
|
82
|
+
EnumAssignmentValidator,
|
|
83
|
+
"validateEnumAssignment",
|
|
84
|
+
).mockImplementation(() => {});
|
|
85
|
+
|
|
86
|
+
CodeGenState.reset();
|
|
87
|
+
setupSymbols();
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
afterEach(() => {
|
|
91
|
+
vi.restoreAllMocks();
|
|
77
92
|
});
|
|
78
93
|
|
|
79
94
|
describe("validate() - simple identifier", () => {
|
|
80
95
|
it("should check const assignment for simple identifier", () => {
|
|
81
96
|
const { target, expression } = parseAssignment("counter");
|
|
82
97
|
|
|
83
|
-
|
|
98
|
+
AssignmentValidator.validate(
|
|
99
|
+
target,
|
|
100
|
+
expression,
|
|
101
|
+
false,
|
|
102
|
+
1,
|
|
103
|
+
defaultCallbacks,
|
|
104
|
+
);
|
|
84
105
|
|
|
85
|
-
expect(
|
|
106
|
+
expect(TypeValidator.checkConstAssignment).toHaveBeenCalledWith(
|
|
86
107
|
"counter",
|
|
87
108
|
);
|
|
88
109
|
});
|
|
89
110
|
|
|
90
111
|
it("should throw when assigning to const variable", () => {
|
|
91
|
-
|
|
112
|
+
vi.mocked(TypeValidator.checkConstAssignment).mockReturnValue(
|
|
92
113
|
"cannot assign to const variable 'x'",
|
|
93
114
|
);
|
|
94
115
|
const { target, expression } = parseAssignment("x");
|
|
95
116
|
|
|
96
|
-
expect(() =>
|
|
97
|
-
|
|
98
|
-
|
|
117
|
+
expect(() =>
|
|
118
|
+
AssignmentValidator.validate(
|
|
119
|
+
target,
|
|
120
|
+
expression,
|
|
121
|
+
false,
|
|
122
|
+
1,
|
|
123
|
+
defaultCallbacks,
|
|
124
|
+
),
|
|
125
|
+
).toThrow("cannot assign to const variable 'x'");
|
|
99
126
|
});
|
|
100
127
|
|
|
101
128
|
it("should invalidate float shadow on assignment", () => {
|
|
102
|
-
floatShadowCurrent.add("__bits_myFloat");
|
|
129
|
+
CodeGenState.floatShadowCurrent.add("__bits_myFloat");
|
|
103
130
|
const { target, expression } = parseAssignment("myFloat");
|
|
104
131
|
|
|
105
|
-
|
|
132
|
+
AssignmentValidator.validate(
|
|
133
|
+
target,
|
|
134
|
+
expression,
|
|
135
|
+
false,
|
|
136
|
+
1,
|
|
137
|
+
defaultCallbacks,
|
|
138
|
+
);
|
|
106
139
|
|
|
107
|
-
expect(floatShadowCurrent.has("__bits_myFloat")).toBe(false);
|
|
140
|
+
expect(CodeGenState.floatShadowCurrent.has("__bits_myFloat")).toBe(false);
|
|
108
141
|
});
|
|
109
142
|
|
|
110
143
|
it("should validate enum assignment for enum-typed variable", () => {
|
|
111
|
-
typeRegistry.set("status", {
|
|
144
|
+
CodeGenState.typeRegistry.set("status", {
|
|
112
145
|
baseType: "Status",
|
|
113
146
|
bitWidth: 8,
|
|
114
147
|
isArray: false,
|
|
@@ -118,16 +151,21 @@ describe("AssignmentValidator", () => {
|
|
|
118
151
|
});
|
|
119
152
|
const { target, expression } = parseAssignment("status");
|
|
120
153
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
expect(mockEnumValidator.validateEnumAssignment).toHaveBeenCalledWith(
|
|
124
|
-
"Status",
|
|
154
|
+
AssignmentValidator.validate(
|
|
155
|
+
target,
|
|
125
156
|
expression,
|
|
157
|
+
false,
|
|
158
|
+
1,
|
|
159
|
+
defaultCallbacks,
|
|
126
160
|
);
|
|
161
|
+
|
|
162
|
+
expect(
|
|
163
|
+
EnumAssignmentValidator.validateEnumAssignment,
|
|
164
|
+
).toHaveBeenCalledWith("Status", expression);
|
|
127
165
|
});
|
|
128
166
|
|
|
129
167
|
it("should validate integer assignment for integer-typed variable", () => {
|
|
130
|
-
typeRegistry.set("counter", {
|
|
168
|
+
CodeGenState.typeRegistry.set("counter", {
|
|
131
169
|
baseType: "u32",
|
|
132
170
|
bitWidth: 32,
|
|
133
171
|
isArray: false,
|
|
@@ -135,9 +173,15 @@ describe("AssignmentValidator", () => {
|
|
|
135
173
|
});
|
|
136
174
|
const { target, expression } = parseAssignment("counter");
|
|
137
175
|
|
|
138
|
-
|
|
176
|
+
AssignmentValidator.validate(
|
|
177
|
+
target,
|
|
178
|
+
expression,
|
|
179
|
+
false,
|
|
180
|
+
1,
|
|
181
|
+
defaultCallbacks,
|
|
182
|
+
);
|
|
139
183
|
|
|
140
|
-
expect(
|
|
184
|
+
expect(TypeValidator.validateIntegerAssignment).toHaveBeenCalledWith(
|
|
141
185
|
"u32",
|
|
142
186
|
expect.any(String),
|
|
143
187
|
null,
|
|
@@ -146,7 +190,7 @@ describe("AssignmentValidator", () => {
|
|
|
146
190
|
});
|
|
147
191
|
|
|
148
192
|
it("should pass isCompound flag to integer validation", () => {
|
|
149
|
-
typeRegistry.set("counter", {
|
|
193
|
+
CodeGenState.typeRegistry.set("counter", {
|
|
150
194
|
baseType: "u32",
|
|
151
195
|
bitWidth: 32,
|
|
152
196
|
isArray: false,
|
|
@@ -154,9 +198,15 @@ describe("AssignmentValidator", () => {
|
|
|
154
198
|
});
|
|
155
199
|
const { target, expression } = parseAssignment("counter");
|
|
156
200
|
|
|
157
|
-
|
|
201
|
+
AssignmentValidator.validate(
|
|
202
|
+
target,
|
|
203
|
+
expression,
|
|
204
|
+
true,
|
|
205
|
+
1,
|
|
206
|
+
defaultCallbacks,
|
|
207
|
+
);
|
|
158
208
|
|
|
159
|
-
expect(
|
|
209
|
+
expect(TypeValidator.validateIntegerAssignment).toHaveBeenCalledWith(
|
|
160
210
|
"u32",
|
|
161
211
|
expect.any(String),
|
|
162
212
|
null,
|
|
@@ -165,37 +215,53 @@ describe("AssignmentValidator", () => {
|
|
|
165
215
|
});
|
|
166
216
|
|
|
167
217
|
it("should rethrow validation error with line:column prefix", () => {
|
|
168
|
-
typeRegistry.set("counter", {
|
|
218
|
+
CodeGenState.typeRegistry.set("counter", {
|
|
169
219
|
baseType: "u8",
|
|
170
220
|
bitWidth: 8,
|
|
171
221
|
isArray: false,
|
|
172
222
|
isConst: false,
|
|
173
223
|
});
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
224
|
+
vi.mocked(TypeValidator.validateIntegerAssignment).mockImplementation(
|
|
225
|
+
() => {
|
|
226
|
+
throw new Error("Error: Cannot assign u32 to u8 (narrowing)");
|
|
227
|
+
},
|
|
228
|
+
);
|
|
177
229
|
const { target, expression } = parseAssignment("counter");
|
|
178
230
|
|
|
179
|
-
expect(() =>
|
|
180
|
-
|
|
181
|
-
|
|
231
|
+
expect(() =>
|
|
232
|
+
AssignmentValidator.validate(
|
|
233
|
+
target,
|
|
234
|
+
expression,
|
|
235
|
+
false,
|
|
236
|
+
1,
|
|
237
|
+
defaultCallbacks,
|
|
238
|
+
),
|
|
239
|
+
).toThrow(/^\d+:\d+ Error: Cannot assign u32 to u8 \(narrowing\)/);
|
|
182
240
|
});
|
|
183
241
|
|
|
184
242
|
it("should handle non-Error validation exceptions", () => {
|
|
185
|
-
typeRegistry.set("counter", {
|
|
243
|
+
CodeGenState.typeRegistry.set("counter", {
|
|
186
244
|
baseType: "u8",
|
|
187
245
|
bitWidth: 8,
|
|
188
246
|
isArray: false,
|
|
189
247
|
isConst: false,
|
|
190
248
|
});
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
249
|
+
vi.mocked(TypeValidator.validateIntegerAssignment).mockImplementation(
|
|
250
|
+
() => {
|
|
251
|
+
throw "string error";
|
|
252
|
+
},
|
|
253
|
+
);
|
|
194
254
|
const { target, expression } = parseAssignment("counter");
|
|
195
255
|
|
|
196
|
-
expect(() =>
|
|
197
|
-
|
|
198
|
-
|
|
256
|
+
expect(() =>
|
|
257
|
+
AssignmentValidator.validate(
|
|
258
|
+
target,
|
|
259
|
+
expression,
|
|
260
|
+
false,
|
|
261
|
+
1,
|
|
262
|
+
defaultCallbacks,
|
|
263
|
+
),
|
|
264
|
+
).toThrow(/^\d+:\d+ string error/);
|
|
199
265
|
});
|
|
200
266
|
});
|
|
201
267
|
|
|
@@ -203,26 +269,36 @@ describe("AssignmentValidator", () => {
|
|
|
203
269
|
it("should check const assignment for array", () => {
|
|
204
270
|
const { target, expression } = parseAssignment("arr[0]");
|
|
205
271
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
272
|
+
AssignmentValidator.validate(
|
|
273
|
+
target,
|
|
274
|
+
expression,
|
|
275
|
+
false,
|
|
276
|
+
1,
|
|
277
|
+
defaultCallbacks,
|
|
210
278
|
);
|
|
279
|
+
|
|
280
|
+
expect(TypeValidator.checkConstAssignment).toHaveBeenCalledWith("arr");
|
|
211
281
|
});
|
|
212
282
|
|
|
213
283
|
it("should throw with 'array element' suffix for const array", () => {
|
|
214
|
-
|
|
284
|
+
vi.mocked(TypeValidator.checkConstAssignment).mockReturnValue(
|
|
215
285
|
"cannot assign to const variable 'arr'",
|
|
216
286
|
);
|
|
217
287
|
const { target, expression } = parseAssignment("arr[0]");
|
|
218
288
|
|
|
219
|
-
expect(() =>
|
|
220
|
-
|
|
221
|
-
|
|
289
|
+
expect(() =>
|
|
290
|
+
AssignmentValidator.validate(
|
|
291
|
+
target,
|
|
292
|
+
expression,
|
|
293
|
+
false,
|
|
294
|
+
1,
|
|
295
|
+
defaultCallbacks,
|
|
296
|
+
),
|
|
297
|
+
).toThrow("cannot assign to const variable 'arr' (array element)");
|
|
222
298
|
});
|
|
223
299
|
|
|
224
300
|
it("should check array bounds for array with dimensions", () => {
|
|
225
|
-
typeRegistry.set("arr", {
|
|
301
|
+
CodeGenState.typeRegistry.set("arr", {
|
|
226
302
|
baseType: "u8",
|
|
227
303
|
bitWidth: 8,
|
|
228
304
|
isConst: false,
|
|
@@ -231,9 +307,15 @@ describe("AssignmentValidator", () => {
|
|
|
231
307
|
});
|
|
232
308
|
const { target, expression } = parseAssignment("arr[0]");
|
|
233
309
|
|
|
234
|
-
|
|
310
|
+
AssignmentValidator.validate(
|
|
311
|
+
target,
|
|
312
|
+
expression,
|
|
313
|
+
false,
|
|
314
|
+
5,
|
|
315
|
+
defaultCallbacks,
|
|
316
|
+
);
|
|
235
317
|
|
|
236
|
-
expect(
|
|
318
|
+
expect(TypeValidator.checkArrayBounds).toHaveBeenCalledWith(
|
|
237
319
|
"arr",
|
|
238
320
|
[10],
|
|
239
321
|
expect.anything(),
|
|
@@ -247,61 +329,74 @@ describe("AssignmentValidator", () => {
|
|
|
247
329
|
it("should check const assignment for struct root", () => {
|
|
248
330
|
const { target, expression } = parseAssignment("config.value");
|
|
249
331
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
332
|
+
AssignmentValidator.validate(
|
|
333
|
+
target,
|
|
334
|
+
expression,
|
|
335
|
+
false,
|
|
336
|
+
1,
|
|
337
|
+
defaultCallbacks,
|
|
254
338
|
);
|
|
339
|
+
|
|
340
|
+
expect(TypeValidator.checkConstAssignment).toHaveBeenCalledWith("config");
|
|
255
341
|
});
|
|
256
342
|
|
|
257
343
|
it("should throw with 'member access' suffix for const struct", () => {
|
|
258
|
-
|
|
344
|
+
vi.mocked(TypeValidator.checkConstAssignment).mockReturnValue(
|
|
259
345
|
"cannot assign to const variable 'config'",
|
|
260
346
|
);
|
|
261
347
|
const { target, expression } = parseAssignment("config.value");
|
|
262
348
|
|
|
263
|
-
expect(() =>
|
|
264
|
-
|
|
265
|
-
|
|
349
|
+
expect(() =>
|
|
350
|
+
AssignmentValidator.validate(
|
|
351
|
+
target,
|
|
352
|
+
expression,
|
|
353
|
+
false,
|
|
354
|
+
1,
|
|
355
|
+
defaultCallbacks,
|
|
356
|
+
),
|
|
357
|
+
).toThrow("cannot assign to const variable 'config' (member access)");
|
|
266
358
|
});
|
|
267
359
|
|
|
268
360
|
it("should throw for read-only register member", () => {
|
|
269
|
-
registerMemberAccess
|
|
361
|
+
const registerMemberAccess = new Map([["GPIO_PIN", "ro"]]);
|
|
362
|
+
setupSymbols({ registerMemberAccess });
|
|
270
363
|
const { target, expression } = parseAssignment("GPIO.PIN");
|
|
271
364
|
|
|
272
|
-
expect(() =>
|
|
273
|
-
|
|
274
|
-
|
|
365
|
+
expect(() =>
|
|
366
|
+
AssignmentValidator.validate(
|
|
367
|
+
target,
|
|
368
|
+
expression,
|
|
369
|
+
false,
|
|
370
|
+
1,
|
|
371
|
+
defaultCallbacks,
|
|
372
|
+
),
|
|
373
|
+
).toThrow("cannot assign to read-only register member 'PIN'");
|
|
275
374
|
});
|
|
276
375
|
|
|
277
376
|
it("should validate callback assignment for callback field", () => {
|
|
278
|
-
typeRegistry.set("handler", {
|
|
377
|
+
CodeGenState.typeRegistry.set("handler", {
|
|
279
378
|
baseType: "Handler",
|
|
280
379
|
bitWidth: 0,
|
|
281
380
|
isArray: false,
|
|
282
381
|
isConst: false,
|
|
283
382
|
});
|
|
284
|
-
callbackFieldTypes.set("Handler.onEvent", "EventCallback");
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
typeRegistry,
|
|
290
|
-
floatShadowCurrent,
|
|
291
|
-
registerMemberAccess,
|
|
292
|
-
callbackFieldTypes,
|
|
293
|
-
isKnownStruct: (name) => name === "Handler",
|
|
294
|
-
isIntegerType: () => false,
|
|
295
|
-
getExpressionType: () => null,
|
|
296
|
-
tryEvaluateConstant: () => undefined,
|
|
297
|
-
isCallbackTypeUsedAsFieldType: () => false,
|
|
298
|
-
});
|
|
383
|
+
CodeGenState.callbackFieldTypes.set("Handler.onEvent", "EventCallback");
|
|
384
|
+
// Mark Handler as a known struct
|
|
385
|
+
if (CodeGenState.symbols) {
|
|
386
|
+
(CodeGenState.symbols.knownStructs as Set<string>).add("Handler");
|
|
387
|
+
}
|
|
299
388
|
|
|
300
389
|
const { target, expression } = parseAssignment("handler.onEvent");
|
|
301
390
|
|
|
302
|
-
|
|
391
|
+
AssignmentValidator.validate(
|
|
392
|
+
target,
|
|
393
|
+
expression,
|
|
394
|
+
false,
|
|
395
|
+
1,
|
|
396
|
+
defaultCallbacks,
|
|
397
|
+
);
|
|
303
398
|
|
|
304
|
-
expect(
|
|
399
|
+
expect(TypeValidator.validateCallbackAssignment).toHaveBeenCalledWith(
|
|
305
400
|
"EventCallback",
|
|
306
401
|
expression,
|
|
307
402
|
"onEvent",
|