c-next 0.1.65 → 0.1.67

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 (73) hide show
  1. package/package.json +5 -1
  2. package/src/transpiler/Transpiler.ts +49 -42
  3. package/src/transpiler/logic/symbols/cnext/__tests__/TSymbolAdapter.test.ts +129 -0
  4. package/src/transpiler/logic/symbols/cnext/adapters/TSymbolAdapter.ts +27 -3
  5. package/src/transpiler/output/codegen/CodeGenerator.ts +131 -186
  6. package/src/transpiler/output/codegen/TypeResolver.ts +2 -2
  7. package/src/transpiler/output/codegen/TypeValidator.ts +1 -1
  8. package/src/transpiler/output/codegen/__tests__/CodeGenerator.coverage.test.ts +1087 -0
  9. package/src/transpiler/output/codegen/__tests__/CodeGenerator.test.ts +665 -1315
  10. package/src/transpiler/output/codegen/__tests__/TypeResolver.test.ts +1 -1
  11. package/src/transpiler/output/codegen/__tests__/TypeValidator.resolution.test.ts +1 -1
  12. package/src/transpiler/output/codegen/__tests__/TypeValidator.test.ts +1 -1
  13. package/src/transpiler/output/codegen/analysis/MemberChainAnalyzer.ts +1 -1
  14. package/src/transpiler/output/codegen/analysis/StringLengthCounter.ts +1 -1
  15. package/src/transpiler/output/codegen/analysis/__tests__/MemberChainAnalyzer.test.ts +1 -1
  16. package/src/transpiler/output/codegen/analysis/__tests__/StringLengthCounter.test.ts +1 -1
  17. package/src/transpiler/output/codegen/assignment/AssignmentClassifier.ts +1 -1
  18. package/src/transpiler/output/codegen/assignment/__tests__/AssignmentClassifier.test.ts +1 -1
  19. package/src/transpiler/output/codegen/assignment/handlers/AccessPatternHandlers.ts +24 -27
  20. package/src/transpiler/output/codegen/assignment/handlers/ArrayHandlers.ts +25 -18
  21. package/src/transpiler/output/codegen/assignment/handlers/BitAccessHandlers.ts +27 -33
  22. package/src/transpiler/output/codegen/assignment/handlers/BitmapHandlers.ts +39 -42
  23. package/src/transpiler/output/codegen/assignment/handlers/RegisterHandlers.ts +39 -97
  24. package/src/transpiler/output/codegen/assignment/handlers/RegisterUtils.ts +75 -0
  25. package/src/transpiler/output/codegen/assignment/handlers/SimpleHandler.ts +9 -6
  26. package/src/transpiler/output/codegen/assignment/handlers/SpecialHandlers.ts +30 -22
  27. package/src/transpiler/output/codegen/assignment/handlers/StringHandlers.ts +42 -50
  28. package/src/transpiler/output/codegen/assignment/handlers/TAssignmentHandler.ts +6 -5
  29. package/src/transpiler/output/codegen/assignment/handlers/__tests__/AccessPatternHandlers.test.ts +81 -134
  30. package/src/transpiler/output/codegen/assignment/handlers/__tests__/ArrayHandlers.test.ts +85 -124
  31. package/src/transpiler/output/codegen/assignment/handlers/__tests__/BitAccessHandlers.test.ts +82 -124
  32. package/src/transpiler/output/codegen/assignment/handlers/__tests__/BitmapHandlers.test.ts +135 -297
  33. package/src/transpiler/output/codegen/assignment/handlers/__tests__/RegisterHandlers.test.ts +105 -227
  34. package/src/transpiler/output/codegen/assignment/handlers/__tests__/RegisterUtils.test.ts +214 -1
  35. package/src/transpiler/output/codegen/assignment/handlers/__tests__/SpecialHandlers.test.ts +66 -127
  36. package/src/transpiler/output/codegen/assignment/handlers/__tests__/StringHandlers.test.ts +37 -83
  37. package/src/transpiler/output/codegen/assignment/handlers/__tests__/handlerTestUtils.ts +162 -0
  38. package/src/transpiler/output/codegen/generators/expressions/PostfixExpressionGenerator.ts +618 -12
  39. package/src/transpiler/output/codegen/generators/expressions/__tests__/PostfixExpressionGenerator.test.ts +819 -0
  40. package/src/transpiler/output/codegen/helpers/ArrayInitHelper.ts +1 -1
  41. package/src/transpiler/output/codegen/helpers/AssignmentExpectedTypeResolver.ts +1 -1
  42. package/src/transpiler/output/codegen/helpers/AssignmentValidator.ts +1 -1
  43. package/src/transpiler/output/codegen/helpers/CppModeHelper.ts +1 -1
  44. package/src/transpiler/output/codegen/helpers/EnumAssignmentValidator.ts +1 -1
  45. package/src/transpiler/output/codegen/helpers/FloatBitHelper.ts +1 -1
  46. package/src/transpiler/output/codegen/helpers/ParameterInputAdapter.ts +337 -0
  47. package/src/transpiler/output/codegen/helpers/ParameterSignatureBuilder.ts +135 -0
  48. package/src/transpiler/output/codegen/helpers/StringDeclHelper.ts +1 -1
  49. package/src/transpiler/output/codegen/helpers/VariableDeclarationFormatter.ts +118 -0
  50. package/src/transpiler/output/codegen/helpers/__tests__/ArrayInitHelper.test.ts +1 -1
  51. package/src/transpiler/output/codegen/helpers/__tests__/AssignmentExpectedTypeResolver.test.ts +1 -1
  52. package/src/transpiler/output/codegen/helpers/__tests__/AssignmentValidator.test.ts +1 -1
  53. package/src/transpiler/output/codegen/helpers/__tests__/CppModeHelper.test.ts +1 -1
  54. package/src/transpiler/output/codegen/helpers/__tests__/EnumAssignmentValidator.test.ts +1 -1
  55. package/src/transpiler/output/codegen/helpers/__tests__/FloatBitHelper.test.ts +1 -1
  56. package/src/transpiler/output/codegen/helpers/__tests__/ParameterInputAdapter.test.ts +426 -0
  57. package/src/transpiler/output/codegen/helpers/__tests__/ParameterSignatureBuilder.test.ts +315 -0
  58. package/src/transpiler/output/codegen/helpers/__tests__/StringDeclHelper.test.ts +1 -1
  59. package/src/transpiler/output/codegen/helpers/__tests__/VariableDeclarationFormatter.test.ts +333 -0
  60. package/src/transpiler/output/codegen/resolution/EnumTypeResolver.ts +1 -1
  61. package/src/transpiler/output/codegen/resolution/ScopeResolver.ts +1 -1
  62. package/src/transpiler/output/codegen/resolution/SizeofResolver.ts +1 -1
  63. package/src/transpiler/output/codegen/resolution/__tests__/EnumTypeResolver.test.ts +1 -1
  64. package/src/transpiler/output/codegen/resolution/__tests__/SizeofResolver.test.ts +1 -1
  65. package/src/transpiler/output/codegen/types/ICodeGenApi.ts +57 -0
  66. package/src/transpiler/output/codegen/types/IParameterInput.ts +58 -0
  67. package/src/transpiler/output/codegen/types/IVariableFormatInput.ts +51 -0
  68. package/src/transpiler/output/headers/BaseHeaderGenerator.ts +20 -35
  69. package/src/transpiler/output/headers/HeaderGeneratorUtils.ts +21 -48
  70. package/src/transpiler/output/headers/__tests__/HeaderGeneratorUtils.test.ts +0 -64
  71. package/src/transpiler/{output/codegen → state}/CodeGenState.ts +46 -26
  72. package/src/transpiler/{output/codegen → state}/__tests__/CodeGenState.test.ts +12 -2
  73. package/src/transpiler/output/codegen/assignment/handlers/IHandlerDeps.ts +0 -161
