c-next 0.1.68 → 0.1.70

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/package.json +1 -1
  2. package/src/transpiler/logic/analysis/FunctionCallAnalyzer.ts +240 -204
  3. package/src/transpiler/logic/analysis/PassByValueAnalyzer.ts +693 -0
  4. package/src/transpiler/logic/analysis/__tests__/FunctionCallAnalyzer.test.ts +86 -5
  5. package/src/transpiler/{output/codegen → logic/analysis}/helpers/AssignmentTargetExtractor.ts +1 -1
  6. package/src/transpiler/{output/codegen → logic/analysis}/helpers/ChildStatementCollector.ts +1 -1
  7. package/src/transpiler/{output/codegen → logic/analysis}/helpers/StatementExpressionCollector.ts +1 -1
  8. package/src/transpiler/{output/codegen → logic/analysis}/helpers/__tests__/AssignmentTargetExtractor.test.ts +2 -2
  9. package/src/transpiler/{output/codegen → logic/analysis}/helpers/__tests__/ChildStatementCollector.test.ts +2 -2
  10. package/src/transpiler/{output/codegen → logic/analysis}/helpers/__tests__/StatementExpressionCollector.test.ts +2 -2
  11. package/src/transpiler/output/codegen/CodeGenerator.ts +160 -742
  12. package/src/transpiler/output/codegen/TypeRegistrationUtils.ts +4 -6
  13. package/src/transpiler/output/codegen/TypeResolver.ts +2 -2
  14. package/src/transpiler/output/codegen/TypeValidator.ts +7 -7
  15. package/src/transpiler/output/codegen/__tests__/CodeGenerator.coverage.test.ts +2 -2
  16. package/src/transpiler/output/codegen/__tests__/CodeGenerator.test.ts +29 -1
  17. package/src/transpiler/output/codegen/__tests__/TypeRegistrationUtils.test.ts +36 -51
  18. package/src/transpiler/output/codegen/__tests__/TypeResolver.test.ts +20 -17
  19. package/src/transpiler/output/codegen/__tests__/TypeValidator.resolution.test.ts +4 -6
  20. package/src/transpiler/output/codegen/__tests__/TypeValidator.test.ts +4 -2
  21. package/src/transpiler/output/codegen/analysis/MemberChainAnalyzer.ts +1 -1
  22. package/src/transpiler/output/codegen/analysis/StringLengthCounter.ts +1 -1
  23. package/src/transpiler/output/codegen/analysis/__tests__/MemberChainAnalyzer.test.ts +9 -9
  24. package/src/transpiler/output/codegen/analysis/__tests__/StringLengthCounter.test.ts +12 -12
  25. package/src/transpiler/output/codegen/assignment/AssignmentClassifier.ts +11 -11
  26. package/src/transpiler/output/codegen/assignment/AssignmentContextBuilder.ts +49 -0
  27. package/src/transpiler/output/codegen/assignment/IAssignmentContext.ts +15 -0
  28. package/src/transpiler/output/codegen/assignment/__tests__/AssignmentClassifier.test.ts +30 -17
  29. package/src/transpiler/output/codegen/assignment/handlers/ArrayHandlers.ts +25 -18
  30. package/src/transpiler/output/codegen/assignment/handlers/BitAccessHandlers.ts +19 -8
  31. package/src/transpiler/output/codegen/assignment/handlers/BitmapHandlers.ts +3 -3
  32. package/src/transpiler/output/codegen/assignment/handlers/SpecialHandlers.ts +4 -4
  33. package/src/transpiler/output/codegen/assignment/handlers/StringHandlers.ts +5 -5
  34. package/src/transpiler/output/codegen/assignment/handlers/__tests__/AccessPatternHandlers.test.ts +9 -1
  35. package/src/transpiler/output/codegen/assignment/handlers/__tests__/ArrayHandlers.test.ts +41 -26
  36. package/src/transpiler/output/codegen/assignment/handlers/__tests__/BitAccessHandlers.test.ts +29 -37
  37. package/src/transpiler/output/codegen/assignment/handlers/__tests__/BitmapHandlers.test.ts +27 -19
  38. package/src/transpiler/output/codegen/assignment/handlers/__tests__/RegisterHandlers.test.ts +10 -1
  39. package/src/transpiler/output/codegen/assignment/handlers/__tests__/SpecialHandlers.test.ts +51 -33
  40. package/src/transpiler/output/codegen/assignment/handlers/__tests__/StringHandlers.test.ts +9 -1
  41. package/src/transpiler/output/codegen/assignment/handlers/__tests__/handlerTestUtils.ts +5 -4
  42. package/src/transpiler/output/codegen/generators/expressions/CallExprGenerator.ts +14 -6
  43. package/src/transpiler/output/codegen/generators/expressions/PostfixExpressionGenerator.ts +19 -16
  44. package/src/transpiler/output/codegen/generators/expressions/__tests__/CallExprGenerator.test.ts +21 -4
  45. package/src/transpiler/output/codegen/generators/expressions/__tests__/PostfixExpressionGenerator.test.ts +15 -2
  46. package/src/transpiler/output/codegen/helpers/ArrayInitHelper.ts +2 -1
  47. package/src/transpiler/output/codegen/helpers/AssignmentExpectedTypeResolver.ts +2 -2
  48. package/src/transpiler/output/codegen/helpers/AssignmentValidator.ts +3 -3
  49. package/src/transpiler/output/codegen/helpers/EnumAssignmentValidator.ts +1 -1
  50. package/src/transpiler/output/codegen/helpers/MemberSeparatorResolver.ts +6 -1
  51. package/src/transpiler/output/codegen/helpers/StringDeclHelper.ts +2 -2
  52. package/src/transpiler/output/codegen/helpers/__tests__/ArrayInitHelper.test.ts +1 -1
  53. package/src/transpiler/output/codegen/helpers/__tests__/AssignmentExpectedTypeResolver.test.ts +7 -7
  54. package/src/transpiler/output/codegen/helpers/__tests__/AssignmentValidator.test.ts +7 -7
  55. package/src/transpiler/output/codegen/helpers/__tests__/EnumAssignmentValidator.test.ts +2 -2
  56. package/src/transpiler/output/codegen/helpers/__tests__/StringDeclHelper.test.ts +4 -4
  57. package/src/transpiler/output/codegen/resolution/EnumTypeResolver.ts +2 -2
  58. package/src/transpiler/output/codegen/resolution/__tests__/EnumTypeResolver.test.ts +5 -5
  59. package/src/transpiler/state/CodeGenState.ts +157 -5
  60. package/src/transpiler/state/__tests__/CodeGenState.test.ts +274 -6
  61. /package/src/transpiler/{output/codegen → logic/analysis}/helpers/TransitiveModificationPropagator.ts +0 -0
  62. /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 TTypeInfo from "./types/TTypeInfo";
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
- typeRegistry.set(options.name, {
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
- typeRegistry.set(options.name, {
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
- typeRegistry.set(options.name, {
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.typeRegistry.get(name);
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.typeRegistry.get(scopedName);
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.typeRegistry.get(scopedName);
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.typeRegistry.get(identifier);
308
+ const typeInfo = CodeGenState.getVariableTypeInfo(identifier);
309
309
  if (typeInfo?.isConst) {
310
310
  return true;
311
311
  }
@@ -332,7 +332,7 @@ class TypeValidator {
332
332
  return;
333
333
  }
334
334
 
335
- const scopeMembers = CodeGenState.scopeMembers.get(currentScope);
335
+ const scopeMembers = CodeGenState.getScopeMembers(currentScope);
336
336
  if (scopeMembers?.has(identifier)) {
337
337
  throw new Error(
338
338
  `Error: Use 'this.${identifier}' to access scope member '${identifier}' inside scope '${currentScope}'`,
@@ -366,7 +366,7 @@ class TypeValidator {
366
366
  );
367
367
  }
368
368
 
369
- const typeInfo = CodeGenState.typeRegistry.get(identifier);
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}'`,
@@ -410,7 +410,7 @@ class TypeValidator {
410
410
  identifier: string,
411
411
  currentScope: string,
412
412
  ): string | null {
413
- const scopeMembers = CodeGenState.scopeMembers.get(currentScope);
413
+ const scopeMembers = CodeGenState.getScopeMembers(currentScope);
414
414
  if (scopeMembers?.has(identifier)) {
415
415
  return `${currentScope}_${identifier}`;
416
416
  }
@@ -428,7 +428,7 @@ class TypeValidator {
428
428
  currentScope: string | null,
429
429
  isKnownStruct: (name: string) => boolean,
430
430
  ): boolean {
431
- const typeInfo = CodeGenState.typeRegistry.get(identifier);
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.typeRegistry.get(text);
793
+ const typeInfo = CodeGenState.getVariableTypeInfo(text);
794
794
  if (typeInfo?.baseType === "bool") {
795
795
  return true;
796
796
  }
@@ -242,7 +242,7 @@ describe("CodeGenerator Coverage Tests", () => {
242
242
 
243
243
  // Manually set up scope context to test the resolution path
244
244
  CodeGenState.currentScope = "Motor";
245
- CodeGenState.scopeMembers.set("Motor", new Set(["speed", "setSpeed"]));
245
+ CodeGenState.setScopeMembers("Motor", new Set(["speed", "setSpeed"]));
246
246
 
247
247
  // Now resolve should return prefixed name (line 633)
248
248
  const resolved = generator.resolveIdentifier("speed");
@@ -253,7 +253,7 @@ describe("CodeGenerator Coverage Tests", () => {
253
253
  const { generator } = setupGenerator("u32 globalVar; void main() {}");
254
254
 
255
255
  CodeGenState.currentScope = "Motor";
256
- CodeGenState.scopeMembers.set("Motor", new Set(["speed"]));
256
+ CodeGenState.setScopeMembers("Motor", new Set(["speed"]));
257
257
 
258
258
  // globalVar is not in Motor scope members
259
259
  const resolved = generator.resolveIdentifier("globalVar");
@@ -7318,12 +7318,15 @@ describe("CodeGenerator", () => {
7318
7318
  expect(code).toContain("cfg.enabled = true");
7319
7319
  });
7320
7320
 
7321
- it("should throw when writing register from inside scope without global prefix", () => {
7321
+ it("should throw when writing register from inside scope when SHADOWED without global prefix", () => {
7322
+ // Issue #779: Ambiguity-aware validation - only require global. when shadowed
7322
7323
  const source = `
7323
7324
  register GPIO @ 0x40000000 {
7324
7325
  DR: u32 rw @ 0x00,
7325
7326
  }
7326
7327
  scope Motor {
7328
+ // Shadow the register name with a scope member
7329
+ u32 GPIO <- 0;
7327
7330
  public void init() {
7328
7331
  GPIO.DR <- 0xFF;
7329
7332
  }
@@ -7342,6 +7345,31 @@ describe("CodeGenerator", () => {
7342
7345
  ).toThrow("Use 'global.GPIO.DR' to access register");
7343
7346
  });
7344
7347
 
7348
+ it("should allow bare register access from inside scope when NOT shadowed", () => {
7349
+ // Issue #779: Ambiguity-aware validation - allow unambiguous access
7350
+ const source = `
7351
+ register GPIO @ 0x40000000 {
7352
+ DR: u32 rw @ 0x00,
7353
+ }
7354
+ scope Motor {
7355
+ public void init() {
7356
+ GPIO.DR <- 0xFF;
7357
+ }
7358
+ }
7359
+ `;
7360
+ const { tree, tokenStream } = CNextSourceParser.parse(source);
7361
+ const generator = new CodeGenerator();
7362
+ const tSymbols = CNextResolver.resolve(tree, "test.cnx");
7363
+ const symbols = TSymbolInfoAdapter.convert(tSymbols);
7364
+ const code = generator.generate(tree, tokenStream, {
7365
+ symbolInfo: symbols,
7366
+ sourcePath: "test.cnx",
7367
+ });
7368
+
7369
+ // Should generate GPIO_DR without error since GPIO is unambiguous
7370
+ expect(code).toContain("GPIO_DR = 0xFF");
7371
+ });
7372
+
7345
7373
  it("should generate scope member write from outside any scope", () => {
7346
7374
  const source = `
7347
7375
  scope Timer {
@@ -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 TTypeInfo from "../types/TTypeInfo";
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
- typeRegistry,
30
- symbols,
31
- {
32
- name: "myVar",
33
- baseType: "UnknownType",
34
- isConst: false,
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(typeRegistry.size).toBe(0);
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
- typeRegistry,
52
- symbols,
53
- {
54
- name: "myVar",
55
- baseType: "MyEnum",
56
- isConst: false,
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(typeRegistry.has("myVar")).toBe(true);
57
+ expect(CodeGenState.hasVariableTypeInfo("myVar")).toBe(true);
64
58
 
65
- const info = typeRegistry.get("myVar")!;
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(typeRegistry, symbols, {
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(typeRegistry.get("myVar")!.isConst).toBe(true);
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(typeRegistry, symbols, {
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(typeRegistry.get("myVar")!.overflowBehavior).toBe("wrap");
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(typeRegistry, symbols, {
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(typeRegistry.get("myVar")!.isAtomic).toBe(true);
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(typeRegistry.size).toBe(0);
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(typeRegistry.has("flags")).toBe(true);
156
+ expect(CodeGenState.hasVariableTypeInfo("flags")).toBe(true);
168
157
 
169
- const info = typeRegistry.get("flags")!;
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 = typeRegistry.get("flagsArray")!;
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(typeRegistry.get("flags")!.bitWidth).toBe(0);
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
- typeRegistry.set("myVar", {
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
- typeRegistry.set("counter", {
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
- typeRegistry.set("point", {
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
- typeRegistry.set("point", {
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
- typeRegistry.set("flags", {
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
- typeRegistry.set("flags", {
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
- typeRegistry.set("data", {
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
- typeRegistry.set("arr", {
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
- typeRegistry.set("val", {
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
- typeRegistry.set("config", {
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
- typeRegistry.set("inputs", {
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
- typeRegistry.set("Motor_speed", {
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
- typeRegistry.set("input", {
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
- typeRegistry.set("value", {
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
- typeRegistry.set("x", {
1026
+ setTypeInfo("x", {
1024
1027
  baseType: "i32",
1025
1028
  bitWidth: 32,
1026
1029
  isArray: false,
@@ -38,16 +38,14 @@ describe("TypeValidator.resolveBareIdentifier", () => {
38
38
 
39
39
  beforeEach(() => {
40
40
  CodeGenState.reset();
41
- CodeGenState.scopeMembers = new Map([
42
- ["Motor", new Set(["speed", "maxSpeed"])],
43
- ]);
44
- CodeGenState.typeRegistry.set("globalCounter", {
41
+ CodeGenState.setScopeMembers("Motor", new Set(["speed", "maxSpeed"]));
42
+ CodeGenState.setVariableTypeInfo("globalCounter", {
45
43
  baseType: "u32",
46
44
  bitWidth: 32,
47
45
  isArray: false,
48
46
  isConst: false,
49
47
  });
50
- CodeGenState.typeRegistry.set("Motor_speed", {
48
+ CodeGenState.setVariableTypeInfo("Motor_speed", {
51
49
  baseType: "u32",
52
50
  bitWidth: 32,
53
51
  isArray: false,
@@ -148,7 +146,7 @@ describe("TypeValidator.resolveBareIdentifier", () => {
148
146
  describe("resolveForMemberAccess", () => {
149
147
  it("prefers scope name over global variable for member access", () => {
150
148
  // Setup: global variable 'LED' exists AND scope 'LED' exists
151
- CodeGenState.typeRegistry.set("LED", {
149
+ CodeGenState.setVariableTypeInfo("LED", {
152
150
  baseType: "u8",
153
151
  bitWidth: 8,
154
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.typeRegistry.set(k, v);
77
+ CodeGenState.setVariableTypeInfo(k, v);
78
78
  }
79
79
  }
80
80
  if (options.callbackTypes) {
@@ -89,7 +89,9 @@ function setupState(options: SetupStateOptions = {}): void {
89
89
  CodeGenState.currentScope = options.currentScope;
90
90
  }
91
91
  if (options.scopeMembers) {
92
- CodeGenState.scopeMembers = options.scopeMembers;
92
+ for (const [scope, members] of options.scopeMembers) {
93
+ CodeGenState.setScopeMembers(scope, members);
94
+ }
93
95
  }
94
96
  if (options.currentParameters) {
95
97
  CodeGenState.currentParameters = options.currentParameters;
@@ -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.typeRegistry.get(baseId);
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.typeRegistry.get(primaryId);
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);