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.
- package/package.json +5 -1
- package/src/transpiler/Transpiler.ts +49 -42
- package/src/transpiler/logic/symbols/cnext/__tests__/TSymbolAdapter.test.ts +129 -0
- package/src/transpiler/logic/symbols/cnext/adapters/TSymbolAdapter.ts +27 -3
- package/src/transpiler/output/codegen/CodeGenerator.ts +131 -186
- package/src/transpiler/output/codegen/TypeResolver.ts +2 -2
- package/src/transpiler/output/codegen/TypeValidator.ts +1 -1
- package/src/transpiler/output/codegen/__tests__/CodeGenerator.coverage.test.ts +1087 -0
- package/src/transpiler/output/codegen/__tests__/CodeGenerator.test.ts +665 -1315
- package/src/transpiler/output/codegen/__tests__/TypeResolver.test.ts +1 -1
- package/src/transpiler/output/codegen/__tests__/TypeValidator.resolution.test.ts +1 -1
- 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 +1 -1
- package/src/transpiler/output/codegen/analysis/__tests__/StringLengthCounter.test.ts +1 -1
- package/src/transpiler/output/codegen/assignment/AssignmentClassifier.ts +1 -1
- package/src/transpiler/output/codegen/assignment/__tests__/AssignmentClassifier.test.ts +1 -1
- package/src/transpiler/output/codegen/assignment/handlers/AccessPatternHandlers.ts +24 -27
- package/src/transpiler/output/codegen/assignment/handlers/ArrayHandlers.ts +25 -18
- package/src/transpiler/output/codegen/assignment/handlers/BitAccessHandlers.ts +27 -33
- package/src/transpiler/output/codegen/assignment/handlers/BitmapHandlers.ts +39 -42
- package/src/transpiler/output/codegen/assignment/handlers/RegisterHandlers.ts +39 -97
- package/src/transpiler/output/codegen/assignment/handlers/RegisterUtils.ts +75 -0
- package/src/transpiler/output/codegen/assignment/handlers/SimpleHandler.ts +9 -6
- package/src/transpiler/output/codegen/assignment/handlers/SpecialHandlers.ts +30 -22
- package/src/transpiler/output/codegen/assignment/handlers/StringHandlers.ts +42 -50
- package/src/transpiler/output/codegen/assignment/handlers/TAssignmentHandler.ts +6 -5
- package/src/transpiler/output/codegen/assignment/handlers/__tests__/AccessPatternHandlers.test.ts +81 -134
- package/src/transpiler/output/codegen/assignment/handlers/__tests__/ArrayHandlers.test.ts +85 -124
- package/src/transpiler/output/codegen/assignment/handlers/__tests__/BitAccessHandlers.test.ts +82 -124
- package/src/transpiler/output/codegen/assignment/handlers/__tests__/BitmapHandlers.test.ts +135 -297
- package/src/transpiler/output/codegen/assignment/handlers/__tests__/RegisterHandlers.test.ts +105 -227
- package/src/transpiler/output/codegen/assignment/handlers/__tests__/RegisterUtils.test.ts +214 -1
- package/src/transpiler/output/codegen/assignment/handlers/__tests__/SpecialHandlers.test.ts +66 -127
- package/src/transpiler/output/codegen/assignment/handlers/__tests__/StringHandlers.test.ts +37 -83
- package/src/transpiler/output/codegen/assignment/handlers/__tests__/handlerTestUtils.ts +162 -0
- package/src/transpiler/output/codegen/generators/expressions/PostfixExpressionGenerator.ts +618 -12
- package/src/transpiler/output/codegen/generators/expressions/__tests__/PostfixExpressionGenerator.test.ts +819 -0
- package/src/transpiler/output/codegen/helpers/ArrayInitHelper.ts +1 -1
- package/src/transpiler/output/codegen/helpers/AssignmentExpectedTypeResolver.ts +1 -1
- package/src/transpiler/output/codegen/helpers/AssignmentValidator.ts +1 -1
- package/src/transpiler/output/codegen/helpers/CppModeHelper.ts +1 -1
- package/src/transpiler/output/codegen/helpers/EnumAssignmentValidator.ts +1 -1
- package/src/transpiler/output/codegen/helpers/FloatBitHelper.ts +1 -1
- package/src/transpiler/output/codegen/helpers/ParameterInputAdapter.ts +337 -0
- package/src/transpiler/output/codegen/helpers/ParameterSignatureBuilder.ts +135 -0
- package/src/transpiler/output/codegen/helpers/StringDeclHelper.ts +1 -1
- package/src/transpiler/output/codegen/helpers/VariableDeclarationFormatter.ts +118 -0
- package/src/transpiler/output/codegen/helpers/__tests__/ArrayInitHelper.test.ts +1 -1
- package/src/transpiler/output/codegen/helpers/__tests__/AssignmentExpectedTypeResolver.test.ts +1 -1
- package/src/transpiler/output/codegen/helpers/__tests__/AssignmentValidator.test.ts +1 -1
- package/src/transpiler/output/codegen/helpers/__tests__/CppModeHelper.test.ts +1 -1
- package/src/transpiler/output/codegen/helpers/__tests__/EnumAssignmentValidator.test.ts +1 -1
- package/src/transpiler/output/codegen/helpers/__tests__/FloatBitHelper.test.ts +1 -1
- package/src/transpiler/output/codegen/helpers/__tests__/ParameterInputAdapter.test.ts +426 -0
- package/src/transpiler/output/codegen/helpers/__tests__/ParameterSignatureBuilder.test.ts +315 -0
- package/src/transpiler/output/codegen/helpers/__tests__/StringDeclHelper.test.ts +1 -1
- package/src/transpiler/output/codegen/helpers/__tests__/VariableDeclarationFormatter.test.ts +333 -0
- package/src/transpiler/output/codegen/resolution/EnumTypeResolver.ts +1 -1
- package/src/transpiler/output/codegen/resolution/ScopeResolver.ts +1 -1
- package/src/transpiler/output/codegen/resolution/SizeofResolver.ts +1 -1
- package/src/transpiler/output/codegen/resolution/__tests__/EnumTypeResolver.test.ts +1 -1
- package/src/transpiler/output/codegen/resolution/__tests__/SizeofResolver.test.ts +1 -1
- package/src/transpiler/output/codegen/types/ICodeGenApi.ts +57 -0
- package/src/transpiler/output/codegen/types/IParameterInput.ts +58 -0
- package/src/transpiler/output/codegen/types/IVariableFormatInput.ts +51 -0
- package/src/transpiler/output/headers/BaseHeaderGenerator.ts +20 -35
- package/src/transpiler/output/headers/HeaderGeneratorUtils.ts +21 -48
- package/src/transpiler/output/headers/__tests__/HeaderGeneratorUtils.test.ts +0 -64
- package/src/transpiler/{output/codegen → state}/CodeGenState.ts +46 -26
- package/src/transpiler/{output/codegen → state}/__tests__/CodeGenState.test.ts +12 -2
- 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 "
|
|
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 "
|
|
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 "
|
|
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 "
|
|
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 "
|
|
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 "
|
|
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 "
|
|
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 "
|
|
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 "
|
|
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 (
|
|
32
|
-
|
|
34
|
+
if (CodeGenState.isKnownScope(firstId) && ctx.identifiers.length >= 2) {
|
|
35
|
+
gen().validateCrossScopeVisibility(firstId, ctx.identifiers[1]);
|
|
33
36
|
}
|
|
34
37
|
|
|
35
|
-
const target =
|
|
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
|
|
45
|
-
if (!
|
|
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 =
|
|
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 =
|
|
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 =
|
|
77
|
-
|
|
78
|
-
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
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) =>
|
|
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
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
|
|
37
|
+
function handleIntegerBit(ctx: IAssignmentContext): string {
|
|
32
38
|
validateNotCompound(ctx);
|
|
33
39
|
|
|
34
40
|
const name = ctx.identifiers[0];
|
|
35
|
-
const bitIndex =
|
|
36
|
-
const typeInfo =
|
|
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 =
|
|
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 =
|
|
73
|
-
const width =
|
|
74
|
-
const typeInfo =
|
|
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 =
|
|
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 =
|
|
114
|
+
const target = gen().generateAssignmentTarget(ctx.targetCtx);
|
|
115
115
|
|
|
116
116
|
// Extract the bit index from the last subscript
|
|
117
|
-
const bitIndex =
|
|
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 =
|
|
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) => `[${
|
|
145
|
+
.map((e) => `[${gen().generateExpression(e)}]`)
|
|
149
146
|
.join("");
|
|
150
|
-
const bitIndex =
|
|
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 += "[" +
|
|
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 =
|
|
194
|
-
const width =
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
112
|
+
const typeInfo = CodeGenState.typeRegistry.get(varName);
|
|
106
113
|
const bitmapType = typeInfo!.bitmapTypeName!;
|
|
107
114
|
|
|
108
|
-
const fieldInfo = getBitmapFieldInfo(bitmapType, fieldName, ctx
|
|
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
|
|
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 =
|
|
133
|
+
const typeInfo = CodeGenState.typeRegistry.get(arrayName);
|
|
133
134
|
const bitmapType = typeInfo!.bitmapTypeName!;
|
|
134
135
|
|
|
135
|
-
const fieldInfo = getBitmapFieldInfo(bitmapType, fieldName, ctx
|
|
136
|
-
const index =
|
|
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 =
|
|
154
|
-
const memberInfo =
|
|
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
|
|
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 =
|
|
173
|
+
const bitmapType =
|
|
174
|
+
CodeGenState.symbols!.registerMemberTypes.get(fullRegMember)!;
|
|
179
175
|
|
|
180
|
-
const fieldInfo = getBitmapFieldInfo(bitmapType, fieldName, ctx
|
|
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 (!
|
|
196
|
+
if (!CodeGenState.currentScope) {
|
|
202
197
|
throw new Error("Error: 'this' can only be used inside a scope");
|
|
203
198
|
}
|
|
204
|
-
scopeName =
|
|
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
|
-
|
|
211
|
+
gen().validateCrossScopeVisibility(scopeName, regName);
|
|
217
212
|
}
|
|
218
213
|
|
|
219
214
|
const fullRegName = `${scopeName}_${regName}`;
|
|
220
215
|
const fullRegMember = `${fullRegName}_${memberName}`;
|
|
221
|
-
const bitmapType =
|
|
216
|
+
const bitmapType =
|
|
217
|
+
CodeGenState.symbols!.registerMemberTypes.get(fullRegMember)!;
|
|
222
218
|
|
|
223
|
-
const fieldInfo = getBitmapFieldInfo(bitmapType, fieldName, ctx
|
|
219
|
+
const fieldInfo = getBitmapFieldInfo(bitmapType, fieldName, ctx);
|
|
224
220
|
|
|
225
221
|
// Check for write-only register (includes w1s, w1c)
|
|
226
|
-
const accessMod =
|
|
222
|
+
const accessMod =
|
|
223
|
+
CodeGenState.symbols!.registerMemberAccess.get(fullRegMember);
|
|
227
224
|
const isWriteOnly =
|
|
228
225
|
accessMod === "wo" || accessMod === "w1s" || accessMod === "w1c";
|
|
229
226
|
|