@@ -5,7 +5,7 @@
5
5
  import { describe, it, expect, beforeEach } from "vitest";
6
6
  import TypeResolver from "../TypeResolver";
7
7
  import SymbolTable from "../../../logic/symbols/SymbolTable";
8
- import CodeGenState from "../CodeGenState";
8
+ import CodeGenState from "../../../state/CodeGenState";
9
9
  import TTypeInfo from "../types/TTypeInfo";
10
10
 
11
11
  describe("TypeResolver", () => {
@@ -1,6 +1,6 @@
1
1
  import { describe, it, expect, beforeEach } from "vitest";
2
2
  import TypeValidator from "../TypeValidator";
3
- import CodeGenState from "../CodeGenState";
3
+ import CodeGenState from "../../../state/CodeGenState";
4
4
  import type ICodeGenSymbols from "../../../types/ICodeGenSymbols";
5
5
 
6
6
  describe("TypeValidator.resolveBareIdentifier", () => {
@@ -6,7 +6,7 @@
6
6
  import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
7
7
  import TypeValidator from "../TypeValidator";
8
8
  import TypeResolver from "../TypeResolver";
9
- import CodeGenState from "../CodeGenState";
9
+ import CodeGenState from "../../../state/CodeGenState";
10
10
  import type ICodeGenSymbols from "../../../types/ICodeGenSymbols";
11
11
  import type TTypeInfo from "../types/TTypeInfo";
12
12
  import type TParameterInfo from "../types/TParameterInfo";
@@ -12,7 +12,7 @@
12
12
  */
13
13
 
14
14
  import * as Parser from "../../../logic/parser/grammar/CNextParser.js";
15
- import CodeGenState from "../CodeGenState.js";
15
+ import CodeGenState from "../../../state/CodeGenState.js";
16
16
 
17
17
  /**
18
18
  * Result of analyzing a member chain for bit access.
@@ -9,7 +9,7 @@
9
9
  */
10
10
 
11
11
  import * as Parser from "../../../logic/parser/grammar/CNextParser";
12
- import CodeGenState from "../CodeGenState";
12
+ import CodeGenState from "../../../state/CodeGenState";
13
13
 
14
14
  /**
15
15
  * Counts .length accesses on string variables in an expression tree.
@@ -8,7 +8,7 @@
8
8
 
9
9
  import { describe, it, expect, beforeEach } from "vitest";
10
10
  import MemberChainAnalyzer from "../MemberChainAnalyzer.js";
11
- import CodeGenState from "../../CodeGenState.js";
11
+ import CodeGenState from "../../../../state/CodeGenState.js";
12
12
  import type * as Parser from "../../../../logic/parser/grammar/CNextParser.js";
13
13
 
14
14
  /** Mock type for PostfixTargetOpContext */
@@ -6,7 +6,7 @@
6
6
  import { describe, it, expect, beforeEach } from "vitest";
7
7
  import StringLengthCounter from "../StringLengthCounter";
8
8
  import CNextSourceParser from "../../../../logic/parser/CNextSourceParser";
9
- import CodeGenState from "../../CodeGenState";
9
+ import CodeGenState from "../../../../state/CodeGenState";
10
10
 
11
11
  /**
12
12
  * Parse a C-Next expression and return the expression context.
@@ -9,7 +9,7 @@
9
9
  */
10
10
  import AssignmentKind from "./AssignmentKind";
11
11
  import IAssignmentContext from "./IAssignmentContext";
12
- import CodeGenState from "../CodeGenState";
12
+ import CodeGenState from "../../../state/CodeGenState";
13
13
  import SubscriptClassifier from "../subscript/SubscriptClassifier";
14
14
  import TTypeInfo from "../types/TTypeInfo";
15
15
  import TypeCheckUtils from "../../../../utils/TypeCheckUtils";
@@ -2,7 +2,7 @@ import { describe, it, expect, beforeEach } from "vitest";
2
2
  import AssignmentClassifier from "../AssignmentClassifier";
3
3
  import AssignmentKind from "../AssignmentKind";
4
4
  import IAssignmentContext from "../IAssignmentContext";
5
- import CodeGenState from "../../CodeGenState";
5
+ import CodeGenState from "../../../../state/CodeGenState";
6
6
  import TTypeInfo from "../../types/TTypeInfo";
7
7
 
8
8
  // ========================================================================
@@ -11,28 +11,31 @@
11
11
  */
12
12
  import AssignmentKind from "../AssignmentKind";
13
13
  import IAssignmentContext from "../IAssignmentContext";
14
- import IHandlerDeps from "./IHandlerDeps";
15
14
  import BitUtils from "../../../../../utils/BitUtils";
16
15
  import TAssignmentHandler from "./TAssignmentHandler";
17
16
  import RegisterUtils from "./RegisterUtils";
17
+ import CodeGenState from "../../../../state/CodeGenState";
18
+ import type ICodeGenApi from "../../types/ICodeGenApi";
19
+
20
+ /** Get typed generator reference */
21
+ function gen(): ICodeGenApi {
22
+ return CodeGenState.generator as ICodeGenApi;
23
+ }
18
24
 
19
25
  /**
20
26
  * Common handler for global access patterns (GLOBAL_MEMBER and GLOBAL_ARRAY).
21
27
  *
22
28
  * Validates cross-scope visibility and generates standard assignment.
23
29
  */
24
- function handleGlobalAccess(
25
- ctx: IAssignmentContext,
26
- deps: IHandlerDeps,
27
- ): string {
30
+ function handleGlobalAccess(ctx: IAssignmentContext): string {
28
31
  const firstId = ctx.identifiers[0];
29
32
 
30
33
  // Validate cross-scope visibility if first id is a scope
31
- if (deps.isKnownScope(firstId) && ctx.identifiers.length >= 2) {
32
- deps.validateCrossScopeVisibility(firstId, ctx.identifiers[1]);
34
+ if (CodeGenState.isKnownScope(firstId) && ctx.identifiers.length >= 2) {
35
+ gen().validateCrossScopeVisibility(firstId, ctx.identifiers[1]);
33
36
  }
34
37
 
35
- const target = deps.generateAssignmentTarget(ctx.targetCtx);
38
+ const target = gen().generateAssignmentTarget(ctx.targetCtx);
36
39
  return `${target} ${ctx.cOp} ${ctx.generatedValue};`;
37
40
  }
38
41
 
@@ -41,22 +44,19 @@ function handleGlobalAccess(
41
44
  *
42
45
  * Validates scope context and generates standard assignment.
43
46
  */
44
- function handleThisAccess(ctx: IAssignmentContext, deps: IHandlerDeps): string {
45
- if (!deps.currentScope) {
47
+ function handleThisAccess(ctx: IAssignmentContext): string {
48
+ if (!CodeGenState.currentScope) {
46
49
  throw new Error("Error: 'this' can only be used inside a scope");
47
50
  }
48
51
 
49
- const target = deps.generateAssignmentTarget(ctx.targetCtx);
52
+ const target = gen().generateAssignmentTarget(ctx.targetCtx);
50
53
  return `${target} ${ctx.cOp} ${ctx.generatedValue};`;
51
54
  }
52
55
 
53
56
  /**
54
57
  * Handle global.reg[bit]: global.GPIO7.DR_SET[bit] <- true
55
58
  */
56
- function handleGlobalRegisterBit(
57
- ctx: IAssignmentContext,
58
- deps: IHandlerDeps,
59
- ): string {
59
+ function handleGlobalRegisterBit(ctx: IAssignmentContext): string {
60
60
  if (ctx.isCompound) {
61
61
  throw new Error(
62
62
  `Compound assignment operators not supported for bit field access: ${ctx.cnextOp}`,
@@ -67,15 +67,15 @@ function handleGlobalRegisterBit(
67
67
  const regName = parts.join("_");
68
68
 
69
69
  // Check for write-only register
70
- const accessMod = deps.symbols.registerMemberAccess.get(regName);
70
+ const accessMod = CodeGenState.symbols!.registerMemberAccess.get(regName);
71
71
  const isWriteOnly = RegisterUtils.isWriteOnlyRegister(accessMod);
72
72
 
73
73
  // Handle bit range vs single bit
74
74
  if (ctx.subscripts.length === 2) {
75
- // Bit range
76
- const start = deps.generateExpression(ctx.subscripts[0]);
77
- const width = deps.generateExpression(ctx.subscripts[1]);
78
- const mask = BitUtils.generateMask(width);
75
+ // Bit range - use shared utility
76
+ const { start, width, mask } = RegisterUtils.extractBitRangeParams(
77
+ ctx.subscripts,
78
+ );
79
79
 
80
80
  if (isWriteOnly) {
81
81
  if (ctx.generatedValue === "0") {
@@ -100,7 +100,7 @@ function handleGlobalRegisterBit(
100
100
  }
101
101
 
102
102
  // Single bit
103
- const bitIndex = deps.generateExpression(ctx.subscripts[0]);
103
+ const bitIndex = gen().generateExpression(ctx.subscripts[0]);
104
104
 
105
105
  if (isWriteOnly) {
106
106
  if (ctx.generatedValue === "false" || ctx.generatedValue === "0") {
@@ -124,12 +124,9 @@ function handleGlobalRegisterBit(
124
124
  * Special case: Detects bit access at the end of chain
125
125
  * (e.g., grid[2][3].flags[0] <- true) and generates RMW.
126
126
  */
127
- function handleMemberChain(
128
- ctx: IAssignmentContext,
129
- deps: IHandlerDeps,
130
- ): string {
127
+ function handleMemberChain(ctx: IAssignmentContext): string {
131
128
  // Check if this is bit access on a struct member
132
- const bitAnalysis = deps.analyzeMemberChainForBitAccess(ctx.targetCtx);
129
+ const bitAnalysis = gen().analyzeMemberChainForBitAccess(ctx.targetCtx);
133
130
 
134
131
  if (bitAnalysis.isBitAccess) {
135
132
  // Validate compound operators not supported for bit access
@@ -147,7 +144,7 @@ function handleMemberChain(
147
144
  }
148
145
 
149
146
  // Normal member chain assignment
150
- const target = deps.generateAssignmentTarget(ctx.targetCtx);
147
+ const target = gen().generateAssignmentTarget(ctx.targetCtx);
151
148
  return `${target} ${ctx.cOp} ${ctx.generatedValue};`;
152
149
  }
153
150
 
@@ -8,18 +8,22 @@
8
8
  */
9
9
  import AssignmentKind from "../AssignmentKind";
10
10
  import IAssignmentContext from "../IAssignmentContext";
11
- import IHandlerDeps from "./IHandlerDeps";
12
11
  import TAssignmentHandler from "./TAssignmentHandler";
12
+ import CodeGenState from "../../../../state/CodeGenState";
13
+ import TypeValidator from "../../TypeValidator";
14
+ import type ICodeGenApi from "../../types/ICodeGenApi";
15
+
16
+ /** Get typed generator reference */
17
+ function gen(): ICodeGenApi {
18
+ return CodeGenState.generator as ICodeGenApi;
19
+ }
13
20
 
14
21
  /**
15
22
  * Handle simple array element: arr[i] <- value
16
23
  */
17
- function handleArrayElement(
18
- ctx: IAssignmentContext,
19
- deps: IHandlerDeps,
20
- ): string {
24
+ function handleArrayElement(ctx: IAssignmentContext): string {
21
25
  const name = ctx.identifiers[0];
22
- const index = deps.generateExpression(ctx.subscripts[0]);
26
+ const index = gen().generateExpression(ctx.subscripts[0]);
23
27
 
24
28
  return `${name}[${index}] ${ctx.cOp} ${ctx.generatedValue};`;
25
29
  }
@@ -27,21 +31,24 @@ function handleArrayElement(
27
31
  /**
28
32
  * Handle multi-dimensional array element: matrix[i][j] <- value
29
33
  */
30
- function handleMultiDimArrayElement(
31
- ctx: IAssignmentContext,
32
- deps: IHandlerDeps,
33
- ): string {
34
+ function handleMultiDimArrayElement(ctx: IAssignmentContext): string {
34
35
  const name = ctx.identifiers[0];
35
- const typeInfo = deps.typeRegistry.get(name);
36
+ const typeInfo = CodeGenState.typeRegistry.get(name);
36
37
 
37
38
  // ADR-036: Compile-time bounds checking for constant indices
38
39
  if (typeInfo?.arrayDimensions) {
39
40
  const line = ctx.subscripts[0]?.start?.line ?? 0;
40
- deps.checkArrayBounds(name, typeInfo.arrayDimensions, ctx.subscripts, line);
41
+ TypeValidator.checkArrayBounds(
42
+ name,
43
+ [...typeInfo.arrayDimensions],
44
+ [...ctx.subscripts],
45
+ line,
46
+ (expr) => gen().tryEvaluateConstant(expr),
47
+ );
41
48
  }
42
49
 
43
50
  const indices = ctx.subscripts
44
- .map((e) => deps.generateExpression(e))
51
+ .map((e) => gen().generateExpression(e))
45
52
  .join("][");
46
53
 
47
54
  return `${name}[${indices}] ${ctx.cOp} ${ctx.generatedValue};`;
@@ -55,7 +62,7 @@ function handleMultiDimArrayElement(
55
62
  * - Only valid on 1D arrays
56
63
  * - Bounds checking at compile time
57
64
  */
58
- function handleArraySlice(ctx: IAssignmentContext, deps: IHandlerDeps): string {
65
+ function handleArraySlice(ctx: IAssignmentContext): string {
59
66
  if (ctx.isCompound) {
60
67
  throw new Error(
61
68
  `Compound assignment operators not supported for slice assignment: ${ctx.cnextOp}`,
@@ -63,7 +70,7 @@ function handleArraySlice(ctx: IAssignmentContext, deps: IHandlerDeps): string {
63
70
  }
64
71
 
65
72
  const name = ctx.identifiers[0];
66
- const typeInfo = deps.typeRegistry.get(name);
73
+ const typeInfo = CodeGenState.typeRegistry.get(name);
67
74
 
68
75
  // Get line number for error messages
69
76
  const line = ctx.subscripts[0].start?.line ?? 0;
@@ -78,7 +85,7 @@ function handleArraySlice(ctx: IAssignmentContext, deps: IHandlerDeps): string {
78
85
  }
79
86
 
80
87
  // Validate offset is compile-time constant
81
- const offsetValue = deps.tryEvaluateConstant(ctx.subscripts[0]);
88
+ const offsetValue = gen().tryEvaluateConstant(ctx.subscripts[0]);
82
89
  if (offsetValue === undefined) {
83
90
  throw new Error(
84
91
  `${line}:0 Error: Slice assignment offset must be a compile-time constant. ` +
@@ -87,7 +94,7 @@ function handleArraySlice(ctx: IAssignmentContext, deps: IHandlerDeps): string {
87
94
  }
88
95
 
89
96
  // Validate length is compile-time constant
90
- const lengthValue = deps.tryEvaluateConstant(ctx.subscripts[1]);
97
+ const lengthValue = gen().tryEvaluateConstant(ctx.subscripts[1]);
91
98
  if (lengthValue === undefined) {
92
99
  throw new Error(
93
100
  `${line}:0 Error: Slice assignment length must be a compile-time constant. ` +
@@ -129,7 +136,7 @@ function handleArraySlice(ctx: IAssignmentContext, deps: IHandlerDeps): string {
129
136
  }
130
137
 
131
138
  // Mark that we need string.h for memcpy
132
- deps.markNeedsString();
139
+ CodeGenState.needsString = true;
133
140
 
134
141
  return `memcpy(&${name}[${offsetValue}], &${ctx.generatedValue}, ${lengthValue});`;
135
142
  }
@@ -9,9 +9,15 @@
9
9
  */
10
10
  import AssignmentKind from "../AssignmentKind";
11
11
  import IAssignmentContext from "../IAssignmentContext";
12
- import IHandlerDeps from "./IHandlerDeps";
13
12
  import BitUtils from "../../../../../utils/BitUtils";
14
13
  import TAssignmentHandler from "./TAssignmentHandler";
14
+ import CodeGenState from "../../../../state/CodeGenState";
15
+ import type ICodeGenApi from "../../types/ICodeGenApi";
16
+
17
+ /** Get typed generator reference */
18
+ function gen(): ICodeGenApi {
19
+ return CodeGenState.generator as ICodeGenApi;
20
+ }
15
21
 
16
22
  /**
17
23
  * Validate compound operators are not used with bit access.
@@ -28,16 +34,16 @@ function validateNotCompound(ctx: IAssignmentContext): void {
28
34
  * Handle single bit on integer variable: flags[3] <- true
29
35
  * Also handles float bit indexing: f32Var[3] <- true
30
36
  */
31
- function handleIntegerBit(ctx: IAssignmentContext, deps: IHandlerDeps): string {
37
+ function handleIntegerBit(ctx: IAssignmentContext): string {
32
38
  validateNotCompound(ctx);
33
39
 
34
40
  const name = ctx.identifiers[0];
35
- const bitIndex = deps.generateExpression(ctx.subscripts[0]);
36
- const typeInfo = deps.typeRegistry.get(name);
41
+ const bitIndex = gen().generateExpression(ctx.subscripts[0]);
42
+ const typeInfo = CodeGenState.typeRegistry.get(name);
37
43
 
38
44
  // Check for float bit indexing
39
45
  if (typeInfo) {
40
- const floatResult = deps.generateFloatBitWrite(
46
+ const floatResult = gen().generateFloatBitWrite(
41
47
  name,
42
48
  typeInfo,
43
49
  bitIndex,
@@ -62,20 +68,17 @@ function handleIntegerBit(ctx: IAssignmentContext, deps: IHandlerDeps): string {
62
68
  * Handle bit range on integer variable: flags[0, 3] <- 5
63
69
  * Also handles float bit range: f32Var[0, 8] <- 0xFF
64
70
  */
65
- function handleIntegerBitRange(
66
- ctx: IAssignmentContext,
67
- deps: IHandlerDeps,
68
- ): string {
71
+ function handleIntegerBitRange(ctx: IAssignmentContext): string {
69
72
  validateNotCompound(ctx);
70
73
 
71
74
  const name = ctx.identifiers[0];
72
- const start = deps.generateExpression(ctx.subscripts[0]);
73
- const width = deps.generateExpression(ctx.subscripts[1]);
74
- const typeInfo = deps.typeRegistry.get(name);
75
+ const start = gen().generateExpression(ctx.subscripts[0]);
76
+ const width = gen().generateExpression(ctx.subscripts[1]);
77
+ const typeInfo = CodeGenState.typeRegistry.get(name);
75
78
 
76
79
  // Check for float bit indexing
77
80
  if (typeInfo) {
78
- const floatResult = deps.generateFloatBitWrite(
81
+ const floatResult = gen().generateFloatBitWrite(
79
82
  name,
80
83
  typeInfo,
81
84
  start,
@@ -101,20 +104,17 @@ function handleIntegerBitRange(
101
104
  * Handle bit on struct member: item.byte[7] <- true
102
105
  * This is handled through MEMBER_CHAIN with bit detection.
103
106
  */
104
- function handleStructMemberBit(
105
- ctx: IAssignmentContext,
106
- deps: IHandlerDeps,
107
- ): string {
107
+ function handleStructMemberBit(ctx: IAssignmentContext): string {
108
108
  validateNotCompound(ctx);
109
109
 
110
110
  // The target up to the last subscript is the struct member path
111
111
  // The last subscript is the bit index
112
112
  // This pattern is complex - the target needs to be built from the member chain
113
113
  // For now, delegate to the existing target generator and build the bit op
114
- const target = deps.generateAssignmentTarget(ctx.targetCtx);
114
+ const target = gen().generateAssignmentTarget(ctx.targetCtx);
115
115
 
116
116
  // Extract the bit index from the last subscript
117
- const bitIndex = deps.generateExpression(ctx.subscripts.at(-1)!);
117
+ const bitIndex = gen().generateExpression(ctx.subscripts.at(-1)!);
118
118
 
119
119
  // Limitation: Uses literal "1" which works for types up to 32 bits.
120
120
  // For 64-bit struct members, would need to track member type through chain.
@@ -127,14 +127,11 @@ function handleStructMemberBit(
127
127
  /**
128
128
  * Handle bit on multi-dimensional array element: matrix[i][j][FIELD_BIT] <- false
129
129
  */
130
- function handleArrayElementBit(
131
- ctx: IAssignmentContext,
132
- deps: IHandlerDeps,
133
- ): string {
130
+ function handleArrayElementBit(ctx: IAssignmentContext): string {
134
131
  validateNotCompound(ctx);
135
132
 
136
133
  const arrayName = ctx.identifiers[0];
137
- const typeInfo = deps.typeRegistry.get(arrayName);
134
+ const typeInfo = CodeGenState.typeRegistry.get(arrayName);
138
135
 
139
136
  if (!typeInfo?.arrayDimensions) {
140
137
  throw new Error(`Error: ${arrayName} is not an array`);
@@ -145,9 +142,9 @@ function handleArrayElementBit(
145
142
  // Array indices are subscripts[0..numDims-1], bit index is subscripts[numDims]
146
143
  const arrayIndices = ctx.subscripts
147
144
  .slice(0, numDims)
148
- .map((e) => `[${deps.generateExpression(e)}]`)
145
+ .map((e) => `[${gen().generateExpression(e)}]`)
149
146
  .join("");
150
- const bitIndex = deps.generateExpression(ctx.subscripts[numDims]);
147
+ const bitIndex = gen().generateExpression(ctx.subscripts[numDims]);
151
148
 
152
149
  const arrayElement = `${arrayName}${arrayIndices}`;
153
150
 
@@ -164,10 +161,7 @@ function handleArrayElementBit(
164
161
  * The target is a chain like array[idx].member or struct.field with a
165
162
  * bit range subscript [start, width] at the end.
166
163
  */
167
- function handleStructChainBitRange(
168
- ctx: IAssignmentContext,
169
- deps: IHandlerDeps,
170
- ): string {
164
+ function handleStructChainBitRange(ctx: IAssignmentContext): string {
171
165
  validateNotCompound(ctx);
172
166
 
173
167
  // Build the base target from postfixOps, excluding the last one (the bit range)
@@ -182,7 +176,7 @@ function handleStructChainBitRange(
182
176
  } else {
183
177
  const exprs = op.expression();
184
178
  if (exprs.length > 0) {
185
- baseTarget += "[" + deps.generateExpression(exprs[0]) + "]";
179
+ baseTarget += "[" + gen().generateExpression(exprs[0]) + "]";
186
180
  }
187
181
  }
188
182
  }
@@ -190,8 +184,8 @@ function handleStructChainBitRange(
190
184
  // Get start and width from the last postfixOp (the bit range)
191
185
  const lastOp = ctx.postfixOps.at(-1)!;
192
186
  const bitRangeExprs = lastOp.expression();
193
- const start = deps.generateExpression(bitRangeExprs[0]);
194
- const width = deps.generateExpression(bitRangeExprs[1]);
187
+ const start = gen().generateExpression(bitRangeExprs[0]);
188
+ const width = gen().generateExpression(bitRangeExprs[1]);
195
189
 
196
190
  // Generate bit range write
197
191
  // Limitation: assumes 32-bit types. For 64-bit struct members,
@@ -11,9 +11,16 @@
11
11
  */
12
12
  import AssignmentKind from "../AssignmentKind";
13
13
  import IAssignmentContext from "../IAssignmentContext";
14
- import IHandlerDeps from "./IHandlerDeps";
15
14
  import BitUtils from "../../../../../utils/BitUtils";
16
15
  import TAssignmentHandler from "./TAssignmentHandler";
16
+ import CodeGenState from "../../../../state/CodeGenState";
17
+ import TypeValidator from "../../TypeValidator";
18
+ import type ICodeGenApi from "../../types/ICodeGenApi";
19
+
20
+ /** Get typed generator reference */
21
+ function gen(): ICodeGenApi {
22
+ return CodeGenState.generator as ICodeGenApi;
23
+ }
17
24
 
18
25
  /**
19
26
  * Calculate mask value and hex string for bitmap field.
@@ -31,9 +38,8 @@ function getBitmapFieldInfo(
31
38
  bitmapType: string,
32
39
  fieldName: string,
33
40
  ctx: IAssignmentContext,
34
- deps: IHandlerDeps,
35
41
  ): { offset: number; width: number } {
36
- const fields = deps.symbols.bitmapFields.get(bitmapType);
42
+ const fields = CodeGenState.symbols!.bitmapFields.get(bitmapType);
37
43
  if (!fields?.has(fieldName)) {
38
44
  throw new Error(
39
45
  `Error: Unknown bitmap field '${fieldName}' on type '${bitmapType}'`,
@@ -51,7 +57,11 @@ function getBitmapFieldInfo(
51
57
 
52
58
  // Validate compile-time literal overflow
53
59
  if (ctx.valueCtx) {
54
- deps.validateBitmapFieldLiteral(ctx.valueCtx, fieldInfo.width, fieldName);
60
+ TypeValidator.validateBitmapFieldLiteral(
61
+ ctx.valueCtx,
62
+ fieldInfo.width,
63
+ fieldName,
64
+ );
55
65
  }
56
66
 
57
67
  return fieldInfo;
@@ -96,44 +106,35 @@ function generateWriteOnlyBitmapWrite(
96
106
  /**
97
107
  * Handle simple bitmap field: flags.Running <- true
98
108
  */
99
- function handleBitmapFieldSingleBit(
100
- ctx: IAssignmentContext,
101
- deps: IHandlerDeps,
102
- ): string {
109
+ function handleBitmapFieldSingleBit(ctx: IAssignmentContext): string {
103
110
  const varName = ctx.identifiers[0];
104
111
  const fieldName = ctx.identifiers[1];
105
- const typeInfo = deps.typeRegistry.get(varName);
112
+ const typeInfo = CodeGenState.typeRegistry.get(varName);
106
113
  const bitmapType = typeInfo!.bitmapTypeName!;
107
114
 
108
- const fieldInfo = getBitmapFieldInfo(bitmapType, fieldName, ctx, deps);
115
+ const fieldInfo = getBitmapFieldInfo(bitmapType, fieldName, ctx);
109
116
  return generateBitmapWrite(varName, fieldInfo, ctx.generatedValue);
110
117
  }
111
118
 
112
119
  /**
113
120
  * Handle multi-bit bitmap field: flags.Mode <- 3
114
121
  */
115
- function handleBitmapFieldMultiBit(
116
- ctx: IAssignmentContext,
117
- deps: IHandlerDeps,
118
- ): string {
122
+ function handleBitmapFieldMultiBit(ctx: IAssignmentContext): string {
119
123
  // Same logic as single bit, generateBitmapWrite handles width
120
- return handleBitmapFieldSingleBit(ctx, deps);
124
+ return handleBitmapFieldSingleBit(ctx);
121
125
  }
122
126
 
123
127
  /**
124
128
  * Handle bitmap array element field: bitmapArr[i].Field <- value
125
129
  */
126
- function handleBitmapArrayElementField(
127
- ctx: IAssignmentContext,
128
- deps: IHandlerDeps,
129
- ): string {
130
+ function handleBitmapArrayElementField(ctx: IAssignmentContext): string {
130
131
  const arrayName = ctx.identifiers[0];
131
132
  const fieldName = ctx.identifiers[1];
132
- const typeInfo = deps.typeRegistry.get(arrayName);
133
+ const typeInfo = CodeGenState.typeRegistry.get(arrayName);
133
134
  const bitmapType = typeInfo!.bitmapTypeName!;
134
135
 
135
- const fieldInfo = getBitmapFieldInfo(bitmapType, fieldName, ctx, deps);
136
- const index = deps.generateExpression(ctx.subscripts[0]);
136
+ const fieldInfo = getBitmapFieldInfo(bitmapType, fieldName, ctx);
137
+ const index = gen().generateExpression(ctx.subscripts[0]);
137
138
  const arrayElement = `${arrayName}[${index}]`;
138
139
 
139
140
  return generateBitmapWrite(arrayElement, fieldInfo, ctx.generatedValue);
@@ -142,22 +143,19 @@ function handleBitmapArrayElementField(
142
143
  /**
143
144
  * Handle struct member bitmap field: device.flags.Active <- true
144
145
  */
145
- function handleStructMemberBitmapField(
146
- ctx: IAssignmentContext,
147
- deps: IHandlerDeps,
148
- ): string {
146
+ function handleStructMemberBitmapField(ctx: IAssignmentContext): string {
149
147
  const structName = ctx.identifiers[0];
150
148
  const memberName = ctx.identifiers[1];
151
149
  const fieldName = ctx.identifiers[2];
152
150
 
153
- const structTypeInfo = deps.typeRegistry.get(structName);
154
- const memberInfo = deps.getMemberTypeInfo(
151
+ const structTypeInfo = CodeGenState.typeRegistry.get(structName);
152
+ const memberInfo = CodeGenState.getMemberTypeInfo(
155
153
  structTypeInfo!.baseType,
156
154
  memberName,
157
155
  );
158
156
  const bitmapType = memberInfo!.baseType;
159
157
 
160
- const fieldInfo = getBitmapFieldInfo(bitmapType, fieldName, ctx, deps);
158
+ const fieldInfo = getBitmapFieldInfo(bitmapType, fieldName, ctx);
161
159
  const memberPath = `${structName}.${memberName}`;
162
160
 
163
161
  return generateBitmapWrite(memberPath, fieldInfo, ctx.generatedValue);
@@ -166,18 +164,16 @@ function handleStructMemberBitmapField(
166
164
  /**
167
165
  * Handle register member bitmap field: MOTOR.CTRL.Running <- true
168
166
  */
169
- function handleRegisterMemberBitmapField(
170
- ctx: IAssignmentContext,
171
- deps: IHandlerDeps,
172
- ): string {
167
+ function handleRegisterMemberBitmapField(ctx: IAssignmentContext): string {
173
168
  const regName = ctx.identifiers[0];
174
169
  const memberName = ctx.identifiers[1];
175
170
  const fieldName = ctx.identifiers[2];
176
171
 
177
172
  const fullRegMember = `${regName}_${memberName}`;
178
- const bitmapType = deps.symbols.registerMemberTypes.get(fullRegMember)!;
173
+ const bitmapType =
174
+ CodeGenState.symbols!.registerMemberTypes.get(fullRegMember)!;
179
175
 
180
- const fieldInfo = getBitmapFieldInfo(bitmapType, fieldName, ctx, deps);
176
+ const fieldInfo = getBitmapFieldInfo(bitmapType, fieldName, ctx);
181
177
  return generateBitmapWrite(fullRegMember, fieldInfo, ctx.generatedValue);
182
178
  }
183
179
 
@@ -189,7 +185,6 @@ function handleRegisterMemberBitmapField(
189
185
  */
190
186
  function handleScopedRegisterMemberBitmapField(
191
187
  ctx: IAssignmentContext,
192
- deps: IHandlerDeps,
193
188
  ): string {
194
189
  let scopeName: string;
195
190
  let regName: string;
@@ -198,10 +193,10 @@ function handleScopedRegisterMemberBitmapField(
198
193
 
199
194
  if (ctx.hasThis) {
200
195
  // this.REG.MEMBER.field - 3 identifiers
201
- if (!deps.currentScope) {
196
+ if (!CodeGenState.currentScope) {
202
197
  throw new Error("Error: 'this' can only be used inside a scope");
203
198
  }
204
- scopeName = deps.currentScope;
199
+ scopeName = CodeGenState.currentScope;
205
200
  regName = ctx.identifiers[0];
206
201
  memberName = ctx.identifiers[1];
207
202
  fieldName = ctx.identifiers[2];
@@ -213,17 +208,19 @@ function handleScopedRegisterMemberBitmapField(
213
208
  fieldName = ctx.identifiers[3];
214
209
 
215
210
  // Validate cross-scope access
216
- deps.validateCrossScopeVisibility(scopeName, regName);
211
+ gen().validateCrossScopeVisibility(scopeName, regName);
217
212
  }
218
213
 
219
214
  const fullRegName = `${scopeName}_${regName}`;
220
215
  const fullRegMember = `${fullRegName}_${memberName}`;
221
- const bitmapType = deps.symbols.registerMemberTypes.get(fullRegMember)!;
216
+ const bitmapType =
217
+ CodeGenState.symbols!.registerMemberTypes.get(fullRegMember)!;
222
218
 
223
- const fieldInfo = getBitmapFieldInfo(bitmapType, fieldName, ctx, deps);
219
+ const fieldInfo = getBitmapFieldInfo(bitmapType, fieldName, ctx);
224
220
 
225
221
  // Check for write-only register (includes w1s, w1c)
226
- const accessMod = deps.symbols.registerMemberAccess.get(fullRegMember);
222
+ const accessMod =
223
+ CodeGenState.symbols!.registerMemberAccess.get(fullRegMember);
227
224
  const isWriteOnly =
228
225
  accessMod === "wo" || accessMod === "w1s" || accessMod === "w1c";
229
226