c-next 0.2.15 → 0.2.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -0
- package/dist/index.js +1403 -427
- package/dist/index.js.map +3 -3
- package/grammar/CNext.g4 +4 -0
- package/package.json +5 -1
- package/src/transpiler/Transpiler.ts +90 -22
- package/src/transpiler/__tests__/DualCodePaths.test.ts +1 -1
- package/src/transpiler/logic/analysis/FunctionCallAnalyzer.ts +57 -10
- package/src/transpiler/logic/analysis/InitializationAnalyzer.ts +186 -14
- package/src/transpiler/logic/analysis/SignedShiftAnalyzer.ts +124 -12
- package/src/transpiler/logic/analysis/__tests__/FunctionCallAnalyzer.test.ts +200 -0
- package/src/transpiler/logic/analysis/__tests__/InitializationAnalyzer.test.ts +386 -1
- package/src/transpiler/logic/analysis/__tests__/SignedShiftAnalyzer.test.ts +211 -0
- package/src/transpiler/logic/parser/grammar/CNext.interp +1 -1
- package/src/transpiler/logic/parser/grammar/CNextParser.ts +154 -86
- package/src/transpiler/logic/symbols/SymbolTable.ts +54 -12
- package/src/transpiler/logic/symbols/SymbolUtils.ts +21 -8
- package/src/transpiler/logic/symbols/__tests__/SymbolTable.test.ts +39 -4
- package/src/transpiler/logic/symbols/__tests__/SymbolUtils.test.ts +2 -1
- package/src/transpiler/logic/symbols/c/utils/DeclaratorUtils.ts +2 -1
- package/src/transpiler/logic/symbols/cnext/__tests__/CNextResolver.integration.test.ts +5 -2
- package/src/transpiler/logic/symbols/cnext/__tests__/ScopeCollector.test.ts +5 -2
- package/src/transpiler/logic/symbols/cnext/collectors/ScopeCollector.ts +7 -2
- package/src/transpiler/logic/symbols/cnext/collectors/VariableCollector.ts +15 -2
- package/src/transpiler/logic/symbols/cnext/utils/TypeUtils.ts +64 -50
- package/src/transpiler/logic/symbols/cpp/utils/DeclaratorUtils.ts +4 -2
- package/src/transpiler/output/codegen/CodeGenerator.ts +151 -94
- package/src/transpiler/output/codegen/__tests__/CodeGenerator.coverage.test.ts +167 -18
- package/src/transpiler/output/codegen/__tests__/CodeGenerator.test.ts +150 -34
- package/src/transpiler/output/codegen/__tests__/TrackVariableTypeHelpers.test.ts +2 -2
- package/src/transpiler/output/codegen/__tests__/TypeValidator.test.ts +11 -0
- package/src/transpiler/output/codegen/generators/declarationGenerators/ScopeGenerator.ts +32 -8
- package/src/transpiler/output/codegen/generators/declarationGenerators/__tests__/ScopeGenerator.test.ts +91 -1
- package/src/transpiler/output/codegen/generators/expressions/BinaryExprGenerator.ts +43 -24
- package/src/transpiler/output/codegen/generators/expressions/CallExprGenerator.ts +48 -43
- package/src/transpiler/output/codegen/generators/expressions/ExpressionGenerator.ts +9 -2
- package/src/transpiler/output/codegen/generators/expressions/__tests__/CallExprGenerator.test.ts +44 -0
- package/src/transpiler/output/codegen/generators/expressions/__tests__/ExpressionGenerator.test.ts +82 -1
- package/src/transpiler/output/codegen/helpers/ParameterInputAdapter.ts +17 -3
- package/src/transpiler/output/codegen/helpers/ParameterSignatureBuilder.ts +17 -4
- package/src/transpiler/output/codegen/helpers/StringDeclHelper.ts +227 -32
- package/src/transpiler/output/codegen/helpers/SymbolLookupHelper.ts +0 -21
- package/src/transpiler/output/codegen/helpers/TypeGenerationHelper.ts +60 -39
- package/src/transpiler/output/codegen/helpers/TypeRegistrationEngine.ts +170 -36
- package/src/transpiler/output/codegen/helpers/VariableDeclHelper.ts +37 -39
- package/src/transpiler/output/codegen/helpers/__tests__/ParameterInputAdapter.test.ts +117 -0
- package/src/transpiler/output/codegen/helpers/__tests__/ParameterSignatureBuilder.test.ts +94 -2
- package/src/transpiler/output/codegen/helpers/__tests__/StringDeclHelper.test.ts +268 -1
- package/src/transpiler/output/codegen/helpers/__tests__/SymbolLookupHelper.test.ts +0 -64
- package/src/transpiler/output/codegen/helpers/__tests__/TypeRegistrationEngine.test.ts +101 -0
- package/src/transpiler/output/codegen/helpers/__tests__/VariableDeclHelper.test.ts +29 -5
- package/src/transpiler/output/codegen/types/ICallbackTypeInfo.ts +2 -1
- package/src/transpiler/output/codegen/types/IParameterInput.ts +7 -0
- package/src/transpiler/output/headers/BaseHeaderGenerator.ts +8 -0
- package/src/transpiler/output/headers/HeaderGeneratorUtils.ts +75 -0
- package/src/transpiler/output/headers/__tests__/HeaderGeneratorUtils.test.ts +280 -0
- package/src/transpiler/output/headers/generators/IHeaderTypeInput.ts +13 -0
- package/src/transpiler/output/headers/generators/generateStructHeader.ts +48 -28
- package/src/transpiler/state/CodeGenState.ts +71 -6
- package/src/transpiler/state/__tests__/CodeGenState.test.ts +253 -11
- package/src/transpiler/types/symbols/c/ICFieldInfo.ts +6 -2
- package/src/transpiler/types/symbols/cpp/ICppFieldInfo.ts +5 -2
- package/src/utils/LiteralUtils.ts +23 -0
- package/src/utils/ScopeUtils.ts +19 -0
- package/src/utils/__tests__/LiteralUtils.test.ts +101 -0
- package/src/utils/__tests__/ScopeUtils.test.ts +10 -0
- package/src/utils/types/IParameterSymbol.ts +1 -0
|
@@ -14,20 +14,33 @@ const RESERVED_FIELD_NAMES = new Set<string>([]);
|
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* Parse array dimensions from declarator text using regex.
|
|
17
|
-
* Extracts numeric values from square bracket notation
|
|
17
|
+
* Extracts both numeric values and macro names from square bracket notation.
|
|
18
|
+
*
|
|
19
|
+
* Issue #981: Support macro-sized array dimensions like [BUF_SIZE].
|
|
20
|
+
* Without this, struct fields with macro-sized arrays are incorrectly treated
|
|
21
|
+
* as non-arrays, causing bit extraction instead of array access.
|
|
18
22
|
*
|
|
19
23
|
* @param text - The declarator text containing array notation
|
|
20
|
-
* @returns Array of dimension sizes
|
|
24
|
+
* @returns Array of dimension sizes (numbers) or macro names (strings),
|
|
25
|
+
* e.g., [8] returns [8], [BUF_SIZE] returns ["BUF_SIZE"], [2][N] returns [2, "N"]
|
|
21
26
|
*/
|
|
22
|
-
function parseArrayDimensions(text: string): number[] {
|
|
23
|
-
const dimensions: number[] = [];
|
|
24
|
-
|
|
27
|
+
function parseArrayDimensions(text: string): (number | string)[] {
|
|
28
|
+
const dimensions: (number | string)[] = [];
|
|
29
|
+
// Match any bracket content: digits, identifiers, or expressions
|
|
30
|
+
// Captures: [8], [BUF_SIZE], [N], [SIZE + 1], etc.
|
|
31
|
+
const arrayMatches = text.match(/\[([^\]]+)\]/g);
|
|
25
32
|
|
|
26
33
|
if (arrayMatches) {
|
|
27
34
|
for (const match of arrayMatches) {
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
35
|
+
const content = match.slice(1, -1).trim();
|
|
36
|
+
// Try to parse as numeric first
|
|
37
|
+
const numericValue = Number.parseInt(content, 10);
|
|
38
|
+
if (!Number.isNaN(numericValue) && String(numericValue) === content) {
|
|
39
|
+
// Pure numeric dimension
|
|
40
|
+
dimensions.push(numericValue);
|
|
41
|
+
} else {
|
|
42
|
+
// Macro name or expression - store as string
|
|
43
|
+
dimensions.push(content);
|
|
31
44
|
}
|
|
32
45
|
}
|
|
33
46
|
}
|
|
@@ -658,6 +658,39 @@ describe("SymbolTable", () => {
|
|
|
658
658
|
const fields = symbolTable.getStructFields("Point");
|
|
659
659
|
expect(fields?.size).toBe(2);
|
|
660
660
|
});
|
|
661
|
+
|
|
662
|
+
it("Issue #981: addCSymbol should register struct fields with macro dimensions", () => {
|
|
663
|
+
// When a C struct with macro-sized array fields is added via addCSymbol,
|
|
664
|
+
// the fields should be registered in structFields for getMemberTypeInfo lookups
|
|
665
|
+
const cStructSymbol: TCSymbol = {
|
|
666
|
+
kind: "struct",
|
|
667
|
+
name: "msg_t",
|
|
668
|
+
sourceFile: "fake_lib.h",
|
|
669
|
+
sourceLine: 5,
|
|
670
|
+
sourceLanguage: ESourceLanguage.C,
|
|
671
|
+
isExported: true,
|
|
672
|
+
isUnion: false,
|
|
673
|
+
fields: new Map([
|
|
674
|
+
[
|
|
675
|
+
"data",
|
|
676
|
+
{ name: "data", type: "uint8_t", arrayDimensions: ["BUF_SIZE"] },
|
|
677
|
+
],
|
|
678
|
+
]),
|
|
679
|
+
};
|
|
680
|
+
|
|
681
|
+
symbolTable.addCSymbol(cStructSymbol);
|
|
682
|
+
|
|
683
|
+
// Struct fields should now be registered
|
|
684
|
+
const fields = symbolTable.getStructFields("msg_t");
|
|
685
|
+
expect(fields).toBeDefined();
|
|
686
|
+
expect(fields?.size).toBe(1);
|
|
687
|
+
|
|
688
|
+
// Field info should include the macro-sized array dimension
|
|
689
|
+
const dataField = symbolTable.getStructFieldInfo("msg_t", "data");
|
|
690
|
+
expect(dataField).toBeDefined();
|
|
691
|
+
expect(dataField?.type).toBe("uint8_t");
|
|
692
|
+
expect(dataField?.arrayDimensions).toEqual(["BUF_SIZE"]);
|
|
693
|
+
});
|
|
661
694
|
});
|
|
662
695
|
|
|
663
696
|
// ========================================================================
|
|
@@ -752,14 +785,16 @@ describe("SymbolTable", () => {
|
|
|
752
785
|
expect(symbolTable.isTypedefStructType("other_t")).toBe(false);
|
|
753
786
|
});
|
|
754
787
|
|
|
755
|
-
it("should
|
|
756
|
-
// Issue #
|
|
788
|
+
it("should return false when underlying struct tag has body (issue #948)", () => {
|
|
789
|
+
// Issue #948: Query-time resolution - if the underlying struct tag
|
|
790
|
+
// has a full body definition, this is NOT an external typedef struct
|
|
757
791
|
symbolTable.markTypedefStructType("point_t", "point.h");
|
|
758
792
|
expect(symbolTable.isTypedefStructType("point_t")).toBe(true);
|
|
759
|
-
//
|
|
793
|
+
// After marking the body, typedef struct type should return false
|
|
794
|
+
// because it's now a complete type (value semantics, not pointer)
|
|
760
795
|
symbolTable.registerStructTagAlias("_point", "point_t");
|
|
761
796
|
symbolTable.markStructTagHasBody("_point");
|
|
762
|
-
expect(symbolTable.isTypedefStructType("point_t")).toBe(
|
|
797
|
+
expect(symbolTable.isTypedefStructType("point_t")).toBe(false);
|
|
763
798
|
});
|
|
764
799
|
|
|
765
800
|
it("should get all typedef struct types", () => {
|
|
@@ -33,9 +33,10 @@ describe("SymbolUtils", () => {
|
|
|
33
33
|
expect(SymbolUtils.parseArrayDimensions("uint8_t data[10];")).toEqual([
|
|
34
34
|
10,
|
|
35
35
|
]);
|
|
36
|
+
// Issue #981: macro-sized arrays are captured as strings
|
|
36
37
|
expect(
|
|
37
38
|
SymbolUtils.parseArrayDimensions("char buffer[BUFFER_SIZE]"),
|
|
38
|
-
).toEqual([]);
|
|
39
|
+
).toEqual(["BUFFER_SIZE"]);
|
|
39
40
|
});
|
|
40
41
|
});
|
|
41
42
|
|
|
@@ -131,8 +131,9 @@ class DeclaratorUtils {
|
|
|
131
131
|
|
|
132
132
|
/**
|
|
133
133
|
* Extract array dimensions from a declarator.
|
|
134
|
+
* Issue #981: Returns (number | string)[] to support macro-sized arrays.
|
|
134
135
|
*/
|
|
135
|
-
static extractArrayDimensions(declarator: any): number[] {
|
|
136
|
+
static extractArrayDimensions(declarator: any): (number | string)[] {
|
|
136
137
|
const directDecl = declarator.directDeclarator?.();
|
|
137
138
|
if (!directDecl) return [];
|
|
138
139
|
|
|
@@ -95,14 +95,15 @@ describe("CNextResolver Integration", () => {
|
|
|
95
95
|
|
|
96
96
|
describe("scope handling", () => {
|
|
97
97
|
it("resolves scope with members", () => {
|
|
98
|
+
// ADR-016: Functions are public by default, variables are private by default
|
|
98
99
|
const code = `
|
|
99
100
|
scope Motor {
|
|
100
101
|
u32 position;
|
|
101
102
|
|
|
102
|
-
|
|
103
|
+
void init() {
|
|
103
104
|
}
|
|
104
105
|
|
|
105
|
-
void update() {
|
|
106
|
+
private void update() {
|
|
106
107
|
}
|
|
107
108
|
}
|
|
108
109
|
`;
|
|
@@ -122,6 +123,7 @@ describe("CNextResolver Integration", () => {
|
|
|
122
123
|
expect(SymbolGuards.isVariable(positionVar!)).toBe(true);
|
|
123
124
|
expect(positionVar!.scope.name).toBe("Motor");
|
|
124
125
|
|
|
126
|
+
// init() is public by default (no modifier needed)
|
|
125
127
|
const initFunc = symbols.find((s) => s.name === "init");
|
|
126
128
|
expect(initFunc).toBeDefined();
|
|
127
129
|
if (SymbolGuards.isFunction(initFunc!)) {
|
|
@@ -129,6 +131,7 @@ describe("CNextResolver Integration", () => {
|
|
|
129
131
|
expect(initFunc.scope.name).toBe("Motor");
|
|
130
132
|
}
|
|
131
133
|
|
|
134
|
+
// update() has explicit 'private' keyword
|
|
132
135
|
const updateFunc = symbols.find((s) => s.name === "update");
|
|
133
136
|
expect(updateFunc).toBeDefined();
|
|
134
137
|
if (SymbolGuards.isFunction(updateFunc!)) {
|
|
@@ -32,11 +32,12 @@ describe("ScopeCollector", () => {
|
|
|
32
32
|
});
|
|
33
33
|
|
|
34
34
|
it("collects scope with functions", () => {
|
|
35
|
+
// ADR-016: Functions are public by default, use explicit 'private' for internal functions
|
|
35
36
|
const code = `
|
|
36
37
|
scope Motor {
|
|
37
|
-
|
|
38
|
+
void init() {
|
|
38
39
|
}
|
|
39
|
-
void update() {
|
|
40
|
+
private void update() {
|
|
40
41
|
}
|
|
41
42
|
}
|
|
42
43
|
`;
|
|
@@ -45,7 +46,9 @@ describe("ScopeCollector", () => {
|
|
|
45
46
|
const result = ScopeCollector.collect(scopeCtx, "test.cnx", new Set());
|
|
46
47
|
|
|
47
48
|
expect(result.scopeSymbol.members).toEqual(["init", "update"]);
|
|
49
|
+
// init() is public by default (no modifier)
|
|
48
50
|
expect(result.scopeSymbol.memberVisibility.get("init")).toBe("public");
|
|
51
|
+
// update() has explicit 'private' keyword
|
|
49
52
|
expect(result.scopeSymbol.memberVisibility.get("update")).toBe("private");
|
|
50
53
|
|
|
51
54
|
expect(result.memberSymbols.length).toBe(2);
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
import * as Parser from "../../../parser/grammar/CNextParser";
|
|
10
10
|
import ESourceLanguage from "../../../../../utils/types/ESourceLanguage";
|
|
11
|
+
import ScopeUtils from "../../../../../utils/ScopeUtils";
|
|
11
12
|
import TSymbol from "../../../../types/symbols/TSymbol";
|
|
12
13
|
import TVisibility from "../../../../types/TVisibility";
|
|
13
14
|
import IScopeCollectorResult from "../types/IScopeCollectorResult";
|
|
@@ -69,10 +70,14 @@ class ScopeCollector {
|
|
|
69
70
|
const memberSymbols: TSymbol[] = [];
|
|
70
71
|
|
|
71
72
|
for (const member of ctx.scopeMember()) {
|
|
72
|
-
// ADR-016: Extract visibility
|
|
73
|
+
// ADR-016: Extract visibility with member-type-aware defaults
|
|
73
74
|
const visibilityMod = member.visibilityModifier();
|
|
75
|
+
const explicitVisibility = visibilityMod?.getText() as
|
|
76
|
+
| TVisibility
|
|
77
|
+
| undefined;
|
|
78
|
+
const isFunction = member.functionDeclaration() !== null;
|
|
74
79
|
const visibility: TVisibility =
|
|
75
|
-
|
|
80
|
+
explicitVisibility ?? ScopeUtils.getDefaultVisibility(isFunction);
|
|
76
81
|
const isPublic = visibility === "public";
|
|
77
82
|
|
|
78
83
|
// Handle variable declarations
|
|
@@ -75,16 +75,28 @@ class VariableCollector {
|
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
/**
|
|
78
|
-
* Collect dimensions from C-Next style arrayType syntax (u16[8] arr, u16[4][4] arr).
|
|
78
|
+
* Collect dimensions from C-Next style arrayType syntax (u16[8] arr, u16[4][4] arr, u16[] arr).
|
|
79
|
+
* Handles size inference from initializer when dimension is empty.
|
|
79
80
|
*/
|
|
80
81
|
private static collectArrayTypeDimensions(
|
|
81
82
|
arrayTypeCtx: Parser.ArrayTypeContext,
|
|
82
83
|
constValues: Map<string, number> | undefined,
|
|
84
|
+
initExpr: Parser.ExpressionContext | null,
|
|
83
85
|
): (number | string)[] {
|
|
84
86
|
const dimensions: (number | string)[] = [];
|
|
85
87
|
for (const dim of arrayTypeCtx.arrayTypeDimension()) {
|
|
86
88
|
const sizeExpr = dim.expression();
|
|
87
|
-
|
|
89
|
+
|
|
90
|
+
if (!sizeExpr) {
|
|
91
|
+
// Issue #636: Empty dimension [] - infer size from array initializer
|
|
92
|
+
if (initExpr) {
|
|
93
|
+
const inferredSize = ArrayInitializerUtils.getInferredSize(initExpr);
|
|
94
|
+
if (inferredSize !== undefined) {
|
|
95
|
+
dimensions.push(inferredSize);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
88
100
|
|
|
89
101
|
const dimText = sizeExpr.getText();
|
|
90
102
|
const literalSize = LiteralUtils.parseIntegerLiteral(dimText);
|
|
@@ -146,6 +158,7 @@ class VariableCollector {
|
|
|
146
158
|
...VariableCollector.collectArrayTypeDimensions(
|
|
147
159
|
arrayTypeCtx,
|
|
148
160
|
constValues,
|
|
161
|
+
initExpr,
|
|
149
162
|
),
|
|
150
163
|
);
|
|
151
164
|
}
|
|
@@ -6,14 +6,16 @@ import * as Parser from "../../../parser/grammar/CNextParser";
|
|
|
6
6
|
import CNEXT_TO_C_TYPE_MAP from "../../../../../utils/constants/TypeMappings";
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
9
|
+
* Common interface for type contexts that share the same type accessors.
|
|
10
|
+
* Both TypeContext and ArrayTypeContext have these methods.
|
|
10
11
|
*/
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
):
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
interface ITypeAccessors {
|
|
13
|
+
primitiveType(): Parser.PrimitiveTypeContext | null;
|
|
14
|
+
userType(): Parser.UserTypeContext | null;
|
|
15
|
+
stringType(): Parser.StringTypeContext | null;
|
|
16
|
+
scopedType(): Parser.ScopedTypeContext | null;
|
|
17
|
+
qualifiedType(): Parser.QualifiedTypeContext | null;
|
|
18
|
+
globalType(): Parser.GlobalTypeContext | null;
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
/**
|
|
@@ -25,19 +27,50 @@ function resolveStringType(stringCtx: Parser.StringTypeContext): string {
|
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
/**
|
|
28
|
-
*
|
|
30
|
+
* Dispatch type resolution for contexts that share common type accessors.
|
|
31
|
+
* Handles scoped, qualified, global, primitive, string, and user types.
|
|
32
|
+
* Used by both bare type contexts and array element type contexts.
|
|
33
|
+
*
|
|
34
|
+
* @returns The resolved type name, or null if no matching type accessor found
|
|
29
35
|
*/
|
|
30
|
-
function
|
|
31
|
-
|
|
32
|
-
|
|
36
|
+
function dispatchTypeResolution(
|
|
37
|
+
accessors: ITypeAccessors,
|
|
38
|
+
scopeName?: string,
|
|
39
|
+
): string | null {
|
|
40
|
+
// Handle this.Type for scoped types (e.g., this.State -> Motor_State)
|
|
41
|
+
if (accessors.scopedType()) {
|
|
42
|
+
const typeName = accessors.scopedType()!.IDENTIFIER().getText();
|
|
43
|
+
return scopeName ? `${scopeName}_${typeName}` : typeName;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Handle global.Type for global types inside scope
|
|
47
|
+
// global.ECategory -> ECategory (just the type name, no scope prefix)
|
|
48
|
+
if (accessors.globalType()) {
|
|
49
|
+
return accessors.globalType()!.IDENTIFIER().getText();
|
|
33
50
|
}
|
|
34
|
-
|
|
35
|
-
|
|
51
|
+
|
|
52
|
+
// Handle Scope.Type from outside scope (e.g., Motor.State -> Motor_State)
|
|
53
|
+
if (accessors.qualifiedType()) {
|
|
54
|
+
const identifiers = accessors.qualifiedType()!.IDENTIFIER();
|
|
55
|
+
return identifiers.map((id) => id.getText()).join("_");
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Handle user-defined types
|
|
59
|
+
if (accessors.userType()) {
|
|
60
|
+
return accessors.userType()!.getText();
|
|
36
61
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
62
|
+
|
|
63
|
+
// Handle primitive types
|
|
64
|
+
if (accessors.primitiveType()) {
|
|
65
|
+
return accessors.primitiveType()!.getText();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Handle string types - preserve capacity for validation (Issue #139)
|
|
69
|
+
if (accessors.stringType()) {
|
|
70
|
+
return resolveStringType(accessors.stringType()!);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return null;
|
|
41
74
|
}
|
|
42
75
|
|
|
43
76
|
class TypeUtils {
|
|
@@ -56,42 +89,23 @@ class TypeUtils {
|
|
|
56
89
|
): string {
|
|
57
90
|
if (!ctx) return "void";
|
|
58
91
|
|
|
59
|
-
// Handle this.Type for scoped types (e.g., this.State -> Motor_State)
|
|
60
|
-
if (ctx.scopedType()) {
|
|
61
|
-
return resolveScopedType(ctx.scopedType()!, scopeName);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// Issue #478: Handle global.Type for global types inside scope
|
|
65
|
-
// global.ECategory -> ECategory (just the type name, no scope prefix)
|
|
66
|
-
if (ctx.globalType()) {
|
|
67
|
-
return ctx.globalType()!.IDENTIFIER().getText();
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// Handle Scope.Type from outside scope (e.g., Motor.State -> Motor_State)
|
|
71
|
-
if (ctx.qualifiedType()) {
|
|
72
|
-
const identifiers = ctx.qualifiedType()!.IDENTIFIER();
|
|
73
|
-
return identifiers.map((id) => id.getText()).join("_");
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// Handle user-defined types
|
|
77
|
-
if (ctx.userType()) {
|
|
78
|
-
return ctx.userType()!.getText();
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// Handle primitive types
|
|
82
|
-
if (ctx.primitiveType()) {
|
|
83
|
-
return ctx.primitiveType()!.getText();
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// Handle string types - preserve capacity for validation (Issue #139)
|
|
87
|
-
if (ctx.stringType()) {
|
|
88
|
-
return resolveStringType(ctx.stringType()!);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
92
|
// Handle arrayType: Type[size] - extract the inner type without dimension
|
|
92
93
|
// The dimension is tracked separately in arrayDimensions
|
|
93
94
|
if (ctx.arrayType()) {
|
|
94
|
-
|
|
95
|
+
const result = dispatchTypeResolution(ctx.arrayType()!, scopeName);
|
|
96
|
+
if (result !== null) {
|
|
97
|
+
return result;
|
|
98
|
+
}
|
|
99
|
+
// Fallback for unrecognized array types - strip the dimension part
|
|
100
|
+
const text = ctx.arrayType()!.getText();
|
|
101
|
+
const bracketIdx = text.indexOf("[");
|
|
102
|
+
return bracketIdx > 0 ? text.substring(0, bracketIdx) : text;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Non-array types - dispatch directly
|
|
106
|
+
const result = dispatchTypeResolution(ctx, scopeName);
|
|
107
|
+
if (result !== null) {
|
|
108
|
+
return result;
|
|
95
109
|
}
|
|
96
110
|
|
|
97
111
|
// Fallback
|
|
@@ -217,8 +217,9 @@ class DeclaratorUtils {
|
|
|
217
217
|
|
|
218
218
|
/**
|
|
219
219
|
* Extract array dimensions from a declarator.
|
|
220
|
+
* Issue #981: Returns (number | string)[] to support macro-sized arrays.
|
|
220
221
|
*/
|
|
221
|
-
static extractArrayDimensions(declarator: any): number[] {
|
|
222
|
+
static extractArrayDimensions(declarator: any): (number | string)[] {
|
|
222
223
|
// For C++, we need to check both pointer and no-pointer declarators
|
|
223
224
|
const ptrDecl = declarator.pointerDeclarator?.();
|
|
224
225
|
if (ptrDecl) {
|
|
@@ -238,8 +239,9 @@ class DeclaratorUtils {
|
|
|
238
239
|
|
|
239
240
|
/**
|
|
240
241
|
* Extract array dimensions from a noPointerDeclarator.
|
|
242
|
+
* Issue #981: Returns (number | string)[] to support macro-sized arrays.
|
|
241
243
|
*/
|
|
242
|
-
static extractArrayDimensionsFromNoPtr(noPtr: any): number[] {
|
|
244
|
+
static extractArrayDimensionsFromNoPtr(noPtr: any): (number | string)[] {
|
|
243
245
|
// Use shared utility for regex-based extraction
|
|
244
246
|
return SymbolUtils.parseArrayDimensions(noPtr.getText());
|
|
245
247
|
}
|