c-next 0.1.61 → 0.1.63
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +86 -63
- package/grammar/CNext.g4 +3 -17
- package/package.json +1 -1
- package/src/cli/serve/ServeCommand.ts +57 -45
- package/src/lib/__tests__/parseCHeader.mocked.test.ts +145 -0
- package/src/transpiler/Transpiler.ts +603 -613
- package/src/transpiler/__tests__/DualCodePaths.test.ts +5 -1
- package/src/transpiler/__tests__/Transpiler.coverage.test.ts +2 -99
- package/src/transpiler/__tests__/Transpiler.test.ts +3 -26
- package/src/transpiler/data/IncludeTreeWalker.ts +1 -1
- package/src/transpiler/logic/analysis/InitializationAnalyzer.ts +23 -52
- package/src/transpiler/logic/parser/grammar/CNext.interp +1 -3
- package/src/transpiler/logic/parser/grammar/CNextListener.ts +0 -22
- package/src/transpiler/logic/parser/grammar/CNextParser.ts +665 -1084
- package/src/transpiler/logic/parser/grammar/CNextVisitor.ts +0 -14
- package/src/transpiler/logic/symbols/CppSymbolCollector.ts +67 -43
- package/src/transpiler/logic/symbols/cnext/collectors/StructCollector.ts +156 -70
- package/src/transpiler/logic/symbols/cnext/collectors/VariableCollector.ts +31 -6
- package/src/transpiler/logic/symbols/cnext/utils/TypeUtils.ts +43 -11
- package/src/transpiler/output/codegen/CodeGenState.ts +811 -0
- package/src/transpiler/output/codegen/CodeGenerator.ts +1410 -2587
- package/src/transpiler/output/codegen/TypeResolver.ts +193 -149
- package/src/transpiler/output/codegen/TypeValidator.ts +148 -370
- package/src/transpiler/output/codegen/__tests__/CodeGenState.test.ts +446 -0
- package/src/transpiler/output/codegen/__tests__/CodeGenerator.test.ts +2082 -52
- package/src/transpiler/output/codegen/__tests__/TrackVariableTypeHelpers.test.ts +1 -1
- package/src/transpiler/output/codegen/__tests__/TypeResolver.test.ts +435 -196
- package/src/transpiler/output/codegen/__tests__/TypeValidator.resolution.test.ts +51 -67
- package/src/transpiler/output/codegen/__tests__/TypeValidator.test.ts +495 -471
- package/src/transpiler/output/codegen/analysis/MemberChainAnalyzer.ts +227 -66
- package/src/transpiler/output/codegen/analysis/StringLengthCounter.ts +55 -58
- package/src/transpiler/output/codegen/analysis/__tests__/MemberChainAnalyzer.test.ts +288 -275
- package/src/transpiler/output/codegen/analysis/__tests__/StringLengthCounter.test.ts +101 -144
- package/src/transpiler/output/codegen/assignment/AssignmentClassifier.ts +195 -133
- package/src/transpiler/output/codegen/assignment/AssignmentContextBuilder.ts +24 -74
- package/src/transpiler/output/codegen/assignment/AssignmentKind.ts +3 -0
- package/src/transpiler/output/codegen/assignment/IAssignmentContext.ts +3 -0
- package/src/transpiler/output/codegen/assignment/__tests__/AssignmentClassifier.test.ts +290 -320
- package/src/transpiler/output/codegen/assignment/handlers/BitAccessHandlers.ts +42 -0
- package/src/transpiler/output/codegen/assignment/handlers/__tests__/BitAccessHandlers.test.ts +76 -2
- package/src/transpiler/output/codegen/generators/GeneratorRegistry.ts +12 -0
- package/src/transpiler/output/codegen/generators/IOrchestrator.ts +5 -1
- package/src/transpiler/output/codegen/generators/__tests__/GeneratorRegistry.test.ts +28 -1
- package/src/transpiler/output/codegen/generators/declarationGenerators/ArrayDimensionUtils.ts +67 -0
- package/src/transpiler/output/codegen/generators/declarationGenerators/RegisterGenerator.ts +11 -24
- package/src/transpiler/output/codegen/generators/declarationGenerators/RegisterMacroGenerator.ts +64 -0
- package/src/transpiler/output/codegen/generators/declarationGenerators/ScopeGenerator.ts +137 -61
- package/src/transpiler/output/codegen/generators/declarationGenerators/ScopedRegisterGenerator.ts +18 -27
- package/src/transpiler/output/codegen/generators/declarationGenerators/StructGenerator.ts +100 -23
- package/src/transpiler/output/codegen/generators/declarationGenerators/__tests__/ArrayDimensionUtils.test.ts +125 -0
- package/src/transpiler/output/codegen/generators/declarationGenerators/__tests__/ScopeGenerator.test.ts +157 -4
- package/src/transpiler/output/codegen/generators/expressions/PostfixExpressionGenerator.ts +5 -1
- package/src/transpiler/output/codegen/generators/statements/ControlFlowGenerator.ts +1 -17
- package/src/transpiler/output/codegen/generators/support/HelperGenerator.ts +23 -22
- package/src/transpiler/output/codegen/helpers/ArrayAccessHelper.ts +129 -0
- package/src/transpiler/output/codegen/helpers/ArrayInitHelper.ts +54 -61
- package/src/transpiler/output/codegen/helpers/AssignmentExpectedTypeResolver.ts +40 -44
- package/src/transpiler/output/codegen/helpers/AssignmentTargetExtractor.ts +17 -45
- package/src/transpiler/output/codegen/helpers/AssignmentValidator.ts +83 -78
- package/src/transpiler/output/codegen/helpers/CppModeHelper.ts +22 -30
- package/src/transpiler/output/codegen/helpers/EnumAssignmentValidator.ts +108 -50
- package/src/transpiler/output/codegen/helpers/FloatBitHelper.ts +16 -31
- package/src/transpiler/output/codegen/helpers/MemberSeparatorResolver.ts +10 -3
- package/src/transpiler/output/codegen/helpers/StringDeclHelper.ts +103 -96
- package/src/transpiler/output/codegen/helpers/SymbolLookupHelper.ts +44 -0
- package/src/transpiler/output/codegen/helpers/TypeGenerationHelper.ts +9 -0
- package/src/transpiler/output/codegen/helpers/__tests__/ArrayAccessHelper.test.ts +479 -0
- package/src/transpiler/output/codegen/helpers/__tests__/ArrayInitHelper.test.ts +58 -103
- package/src/transpiler/output/codegen/helpers/__tests__/AssignmentExpectedTypeResolver.test.ts +97 -40
- package/src/transpiler/output/codegen/helpers/__tests__/AssignmentValidator.test.ts +223 -128
- package/src/transpiler/output/codegen/helpers/__tests__/CppModeHelper.test.ts +68 -41
- package/src/transpiler/output/codegen/helpers/__tests__/EnumAssignmentValidator.test.ts +198 -47
- package/src/transpiler/output/codegen/helpers/__tests__/FloatBitHelper.test.ts +39 -37
- package/src/transpiler/output/codegen/helpers/__tests__/MemberSeparatorResolver.test.ts +1 -0
- package/src/transpiler/output/codegen/helpers/__tests__/StringDeclHelper.test.ts +191 -453
- package/src/transpiler/output/codegen/helpers/__tests__/SymbolLookupHelper.test.ts +201 -0
- package/src/transpiler/output/codegen/helpers/__tests__/TypeGenerationHelper.test.ts +50 -0
- package/src/transpiler/output/codegen/resolution/EnumTypeResolver.ts +229 -0
- package/src/transpiler/output/codegen/resolution/ScopeResolver.ts +60 -0
- package/src/transpiler/output/codegen/resolution/SizeofResolver.ts +177 -0
- package/src/transpiler/output/codegen/resolution/__tests__/EnumTypeResolver.test.ts +336 -0
- package/src/transpiler/output/codegen/resolution/__tests__/SizeofResolver.test.ts +201 -0
- package/src/transpiler/output/codegen/types/IArrayAccessDeps.ts +23 -0
- package/src/transpiler/output/codegen/types/IArrayAccessInfo.ts +26 -0
- package/src/transpiler/output/codegen/types/IMemberSeparatorDeps.ts +7 -0
- package/src/transpiler/output/codegen/utils/CodegenParserUtils.ts +98 -0
- package/src/transpiler/output/codegen/utils/ExpressionUnwrapper.ts +22 -22
- package/src/transpiler/output/codegen/utils/__tests__/CodegenParserUtils.test.ts +228 -0
- package/src/transpiler/types/IFileResult.ts +0 -4
- package/src/transpiler/types/IPipelineFile.ts +27 -0
- package/src/transpiler/types/IPipelineInput.ts +23 -0
- package/src/transpiler/types/TranspilerState.ts +1 -1
- package/src/utils/FormatUtils.ts +28 -2
- package/src/utils/MapUtils.ts +25 -0
- package/src/utils/PostfixAnalysisUtils.ts +48 -0
- package/src/utils/__tests__/FormatUtils.test.ts +42 -0
- package/src/utils/__tests__/MapUtils.test.ts +85 -0
- package/src/utils/constants/OperatorMappings.ts +19 -0
- package/src/transpiler/logic/StandaloneContextBuilder.ts +0 -150
- package/src/transpiler/logic/__tests__/StandaloneContextBuilder.test.ts +0 -647
- package/src/transpiler/output/codegen/types/ITypeResolverDeps.ts +0 -23
- package/src/transpiler/output/codegen/types/ITypeValidatorDeps.ts +0 -53
- package/src/transpiler/types/ITranspileContext.ts +0 -49
- package/src/transpiler/types/ITranspileContribution.ts +0 -32
|
@@ -77,8 +77,6 @@ import { FieldInitializerListContext } from "./CNextParser.js";
|
|
|
77
77
|
import { FieldInitializerContext } from "./CNextParser.js";
|
|
78
78
|
import { ArrayInitializerContext } from "./CNextParser.js";
|
|
79
79
|
import { ArrayInitializerElementContext } from "./CNextParser.js";
|
|
80
|
-
import { MemberAccessContext } from "./CNextParser.js";
|
|
81
|
-
import { ArrayAccessContext } from "./CNextParser.js";
|
|
82
80
|
import { ArgumentListContext } from "./CNextParser.js";
|
|
83
81
|
import { TypeContext } from "./CNextParser.js";
|
|
84
82
|
import { ScopedTypeContext } from "./CNextParser.js";
|
|
@@ -546,18 +544,6 @@ export class CNextVisitor<Result> extends AbstractParseTreeVisitor<Result> {
|
|
|
546
544
|
* @return the visitor result
|
|
547
545
|
*/
|
|
548
546
|
visitArrayInitializerElement?: (ctx: ArrayInitializerElementContext) => Result;
|
|
549
|
-
/**
|
|
550
|
-
* Visit a parse tree produced by `CNextParser.memberAccess`.
|
|
551
|
-
* @param ctx the parse tree
|
|
552
|
-
* @return the visitor result
|
|
553
|
-
*/
|
|
554
|
-
visitMemberAccess?: (ctx: MemberAccessContext) => Result;
|
|
555
|
-
/**
|
|
556
|
-
* Visit a parse tree produced by `CNextParser.arrayAccess`.
|
|
557
|
-
* @param ctx the parse tree
|
|
558
|
-
* @return the visitor result
|
|
559
|
-
*/
|
|
560
|
-
visitArrayAccess?: (ctx: ArrayAccessContext) => Result;
|
|
561
547
|
/**
|
|
562
548
|
* Visit a parse tree produced by `CNextParser.argumentList`.
|
|
563
549
|
* @param ctx the parse tree
|
|
@@ -39,6 +39,55 @@ class CppSymbolCollector {
|
|
|
39
39
|
return SymbolCollectorContext.getWarnings(this.ctx);
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
// ========================================================================
|
|
43
|
+
// Symbol Creation Helpers (Issue #707: Reduce code duplication)
|
|
44
|
+
// ========================================================================
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Add a class/struct symbol to the symbol table.
|
|
48
|
+
*/
|
|
49
|
+
private _addClassSymbol(fullName: string, line: number): void {
|
|
50
|
+
SymbolCollectorContext.addSymbol(this.ctx, {
|
|
51
|
+
name: fullName,
|
|
52
|
+
kind: ESymbolKind.Class,
|
|
53
|
+
sourceFile: this.ctx.sourceFile,
|
|
54
|
+
sourceLine: line,
|
|
55
|
+
sourceLanguage: ESourceLanguage.Cpp,
|
|
56
|
+
isExported: true,
|
|
57
|
+
parent: this.currentNamespace,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Add a member function symbol to the symbol table.
|
|
63
|
+
*/
|
|
64
|
+
private _addMemberFunctionSymbol(
|
|
65
|
+
className: string,
|
|
66
|
+
funcName: string,
|
|
67
|
+
returnType: string,
|
|
68
|
+
params: Array<{
|
|
69
|
+
name: string;
|
|
70
|
+
type: string;
|
|
71
|
+
isConst: boolean;
|
|
72
|
+
isArray: boolean;
|
|
73
|
+
}>,
|
|
74
|
+
line: number,
|
|
75
|
+
isDeclaration: boolean,
|
|
76
|
+
): void {
|
|
77
|
+
SymbolCollectorContext.addSymbol(this.ctx, {
|
|
78
|
+
name: `${className}::${funcName}`,
|
|
79
|
+
kind: ESymbolKind.Function,
|
|
80
|
+
type: returnType,
|
|
81
|
+
sourceFile: this.ctx.sourceFile,
|
|
82
|
+
sourceLine: line,
|
|
83
|
+
sourceLanguage: ESourceLanguage.Cpp,
|
|
84
|
+
isExported: true,
|
|
85
|
+
isDeclaration: isDeclaration || undefined,
|
|
86
|
+
parent: className,
|
|
87
|
+
parameters: params.length > 0 ? params : undefined,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
42
91
|
/**
|
|
43
92
|
* Collect all symbols from a C++ translation unit
|
|
44
93
|
*/
|
|
@@ -257,15 +306,7 @@ class CppSymbolCollector {
|
|
|
257
306
|
const memberSpec = anonymousClassSpec.memberSpecification?.();
|
|
258
307
|
if (!memberSpec) return false;
|
|
259
308
|
|
|
260
|
-
|
|
261
|
-
name: fullName,
|
|
262
|
-
kind: ESymbolKind.Class,
|
|
263
|
-
sourceFile: this.ctx.sourceFile,
|
|
264
|
-
sourceLine: line,
|
|
265
|
-
sourceLanguage: ESourceLanguage.Cpp,
|
|
266
|
-
isExported: true,
|
|
267
|
-
parent: this.currentNamespace,
|
|
268
|
-
});
|
|
309
|
+
this._addClassSymbol(fullName, line);
|
|
269
310
|
this.collectClassMembers(fullName, memberSpec);
|
|
270
311
|
return true;
|
|
271
312
|
}
|
|
@@ -348,15 +389,7 @@ class CppSymbolCollector {
|
|
|
348
389
|
? `${this.currentNamespace}::${name}`
|
|
349
390
|
: name;
|
|
350
391
|
|
|
351
|
-
|
|
352
|
-
name: fullName,
|
|
353
|
-
kind: ESymbolKind.Class,
|
|
354
|
-
sourceFile: this.ctx.sourceFile,
|
|
355
|
-
sourceLine: line,
|
|
356
|
-
sourceLanguage: ESourceLanguage.Cpp,
|
|
357
|
-
isExported: true,
|
|
358
|
-
parent: this.currentNamespace,
|
|
359
|
-
});
|
|
392
|
+
this._addClassSymbol(fullName, line);
|
|
360
393
|
|
|
361
394
|
// Extract struct/class field information if SymbolTable is available
|
|
362
395
|
if (this.ctx.symbolTable) {
|
|
@@ -429,18 +462,14 @@ class CppSymbolCollector {
|
|
|
429
462
|
? this.extractTypeFromDeclSpecSeq(declSpecSeq)
|
|
430
463
|
: "void";
|
|
431
464
|
const params = this.extractFunctionParameters(declarator);
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
isExported: true,
|
|
441
|
-
parent: className,
|
|
442
|
-
parameters: params.length > 0 ? params : undefined,
|
|
443
|
-
});
|
|
465
|
+
this._addMemberFunctionSymbol(
|
|
466
|
+
className,
|
|
467
|
+
funcName,
|
|
468
|
+
returnType,
|
|
469
|
+
params,
|
|
470
|
+
line,
|
|
471
|
+
false,
|
|
472
|
+
);
|
|
444
473
|
}
|
|
445
474
|
|
|
446
475
|
/**
|
|
@@ -484,19 +513,14 @@ class CppSymbolCollector {
|
|
|
484
513
|
line: number,
|
|
485
514
|
): void {
|
|
486
515
|
const params = this.extractFunctionParameters(declarator);
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
isExported: true,
|
|
496
|
-
isDeclaration: true,
|
|
497
|
-
parent: className,
|
|
498
|
-
parameters: params.length > 0 ? params : undefined,
|
|
499
|
-
});
|
|
516
|
+
this._addMemberFunctionSymbol(
|
|
517
|
+
className,
|
|
518
|
+
funcName,
|
|
519
|
+
returnType,
|
|
520
|
+
params,
|
|
521
|
+
line,
|
|
522
|
+
true,
|
|
523
|
+
);
|
|
500
524
|
}
|
|
501
525
|
|
|
502
526
|
/**
|
|
@@ -11,29 +11,98 @@ import IFieldInfo from "../../types/IFieldInfo";
|
|
|
11
11
|
import TypeUtils from "../utils/TypeUtils";
|
|
12
12
|
import LiteralUtils from "../../../../../utils/LiteralUtils";
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
14
|
+
/**
|
|
15
|
+
* Result of processing an arrayType syntax context.
|
|
16
|
+
*/
|
|
17
|
+
interface IArrayTypeResult {
|
|
18
|
+
isArray: boolean;
|
|
19
|
+
dimension: number | undefined;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Process arrayType syntax (e.g., Item[3] items) and return array info.
|
|
24
|
+
*/
|
|
25
|
+
function processArrayTypeSyntax(
|
|
26
|
+
arrayTypeCtx: Parser.ArrayTypeContext | null | undefined,
|
|
27
|
+
constValues?: Map<string, number>,
|
|
28
|
+
): IArrayTypeResult {
|
|
29
|
+
if (!arrayTypeCtx) {
|
|
30
|
+
return { isArray: false, dimension: undefined };
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const sizeExpr = arrayTypeCtx.expression();
|
|
34
|
+
if (!sizeExpr) {
|
|
35
|
+
return { isArray: true, dimension: undefined };
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const resolved = tryResolveExpressionDimension(sizeExpr, constValues);
|
|
39
|
+
return { isArray: true, dimension: resolved };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Process string type fields and update dimensions array.
|
|
44
|
+
*/
|
|
45
|
+
function processStringField(
|
|
46
|
+
stringCtx: Parser.StringTypeContext,
|
|
47
|
+
arrayDims: Parser.ArrayDimensionContext[],
|
|
48
|
+
dimensions: number[],
|
|
49
|
+
constValues?: Map<string, number>,
|
|
50
|
+
): boolean {
|
|
51
|
+
const intLiteral = stringCtx.INTEGER_LITERAL();
|
|
52
|
+
if (!intLiteral) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const capacity = Number.parseInt(intLiteral.getText(), 10);
|
|
57
|
+
|
|
58
|
+
// If there are array dimensions, they come BEFORE string capacity
|
|
59
|
+
if (arrayDims.length > 0) {
|
|
60
|
+
parseArrayDimensions(arrayDims, dimensions, constValues);
|
|
61
|
+
}
|
|
62
|
+
// String capacity becomes final dimension (+1 for null terminator)
|
|
63
|
+
dimensions.push(capacity + 1);
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Try to resolve a single expression as a numeric dimension.
|
|
69
|
+
* Handles integer literals and const references.
|
|
70
|
+
*/
|
|
71
|
+
function tryResolveExpressionDimension(
|
|
72
|
+
sizeExpr: Parser.ExpressionContext,
|
|
73
|
+
constValues?: Map<string, number>,
|
|
74
|
+
): number | undefined {
|
|
75
|
+
const dimText = sizeExpr.getText();
|
|
76
|
+
const literalSize = LiteralUtils.parseIntegerLiteral(dimText);
|
|
77
|
+
if (literalSize !== undefined) {
|
|
78
|
+
return literalSize;
|
|
79
|
+
}
|
|
80
|
+
if (constValues?.has(dimText)) {
|
|
81
|
+
return constValues.get(dimText);
|
|
82
|
+
}
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Parse array dimension expressions and append resolved sizes to dimensions array.
|
|
88
|
+
*/
|
|
89
|
+
function parseArrayDimensions(
|
|
90
|
+
arrayDims: Parser.ArrayDimensionContext[],
|
|
91
|
+
dimensions: number[],
|
|
92
|
+
constValues?: Map<string, number>,
|
|
93
|
+
): void {
|
|
94
|
+
for (const dim of arrayDims) {
|
|
95
|
+
const sizeExpr = dim.expression();
|
|
96
|
+
if (sizeExpr) {
|
|
97
|
+
const resolved = tryResolveExpressionDimension(sizeExpr, constValues);
|
|
98
|
+
if (resolved !== undefined) {
|
|
99
|
+
dimensions.push(resolved);
|
|
33
100
|
}
|
|
34
101
|
}
|
|
35
102
|
}
|
|
103
|
+
}
|
|
36
104
|
|
|
105
|
+
class StructCollector {
|
|
37
106
|
/**
|
|
38
107
|
* Collect a struct declaration and return an IStructSymbol.
|
|
39
108
|
*
|
|
@@ -56,57 +125,12 @@ class StructCollector {
|
|
|
56
125
|
const fields = new Map<string, IFieldInfo>();
|
|
57
126
|
|
|
58
127
|
for (const member of ctx.structMember()) {
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
const arrayDims = member.arrayDimension();
|
|
66
|
-
const dimensions: number[] = [];
|
|
67
|
-
let isArray = false;
|
|
68
|
-
|
|
69
|
-
// Handle string types specially
|
|
70
|
-
if (typeCtx.stringType()) {
|
|
71
|
-
const stringCtx = typeCtx.stringType()!;
|
|
72
|
-
const intLiteral = stringCtx.INTEGER_LITERAL();
|
|
73
|
-
|
|
74
|
-
if (intLiteral) {
|
|
75
|
-
const capacity = Number.parseInt(intLiteral.getText(), 10);
|
|
76
|
-
|
|
77
|
-
// If there are array dimensions, they come BEFORE string capacity
|
|
78
|
-
if (arrayDims.length > 0) {
|
|
79
|
-
StructCollector.parseArrayDimensions(
|
|
80
|
-
arrayDims,
|
|
81
|
-
dimensions,
|
|
82
|
-
constValues,
|
|
83
|
-
);
|
|
84
|
-
}
|
|
85
|
-
// String capacity becomes final dimension (+1 for null terminator)
|
|
86
|
-
dimensions.push(capacity + 1);
|
|
87
|
-
isArray = true;
|
|
88
|
-
}
|
|
89
|
-
} else if (arrayDims.length > 0) {
|
|
90
|
-
// Non-string array
|
|
91
|
-
isArray = true;
|
|
92
|
-
StructCollector.parseArrayDimensions(
|
|
93
|
-
arrayDims,
|
|
94
|
-
dimensions,
|
|
95
|
-
constValues,
|
|
96
|
-
);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
const fieldInfo: IFieldInfo = {
|
|
100
|
-
type: fieldType,
|
|
101
|
-
isArray,
|
|
102
|
-
isConst,
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
if (dimensions.length > 0) {
|
|
106
|
-
fieldInfo.dimensions = dimensions;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
fields.set(fieldName, fieldInfo);
|
|
128
|
+
const fieldInfo = StructCollector.collectField(
|
|
129
|
+
member,
|
|
130
|
+
scopeName,
|
|
131
|
+
constValues,
|
|
132
|
+
);
|
|
133
|
+
fields.set(member.IDENTIFIER().getText(), fieldInfo);
|
|
110
134
|
}
|
|
111
135
|
|
|
112
136
|
return {
|
|
@@ -120,6 +144,68 @@ class StructCollector {
|
|
|
120
144
|
fields,
|
|
121
145
|
};
|
|
122
146
|
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Collect a single struct field and return its IFieldInfo.
|
|
150
|
+
*/
|
|
151
|
+
private static collectField(
|
|
152
|
+
member: Parser.StructMemberContext,
|
|
153
|
+
scopeName?: string,
|
|
154
|
+
constValues?: Map<string, number>,
|
|
155
|
+
): IFieldInfo {
|
|
156
|
+
const typeCtx = member.type();
|
|
157
|
+
const fieldType = TypeUtils.getTypeName(typeCtx, scopeName);
|
|
158
|
+
// Note: C-Next struct members don't have const modifier in grammar
|
|
159
|
+
const isConst = false;
|
|
160
|
+
|
|
161
|
+
const arrayDims = member.arrayDimension();
|
|
162
|
+
const dimensions: number[] = [];
|
|
163
|
+
let isArray = false;
|
|
164
|
+
|
|
165
|
+
// Check for C-Next style arrayType syntax: Item[3] items -> typeCtx.arrayType()
|
|
166
|
+
const arrayTypeResult = processArrayTypeSyntax(
|
|
167
|
+
typeCtx.arrayType(),
|
|
168
|
+
constValues,
|
|
169
|
+
);
|
|
170
|
+
if (arrayTypeResult.isArray) {
|
|
171
|
+
isArray = true;
|
|
172
|
+
if (arrayTypeResult.dimension !== undefined) {
|
|
173
|
+
dimensions.push(arrayTypeResult.dimension);
|
|
174
|
+
}
|
|
175
|
+
// Note: non-literal, non-const expressions (like global.EnumName.COUNT)
|
|
176
|
+
// won't be resolvable at symbol collection time - dimensions stays empty
|
|
177
|
+
// but isArray is still true so the field is tracked as an array
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Handle string types specially
|
|
181
|
+
if (typeCtx.stringType()) {
|
|
182
|
+
const stringHandled = processStringField(
|
|
183
|
+
typeCtx.stringType()!,
|
|
184
|
+
arrayDims,
|
|
185
|
+
dimensions,
|
|
186
|
+
constValues,
|
|
187
|
+
);
|
|
188
|
+
if (stringHandled) {
|
|
189
|
+
isArray = true;
|
|
190
|
+
}
|
|
191
|
+
} else if (arrayDims.length > 0) {
|
|
192
|
+
// Non-string array
|
|
193
|
+
isArray = true;
|
|
194
|
+
parseArrayDimensions(arrayDims, dimensions, constValues);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const fieldInfo: IFieldInfo = {
|
|
198
|
+
type: fieldType,
|
|
199
|
+
isArray,
|
|
200
|
+
isConst,
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
if (dimensions.length > 0) {
|
|
204
|
+
fieldInfo.dimensions = dimensions;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return fieldInfo;
|
|
208
|
+
}
|
|
123
209
|
}
|
|
124
210
|
|
|
125
211
|
export default StructCollector;
|
|
@@ -9,6 +9,7 @@ import ESymbolKind from "../../../../../utils/types/ESymbolKind";
|
|
|
9
9
|
import IVariableSymbol from "../../types/IVariableSymbol";
|
|
10
10
|
import ArrayInitializerUtils from "../utils/ArrayInitializerUtils";
|
|
11
11
|
import TypeUtils from "../utils/TypeUtils";
|
|
12
|
+
import LiteralUtils from "../../../../../utils/LiteralUtils";
|
|
12
13
|
|
|
13
14
|
class VariableCollector {
|
|
14
15
|
/**
|
|
@@ -101,17 +102,41 @@ class VariableCollector {
|
|
|
101
102
|
// Issue #468: Check for atomic modifier
|
|
102
103
|
const isAtomic = ctx.atomicModifier() !== null;
|
|
103
104
|
|
|
104
|
-
// Check for array dimensions
|
|
105
|
+
// Check for array dimensions - both C-style (arrayDimension) and C-Next style (arrayType)
|
|
105
106
|
const arrayDims = ctx.arrayDimension();
|
|
106
|
-
const
|
|
107
|
+
const arrayTypeCtx = typeCtx.arrayType();
|
|
108
|
+
const hasArrayTypeSyntax = arrayTypeCtx !== null;
|
|
109
|
+
const isArray = arrayDims.length > 0 || hasArrayTypeSyntax;
|
|
107
110
|
const initExpr = ctx.expression();
|
|
108
|
-
const arrayDimensions =
|
|
109
|
-
|
|
111
|
+
const arrayDimensions: (number | string)[] = [];
|
|
112
|
+
|
|
113
|
+
// Collect dimension from arrayType syntax (u16[8] arr)
|
|
114
|
+
if (hasArrayTypeSyntax) {
|
|
115
|
+
const sizeExpr = arrayTypeCtx.expression();
|
|
116
|
+
if (sizeExpr) {
|
|
117
|
+
const dimText = sizeExpr.getText();
|
|
118
|
+
const literalSize = LiteralUtils.parseIntegerLiteral(dimText);
|
|
119
|
+
if (literalSize !== undefined) {
|
|
120
|
+
arrayDimensions.push(literalSize);
|
|
121
|
+
} else if (constValues?.has(dimText)) {
|
|
122
|
+
arrayDimensions.push(constValues.get(dimText)!);
|
|
123
|
+
} else {
|
|
124
|
+
// Keep as string for macro/enum references
|
|
125
|
+
arrayDimensions.push(dimText);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Collect additional dimensions from arrayDimension syntax
|
|
131
|
+
if (arrayDims.length > 0) {
|
|
132
|
+
arrayDimensions.push(
|
|
133
|
+
...VariableCollector.collectArrayDimensions(
|
|
110
134
|
arrayDims,
|
|
111
135
|
constValues,
|
|
112
136
|
initExpr,
|
|
113
|
-
)
|
|
114
|
-
|
|
137
|
+
),
|
|
138
|
+
);
|
|
139
|
+
}
|
|
115
140
|
|
|
116
141
|
// Issue #282: Capture initial value for const inlining
|
|
117
142
|
const initialValue = initExpr?.getText();
|
|
@@ -5,6 +5,41 @@
|
|
|
5
5
|
import * as Parser from "../../../parser/grammar/CNextParser";
|
|
6
6
|
import CNEXT_TO_C_TYPE_MAP from "../../../../../utils/constants/TypeMappings";
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Resolve scoped type (this.Type) to full name.
|
|
10
|
+
*/
|
|
11
|
+
function resolveScopedType(
|
|
12
|
+
scopedTypeCtx: Parser.ScopedTypeContext,
|
|
13
|
+
scopeName?: string,
|
|
14
|
+
): string {
|
|
15
|
+
const typeName = scopedTypeCtx.IDENTIFIER().getText();
|
|
16
|
+
return scopeName ? `${scopeName}_${typeName}` : typeName;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Resolve string type with optional capacity.
|
|
21
|
+
*/
|
|
22
|
+
function resolveStringType(stringCtx: Parser.StringTypeContext): string {
|
|
23
|
+
const intLiteral = stringCtx.INTEGER_LITERAL();
|
|
24
|
+
return intLiteral ? `string<${intLiteral.getText()}>` : "string";
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Extract inner type from arrayType context.
|
|
29
|
+
*/
|
|
30
|
+
function resolveArrayInnerType(arrayTypeCtx: Parser.ArrayTypeContext): string {
|
|
31
|
+
if (arrayTypeCtx.primitiveType()) {
|
|
32
|
+
return arrayTypeCtx.primitiveType()!.getText();
|
|
33
|
+
}
|
|
34
|
+
if (arrayTypeCtx.userType()) {
|
|
35
|
+
return arrayTypeCtx.userType()!.getText();
|
|
36
|
+
}
|
|
37
|
+
// Fallback for other nested types - strip the dimension part
|
|
38
|
+
const text = arrayTypeCtx.getText();
|
|
39
|
+
const bracketIdx = text.indexOf("[");
|
|
40
|
+
return bracketIdx > 0 ? text.substring(0, bracketIdx) : text;
|
|
41
|
+
}
|
|
42
|
+
|
|
8
43
|
class TypeUtils {
|
|
9
44
|
/**
|
|
10
45
|
* Extract the type name from a type context.
|
|
@@ -23,11 +58,7 @@ class TypeUtils {
|
|
|
23
58
|
|
|
24
59
|
// Handle this.Type for scoped types (e.g., this.State -> Motor_State)
|
|
25
60
|
if (ctx.scopedType()) {
|
|
26
|
-
|
|
27
|
-
if (scopeName) {
|
|
28
|
-
return `${scopeName}_${typeName}`;
|
|
29
|
-
}
|
|
30
|
-
return typeName;
|
|
61
|
+
return resolveScopedType(ctx.scopedType()!, scopeName);
|
|
31
62
|
}
|
|
32
63
|
|
|
33
64
|
// Issue #478: Handle global.Type for global types inside scope
|
|
@@ -54,12 +85,13 @@ class TypeUtils {
|
|
|
54
85
|
|
|
55
86
|
// Handle string types - preserve capacity for validation (Issue #139)
|
|
56
87
|
if (ctx.stringType()) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
88
|
+
return resolveStringType(ctx.stringType()!);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Handle arrayType: Type[size] - extract the inner type without dimension
|
|
92
|
+
// The dimension is tracked separately in arrayDimensions
|
|
93
|
+
if (ctx.arrayType()) {
|
|
94
|
+
return resolveArrayInnerType(ctx.arrayType()!);
|
|
63
95
|
}
|
|
64
96
|
|
|
65
97
|
// Fallback
|