c-next 0.1.70 → 0.1.72
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 +1 -1
- package/src/lib/__tests__/parseCHeader.mocked.test.ts +69 -54
- package/src/lib/parseCHeader.ts +56 -23
- package/src/lib/parseWithSymbols.ts +195 -53
- package/src/transpiler/Transpiler.ts +180 -63
- package/src/transpiler/logic/analysis/FunctionCallAnalyzer.ts +1 -2
- package/src/transpiler/logic/analysis/InitializationAnalyzer.ts +1 -2
- package/src/transpiler/logic/analysis/PassByValueAnalyzer.ts +51 -2
- package/src/transpiler/logic/analysis/__tests__/FunctionCallAnalyzer.test.ts +18 -12
- package/src/transpiler/logic/analysis/__tests__/InitializationAnalyzer.test.ts +9 -9
- package/src/transpiler/logic/analysis/__tests__/runAnalyzers.test.ts +5 -5
- package/src/transpiler/logic/symbols/SymbolTable.ts +729 -265
- package/src/transpiler/logic/symbols/SymbolUtils.ts +2 -2
- package/src/transpiler/logic/symbols/__tests__/SymbolTable.test.ts +415 -751
- package/src/transpiler/logic/symbols/c/__tests__/CResolver.integration.test.ts +573 -0
- package/src/transpiler/logic/symbols/c/__tests__/testHelpers.ts +20 -0
- package/src/transpiler/logic/symbols/c/collectors/EnumCollector.ts +82 -0
- package/src/transpiler/logic/symbols/c/collectors/FunctionCollector.ts +106 -0
- package/src/transpiler/logic/symbols/c/collectors/StructCollector.ts +173 -0
- package/src/transpiler/logic/symbols/c/collectors/TypedefCollector.ts +35 -0
- package/src/transpiler/logic/symbols/c/collectors/VariableCollector.ts +80 -0
- package/src/transpiler/logic/symbols/c/index.ts +333 -0
- package/src/transpiler/logic/symbols/c/utils/DeclaratorUtils.ts +269 -0
- package/src/transpiler/logic/symbols/cnext/__tests__/BitmapCollector.test.ts +50 -11
- package/src/transpiler/logic/symbols/cnext/__tests__/CNextResolver.integration.test.ts +45 -34
- package/src/transpiler/logic/symbols/cnext/__tests__/EnumCollector.test.ts +30 -13
- package/src/transpiler/logic/symbols/cnext/__tests__/FunctionCollector.test.ts +279 -64
- package/src/transpiler/logic/symbols/cnext/__tests__/RegisterCollector.test.ts +60 -13
- package/src/transpiler/logic/symbols/cnext/__tests__/ScopeCollector.test.ts +40 -37
- package/src/transpiler/logic/symbols/cnext/__tests__/StructCollector.test.ts +131 -45
- package/src/transpiler/logic/symbols/cnext/__tests__/TSymbolInfoAdapter.test.ts +223 -139
- package/src/transpiler/logic/symbols/cnext/__tests__/VariableCollector.test.ts +79 -25
- package/src/transpiler/logic/symbols/cnext/__tests__/testUtils.ts +53 -0
- package/src/transpiler/logic/symbols/cnext/adapters/TSymbolInfoAdapter.ts +83 -43
- package/src/transpiler/logic/symbols/cnext/collectors/BitmapCollector.ts +14 -13
- package/src/transpiler/logic/symbols/cnext/collectors/EnumCollector.ts +11 -10
- package/src/transpiler/logic/symbols/cnext/collectors/FunctionCollector.ts +83 -34
- package/src/transpiler/logic/symbols/cnext/collectors/RegisterCollector.ts +22 -18
- package/src/transpiler/logic/symbols/cnext/collectors/ScopeCollector.ts +53 -35
- package/src/transpiler/logic/symbols/cnext/collectors/StructCollector.ts +30 -23
- package/src/transpiler/logic/symbols/cnext/collectors/VariableCollector.ts +18 -19
- package/src/transpiler/logic/symbols/cnext/index.ts +36 -14
- package/src/transpiler/logic/symbols/cnext/types/IScopeCollectorResult.ts +2 -2
- package/src/transpiler/logic/symbols/cnext/utils/SymbolNameUtils.ts +27 -0
- package/src/transpiler/logic/symbols/cpp/__tests__/CppResolver.integration.test.ts +270 -0
- package/src/transpiler/logic/symbols/cpp/__tests__/testHelpers.ts +20 -0
- package/src/transpiler/logic/symbols/cpp/collectors/ClassCollector.ts +317 -0
- package/src/transpiler/logic/symbols/cpp/collectors/EnumCollector.ts +71 -0
- package/src/transpiler/logic/symbols/cpp/collectors/FunctionCollector.ts +155 -0
- package/src/transpiler/logic/symbols/cpp/collectors/NamespaceCollector.ts +65 -0
- package/src/transpiler/logic/symbols/cpp/collectors/TypeAliasCollector.ts +46 -0
- package/src/transpiler/logic/symbols/cpp/collectors/VariableCollector.ts +54 -0
- package/src/transpiler/logic/symbols/cpp/index.ts +366 -0
- package/src/transpiler/logic/symbols/cpp/utils/DeclaratorUtils.ts +248 -0
- package/src/transpiler/logic/symbols/shared/IExtractedParameter.ts +18 -0
- package/src/transpiler/logic/symbols/shared/ParameterExtractorUtils.ts +73 -0
- package/src/transpiler/output/codegen/CodeGenerator.ts +268 -1674
- package/src/transpiler/output/codegen/__tests__/CodeGenerator.test.ts +7 -1
- package/src/transpiler/output/codegen/assignment/AssignmentClassifier.ts +2 -1
- package/src/transpiler/output/codegen/assignment/handlers/AssignmentHandlerUtils.ts +7 -1
- package/src/transpiler/output/codegen/assignment/handlers/BitmapHandlers.ts +6 -2
- package/src/transpiler/output/codegen/assignment/handlers/RegisterHandlers.ts +2 -1
- package/src/transpiler/output/codegen/generators/declarationGenerators/ScopeGenerator.ts +21 -8
- package/src/transpiler/output/codegen/generators/declarationGenerators/ScopedRegisterGenerator.ts +3 -2
- package/src/transpiler/output/codegen/generators/expressions/CallExprUtils.ts +9 -3
- package/src/transpiler/output/codegen/generators/expressions/__tests__/CallExprGenerator.test.ts +3 -4
- package/src/transpiler/output/codegen/generators/expressions/__tests__/CallExprUtils.test.ts +4 -8
- package/src/transpiler/output/codegen/helpers/ArgumentGenerator.ts +236 -0
- package/src/transpiler/output/codegen/helpers/CppConstructorHelper.ts +3 -3
- package/src/transpiler/output/codegen/helpers/FunctionContextManager.ts +435 -0
- package/src/transpiler/output/codegen/helpers/StringOperationsHelper.ts +203 -0
- package/src/transpiler/output/codegen/helpers/SymbolLookupHelper.ts +8 -12
- package/src/transpiler/output/codegen/helpers/TypeRegistrationEngine.ts +520 -0
- package/src/transpiler/output/codegen/helpers/VariableDeclHelper.ts +735 -0
- package/src/transpiler/output/codegen/helpers/VariableDeclarationFormatter.ts +1 -1
- package/src/transpiler/output/codegen/helpers/__tests__/ArgumentGenerator.test.ts +521 -0
- package/src/transpiler/output/codegen/helpers/__tests__/CppConstructorHelper.test.ts +4 -5
- package/src/transpiler/output/codegen/helpers/__tests__/FunctionContextManager.test.ts +983 -0
- package/src/transpiler/output/codegen/helpers/__tests__/StringOperationsHelper.test.ts +269 -0
- package/src/transpiler/output/codegen/helpers/__tests__/SymbolLookupHelper.test.ts +31 -32
- package/src/transpiler/output/codegen/helpers/__tests__/TypeRegistrationEngine.test.ts +186 -0
- package/src/transpiler/output/codegen/helpers/__tests__/VariableDeclHelper.test.ts +460 -0
- package/src/transpiler/output/codegen/helpers/types/IArgumentGeneratorCallbacks.ts +32 -0
- package/src/transpiler/output/codegen/resolution/EnumTypeResolver.ts +5 -1
- package/src/transpiler/output/codegen/types/IFunctionContextCallbacks.ts +12 -0
- package/src/transpiler/output/codegen/types/IVariableFormatInput.ts +1 -1
- package/src/transpiler/output/codegen/utils/QualifiedNameGenerator.ts +114 -0
- package/src/transpiler/output/codegen/utils/__tests__/QualifiedNameGenerator.test.ts +183 -0
- package/src/transpiler/output/headers/BaseHeaderGenerator.ts +4 -4
- package/src/transpiler/output/headers/ExternalTypeHeaderBuilder.ts +7 -7
- package/src/transpiler/output/headers/HeaderGenerator.ts +9 -7
- package/src/transpiler/output/headers/HeaderGeneratorUtils.ts +19 -20
- package/src/transpiler/output/headers/__tests__/BaseHeaderGenerator.test.ts +15 -18
- package/src/transpiler/output/headers/__tests__/CHeaderGenerator.test.ts +63 -64
- package/src/transpiler/output/headers/__tests__/CppHeaderGenerator.test.ts +36 -32
- package/src/transpiler/output/headers/__tests__/ExternalTypeHeaderBuilder.test.ts +26 -26
- package/src/transpiler/output/headers/__tests__/HeaderGenerator.test.ts +87 -59
- package/src/transpiler/output/headers/__tests__/HeaderGeneratorUtils.test.ts +57 -58
- package/src/transpiler/output/headers/adapters/HeaderSymbolAdapter.ts +222 -0
- package/src/transpiler/output/headers/adapters/__tests__/HeaderSymbolAdapter.test.ts +538 -0
- package/src/transpiler/output/headers/types/IGroupedSymbols.ts +8 -8
- package/src/transpiler/output/headers/types/IHeaderSymbol.ts +62 -0
- package/src/transpiler/state/CodeGenState.ts +20 -33
- package/src/transpiler/state/SymbolRegistry.ts +181 -0
- package/src/transpiler/{types → state}/TranspilerState.ts +1 -1
- package/src/transpiler/state/__tests__/CodeGenState.test.ts +67 -59
- package/src/transpiler/state/__tests__/SymbolRegistry.test.ts +249 -0
- package/src/transpiler/{types → state}/__tests__/TranspilerState.test.ts +1 -1
- package/src/transpiler/types/ICachedFileEntry.ts +1 -1
- package/src/transpiler/types/IConflict.ts +14 -0
- package/src/transpiler/types/IPipelineInput.ts +0 -3
- package/src/transpiler/types/ISerializedSymbol.ts +11 -0
- package/src/transpiler/types/TPrimitiveKind.ts +20 -0
- package/src/transpiler/types/TType.ts +103 -0
- package/src/transpiler/types/TVisibility.ts +6 -0
- package/src/transpiler/types/symbol-kinds/TSymbolKind.ts +10 -0
- package/src/transpiler/types/symbol-kinds/TSymbolKindC.ts +12 -0
- package/src/transpiler/types/symbol-kinds/TSymbolKindCNext.ts +16 -0
- package/src/transpiler/types/symbol-kinds/TSymbolKindCpp.ts +14 -0
- package/src/transpiler/types/symbols/IBaseSymbol.ts +31 -0
- package/src/transpiler/{logic/symbols/types → types/symbols}/IBitmapFieldInfo.ts +2 -2
- package/src/transpiler/types/symbols/IBitmapSymbol.ts +21 -0
- package/src/transpiler/{logic/symbols/types → types/symbols}/IEnumSymbol.ts +5 -6
- package/src/transpiler/types/symbols/IFieldInfo.ts +26 -0
- package/src/transpiler/types/symbols/IFunctionSymbol.ts +30 -0
- package/src/transpiler/types/symbols/IParameterInfo.ts +26 -0
- package/src/transpiler/{logic/symbols/types → types/symbols}/IRegisterMemberInfo.ts +4 -4
- package/src/transpiler/types/symbols/IRegisterSymbol.ts +18 -0
- package/src/transpiler/types/symbols/IScopeSymbol.ts +32 -0
- package/src/transpiler/{logic/symbols/types → types/symbols}/IStructFieldInfo.ts +2 -1
- package/src/transpiler/types/symbols/IStructSymbol.ts +15 -0
- package/src/transpiler/types/symbols/IVariableSymbol.ts +30 -0
- package/src/transpiler/types/symbols/SymbolGuards.ts +43 -0
- package/src/transpiler/types/symbols/TAnySymbol.ts +22 -0
- package/src/transpiler/types/symbols/TSymbol.ts +32 -0
- package/src/transpiler/types/symbols/__tests__/IBaseSymbol.test.ts +56 -0
- package/src/transpiler/types/symbols/__tests__/SymbolGuards.test.ts +57 -0
- package/src/transpiler/types/symbols/c/ICBaseSymbol.ts +28 -0
- package/src/transpiler/types/symbols/c/ICEnumMemberSymbol.ts +17 -0
- package/src/transpiler/types/symbols/c/ICEnumSymbol.ts +17 -0
- package/src/transpiler/types/symbols/c/ICFieldInfo.ts +16 -0
- package/src/transpiler/types/symbols/c/ICFunctionSymbol.ts +21 -0
- package/src/transpiler/types/symbols/c/ICParameterInfo.ts +19 -0
- package/src/transpiler/types/symbols/c/ICStructSymbol.ts +21 -0
- package/src/transpiler/types/symbols/c/ICTypedefSymbol.ts +14 -0
- package/src/transpiler/types/symbols/c/ICVariableSymbol.ts +26 -0
- package/src/transpiler/types/symbols/c/TCSymbol.ts +26 -0
- package/src/transpiler/types/symbols/cpp/ICppBaseSymbol.ts +31 -0
- package/src/transpiler/types/symbols/cpp/ICppClassSymbol.ts +15 -0
- package/src/transpiler/types/symbols/cpp/ICppEnumMemberSymbol.ts +14 -0
- package/src/transpiler/types/symbols/cpp/ICppEnumSymbol.ts +14 -0
- package/src/transpiler/types/symbols/cpp/ICppFieldInfo.ts +16 -0
- package/src/transpiler/types/symbols/cpp/ICppFunctionSymbol.ts +21 -0
- package/src/transpiler/types/symbols/cpp/ICppNamespaceSymbol.ts +11 -0
- package/src/transpiler/types/symbols/cpp/ICppParameterInfo.ts +19 -0
- package/src/transpiler/types/symbols/cpp/ICppStructSymbol.ts +16 -0
- package/src/transpiler/types/symbols/cpp/ICppTypeAliasSymbol.ts +14 -0
- package/src/transpiler/types/symbols/cpp/ICppVariableSymbol.ts +23 -0
- package/src/transpiler/types/symbols/cpp/TCppSymbol.ts +30 -0
- package/src/utils/CppNamespaceUtils.ts +3 -4
- package/src/utils/FunctionUtils.ts +92 -0
- package/src/utils/ParameterUtils.ts +55 -0
- package/src/utils/PrimitiveKindUtils.ts +33 -0
- package/src/utils/ScopeUtils.ts +105 -0
- package/src/utils/TTypeUtils.ts +159 -0
- package/src/utils/TypeResolver.ts +132 -0
- package/src/utils/__tests__/CppNamespaceUtils.test.ts +92 -99
- package/src/utils/__tests__/FunctionUtils.test.ts +284 -0
- package/src/utils/__tests__/ParameterUtils.test.ts +174 -0
- package/src/utils/__tests__/PrimitiveKindUtils.test.ts +59 -0
- package/src/utils/__tests__/ScopeUtils.test.ts +53 -0
- package/src/utils/__tests__/TTypeUtils.test.ts +245 -0
- package/src/utils/__tests__/TypeResolver.test.ts +332 -0
- package/src/utils/cache/CacheManager.ts +91 -50
- package/src/utils/cache/__tests__/CacheManager.test.ts +180 -114
- package/src/transpiler/logic/symbols/AutoConstUpdater.ts +0 -93
- package/src/transpiler/logic/symbols/CSymbolCollector.ts +0 -648
- package/src/transpiler/logic/symbols/CppSymbolCollector.ts +0 -874
- package/src/transpiler/logic/symbols/SymbolCollectorContext.ts +0 -68
- package/src/transpiler/logic/symbols/__tests__/AutoConstUpdater.test.ts +0 -418
- package/src/transpiler/logic/symbols/__tests__/CSymbolCollector.test.ts +0 -685
- package/src/transpiler/logic/symbols/__tests__/CppSymbolCollector.test.ts +0 -1146
- package/src/transpiler/logic/symbols/__tests__/SymbolCollectorContext.test.ts +0 -290
- package/src/transpiler/logic/symbols/__tests__/cTestHelpers.ts +0 -43
- package/src/transpiler/logic/symbols/__tests__/cppTestHelpers.ts +0 -40
- package/src/transpiler/logic/symbols/cnext/__tests__/TSymbolAdapter.test.ts +0 -595
- package/src/transpiler/logic/symbols/cnext/adapters/TSymbolAdapter.ts +0 -345
- package/src/transpiler/logic/symbols/types/IBaseSymbol.ts +0 -27
- package/src/transpiler/logic/symbols/types/IBitmapSymbol.ts +0 -23
- package/src/transpiler/logic/symbols/types/ICollectorContext.ts +0 -19
- package/src/transpiler/logic/symbols/types/IConflict.ts +0 -20
- package/src/transpiler/logic/symbols/types/IFieldInfo.ts +0 -18
- package/src/transpiler/logic/symbols/types/IFunctionSymbol.ts +0 -25
- package/src/transpiler/logic/symbols/types/IParameterInfo.ts +0 -24
- package/src/transpiler/logic/symbols/types/IRegisterSymbol.ts +0 -20
- package/src/transpiler/logic/symbols/types/IScopeSymbol.ts +0 -19
- package/src/transpiler/logic/symbols/types/IStructSymbol.ts +0 -16
- package/src/transpiler/logic/symbols/types/IVariableSymbol.ts +0 -30
- package/src/transpiler/logic/symbols/types/TSymbol.ts +0 -36
- package/src/transpiler/logic/symbols/types/__tests__/SymbolGuards.test.ts +0 -244
- package/src/transpiler/logic/symbols/types/typeGuards.ts +0 -44
- package/src/utils/types/ESymbolKind.ts +0 -19
- package/src/utils/types/ISymbol.ts +0 -64
- /package/src/transpiler/{types → constants}/BITMAP_BACKING_TYPE.ts +0 -0
- /package/src/transpiler/{types → constants}/BITMAP_SIZE.ts +0 -0
|
@@ -0,0 +1,435 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FunctionContextManager - Manages function context lifecycle and parameter processing
|
|
3
|
+
*
|
|
4
|
+
* Issue #793: Extracted from CodeGenerator to reduce file size.
|
|
5
|
+
*
|
|
6
|
+
* Handles:
|
|
7
|
+
* - Function context setup/cleanup lifecycle
|
|
8
|
+
* - Parameter type resolution and registration
|
|
9
|
+
* - Return type resolution (including main() special case)
|
|
10
|
+
* - Function body enter/exit coordination
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import * as Parser from "../../../logic/parser/grammar/CNextParser.js";
|
|
14
|
+
import CodeGenState from "../../../state/CodeGenState.js";
|
|
15
|
+
import TYPE_WIDTH from "../types/TYPE_WIDTH.js";
|
|
16
|
+
import ArrayDimensionParser from "./ArrayDimensionParser.js";
|
|
17
|
+
import IFunctionContextCallbacks from "../types/IFunctionContextCallbacks.js";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Result from resolving parameter type information.
|
|
21
|
+
*/
|
|
22
|
+
interface IParameterTypeInfo {
|
|
23
|
+
typeName: string;
|
|
24
|
+
isStruct: boolean;
|
|
25
|
+
isCallback: boolean;
|
|
26
|
+
isString: boolean;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Result from resolving return type and params for a function.
|
|
31
|
+
*/
|
|
32
|
+
interface IReturnTypeAndParams {
|
|
33
|
+
actualReturnType: string;
|
|
34
|
+
initialParams: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Manages function context lifecycle and parameter processing.
|
|
39
|
+
*/
|
|
40
|
+
class FunctionContextManager {
|
|
41
|
+
/**
|
|
42
|
+
* Set up context for function generation.
|
|
43
|
+
* - Sets current function name (with scope prefix if in a scope)
|
|
44
|
+
* - Sets return type for enum inference
|
|
45
|
+
* - Processes parameters for ADR-006 pointer semantics
|
|
46
|
+
* - Clears local variables and marks in function body
|
|
47
|
+
*/
|
|
48
|
+
static setupFunctionContext(
|
|
49
|
+
name: string,
|
|
50
|
+
ctx: Parser.FunctionDeclarationContext,
|
|
51
|
+
callbacks: IFunctionContextCallbacks,
|
|
52
|
+
): void {
|
|
53
|
+
// Issue #269: Set current function name for pass-by-value lookup
|
|
54
|
+
const fullFuncName = CodeGenState.currentScope
|
|
55
|
+
? `${CodeGenState.currentScope}_${name}`
|
|
56
|
+
: name;
|
|
57
|
+
CodeGenState.currentFunctionName = fullFuncName;
|
|
58
|
+
|
|
59
|
+
// Issue #477: Set return type for enum inference in return statements
|
|
60
|
+
CodeGenState.currentFunctionReturnType = ctx.type().getText();
|
|
61
|
+
|
|
62
|
+
// Track parameters for ADR-006 pointer semantics
|
|
63
|
+
FunctionContextManager.processParameterList(
|
|
64
|
+
ctx.parameterList() ?? null,
|
|
65
|
+
callbacks,
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
// ADR-016: Clear local variables and mark that we're in a function body
|
|
69
|
+
CodeGenState.localVariables.clear();
|
|
70
|
+
CodeGenState.floatBitShadows.clear();
|
|
71
|
+
CodeGenState.floatShadowCurrent.clear();
|
|
72
|
+
CodeGenState.inFunctionBody = true;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Clean up context after function generation.
|
|
77
|
+
* Resets all function-related state.
|
|
78
|
+
*/
|
|
79
|
+
static cleanupFunctionContext(): void {
|
|
80
|
+
CodeGenState.inFunctionBody = false;
|
|
81
|
+
CodeGenState.localVariables.clear();
|
|
82
|
+
CodeGenState.floatBitShadows.clear();
|
|
83
|
+
CodeGenState.floatShadowCurrent.clear();
|
|
84
|
+
CodeGenState.mainArgsName = null;
|
|
85
|
+
CodeGenState.currentFunctionName = null;
|
|
86
|
+
CodeGenState.currentFunctionReturnType = null;
|
|
87
|
+
FunctionContextManager.clearParameters();
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Resolve return type and initial params for function.
|
|
92
|
+
* Handles main() special cases:
|
|
93
|
+
* - main(u8 args[][]) -> int main(int argc, char *argv[])
|
|
94
|
+
* - main() -> int main() (for C++ compatibility)
|
|
95
|
+
*/
|
|
96
|
+
static resolveReturnTypeAndParams(
|
|
97
|
+
name: string,
|
|
98
|
+
returnType: string,
|
|
99
|
+
isMainWithArgs: boolean,
|
|
100
|
+
ctx: Parser.FunctionDeclarationContext,
|
|
101
|
+
): IReturnTypeAndParams {
|
|
102
|
+
if (isMainWithArgs) {
|
|
103
|
+
// Special case: main(u8 args[][]) -> int main(int argc, char *argv[])
|
|
104
|
+
const argsParam = ctx.parameterList()!.parameter()[0];
|
|
105
|
+
CodeGenState.mainArgsName = argsParam.IDENTIFIER().getText();
|
|
106
|
+
return {
|
|
107
|
+
actualReturnType: "int",
|
|
108
|
+
initialParams: "int argc, char *argv[]",
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// For main() without args, always use int return type for C++ compatibility
|
|
113
|
+
const actualReturnType = name === "main" ? "int" : returnType;
|
|
114
|
+
return { actualReturnType, initialParams: "" };
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Process parameter list and register parameters in state.
|
|
119
|
+
*/
|
|
120
|
+
static processParameterList(
|
|
121
|
+
params: Parser.ParameterListContext | null,
|
|
122
|
+
callbacks: IFunctionContextCallbacks,
|
|
123
|
+
): void {
|
|
124
|
+
CodeGenState.currentParameters.clear();
|
|
125
|
+
if (!params) return;
|
|
126
|
+
|
|
127
|
+
for (const param of params.parameter()) {
|
|
128
|
+
FunctionContextManager.processParameter(param, callbacks);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Process a single parameter declaration.
|
|
134
|
+
*/
|
|
135
|
+
static processParameter(
|
|
136
|
+
param: Parser.ParameterContext,
|
|
137
|
+
callbacks: IFunctionContextCallbacks,
|
|
138
|
+
): void {
|
|
139
|
+
const name = param.IDENTIFIER().getText();
|
|
140
|
+
// Check both C-Next style (u8[8] param) and legacy style (u8 param[8])
|
|
141
|
+
const isArray =
|
|
142
|
+
param.arrayDimension().length > 0 || param.type().arrayType() !== null;
|
|
143
|
+
const isConst = param.constModifier() !== null;
|
|
144
|
+
const typeCtx = param.type();
|
|
145
|
+
|
|
146
|
+
// Resolve type information
|
|
147
|
+
const typeInfo = FunctionContextManager.resolveParameterTypeInfo(
|
|
148
|
+
typeCtx,
|
|
149
|
+
callbacks,
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
// Register in currentParameters
|
|
153
|
+
const paramInfo = {
|
|
154
|
+
name,
|
|
155
|
+
baseType: typeInfo.typeName,
|
|
156
|
+
isArray,
|
|
157
|
+
isStruct: typeInfo.isStruct,
|
|
158
|
+
isConst,
|
|
159
|
+
isCallback: typeInfo.isCallback,
|
|
160
|
+
isString: typeInfo.isString,
|
|
161
|
+
};
|
|
162
|
+
CodeGenState.currentParameters.set(name, paramInfo);
|
|
163
|
+
|
|
164
|
+
// Register in typeRegistry
|
|
165
|
+
FunctionContextManager.registerParameterType(
|
|
166
|
+
name,
|
|
167
|
+
typeInfo,
|
|
168
|
+
param,
|
|
169
|
+
isArray,
|
|
170
|
+
isConst,
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Resolve type name and flags from a type context.
|
|
176
|
+
*/
|
|
177
|
+
static resolveParameterTypeInfo(
|
|
178
|
+
typeCtx: Parser.TypeContext,
|
|
179
|
+
callbacks: IFunctionContextCallbacks,
|
|
180
|
+
): IParameterTypeInfo {
|
|
181
|
+
if (typeCtx.primitiveType()) {
|
|
182
|
+
return {
|
|
183
|
+
typeName: typeCtx.primitiveType()!.getText(),
|
|
184
|
+
isStruct: false,
|
|
185
|
+
isCallback: false,
|
|
186
|
+
isString: false,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (typeCtx.userType()) {
|
|
191
|
+
const typeName = typeCtx.userType()!.getText();
|
|
192
|
+
return {
|
|
193
|
+
typeName,
|
|
194
|
+
isStruct: callbacks.isStructType(typeName),
|
|
195
|
+
isCallback: CodeGenState.callbackTypes.has(typeName),
|
|
196
|
+
isString: false,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (typeCtx.qualifiedType()) {
|
|
201
|
+
const identifierNames = typeCtx
|
|
202
|
+
.qualifiedType()!
|
|
203
|
+
.IDENTIFIER()
|
|
204
|
+
.map((id) => id.getText());
|
|
205
|
+
const typeName = callbacks.resolveQualifiedType(identifierNames);
|
|
206
|
+
return {
|
|
207
|
+
typeName,
|
|
208
|
+
isStruct: callbacks.isStructType(typeName),
|
|
209
|
+
isCallback: false,
|
|
210
|
+
isString: false,
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (typeCtx.scopedType()) {
|
|
215
|
+
const localTypeName = typeCtx.scopedType()!.IDENTIFIER().getText();
|
|
216
|
+
const typeName = CodeGenState.currentScope
|
|
217
|
+
? `${CodeGenState.currentScope}_${localTypeName}`
|
|
218
|
+
: localTypeName;
|
|
219
|
+
return {
|
|
220
|
+
typeName,
|
|
221
|
+
isStruct: callbacks.isStructType(typeName),
|
|
222
|
+
isCallback: false,
|
|
223
|
+
isString: false,
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if (typeCtx.globalType()) {
|
|
228
|
+
const typeName = typeCtx.globalType()!.IDENTIFIER().getText();
|
|
229
|
+
return {
|
|
230
|
+
typeName,
|
|
231
|
+
isStruct: callbacks.isStructType(typeName),
|
|
232
|
+
isCallback: false,
|
|
233
|
+
isString: false,
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
if (typeCtx.stringType()) {
|
|
238
|
+
return {
|
|
239
|
+
typeName: "string",
|
|
240
|
+
isStruct: false,
|
|
241
|
+
isCallback: false,
|
|
242
|
+
isString: true,
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Handle C-Next style array type (u8[8] param) - extract base type
|
|
247
|
+
if (typeCtx.arrayType()) {
|
|
248
|
+
const arrayTypeCtx = typeCtx.arrayType()!;
|
|
249
|
+
if (arrayTypeCtx.primitiveType()) {
|
|
250
|
+
return {
|
|
251
|
+
typeName: arrayTypeCtx.primitiveType()!.getText(),
|
|
252
|
+
isStruct: false,
|
|
253
|
+
isCallback: false,
|
|
254
|
+
isString: false,
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
if (arrayTypeCtx.userType()) {
|
|
258
|
+
const typeName = arrayTypeCtx.userType()!.getText();
|
|
259
|
+
return {
|
|
260
|
+
typeName,
|
|
261
|
+
isStruct: callbacks.isStructType(typeName),
|
|
262
|
+
isCallback: CodeGenState.callbackTypes.has(typeName),
|
|
263
|
+
isString: false,
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
// Handle string array type (string<32>[5] param)
|
|
267
|
+
if (arrayTypeCtx.stringType()) {
|
|
268
|
+
const stringCtx = arrayTypeCtx.stringType()!;
|
|
269
|
+
return {
|
|
270
|
+
typeName: stringCtx.getText(), // "string<32>"
|
|
271
|
+
isStruct: false,
|
|
272
|
+
isCallback: false,
|
|
273
|
+
isString: true,
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Fallback
|
|
279
|
+
return {
|
|
280
|
+
typeName: typeCtx.getText(),
|
|
281
|
+
isStruct: false,
|
|
282
|
+
isCallback: false,
|
|
283
|
+
isString: false,
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Register a parameter in the type registry.
|
|
289
|
+
*/
|
|
290
|
+
static registerParameterType(
|
|
291
|
+
name: string,
|
|
292
|
+
typeInfo: IParameterTypeInfo,
|
|
293
|
+
param: Parser.ParameterContext,
|
|
294
|
+
isArray: boolean,
|
|
295
|
+
isConst: boolean,
|
|
296
|
+
): void {
|
|
297
|
+
const { typeName, isString } = typeInfo;
|
|
298
|
+
const typeCtx = param.type();
|
|
299
|
+
|
|
300
|
+
const isEnum = CodeGenState.symbols!.knownEnums.has(typeName);
|
|
301
|
+
const isBitmap = CodeGenState.symbols!.knownBitmaps.has(typeName);
|
|
302
|
+
|
|
303
|
+
// Extract array dimensions
|
|
304
|
+
const arrayDimensions = FunctionContextManager.extractParamArrayDimensions(
|
|
305
|
+
param,
|
|
306
|
+
typeCtx,
|
|
307
|
+
isArray,
|
|
308
|
+
);
|
|
309
|
+
|
|
310
|
+
// Add string capacity dimension if applicable
|
|
311
|
+
const stringCapacity = FunctionContextManager.getStringCapacity(
|
|
312
|
+
typeCtx,
|
|
313
|
+
isString,
|
|
314
|
+
);
|
|
315
|
+
if (isArray && stringCapacity !== undefined) {
|
|
316
|
+
arrayDimensions.push(stringCapacity + 1);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
const registeredType = {
|
|
320
|
+
baseType: typeName,
|
|
321
|
+
bitWidth: isBitmap
|
|
322
|
+
? CodeGenState.symbols!.bitmapBitWidth.get(typeName) || 0
|
|
323
|
+
: TYPE_WIDTH[typeName] || 0,
|
|
324
|
+
isArray,
|
|
325
|
+
arrayDimensions: arrayDimensions.length > 0 ? arrayDimensions : undefined,
|
|
326
|
+
isConst,
|
|
327
|
+
isEnum,
|
|
328
|
+
enumTypeName: isEnum ? typeName : undefined,
|
|
329
|
+
isBitmap,
|
|
330
|
+
bitmapTypeName: isBitmap ? typeName : undefined,
|
|
331
|
+
isString,
|
|
332
|
+
stringCapacity,
|
|
333
|
+
isParameter: true,
|
|
334
|
+
};
|
|
335
|
+
CodeGenState.setVariableTypeInfo(name, registeredType);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Extract array dimensions from parameter (C-style or C-Next style).
|
|
340
|
+
*/
|
|
341
|
+
static extractParamArrayDimensions(
|
|
342
|
+
param: Parser.ParameterContext,
|
|
343
|
+
typeCtx: Parser.TypeContext,
|
|
344
|
+
isArray: boolean,
|
|
345
|
+
): number[] {
|
|
346
|
+
if (!isArray) return [];
|
|
347
|
+
|
|
348
|
+
// Try C-style first (param.arrayDimension())
|
|
349
|
+
if (param.arrayDimension().length > 0) {
|
|
350
|
+
return ArrayDimensionParser.parseForParameters(param.arrayDimension());
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// C-Next style: get dimensions from arrayType
|
|
354
|
+
const arrayTypeCtx = typeCtx.arrayType();
|
|
355
|
+
if (!arrayTypeCtx) return [];
|
|
356
|
+
|
|
357
|
+
const dimensions: number[] = [];
|
|
358
|
+
for (const dim of arrayTypeCtx.arrayTypeDimension()) {
|
|
359
|
+
const expr = dim.expression();
|
|
360
|
+
if (!expr) continue;
|
|
361
|
+
const size = Number.parseInt(expr.getText(), 10);
|
|
362
|
+
if (!Number.isNaN(size)) {
|
|
363
|
+
dimensions.push(size);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
return dimensions;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Extract string capacity from a string type context.
|
|
371
|
+
*/
|
|
372
|
+
static getStringCapacity(
|
|
373
|
+
typeCtx: Parser.TypeContext,
|
|
374
|
+
isString: boolean,
|
|
375
|
+
): number | undefined {
|
|
376
|
+
if (!isString) return undefined;
|
|
377
|
+
|
|
378
|
+
// Check direct stringType (e.g., string<32> param)
|
|
379
|
+
if (typeCtx.stringType()) {
|
|
380
|
+
const intLiteral = typeCtx.stringType()!.INTEGER_LITERAL();
|
|
381
|
+
if (intLiteral) {
|
|
382
|
+
return Number.parseInt(intLiteral.getText(), 10);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// Check arrayType with stringType (e.g., string<32>[5] param)
|
|
387
|
+
if (typeCtx.arrayType()?.stringType()) {
|
|
388
|
+
const intLiteral = typeCtx.arrayType()!.stringType()!.INTEGER_LITERAL();
|
|
389
|
+
if (intLiteral) {
|
|
390
|
+
return Number.parseInt(intLiteral.getText(), 10);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
return undefined;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* Clear parameter tracking when leaving a function.
|
|
399
|
+
*/
|
|
400
|
+
static clearParameters(): void {
|
|
401
|
+
// ADR-025: Remove parameter types from typeRegistry
|
|
402
|
+
for (const name of CodeGenState.currentParameters.keys()) {
|
|
403
|
+
CodeGenState.deleteVariableTypeInfo(name);
|
|
404
|
+
}
|
|
405
|
+
CodeGenState.currentParameters.clear();
|
|
406
|
+
CodeGenState.localArrays.clear();
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Enter function body - clears local variables and sets inFunctionBody flag.
|
|
411
|
+
* This is a simpler version used when only body lifecycle is needed.
|
|
412
|
+
*/
|
|
413
|
+
static enterFunctionBody(): void {
|
|
414
|
+
CodeGenState.localVariables.clear();
|
|
415
|
+
CodeGenState.floatBitShadows.clear();
|
|
416
|
+
CodeGenState.floatShadowCurrent.clear();
|
|
417
|
+
CodeGenState.inFunctionBody = true;
|
|
418
|
+
CodeGenState.enterFunctionBody();
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* Exit function body - clears local variables and inFunctionBody flag.
|
|
423
|
+
* This is a simpler version used when only body lifecycle is needed.
|
|
424
|
+
*/
|
|
425
|
+
static exitFunctionBody(): void {
|
|
426
|
+
CodeGenState.inFunctionBody = false;
|
|
427
|
+
CodeGenState.localVariables.clear();
|
|
428
|
+
CodeGenState.floatBitShadows.clear();
|
|
429
|
+
CodeGenState.floatShadowCurrent.clear();
|
|
430
|
+
CodeGenState.mainArgsName = null;
|
|
431
|
+
CodeGenState.exitFunctionBody();
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
export default FunctionContextManager;
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StringOperationsHelper - String operation detection and extraction
|
|
3
|
+
*
|
|
4
|
+
* Extracted from CodeGenerator to reduce file size.
|
|
5
|
+
* Handles detection of string concatenation and substring patterns.
|
|
6
|
+
*
|
|
7
|
+
* ADR-045: String type support
|
|
8
|
+
* Issue #707: Uses ExpressionUnwrapper for tree navigation
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import * as Parser from "../../../logic/parser/grammar/CNextParser.js";
|
|
12
|
+
import CodeGenState from "../../../state/CodeGenState.js";
|
|
13
|
+
import StringUtils from "../../../../utils/StringUtils.js";
|
|
14
|
+
import ExpressionUnwrapper from "../utils/ExpressionUnwrapper.js";
|
|
15
|
+
|
|
16
|
+
/** Regex for identifying valid C/C++ identifiers */
|
|
17
|
+
const IDENTIFIER_REGEX = /^[a-zA-Z_]\w*$/;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* String concatenation operands extracted from expression.
|
|
21
|
+
*/
|
|
22
|
+
interface IStringConcatOps {
|
|
23
|
+
left: string;
|
|
24
|
+
right: string;
|
|
25
|
+
leftCapacity: number;
|
|
26
|
+
rightCapacity: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Substring extraction operands extracted from expression.
|
|
31
|
+
*/
|
|
32
|
+
interface ISubstringOps {
|
|
33
|
+
source: string;
|
|
34
|
+
start: string;
|
|
35
|
+
length: string;
|
|
36
|
+
sourceCapacity: number;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Callbacks for substring operand extraction.
|
|
41
|
+
*/
|
|
42
|
+
interface ISubstringCallbacks {
|
|
43
|
+
/** Generate expression code */
|
|
44
|
+
generateExpression: (ctx: Parser.ExpressionContext) => string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Helper for string operation detection and extraction.
|
|
49
|
+
* All methods are static - uses CodeGenState for shared state.
|
|
50
|
+
*/
|
|
51
|
+
class StringOperationsHelper {
|
|
52
|
+
// ========================================================================
|
|
53
|
+
// Tier 1: Pure Utilities (no callbacks needed)
|
|
54
|
+
// ========================================================================
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Get the capacity of a string expression.
|
|
58
|
+
* For string literals, capacity equals content length.
|
|
59
|
+
* For string variables, capacity is from the type registry.
|
|
60
|
+
*
|
|
61
|
+
* ADR-045: String capacity resolution for concatenation and bounds checking.
|
|
62
|
+
*
|
|
63
|
+
* @param exprCode - Expression code text (e.g., "hello" or varName)
|
|
64
|
+
* @returns Capacity in characters, or null if not a string
|
|
65
|
+
*/
|
|
66
|
+
static getStringExprCapacity(exprCode: string): number | null {
|
|
67
|
+
// String literal - capacity equals content length
|
|
68
|
+
if (exprCode.startsWith('"') && exprCode.endsWith('"')) {
|
|
69
|
+
return StringUtils.literalLength(exprCode);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Variable - check type registry
|
|
73
|
+
if (IDENTIFIER_REGEX.test(exprCode)) {
|
|
74
|
+
const typeInfo = CodeGenState.getVariableTypeInfo(exprCode);
|
|
75
|
+
if (typeInfo?.isString && typeInfo.stringCapacity !== undefined) {
|
|
76
|
+
return typeInfo.stringCapacity;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Check if an expression is a string concatenation (contains + with string operands).
|
|
85
|
+
* Returns the operand expressions and capacities if it is, null otherwise.
|
|
86
|
+
*
|
|
87
|
+
* ADR-045: String concatenation detection for strncpy/strncat generation.
|
|
88
|
+
* Issue #707: Uses ExpressionUnwrapper for tree navigation.
|
|
89
|
+
*
|
|
90
|
+
* @param ctx - Expression context to check
|
|
91
|
+
* @returns Concatenation operands or null if not a string concat
|
|
92
|
+
*/
|
|
93
|
+
static getStringConcatOperands(
|
|
94
|
+
ctx: Parser.ExpressionContext,
|
|
95
|
+
): IStringConcatOps | null {
|
|
96
|
+
// Navigate to the additive expression level using ExpressionUnwrapper
|
|
97
|
+
const add = ExpressionUnwrapper.getAdditiveExpression(ctx);
|
|
98
|
+
if (!add) return null;
|
|
99
|
+
const multExprs = add.multiplicativeExpression();
|
|
100
|
+
|
|
101
|
+
// Need exactly 2 operands for simple concatenation
|
|
102
|
+
if (multExprs.length !== 2) return null;
|
|
103
|
+
|
|
104
|
+
// Check if this is addition (not subtraction)
|
|
105
|
+
// Use MINUS() token check instead of text.includes("-") to avoid
|
|
106
|
+
// false positives from identifiers/literals containing hyphens
|
|
107
|
+
if (add.MINUS().length > 0) return null;
|
|
108
|
+
|
|
109
|
+
// Get the operand texts
|
|
110
|
+
const leftText = multExprs[0].getText();
|
|
111
|
+
const rightText = multExprs[1].getText();
|
|
112
|
+
|
|
113
|
+
// Check if at least one operand is a string
|
|
114
|
+
const leftCapacity = StringOperationsHelper.getStringExprCapacity(leftText);
|
|
115
|
+
const rightCapacity =
|
|
116
|
+
StringOperationsHelper.getStringExprCapacity(rightText);
|
|
117
|
+
|
|
118
|
+
if (leftCapacity === null && rightCapacity === null) {
|
|
119
|
+
return null; // Neither is a string
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// If one is null, it's not a valid string concatenation
|
|
123
|
+
if (leftCapacity === null || rightCapacity === null) {
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return {
|
|
128
|
+
left: leftText,
|
|
129
|
+
right: rightText,
|
|
130
|
+
leftCapacity,
|
|
131
|
+
rightCapacity,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// ========================================================================
|
|
136
|
+
// Tier 2: Operations with Callbacks
|
|
137
|
+
// ========================================================================
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Check if an expression is a substring extraction (string[start, length]).
|
|
141
|
+
* Returns the source string, start, length, and source capacity if it is.
|
|
142
|
+
*
|
|
143
|
+
* ADR-045: Substring extraction detection for safe string slicing.
|
|
144
|
+
* Issue #707: Uses ExpressionUnwrapper for tree navigation.
|
|
145
|
+
* Issue #140: Handles both [start, length] and single-char [index] patterns.
|
|
146
|
+
*
|
|
147
|
+
* @param ctx - Expression context to check
|
|
148
|
+
* @param callbacks - Callbacks for expression generation
|
|
149
|
+
* @returns Substring operands or null if not a substring extraction
|
|
150
|
+
*/
|
|
151
|
+
static getSubstringOperands(
|
|
152
|
+
ctx: Parser.ExpressionContext,
|
|
153
|
+
callbacks: ISubstringCallbacks,
|
|
154
|
+
): ISubstringOps | null {
|
|
155
|
+
// Navigate to the postfix expression level using shared utility
|
|
156
|
+
const postfix = ExpressionUnwrapper.getPostfixExpression(ctx);
|
|
157
|
+
if (!postfix) return null;
|
|
158
|
+
|
|
159
|
+
const primary = postfix.primaryExpression();
|
|
160
|
+
const ops = postfix.postfixOp();
|
|
161
|
+
|
|
162
|
+
// Need exactly one postfix operation (the [start, length])
|
|
163
|
+
if (ops.length !== 1) return null;
|
|
164
|
+
|
|
165
|
+
const op = ops[0];
|
|
166
|
+
const exprs = op.expression();
|
|
167
|
+
|
|
168
|
+
// Get the source variable name first
|
|
169
|
+
const sourceId = primary.IDENTIFIER();
|
|
170
|
+
if (!sourceId) return null;
|
|
171
|
+
|
|
172
|
+
const sourceName = sourceId.getText();
|
|
173
|
+
|
|
174
|
+
// Check if source is a string type
|
|
175
|
+
const typeInfo = CodeGenState.getVariableTypeInfo(sourceName);
|
|
176
|
+
if (!typeInfo?.isString || typeInfo.stringCapacity === undefined) {
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Issue #140: Handle both [start, length] pattern (2 expressions)
|
|
181
|
+
// and single-character access [index] pattern (1 expression, treated as [index, 1])
|
|
182
|
+
if (exprs.length === 2) {
|
|
183
|
+
return {
|
|
184
|
+
source: sourceName,
|
|
185
|
+
start: callbacks.generateExpression(exprs[0]),
|
|
186
|
+
length: callbacks.generateExpression(exprs[1]),
|
|
187
|
+
sourceCapacity: typeInfo.stringCapacity,
|
|
188
|
+
};
|
|
189
|
+
} else if (exprs.length === 1) {
|
|
190
|
+
// Single-character access: source[i] is sugar for source[i, 1]
|
|
191
|
+
return {
|
|
192
|
+
source: sourceName,
|
|
193
|
+
start: callbacks.generateExpression(exprs[0]),
|
|
194
|
+
length: "1",
|
|
195
|
+
sourceCapacity: typeInfo.stringCapacity,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
return null;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export default StringOperationsHelper;
|
|
@@ -5,14 +5,14 @@
|
|
|
5
5
|
* Extracts common lookup patterns for improved testability.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import
|
|
8
|
+
import TSymbolKind from "../../../types/symbol-kinds/TSymbolKind.js";
|
|
9
9
|
import ESourceLanguage from "../../../../utils/types/ESourceLanguage.js";
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Symbol interface for lookups
|
|
13
13
|
*/
|
|
14
14
|
interface ISymbol {
|
|
15
|
-
kind:
|
|
15
|
+
kind: TSymbolKind;
|
|
16
16
|
sourceLanguage: ESourceLanguage;
|
|
17
17
|
}
|
|
18
18
|
|
|
@@ -31,7 +31,7 @@ class SymbolLookupHelper {
|
|
|
31
31
|
static hasSymbolWithKindAndLanguage(
|
|
32
32
|
symbolTable: ISymbolTable | null | undefined,
|
|
33
33
|
name: string,
|
|
34
|
-
kind:
|
|
34
|
+
kind: TSymbolKind,
|
|
35
35
|
languages: ESourceLanguage[],
|
|
36
36
|
): boolean {
|
|
37
37
|
if (!symbolTable) return false;
|
|
@@ -53,7 +53,7 @@ class SymbolLookupHelper {
|
|
|
53
53
|
return SymbolLookupHelper.hasSymbolWithKindAndLanguage(
|
|
54
54
|
symbolTable,
|
|
55
55
|
typeName,
|
|
56
|
-
|
|
56
|
+
"enum",
|
|
57
57
|
[ESourceLanguage.Cpp],
|
|
58
58
|
);
|
|
59
59
|
}
|
|
@@ -69,7 +69,7 @@ class SymbolLookupHelper {
|
|
|
69
69
|
return SymbolLookupHelper.hasSymbolWithKindAndLanguage(
|
|
70
70
|
symbolTable,
|
|
71
71
|
name,
|
|
72
|
-
|
|
72
|
+
"function",
|
|
73
73
|
[ESourceLanguage.C, ESourceLanguage.Cpp],
|
|
74
74
|
);
|
|
75
75
|
}
|
|
@@ -84,7 +84,7 @@ class SymbolLookupHelper {
|
|
|
84
84
|
if (!symbolTable) return false;
|
|
85
85
|
|
|
86
86
|
const symbols = symbolTable.getOverloads(name);
|
|
87
|
-
return symbols.some((sym) => sym.kind ===
|
|
87
|
+
return symbols.some((sym) => sym.kind === "namespace");
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
/**
|
|
@@ -99,11 +99,7 @@ class SymbolLookupHelper {
|
|
|
99
99
|
if (!symbolTable) return false;
|
|
100
100
|
|
|
101
101
|
const symbols = symbolTable.getOverloads(typeName);
|
|
102
|
-
const cppTypeKinds = new Set([
|
|
103
|
-
ESymbolKind.Struct,
|
|
104
|
-
ESymbolKind.Class,
|
|
105
|
-
ESymbolKind.Type,
|
|
106
|
-
]);
|
|
102
|
+
const cppTypeKinds = new Set<TSymbolKind>(["struct", "class", "type"]);
|
|
107
103
|
|
|
108
104
|
return symbols.some(
|
|
109
105
|
(sym) =>
|
|
@@ -123,7 +119,7 @@ class SymbolLookupHelper {
|
|
|
123
119
|
return SymbolLookupHelper.hasSymbolWithKindAndLanguage(
|
|
124
120
|
symbolTable,
|
|
125
121
|
name,
|
|
126
|
-
|
|
122
|
+
"function",
|
|
127
123
|
[ESourceLanguage.CNext],
|
|
128
124
|
);
|
|
129
125
|
}
|