c-next 0.1.69 → 0.1.71

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (247) hide show
  1. package/package.json +1 -1
  2. package/src/lib/__tests__/parseCHeader.mocked.test.ts +69 -54
  3. package/src/lib/parseCHeader.ts +56 -23
  4. package/src/lib/parseWithSymbols.ts +195 -53
  5. package/src/transpiler/Transpiler.ts +173 -60
  6. package/src/transpiler/logic/analysis/FunctionCallAnalyzer.ts +240 -205
  7. package/src/transpiler/logic/analysis/InitializationAnalyzer.ts +1 -2
  8. package/src/transpiler/logic/analysis/PassByValueAnalyzer.ts +742 -0
  9. package/src/transpiler/logic/analysis/__tests__/FunctionCallAnalyzer.test.ts +102 -15
  10. package/src/transpiler/logic/analysis/__tests__/InitializationAnalyzer.test.ts +9 -9
  11. package/src/transpiler/logic/analysis/__tests__/runAnalyzers.test.ts +5 -5
  12. package/src/transpiler/{output/codegen → logic/analysis}/helpers/AssignmentTargetExtractor.ts +1 -1
  13. package/src/transpiler/{output/codegen → logic/analysis}/helpers/ChildStatementCollector.ts +1 -1
  14. package/src/transpiler/{output/codegen → logic/analysis}/helpers/StatementExpressionCollector.ts +1 -1
  15. package/src/transpiler/{output/codegen → logic/analysis}/helpers/__tests__/AssignmentTargetExtractor.test.ts +2 -2
  16. package/src/transpiler/{output/codegen → logic/analysis}/helpers/__tests__/ChildStatementCollector.test.ts +2 -2
  17. package/src/transpiler/{output/codegen → logic/analysis}/helpers/__tests__/StatementExpressionCollector.test.ts +2 -2
  18. package/src/transpiler/logic/symbols/SymbolTable.ts +676 -258
  19. package/src/transpiler/logic/symbols/SymbolUtils.ts +2 -2
  20. package/src/transpiler/logic/symbols/__tests__/SymbolTable.test.ts +290 -782
  21. package/src/transpiler/logic/symbols/c/__tests__/CResolver.integration.test.ts +573 -0
  22. package/src/transpiler/logic/symbols/c/__tests__/testHelpers.ts +20 -0
  23. package/src/transpiler/logic/symbols/c/collectors/EnumCollector.ts +82 -0
  24. package/src/transpiler/logic/symbols/c/collectors/FunctionCollector.ts +106 -0
  25. package/src/transpiler/logic/symbols/c/collectors/StructCollector.ts +173 -0
  26. package/src/transpiler/logic/symbols/c/collectors/TypedefCollector.ts +35 -0
  27. package/src/transpiler/logic/symbols/c/collectors/VariableCollector.ts +80 -0
  28. package/src/transpiler/logic/symbols/c/index.ts +333 -0
  29. package/src/transpiler/logic/symbols/c/utils/DeclaratorUtils.ts +269 -0
  30. package/src/transpiler/logic/symbols/cnext/__tests__/BitmapCollector.test.ts +50 -11
  31. package/src/transpiler/logic/symbols/cnext/__tests__/CNextResolver.integration.test.ts +45 -34
  32. package/src/transpiler/logic/symbols/cnext/__tests__/EnumCollector.test.ts +30 -13
  33. package/src/transpiler/logic/symbols/cnext/__tests__/FunctionCollector.test.ts +279 -64
  34. package/src/transpiler/logic/symbols/cnext/__tests__/RegisterCollector.test.ts +60 -13
  35. package/src/transpiler/logic/symbols/cnext/__tests__/ScopeCollector.test.ts +40 -37
  36. package/src/transpiler/logic/symbols/cnext/__tests__/StructCollector.test.ts +131 -45
  37. package/src/transpiler/logic/symbols/cnext/__tests__/TSymbolInfoAdapter.test.ts +223 -139
  38. package/src/transpiler/logic/symbols/cnext/__tests__/VariableCollector.test.ts +79 -25
  39. package/src/transpiler/logic/symbols/cnext/__tests__/testUtils.ts +53 -0
  40. package/src/transpiler/logic/symbols/cnext/adapters/TSymbolInfoAdapter.ts +83 -43
  41. package/src/transpiler/logic/symbols/cnext/collectors/BitmapCollector.ts +14 -13
  42. package/src/transpiler/logic/symbols/cnext/collectors/EnumCollector.ts +11 -10
  43. package/src/transpiler/logic/symbols/cnext/collectors/FunctionCollector.ts +83 -34
  44. package/src/transpiler/logic/symbols/cnext/collectors/RegisterCollector.ts +22 -18
  45. package/src/transpiler/logic/symbols/cnext/collectors/ScopeCollector.ts +53 -35
  46. package/src/transpiler/logic/symbols/cnext/collectors/StructCollector.ts +30 -23
  47. package/src/transpiler/logic/symbols/cnext/collectors/VariableCollector.ts +18 -19
  48. package/src/transpiler/logic/symbols/cnext/index.ts +36 -14
  49. package/src/transpiler/logic/symbols/cnext/types/IScopeCollectorResult.ts +2 -2
  50. package/src/transpiler/logic/symbols/cnext/utils/SymbolNameUtils.ts +27 -0
  51. package/src/transpiler/logic/symbols/cpp/__tests__/CppResolver.integration.test.ts +270 -0
  52. package/src/transpiler/logic/symbols/cpp/__tests__/testHelpers.ts +20 -0
  53. package/src/transpiler/logic/symbols/cpp/collectors/ClassCollector.ts +317 -0
  54. package/src/transpiler/logic/symbols/cpp/collectors/EnumCollector.ts +71 -0
  55. package/src/transpiler/logic/symbols/cpp/collectors/FunctionCollector.ts +155 -0
  56. package/src/transpiler/logic/symbols/cpp/collectors/NamespaceCollector.ts +65 -0
  57. package/src/transpiler/logic/symbols/cpp/collectors/TypeAliasCollector.ts +46 -0
  58. package/src/transpiler/logic/symbols/cpp/collectors/VariableCollector.ts +54 -0
  59. package/src/transpiler/logic/symbols/cpp/index.ts +366 -0
  60. package/src/transpiler/logic/symbols/cpp/utils/DeclaratorUtils.ts +248 -0
  61. package/src/transpiler/logic/symbols/shared/IExtractedParameter.ts +18 -0
  62. package/src/transpiler/logic/symbols/shared/ParameterExtractorUtils.ts +73 -0
  63. package/src/transpiler/output/codegen/CodeGenerator.ts +310 -2288
  64. package/src/transpiler/output/codegen/TypeRegistrationUtils.ts +4 -6
  65. package/src/transpiler/output/codegen/TypeResolver.ts +2 -2
  66. package/src/transpiler/output/codegen/TypeValidator.ts +5 -5
  67. package/src/transpiler/output/codegen/__tests__/CodeGenerator.test.ts +7 -1
  68. package/src/transpiler/output/codegen/__tests__/TypeRegistrationUtils.test.ts +36 -51
  69. package/src/transpiler/output/codegen/__tests__/TypeResolver.test.ts +20 -17
  70. package/src/transpiler/output/codegen/__tests__/TypeValidator.resolution.test.ts +3 -3
  71. package/src/transpiler/output/codegen/__tests__/TypeValidator.test.ts +1 -1
  72. package/src/transpiler/output/codegen/analysis/MemberChainAnalyzer.ts +1 -1
  73. package/src/transpiler/output/codegen/analysis/StringLengthCounter.ts +1 -1
  74. package/src/transpiler/output/codegen/analysis/__tests__/MemberChainAnalyzer.test.ts +9 -9
  75. package/src/transpiler/output/codegen/analysis/__tests__/StringLengthCounter.test.ts +12 -12
  76. package/src/transpiler/output/codegen/assignment/AssignmentClassifier.ts +13 -12
  77. package/src/transpiler/output/codegen/assignment/__tests__/AssignmentClassifier.test.ts +23 -17
  78. package/src/transpiler/output/codegen/assignment/handlers/ArrayHandlers.ts +2 -2
  79. package/src/transpiler/output/codegen/assignment/handlers/AssignmentHandlerUtils.ts +7 -1
  80. package/src/transpiler/output/codegen/assignment/handlers/BitAccessHandlers.ts +3 -3
  81. package/src/transpiler/output/codegen/assignment/handlers/BitmapHandlers.ts +9 -5
  82. package/src/transpiler/output/codegen/assignment/handlers/RegisterHandlers.ts +2 -1
  83. package/src/transpiler/output/codegen/assignment/handlers/SpecialHandlers.ts +4 -4
  84. package/src/transpiler/output/codegen/assignment/handlers/StringHandlers.ts +5 -5
  85. package/src/transpiler/output/codegen/assignment/handlers/__tests__/ArrayHandlers.test.ts +23 -25
  86. package/src/transpiler/output/codegen/assignment/handlers/__tests__/BitAccessHandlers.test.ts +20 -36
  87. package/src/transpiler/output/codegen/assignment/handlers/__tests__/BitmapHandlers.test.ts +18 -18
  88. package/src/transpiler/output/codegen/assignment/handlers/__tests__/SpecialHandlers.test.ts +42 -32
  89. package/src/transpiler/output/codegen/assignment/handlers/__tests__/handlerTestUtils.ts +5 -4
  90. package/src/transpiler/output/codegen/generators/declarationGenerators/ScopeGenerator.ts +21 -8
  91. package/src/transpiler/output/codegen/generators/declarationGenerators/ScopedRegisterGenerator.ts +3 -2
  92. package/src/transpiler/output/codegen/generators/expressions/CallExprGenerator.ts +14 -6
  93. package/src/transpiler/output/codegen/generators/expressions/CallExprUtils.ts +9 -3
  94. package/src/transpiler/output/codegen/generators/expressions/PostfixExpressionGenerator.ts +19 -16
  95. package/src/transpiler/output/codegen/generators/expressions/__tests__/CallExprGenerator.test.ts +24 -8
  96. package/src/transpiler/output/codegen/generators/expressions/__tests__/CallExprUtils.test.ts +4 -8
  97. package/src/transpiler/output/codegen/generators/expressions/__tests__/PostfixExpressionGenerator.test.ts +15 -2
  98. package/src/transpiler/output/codegen/helpers/ArgumentGenerator.ts +236 -0
  99. package/src/transpiler/output/codegen/helpers/ArrayInitHelper.ts +2 -1
  100. package/src/transpiler/output/codegen/helpers/AssignmentExpectedTypeResolver.ts +2 -2
  101. package/src/transpiler/output/codegen/helpers/AssignmentValidator.ts +3 -3
  102. package/src/transpiler/output/codegen/helpers/CppConstructorHelper.ts +3 -3
  103. package/src/transpiler/output/codegen/helpers/EnumAssignmentValidator.ts +1 -1
  104. package/src/transpiler/output/codegen/helpers/FunctionContextManager.ts +435 -0
  105. package/src/transpiler/output/codegen/helpers/StringDeclHelper.ts +2 -2
  106. package/src/transpiler/output/codegen/helpers/StringOperationsHelper.ts +203 -0
  107. package/src/transpiler/output/codegen/helpers/SymbolLookupHelper.ts +8 -12
  108. package/src/transpiler/output/codegen/helpers/TypeRegistrationEngine.ts +520 -0
  109. package/src/transpiler/output/codegen/helpers/VariableDeclHelper.ts +735 -0
  110. package/src/transpiler/output/codegen/helpers/VariableDeclarationFormatter.ts +1 -1
  111. package/src/transpiler/output/codegen/helpers/__tests__/ArgumentGenerator.test.ts +521 -0
  112. package/src/transpiler/output/codegen/helpers/__tests__/ArrayInitHelper.test.ts +1 -1
  113. package/src/transpiler/output/codegen/helpers/__tests__/AssignmentExpectedTypeResolver.test.ts +7 -7
  114. package/src/transpiler/output/codegen/helpers/__tests__/AssignmentValidator.test.ts +7 -7
  115. package/src/transpiler/output/codegen/helpers/__tests__/CppConstructorHelper.test.ts +4 -5
  116. package/src/transpiler/output/codegen/helpers/__tests__/EnumAssignmentValidator.test.ts +2 -2
  117. package/src/transpiler/output/codegen/helpers/__tests__/FunctionContextManager.test.ts +983 -0
  118. package/src/transpiler/output/codegen/helpers/__tests__/StringDeclHelper.test.ts +4 -4
  119. package/src/transpiler/output/codegen/helpers/__tests__/StringOperationsHelper.test.ts +269 -0
  120. package/src/transpiler/output/codegen/helpers/__tests__/SymbolLookupHelper.test.ts +31 -32
  121. package/src/transpiler/output/codegen/helpers/__tests__/TypeRegistrationEngine.test.ts +186 -0
  122. package/src/transpiler/output/codegen/helpers/__tests__/VariableDeclHelper.test.ts +460 -0
  123. package/src/transpiler/output/codegen/helpers/types/IArgumentGeneratorCallbacks.ts +32 -0
  124. package/src/transpiler/output/codegen/resolution/EnumTypeResolver.ts +7 -3
  125. package/src/transpiler/output/codegen/resolution/__tests__/EnumTypeResolver.test.ts +5 -5
  126. package/src/transpiler/output/codegen/types/IFunctionContextCallbacks.ts +12 -0
  127. package/src/transpiler/output/codegen/types/IVariableFormatInput.ts +1 -1
  128. package/src/transpiler/output/codegen/utils/QualifiedNameGenerator.ts +114 -0
  129. package/src/transpiler/output/codegen/utils/__tests__/QualifiedNameGenerator.test.ts +183 -0
  130. package/src/transpiler/output/headers/BaseHeaderGenerator.ts +4 -4
  131. package/src/transpiler/output/headers/ExternalTypeHeaderBuilder.ts +7 -7
  132. package/src/transpiler/output/headers/HeaderGenerator.ts +9 -7
  133. package/src/transpiler/output/headers/HeaderGeneratorUtils.ts +19 -20
  134. package/src/transpiler/output/headers/__tests__/BaseHeaderGenerator.test.ts +15 -18
  135. package/src/transpiler/output/headers/__tests__/CHeaderGenerator.test.ts +63 -64
  136. package/src/transpiler/output/headers/__tests__/CppHeaderGenerator.test.ts +36 -32
  137. package/src/transpiler/output/headers/__tests__/ExternalTypeHeaderBuilder.test.ts +26 -26
  138. package/src/transpiler/output/headers/__tests__/HeaderGenerator.test.ts +87 -59
  139. package/src/transpiler/output/headers/__tests__/HeaderGeneratorUtils.test.ts +57 -58
  140. package/src/transpiler/output/headers/adapters/HeaderSymbolAdapter.ts +222 -0
  141. package/src/transpiler/output/headers/adapters/__tests__/HeaderSymbolAdapter.test.ts +538 -0
  142. package/src/transpiler/output/headers/types/IGroupedSymbols.ts +8 -8
  143. package/src/transpiler/output/headers/types/IHeaderSymbol.ts +62 -0
  144. package/src/transpiler/state/CodeGenState.ts +109 -4
  145. package/src/transpiler/state/SymbolRegistry.ts +181 -0
  146. package/src/transpiler/{types → state}/TranspilerState.ts +1 -1
  147. package/src/transpiler/state/__tests__/CodeGenState.test.ts +277 -1
  148. package/src/transpiler/state/__tests__/SymbolRegistry.test.ts +249 -0
  149. package/src/transpiler/{types → state}/__tests__/TranspilerState.test.ts +1 -1
  150. package/src/transpiler/types/ICachedFileEntry.ts +1 -1
  151. package/src/transpiler/types/IConflict.ts +14 -0
  152. package/src/transpiler/types/ISerializedSymbol.ts +11 -0
  153. package/src/transpiler/types/TPrimitiveKind.ts +20 -0
  154. package/src/transpiler/types/TType.ts +103 -0
  155. package/src/transpiler/types/TVisibility.ts +6 -0
  156. package/src/transpiler/types/symbol-kinds/TSymbolKind.ts +10 -0
  157. package/src/transpiler/types/symbol-kinds/TSymbolKindC.ts +12 -0
  158. package/src/transpiler/types/symbol-kinds/TSymbolKindCNext.ts +16 -0
  159. package/src/transpiler/types/symbol-kinds/TSymbolKindCpp.ts +14 -0
  160. package/src/transpiler/types/symbols/IBaseSymbol.ts +31 -0
  161. package/src/transpiler/{logic/symbols/types → types/symbols}/IBitmapFieldInfo.ts +2 -2
  162. package/src/transpiler/types/symbols/IBitmapSymbol.ts +21 -0
  163. package/src/transpiler/{logic/symbols/types → types/symbols}/IEnumSymbol.ts +5 -6
  164. package/src/transpiler/types/symbols/IFieldInfo.ts +26 -0
  165. package/src/transpiler/types/symbols/IFunctionSymbol.ts +30 -0
  166. package/src/transpiler/types/symbols/IParameterInfo.ts +26 -0
  167. package/src/transpiler/{logic/symbols/types → types/symbols}/IRegisterMemberInfo.ts +4 -4
  168. package/src/transpiler/types/symbols/IRegisterSymbol.ts +18 -0
  169. package/src/transpiler/types/symbols/IScopeSymbol.ts +32 -0
  170. package/src/transpiler/{logic/symbols/types → types/symbols}/IStructFieldInfo.ts +2 -1
  171. package/src/transpiler/types/symbols/IStructSymbol.ts +15 -0
  172. package/src/transpiler/types/symbols/IVariableSymbol.ts +30 -0
  173. package/src/transpiler/types/symbols/SymbolGuards.ts +43 -0
  174. package/src/transpiler/types/symbols/TAnySymbol.ts +22 -0
  175. package/src/transpiler/types/symbols/TSymbol.ts +32 -0
  176. package/src/transpiler/types/symbols/__tests__/IBaseSymbol.test.ts +56 -0
  177. package/src/transpiler/types/symbols/__tests__/SymbolGuards.test.ts +57 -0
  178. package/src/transpiler/types/symbols/c/ICBaseSymbol.ts +28 -0
  179. package/src/transpiler/types/symbols/c/ICEnumMemberSymbol.ts +17 -0
  180. package/src/transpiler/types/symbols/c/ICEnumSymbol.ts +17 -0
  181. package/src/transpiler/types/symbols/c/ICFieldInfo.ts +16 -0
  182. package/src/transpiler/types/symbols/c/ICFunctionSymbol.ts +21 -0
  183. package/src/transpiler/types/symbols/c/ICParameterInfo.ts +19 -0
  184. package/src/transpiler/types/symbols/c/ICStructSymbol.ts +21 -0
  185. package/src/transpiler/types/symbols/c/ICTypedefSymbol.ts +14 -0
  186. package/src/transpiler/types/symbols/c/ICVariableSymbol.ts +26 -0
  187. package/src/transpiler/types/symbols/c/TCSymbol.ts +26 -0
  188. package/src/transpiler/types/symbols/cpp/ICppBaseSymbol.ts +31 -0
  189. package/src/transpiler/types/symbols/cpp/ICppClassSymbol.ts +15 -0
  190. package/src/transpiler/types/symbols/cpp/ICppEnumMemberSymbol.ts +14 -0
  191. package/src/transpiler/types/symbols/cpp/ICppEnumSymbol.ts +14 -0
  192. package/src/transpiler/types/symbols/cpp/ICppFieldInfo.ts +16 -0
  193. package/src/transpiler/types/symbols/cpp/ICppFunctionSymbol.ts +21 -0
  194. package/src/transpiler/types/symbols/cpp/ICppNamespaceSymbol.ts +11 -0
  195. package/src/transpiler/types/symbols/cpp/ICppParameterInfo.ts +19 -0
  196. package/src/transpiler/types/symbols/cpp/ICppStructSymbol.ts +16 -0
  197. package/src/transpiler/types/symbols/cpp/ICppTypeAliasSymbol.ts +14 -0
  198. package/src/transpiler/types/symbols/cpp/ICppVariableSymbol.ts +23 -0
  199. package/src/transpiler/types/symbols/cpp/TCppSymbol.ts +30 -0
  200. package/src/utils/CppNamespaceUtils.ts +3 -4
  201. package/src/utils/FunctionUtils.ts +92 -0
  202. package/src/utils/ParameterUtils.ts +55 -0
  203. package/src/utils/PrimitiveKindUtils.ts +33 -0
  204. package/src/utils/ScopeUtils.ts +105 -0
  205. package/src/utils/TTypeUtils.ts +159 -0
  206. package/src/utils/TypeResolver.ts +132 -0
  207. package/src/utils/__tests__/CppNamespaceUtils.test.ts +92 -99
  208. package/src/utils/__tests__/FunctionUtils.test.ts +284 -0
  209. package/src/utils/__tests__/ParameterUtils.test.ts +174 -0
  210. package/src/utils/__tests__/PrimitiveKindUtils.test.ts +59 -0
  211. package/src/utils/__tests__/ScopeUtils.test.ts +53 -0
  212. package/src/utils/__tests__/TTypeUtils.test.ts +245 -0
  213. package/src/utils/__tests__/TypeResolver.test.ts +332 -0
  214. package/src/utils/cache/CacheManager.ts +91 -50
  215. package/src/utils/cache/__tests__/CacheManager.test.ts +180 -114
  216. package/src/transpiler/logic/symbols/AutoConstUpdater.ts +0 -93
  217. package/src/transpiler/logic/symbols/CSymbolCollector.ts +0 -648
  218. package/src/transpiler/logic/symbols/CppSymbolCollector.ts +0 -874
  219. package/src/transpiler/logic/symbols/SymbolCollectorContext.ts +0 -68
  220. package/src/transpiler/logic/symbols/__tests__/AutoConstUpdater.test.ts +0 -418
  221. package/src/transpiler/logic/symbols/__tests__/CSymbolCollector.test.ts +0 -685
  222. package/src/transpiler/logic/symbols/__tests__/CppSymbolCollector.test.ts +0 -1146
  223. package/src/transpiler/logic/symbols/__tests__/SymbolCollectorContext.test.ts +0 -290
  224. package/src/transpiler/logic/symbols/__tests__/cTestHelpers.ts +0 -43
  225. package/src/transpiler/logic/symbols/__tests__/cppTestHelpers.ts +0 -40
  226. package/src/transpiler/logic/symbols/cnext/__tests__/TSymbolAdapter.test.ts +0 -595
  227. package/src/transpiler/logic/symbols/cnext/adapters/TSymbolAdapter.ts +0 -345
  228. package/src/transpiler/logic/symbols/types/IBaseSymbol.ts +0 -27
  229. package/src/transpiler/logic/symbols/types/IBitmapSymbol.ts +0 -23
  230. package/src/transpiler/logic/symbols/types/ICollectorContext.ts +0 -19
  231. package/src/transpiler/logic/symbols/types/IConflict.ts +0 -20
  232. package/src/transpiler/logic/symbols/types/IFieldInfo.ts +0 -18
  233. package/src/transpiler/logic/symbols/types/IFunctionSymbol.ts +0 -25
  234. package/src/transpiler/logic/symbols/types/IParameterInfo.ts +0 -24
  235. package/src/transpiler/logic/symbols/types/IRegisterSymbol.ts +0 -20
  236. package/src/transpiler/logic/symbols/types/IScopeSymbol.ts +0 -19
  237. package/src/transpiler/logic/symbols/types/IStructSymbol.ts +0 -16
  238. package/src/transpiler/logic/symbols/types/IVariableSymbol.ts +0 -30
  239. package/src/transpiler/logic/symbols/types/TSymbol.ts +0 -36
  240. package/src/transpiler/logic/symbols/types/__tests__/SymbolGuards.test.ts +0 -244
  241. package/src/transpiler/logic/symbols/types/typeGuards.ts +0 -44
  242. package/src/utils/types/ESymbolKind.ts +0 -19
  243. package/src/utils/types/ISymbol.ts +0 -64
  244. /package/src/transpiler/{types → constants}/BITMAP_BACKING_TYPE.ts +0 -0
  245. /package/src/transpiler/{types → constants}/BITMAP_SIZE.ts +0 -0
  246. /package/src/transpiler/{output/codegen → logic/analysis}/helpers/TransitiveModificationPropagator.ts +0 -0
  247. /package/src/transpiler/{output/codegen → logic/analysis}/helpers/__tests__/TransitiveModificationPropagator.test.ts +0 -0
@@ -1,14 +1,27 @@
1
1
  /**
2
2
  * Unified Symbol Table
3
3
  * Stores symbols from all source languages and detects conflicts
4
+ *
5
+ * ADR-055 Phase 7: Fully typed symbol storage using discriminated unions.
6
+ * - TSymbol: C-Next symbols (rich type system with TType)
7
+ * - TCSymbol: C header symbols (string types)
8
+ * - TCppSymbol: C++ header symbols (string types)
4
9
  */
5
10
 
6
- import ISymbol from "../../../utils/types/ISymbol";
7
11
  import ESourceLanguage from "../../../utils/types/ESourceLanguage";
8
- import ESymbolKind from "../../../utils/types/ESymbolKind";
9
12
  import LiteralUtils from "../../../utils/LiteralUtils";
10
- import IConflict from "./types/IConflict";
11
- import IStructFieldInfo from "./types/IStructFieldInfo";
13
+ import IConflict from "../../types/IConflict";
14
+ import IStructFieldInfo from "../../types/symbols/IStructFieldInfo";
15
+ import TSymbol from "../../types/symbols/TSymbol";
16
+ import TCSymbol from "../../types/symbols/c/TCSymbol";
17
+ import TCppSymbol from "../../types/symbols/cpp/TCppSymbol";
18
+ import TAnySymbol from "../../types/symbols/TAnySymbol";
19
+ import IStructSymbol from "../../types/symbols/IStructSymbol";
20
+ import IEnumSymbol from "../../types/symbols/IEnumSymbol";
21
+ import IFunctionSymbol from "../../types/symbols/IFunctionSymbol";
22
+ import IVariableSymbol from "../../types/symbols/IVariableSymbol";
23
+ import TypeResolver from "../../../utils/TypeResolver";
24
+ import SymbolNameUtils from "./cnext/utils/SymbolNameUtils";
12
25
 
13
26
  /**
14
27
  * Central symbol table for cross-language interoperability
@@ -19,11 +32,39 @@ import IStructFieldInfo from "./types/IStructFieldInfo";
19
32
  * - OK: Function overloads in C++ (different signatures)
20
33
  */
21
34
  class SymbolTable {
22
- /** All symbols indexed by name */
23
- private readonly symbols: Map<string, ISymbol[]> = new Map();
35
+ // ========================================================================
36
+ // C-Next Symbol Storage (TSymbol)
37
+ // ========================================================================
38
+
39
+ /** All C-Next TSymbols indexed by name */
40
+ private readonly tSymbols: Map<string, TSymbol[]> = new Map();
41
+
42
+ /** C-Next TSymbols indexed by source file */
43
+ private readonly tSymbolsByFile: Map<string, TSymbol[]> = new Map();
44
+
45
+ // ========================================================================
46
+ // C Symbol Storage (TCSymbol)
47
+ // ========================================================================
48
+
49
+ /** All C symbols indexed by name */
50
+ private readonly cSymbols: Map<string, TCSymbol[]> = new Map();
51
+
52
+ /** C symbols indexed by source file */
53
+ private readonly cSymbolsByFile: Map<string, TCSymbol[]> = new Map();
54
+
55
+ // ========================================================================
56
+ // C++ Symbol Storage (TCppSymbol)
57
+ // ========================================================================
58
+
59
+ /** All C++ symbols indexed by name */
60
+ private readonly cppSymbols: Map<string, TCppSymbol[]> = new Map();
24
61
 
25
- /** Symbols indexed by source file */
26
- private readonly byFile: Map<string, ISymbol[]> = new Map();
62
+ /** C++ symbols indexed by source file */
63
+ private readonly cppSymbolsByFile: Map<string, TCppSymbol[]> = new Map();
64
+
65
+ // ========================================================================
66
+ // Auxiliary Data (shared across languages)
67
+ // ========================================================================
27
68
 
28
69
  /** Struct field information: struct name -> (field name -> field info) */
29
70
  private readonly structFields: Map<string, Map<string, IStructFieldInfo>> =
@@ -42,331 +83,466 @@ class SymbolTable {
42
83
  */
43
84
  private readonly enumBitWidth: Map<string, number> = new Map();
44
85
 
86
+ // ========================================================================
87
+ // C-Next Symbol Methods (TSymbol)
88
+ // ========================================================================
89
+
45
90
  /**
46
- * Add a symbol to the table
91
+ * Add a C-Next TSymbol to the table
47
92
  */
48
- addSymbol(symbol: ISymbol): void {
93
+ addTSymbol(symbol: TSymbol): void {
49
94
  // Add to name index
50
- const existing = this.symbols.get(symbol.name);
95
+ const existing = this.tSymbols.get(symbol.name);
51
96
  if (existing) {
52
97
  existing.push(symbol);
53
98
  } else {
54
- this.symbols.set(symbol.name, [symbol]);
99
+ this.tSymbols.set(symbol.name, [symbol]);
55
100
  }
56
101
 
57
102
  // Add to file index
58
- const fileSymbols = this.byFile.get(symbol.sourceFile);
103
+ const fileSymbols = this.tSymbolsByFile.get(symbol.sourceFile);
59
104
  if (fileSymbols) {
60
105
  fileSymbols.push(symbol);
61
106
  } else {
62
- this.byFile.set(symbol.sourceFile, [symbol]);
107
+ this.tSymbolsByFile.set(symbol.sourceFile, [symbol]);
108
+ }
109
+
110
+ // Auto-register struct fields for TypeResolver.getMemberTypeInfo()
111
+ if (symbol.kind === "struct") {
112
+ this.registerStructFields(symbol);
63
113
  }
64
114
  }
65
115
 
66
116
  /**
67
- * Add multiple symbols at once
117
+ * Register struct fields in structFields map for cross-file type resolution.
118
+ * Called automatically when adding struct symbols.
68
119
  */
69
- addSymbols(symbols: ISymbol[]): void {
120
+ private registerStructFields(struct: IStructSymbol): void {
121
+ const mangledName = SymbolNameUtils.getMangledName(struct);
122
+
123
+ for (const [fieldName, fieldInfo] of struct.fields) {
124
+ // Convert TType to string for structFields map
125
+ const typeString = TypeResolver.getTypeName(fieldInfo.type);
126
+
127
+ // Filter to only numeric dimensions (structFields doesn't support string dims)
128
+ const numericDims = fieldInfo.dimensions?.filter(
129
+ (d): d is number => typeof d === "number",
130
+ );
131
+
132
+ this.addStructField(
133
+ mangledName,
134
+ fieldName,
135
+ typeString,
136
+ numericDims && numericDims.length > 0 ? numericDims : undefined,
137
+ );
138
+ }
139
+ }
140
+
141
+ /**
142
+ * Add multiple C-Next TSymbols at once
143
+ */
144
+ addTSymbols(symbols: TSymbol[]): void {
70
145
  for (const symbol of symbols) {
71
- this.addSymbol(symbol);
146
+ this.addTSymbol(symbol);
72
147
  }
73
148
  }
74
149
 
75
150
  /**
76
- * Get a symbol by name (returns first match, or undefined)
151
+ * Get a TSymbol by name (returns first match, or undefined)
77
152
  */
78
- getSymbol(name: string): ISymbol | undefined {
79
- const symbols = this.symbols.get(name);
153
+ getTSymbol(name: string): TSymbol | undefined {
154
+ const symbols = this.tSymbols.get(name);
80
155
  return symbols?.[0];
81
156
  }
82
157
 
83
158
  /**
84
- * Get all symbols with a given name (for overload detection)
159
+ * Get all TSymbols with a given name (for overload detection)
85
160
  */
86
- getOverloads(name: string): ISymbol[] {
87
- return this.symbols.get(name) ?? [];
161
+ getTOverloads(name: string): TSymbol[] {
162
+ return this.tSymbols.get(name) ?? [];
88
163
  }
89
164
 
90
165
  /**
91
- * Check if a symbol exists
166
+ * Get TSymbols by source file
92
167
  */
93
- hasSymbol(name: string): boolean {
94
- return this.symbols.has(name);
168
+ getTSymbolsByFile(file: string): TSymbol[] {
169
+ return this.tSymbolsByFile.get(file) ?? [];
95
170
  }
96
171
 
97
172
  /**
98
- * Check if a symbol has conflicts
173
+ * Get all TSymbols
99
174
  */
100
- hasConflict(name: string): boolean {
101
- const symbols = this.symbols.get(name);
102
- if (!symbols || symbols.length <= 1) {
103
- return false;
175
+ getAllTSymbols(): TSymbol[] {
176
+ const result: TSymbol[] = [];
177
+ for (const symbols of this.tSymbols.values()) {
178
+ result.push(...symbols);
104
179
  }
180
+ return result;
181
+ }
105
182
 
106
- return this.detectConflict(symbols) !== null;
183
+ /**
184
+ * Get all struct symbols (type-safe filtering)
185
+ */
186
+ getStructSymbols(): IStructSymbol[] {
187
+ return this.getAllTSymbols().filter(
188
+ (s): s is IStructSymbol => s.kind === "struct",
189
+ );
107
190
  }
108
191
 
109
192
  /**
110
- * Get all conflicts in the symbol table
111
- * Per user requirement: Strict errors for cross-language conflicts
193
+ * Get all enum symbols (type-safe filtering)
112
194
  */
113
- getConflicts(): IConflict[] {
114
- const conflicts: IConflict[] = [];
195
+ getEnumSymbols(): IEnumSymbol[] {
196
+ return this.getAllTSymbols().filter(
197
+ (s): s is IEnumSymbol => s.kind === "enum",
198
+ );
199
+ }
115
200
 
116
- for (const [, symbols] of this.symbols) {
117
- if (symbols.length <= 1) continue;
201
+ /**
202
+ * Get all function symbols (type-safe filtering)
203
+ */
204
+ getFunctionSymbols(): IFunctionSymbol[] {
205
+ return this.getAllTSymbols().filter(
206
+ (s): s is IFunctionSymbol => s.kind === "function",
207
+ );
208
+ }
118
209
 
119
- const conflict = this.detectConflict(symbols);
120
- if (conflict) {
121
- conflicts.push(conflict);
122
- }
123
- }
210
+ /**
211
+ * Get all variable symbols (type-safe filtering)
212
+ */
213
+ getVariableSymbols(): IVariableSymbol[] {
214
+ return this.getAllTSymbols().filter(
215
+ (s): s is IVariableSymbol => s.kind === "variable",
216
+ );
217
+ }
124
218
 
125
- return conflicts;
219
+ /**
220
+ * Get struct field type directly from TSymbol storage.
221
+ * This method queries IStructSymbol.fields directly, eliminating the need
222
+ * for the separate structFields Map for C-Next symbols.
223
+ *
224
+ * @param structName Name of the struct
225
+ * @param fieldName Name of the field
226
+ * @returns Field type string or undefined if not found
227
+ */
228
+ getTStructFieldType(
229
+ structName: string,
230
+ fieldName: string,
231
+ ): string | undefined {
232
+ const struct = this.getTOverloads(structName).find(
233
+ (s): s is IStructSymbol => s.kind === "struct",
234
+ );
235
+ if (!struct) {
236
+ return undefined;
237
+ }
238
+ const field = struct.fields.get(fieldName);
239
+ return field ? TypeResolver.getTypeName(field.type) : undefined;
126
240
  }
127
241
 
128
242
  /**
129
- * Get symbols by source file
243
+ * Check if a TSymbol exists by name
130
244
  */
131
- getSymbolsByFile(file: string): ISymbol[] {
132
- return this.byFile.get(file) ?? [];
245
+ hasTSymbol(name: string): boolean {
246
+ return this.tSymbols.has(name);
133
247
  }
134
248
 
135
249
  /**
136
- * Get symbols by source language
250
+ * Get TSymbol count
137
251
  */
138
- getSymbolsByLanguage(lang: ESourceLanguage): ISymbol[] {
139
- const result: ISymbol[] = [];
140
- for (const symbols of this.symbols.values()) {
141
- for (const symbol of symbols) {
142
- if (symbol.sourceLanguage === lang) {
143
- result.push(symbol);
144
- }
145
- }
252
+ getTSize(): number {
253
+ let count = 0;
254
+ for (const symbols of this.tSymbols.values()) {
255
+ count += symbols.length;
146
256
  }
147
- return result;
257
+ return count;
148
258
  }
149
259
 
260
+ // ========================================================================
261
+ // C Symbol Methods (TCSymbol)
262
+ // ========================================================================
263
+
150
264
  /**
151
- * Get all symbols
265
+ * Add a C symbol to the table
152
266
  */
153
- getAllSymbols(): ISymbol[] {
154
- const result: ISymbol[] = [];
155
- for (const symbols of this.symbols.values()) {
156
- result.push(...symbols);
267
+ addCSymbol(symbol: TCSymbol): void {
268
+ // Add to name index
269
+ const existing = this.cSymbols.get(symbol.name);
270
+ if (existing) {
271
+ existing.push(symbol);
272
+ } else {
273
+ this.cSymbols.set(symbol.name, [symbol]);
274
+ }
275
+
276
+ // Add to file index
277
+ const fileSymbols = this.cSymbolsByFile.get(symbol.sourceFile);
278
+ if (fileSymbols) {
279
+ fileSymbols.push(symbol);
280
+ } else {
281
+ this.cSymbolsByFile.set(symbol.sourceFile, [symbol]);
157
282
  }
158
- return result;
159
283
  }
160
284
 
161
285
  /**
162
- * Add struct field information
163
- * @param structName Name of the struct
164
- * @param fieldName Name of the field
165
- * @param fieldType Type of the field (e.g., "uint32_t")
166
- * @param arrayDimensions Optional array dimensions if field is an array
286
+ * Add multiple C symbols at once
167
287
  */
168
- addStructField(
169
- structName: string,
170
- fieldName: string,
171
- fieldType: string,
172
- arrayDimensions?: number[],
173
- ): void {
174
- let fields = this.structFields.get(structName);
175
- if (!fields) {
176
- fields = new Map();
177
- this.structFields.set(structName, fields);
288
+ addCSymbols(symbols: TCSymbol[]): void {
289
+ for (const symbol of symbols) {
290
+ this.addCSymbol(symbol);
178
291
  }
179
-
180
- fields.set(fieldName, {
181
- type: fieldType,
182
- arrayDimensions,
183
- });
184
292
  }
185
293
 
186
294
  /**
187
- * Get struct field type
188
- * @param structName Name of the struct
189
- * @param fieldName Name of the field
190
- * @returns Field type or undefined if not found
295
+ * Get a C symbol by name (returns first match, or undefined)
191
296
  */
192
- getStructFieldType(
193
- structName: string,
194
- fieldName: string,
195
- ): string | undefined {
196
- const fields = this.structFields.get(structName);
197
- return fields?.get(fieldName)?.type;
297
+ getCSymbol(name: string): TCSymbol | undefined {
298
+ const symbols = this.cSymbols.get(name);
299
+ return symbols?.[0];
198
300
  }
199
301
 
200
302
  /**
201
- * Get struct field info (type and array dimensions)
202
- * @param structName Name of the struct
203
- * @param fieldName Name of the field
204
- * @returns Field info or undefined if not found
303
+ * Get all C symbols with a given name
205
304
  */
206
- getStructFieldInfo(
207
- structName: string,
208
- fieldName: string,
209
- ): IStructFieldInfo | undefined {
210
- const fields = this.structFields.get(structName);
211
- return fields?.get(fieldName);
305
+ getCOverloads(name: string): TCSymbol[] {
306
+ return this.cSymbols.get(name) ?? [];
212
307
  }
213
308
 
214
309
  /**
215
- * Issue #196 Bug 3: Mark a struct as requiring 'struct' keyword in C
216
- * @param structName Name of the struct (e.g., "NamedPoint")
310
+ * Get C symbols by source file
217
311
  */
218
- markNeedsStructKeyword(structName: string): void {
219
- this.needsStructKeyword.add(structName);
312
+ getCSymbolsByFile(file: string): TCSymbol[] {
313
+ return this.cSymbolsByFile.get(file) ?? [];
220
314
  }
221
315
 
222
316
  /**
223
- * Issue #196 Bug 3: Check if a struct requires 'struct' keyword in C
224
- * @param structName Name of the struct
225
- * @returns true if the struct was defined as 'struct Name { ... }' without typedef
317
+ * Get all C symbols
226
318
  */
227
- checkNeedsStructKeyword(structName: string): boolean {
228
- return this.needsStructKeyword.has(structName);
319
+ getAllCSymbols(): TCSymbol[] {
320
+ const result: TCSymbol[] = [];
321
+ for (const symbols of this.cSymbols.values()) {
322
+ result.push(...symbols);
323
+ }
324
+ return result;
229
325
  }
230
326
 
327
+ // ========================================================================
328
+ // C++ Symbol Methods (TCppSymbol)
329
+ // ========================================================================
330
+
231
331
  /**
232
- * Issue #196 Bug 3: Get all struct names requiring 'struct' keyword
233
- * @returns Array of struct names
332
+ * Add a C++ symbol to the table
234
333
  */
235
- getAllNeedsStructKeyword(): string[] {
236
- return Array.from(this.needsStructKeyword);
334
+ addCppSymbol(symbol: TCppSymbol): void {
335
+ // Add to name index
336
+ const existing = this.cppSymbols.get(symbol.name);
337
+ if (existing) {
338
+ existing.push(symbol);
339
+ } else {
340
+ this.cppSymbols.set(symbol.name, [symbol]);
341
+ }
342
+
343
+ // Add to file index
344
+ const fileSymbols = this.cppSymbolsByFile.get(symbol.sourceFile);
345
+ if (fileSymbols) {
346
+ fileSymbols.push(symbol);
347
+ } else {
348
+ this.cppSymbolsByFile.set(symbol.sourceFile, [symbol]);
349
+ }
237
350
  }
238
351
 
239
352
  /**
240
- * Issue #196 Bug 3: Restore needsStructKeyword from cache
241
- * @param structNames Array of struct names requiring 'struct' keyword
353
+ * Add multiple C++ symbols at once
242
354
  */
243
- restoreNeedsStructKeyword(structNames: string[]): void {
244
- for (const name of structNames) {
245
- this.needsStructKeyword.add(name);
355
+ addCppSymbols(symbols: TCppSymbol[]): void {
356
+ for (const symbol of symbols) {
357
+ this.addCppSymbol(symbol);
246
358
  }
247
359
  }
248
360
 
249
361
  /**
250
- * Issue #208: Add enum bit width for a typed enum
251
- * @param enumName Name of the enum (e.g., "EPressureType")
252
- * @param bitWidth Bit width from backing type (e.g., 8 for uint8_t)
362
+ * Get a C++ symbol by name (returns first match, or undefined)
253
363
  */
254
- addEnumBitWidth(enumName: string, bitWidth: number): void {
255
- this.enumBitWidth.set(enumName, bitWidth);
364
+ getCppSymbol(name: string): TCppSymbol | undefined {
365
+ const symbols = this.cppSymbols.get(name);
366
+ return symbols?.[0];
256
367
  }
257
368
 
258
369
  /**
259
- * Issue #208: Get enum bit width for a typed enum
260
- * @param enumName Name of the enum
261
- * @returns Bit width or undefined if not a typed enum
370
+ * Get all C++ symbols with a given name
262
371
  */
263
- getEnumBitWidth(enumName: string): number | undefined {
264
- return this.enumBitWidth.get(enumName);
372
+ getCppOverloads(name: string): TCppSymbol[] {
373
+ return this.cppSymbols.get(name) ?? [];
265
374
  }
266
375
 
267
376
  /**
268
- * Issue #208: Get all enum bit widths for cache serialization
269
- * @returns Map of enum name -> bit width
377
+ * Get C++ symbols by source file
270
378
  */
271
- getAllEnumBitWidths(): Map<string, number> {
272
- return this.enumBitWidth;
379
+ getCppSymbolsByFile(file: string): TCppSymbol[] {
380
+ return this.cppSymbolsByFile.get(file) ?? [];
273
381
  }
274
382
 
275
383
  /**
276
- * Issue #208: Restore enum bit widths from cache
277
- * @param bitWidths Map of enum name -> bit width
384
+ * Get all C++ symbols
278
385
  */
279
- restoreEnumBitWidths(bitWidths: Map<string, number>): void {
280
- for (const [enumName, width] of bitWidths) {
281
- this.enumBitWidth.set(enumName, width);
386
+ getAllCppSymbols(): TCppSymbol[] {
387
+ const result: TCppSymbol[] = [];
388
+ for (const symbols of this.cppSymbols.values()) {
389
+ result.push(...symbols);
282
390
  }
391
+ return result;
283
392
  }
284
393
 
394
+ // ========================================================================
395
+ // Cross-Language Methods
396
+ // ========================================================================
397
+
285
398
  /**
286
- * Get all fields for a struct
287
- * @param structName Name of the struct
288
- * @returns Map of field names to field info, or undefined if struct not found
399
+ * Get all symbols across all languages
289
400
  */
290
- getStructFields(
291
- structName: string,
292
- ): Map<string, IStructFieldInfo> | undefined {
293
- return this.structFields.get(structName);
401
+ getAllSymbols(): TAnySymbol[] {
402
+ return [
403
+ ...this.getAllTSymbols(),
404
+ ...this.getAllCSymbols(),
405
+ ...this.getAllCppSymbols(),
406
+ ];
294
407
  }
295
408
 
296
409
  /**
297
- * Get all struct fields for cache serialization
298
- * @returns Map of struct name -> (field name -> field info)
410
+ * Get first symbol matching a name across all languages.
411
+ * Searches TSymbol, then C, then C++ collections.
412
+ * Used by ISymbolLookup interface for constructor detection.
299
413
  */
300
- getAllStructFields(): Map<string, Map<string, IStructFieldInfo>> {
301
- return this.structFields;
414
+ getSymbol(name: string): TAnySymbol | undefined {
415
+ return (
416
+ this.getTSymbol(name) ?? this.getCSymbol(name) ?? this.getCppSymbol(name)
417
+ );
302
418
  }
303
419
 
304
420
  /**
305
- * Restore struct fields from cache
306
- * Merges cached fields into the existing structFields map
307
- * @param fields Map of struct name -> (field name -> field info)
421
+ * Get all overloads for a name across all languages
308
422
  */
309
- restoreStructFields(
310
- fields: Map<string, Map<string, IStructFieldInfo>>,
311
- ): void {
312
- for (const [structName, fieldMap] of fields) {
313
- // Get or create the struct's field map
314
- let existingFields = this.structFields.get(structName);
315
- if (!existingFields) {
316
- existingFields = new Map();
317
- this.structFields.set(structName, existingFields);
318
- }
423
+ getOverloads(name: string): TAnySymbol[] {
424
+ return [
425
+ ...this.getTOverloads(name),
426
+ ...this.getCOverloads(name),
427
+ ...this.getCppOverloads(name),
428
+ ];
429
+ }
319
430
 
320
- // Merge fields
321
- for (const [fieldName, fieldInfo] of fieldMap) {
322
- existingFields.set(fieldName, fieldInfo);
323
- }
324
- }
431
+ /**
432
+ * Get symbols by source file across all languages
433
+ */
434
+ getSymbolsByFile(file: string): TAnySymbol[] {
435
+ return [
436
+ ...this.getTSymbolsByFile(file),
437
+ ...this.getCSymbolsByFile(file),
438
+ ...this.getCppSymbolsByFile(file),
439
+ ];
325
440
  }
326
441
 
327
442
  /**
328
- * Get struct names defined in a specific source file
329
- * @param file Source file path
330
- * @returns Array of struct names defined in that file
443
+ * Get symbols by source language
331
444
  */
332
- getStructNamesByFile(file: string): string[] {
333
- const fileSymbols = this.byFile.get(file) ?? [];
334
- // Issue #196: Include any symbol that has struct fields registered
335
- // The dual-parse strategy may register typedef'd anonymous structs as variables
336
- // (e.g., "typedef struct { ... } Rectangle;" -> Rectangle has kind=variable)
337
- // But the C parser still adds struct fields for it
338
- const symbolNames = fileSymbols.map((s) => s.name);
339
- return symbolNames.filter((name) => this.structFields.has(name));
445
+ getSymbolsByLanguage(lang: ESourceLanguage): TAnySymbol[] {
446
+ switch (lang) {
447
+ case ESourceLanguage.CNext:
448
+ return this.getAllTSymbols();
449
+ case ESourceLanguage.C:
450
+ return this.getAllCSymbols();
451
+ case ESourceLanguage.Cpp:
452
+ return this.getAllCppSymbols();
453
+ }
340
454
  }
341
455
 
342
456
  /**
343
- * Clear all symbols
457
+ * Check if a symbol exists in any language
344
458
  */
345
- clear(): void {
346
- this.symbols.clear();
347
- this.byFile.clear();
348
- this.structFields.clear();
349
- this.needsStructKeyword.clear();
350
- this.enumBitWidth.clear();
459
+ hasSymbol(name: string): boolean {
460
+ return (
461
+ this.tSymbols.has(name) ||
462
+ this.cSymbols.has(name) ||
463
+ this.cppSymbols.has(name)
464
+ );
351
465
  }
352
466
 
353
467
  /**
354
- * Get symbol count
468
+ * Get total symbol count
355
469
  */
356
470
  get size(): number {
471
+ return this.getTSize() + this.getCSize() + this.getCppSize();
472
+ }
473
+
474
+ /**
475
+ * Get C symbol count
476
+ */
477
+ getCSize(): number {
357
478
  let count = 0;
358
- for (const symbols of this.symbols.values()) {
479
+ for (const symbols of this.cSymbols.values()) {
359
480
  count += symbols.length;
360
481
  }
361
482
  return count;
362
483
  }
363
484
 
485
+ /**
486
+ * Get C++ symbol count
487
+ */
488
+ getCppSize(): number {
489
+ let count = 0;
490
+ for (const symbols of this.cppSymbols.values()) {
491
+ count += symbols.length;
492
+ }
493
+ return count;
494
+ }
495
+
496
+ // ========================================================================
497
+ // Conflict Detection
498
+ // ========================================================================
499
+
500
+ /**
501
+ * Check if a symbol has conflicts
502
+ */
503
+ hasConflict(name: string): boolean {
504
+ const allSymbols = this.getOverloads(name);
505
+ if (allSymbols.length <= 1) {
506
+ return false;
507
+ }
508
+
509
+ return this.detectConflict(allSymbols) !== null;
510
+ }
511
+
512
+ /**
513
+ * Get all conflicts in the symbol table
514
+ * Per user requirement: Strict errors for cross-language conflicts
515
+ */
516
+ getConflicts(): IConflict[] {
517
+ const conflicts: IConflict[] = [];
518
+ const allNames = new Set<string>();
519
+
520
+ // Collect all symbol names from all languages
521
+ for (const name of this.tSymbols.keys()) allNames.add(name);
522
+ for (const name of this.cSymbols.keys()) allNames.add(name);
523
+ for (const name of this.cppSymbols.keys()) allNames.add(name);
524
+
525
+ for (const name of allNames) {
526
+ const symbols = this.getOverloads(name);
527
+ if (symbols.length <= 1) continue;
528
+
529
+ const conflict = this.detectConflict(symbols);
530
+ if (conflict) {
531
+ conflicts.push(conflict);
532
+ }
533
+ }
534
+
535
+ return conflicts;
536
+ }
537
+
364
538
  /**
365
539
  * Detect if a set of symbols with the same name represents a conflict
366
540
  */
367
- private detectConflict(symbols: ISymbol[]): IConflict | null {
541
+ private detectConflict(symbols: TAnySymbol[]): IConflict | null {
368
542
  // Filter out pure declarations (extern in C) - they don't count as definitions
369
- const definitions = symbols.filter((s) => !s.isDeclaration);
543
+ const definitions = symbols.filter(
544
+ (s) => !("isDeclaration" in s && s.isDeclaration),
545
+ );
370
546
 
371
547
  if (definitions.length <= 1) {
372
548
  // 0 or 1 definitions = no conflict
@@ -374,47 +550,58 @@ class SymbolTable {
374
550
  }
375
551
 
376
552
  // Issue #221: Filter out function parameters from conflict detection
377
- // Function parameters have a parent (their containing function) but their name
378
- // is NOT qualified with the parent prefix (unlike scope-level variables like Math_counter).
379
- // Parameters with the same name in different functions are not conflicts.
553
+ // Function parameters have a parent but their name is NOT qualified with the parent prefix.
380
554
  const globalDefinitions = definitions.filter((def) => {
381
- // If no parent, it's a global symbol - keep it
382
- if (!def.parent) return true;
383
-
384
- // Variables with a parent need special handling
385
- if (def.kind === ESymbolKind.Variable) {
386
- // Scope-level variables have qualified names (e.g., "Math_counter" with parent "Math")
387
- // Function parameters have unqualified names (e.g., "x" with parent "Math_add")
388
- // If the name starts with parent_, it's a scope-level variable - keep it
389
- // If not, it's a function parameter - filter it out
390
- const isQualifiedName = def.name.startsWith(def.parent + "_");
391
- return isQualifiedName;
555
+ // C-Next variables with scope need special handling
556
+ if (
557
+ def.sourceLanguage === ESourceLanguage.CNext &&
558
+ def.kind === "variable"
559
+ ) {
560
+ // After sourceLanguage check, def is narrowed to TSymbol
561
+ // After kind check, def is narrowed to IVariableSymbol
562
+ // Global scope means no conflict filtering needed
563
+ if (def.scope.name === "") return true;
564
+ // Scope-level variables vs function parameters:
565
+ // We can't easily distinguish here, so keep all for now
566
+ return true;
567
+ }
568
+ // C/C++ symbols: check parent field
569
+ if ("parent" in def && def.parent) {
570
+ // Non-variable symbols with parents are kept
571
+ if (def.kind !== "variable") return true;
572
+ // Variables with parents might be function parameters - filter out
573
+ return false;
392
574
  }
393
-
394
- // Non-variable symbols with parents (functions, enums, etc.) are kept
395
575
  return true;
396
576
  });
397
577
 
398
578
  if (globalDefinitions.length <= 1) {
399
- // After filtering parameters, 0 or 1 definitions = no conflict
400
579
  return null;
401
580
  }
402
581
 
403
582
  // Check for C++ function overloads (different signatures are OK)
404
- const cppFunctions = definitions.filter(
405
- (s) => s.sourceLanguage === ESourceLanguage.Cpp && s.signature,
583
+ const cppFunctions = globalDefinitions.filter(
584
+ (s) =>
585
+ s.sourceLanguage === ESourceLanguage.Cpp &&
586
+ s.kind === "function" &&
587
+ "parameters" in s,
406
588
  );
407
- if (cppFunctions.length === definitions.length) {
408
- // All are C++ functions with signatures
409
- const uniqueSignatures = new Set(cppFunctions.map((s) => s.signature));
589
+ if (cppFunctions.length === globalDefinitions.length) {
590
+ // All are C++ functions with signatures - check for unique signatures
591
+ const signatures = cppFunctions.map((f) => {
592
+ if ("parameters" in f && f.parameters) {
593
+ const params = f.parameters as ReadonlyArray<{ type?: string }>;
594
+ return params.map((p) => p.type ?? "").join(",");
595
+ }
596
+ return "";
597
+ });
598
+ const uniqueSignatures = new Set(signatures);
410
599
  if (uniqueSignatures.size === cppFunctions.length) {
411
- // All signatures are unique = valid overload, no conflict
412
600
  return null;
413
601
  }
414
602
  }
415
603
 
416
604
  // Check for cross-language conflict (C-Next vs C or C++)
417
- // Issue #221: Use globalDefinitions for C-Next to exclude function parameters
418
605
  const cnextDefs = globalDefinitions.filter(
419
606
  (s) => s.sourceLanguage === ESourceLanguage.CNext,
420
607
  );
@@ -426,7 +613,6 @@ class SymbolTable {
426
613
  );
427
614
 
428
615
  if (cnextDefs.length > 0 && (cDefs.length > 0 || cppDefs.length > 0)) {
429
- // C-Next + C/C++ conflict = ERROR
430
616
  const locations = globalDefinitions.map(
431
617
  (s) =>
432
618
  `${s.sourceLanguage.toUpperCase()} (${s.sourceFile}:${s.sourceLine})`,
@@ -452,15 +638,204 @@ class SymbolTable {
452
638
  }
453
639
 
454
640
  // Same symbol in C and C++ - typically OK (same symbol)
455
- // But if they have different types, might be a warning
456
641
  if (cDefs.length > 0 && cppDefs.length > 0) {
457
- // For now, allow C/C++ to share symbols (common pattern)
458
642
  return null;
459
643
  }
460
644
 
461
645
  return null;
462
646
  }
463
647
 
648
+ // ========================================================================
649
+ // Struct Field Information
650
+ // ========================================================================
651
+
652
+ /**
653
+ * Add struct field information
654
+ * @param structName Name of the struct
655
+ * @param fieldName Name of the field
656
+ * @param fieldType Type of the field (e.g., "uint32_t")
657
+ * @param arrayDimensions Optional array dimensions if field is an array
658
+ */
659
+ addStructField(
660
+ structName: string,
661
+ fieldName: string,
662
+ fieldType: string,
663
+ arrayDimensions?: number[],
664
+ ): void {
665
+ let fields = this.structFields.get(structName);
666
+ if (!fields) {
667
+ fields = new Map();
668
+ this.structFields.set(structName, fields);
669
+ }
670
+
671
+ fields.set(fieldName, {
672
+ type: fieldType,
673
+ arrayDimensions,
674
+ });
675
+ }
676
+
677
+ /**
678
+ * Get struct field type
679
+ * @param structName Name of the struct
680
+ * @param fieldName Name of the field
681
+ * @returns Field type or undefined if not found
682
+ */
683
+ getStructFieldType(
684
+ structName: string,
685
+ fieldName: string,
686
+ ): string | undefined {
687
+ const fields = this.structFields.get(structName);
688
+ return fields?.get(fieldName)?.type;
689
+ }
690
+
691
+ /**
692
+ * Get struct field info (type and array dimensions)
693
+ * @param structName Name of the struct
694
+ * @param fieldName Name of the field
695
+ * @returns Field info or undefined if not found
696
+ */
697
+ getStructFieldInfo(
698
+ structName: string,
699
+ fieldName: string,
700
+ ): IStructFieldInfo | undefined {
701
+ const fields = this.structFields.get(structName);
702
+ return fields?.get(fieldName);
703
+ }
704
+
705
+ /**
706
+ * Get all fields for a struct
707
+ * @param structName Name of the struct
708
+ * @returns Map of field names to field info, or undefined if struct not found
709
+ */
710
+ getStructFields(
711
+ structName: string,
712
+ ): Map<string, IStructFieldInfo> | undefined {
713
+ return this.structFields.get(structName);
714
+ }
715
+
716
+ /**
717
+ * Get all struct fields for cache serialization
718
+ * @returns Map of struct name -> (field name -> field info)
719
+ */
720
+ getAllStructFields(): Map<string, Map<string, IStructFieldInfo>> {
721
+ return this.structFields;
722
+ }
723
+
724
+ /**
725
+ * Restore struct fields from cache
726
+ * Merges cached fields into the existing structFields map
727
+ * @param fields Map of struct name -> (field name -> field info)
728
+ */
729
+ restoreStructFields(
730
+ fields: Map<string, Map<string, IStructFieldInfo>>,
731
+ ): void {
732
+ for (const [structName, fieldMap] of fields) {
733
+ let existingFields = this.structFields.get(structName);
734
+ if (!existingFields) {
735
+ existingFields = new Map();
736
+ this.structFields.set(structName, existingFields);
737
+ }
738
+
739
+ for (const [fieldName, fieldInfo] of fieldMap) {
740
+ existingFields.set(fieldName, fieldInfo);
741
+ }
742
+ }
743
+ }
744
+
745
+ /**
746
+ * Get struct names defined in a specific source file
747
+ * @param file Source file path
748
+ * @returns Array of struct names defined in that file
749
+ */
750
+ getStructNamesByFile(file: string): string[] {
751
+ const fileSymbols = this.getSymbolsByFile(file);
752
+ const symbolNames = fileSymbols.map((s) => s.name);
753
+ return symbolNames.filter((name) => this.structFields.has(name));
754
+ }
755
+
756
+ // ========================================================================
757
+ // Struct Keyword Tracking
758
+ // ========================================================================
759
+
760
+ /**
761
+ * Issue #196 Bug 3: Mark a struct as requiring 'struct' keyword in C
762
+ * @param structName Name of the struct (e.g., "NamedPoint")
763
+ */
764
+ markNeedsStructKeyword(structName: string): void {
765
+ this.needsStructKeyword.add(structName);
766
+ }
767
+
768
+ /**
769
+ * Issue #196 Bug 3: Check if a struct requires 'struct' keyword in C
770
+ * @param structName Name of the struct
771
+ * @returns true if the struct was defined as 'struct Name { ... }' without typedef
772
+ */
773
+ checkNeedsStructKeyword(structName: string): boolean {
774
+ return this.needsStructKeyword.has(structName);
775
+ }
776
+
777
+ /**
778
+ * Issue #196 Bug 3: Get all struct names requiring 'struct' keyword
779
+ * @returns Array of struct names
780
+ */
781
+ getAllNeedsStructKeyword(): string[] {
782
+ return Array.from(this.needsStructKeyword);
783
+ }
784
+
785
+ /**
786
+ * Issue #196 Bug 3: Restore needsStructKeyword from cache
787
+ * @param structNames Array of struct names requiring 'struct' keyword
788
+ */
789
+ restoreNeedsStructKeyword(structNames: string[]): void {
790
+ for (const name of structNames) {
791
+ this.needsStructKeyword.add(name);
792
+ }
793
+ }
794
+
795
+ // ========================================================================
796
+ // Enum Bit Width Tracking
797
+ // ========================================================================
798
+
799
+ /**
800
+ * Issue #208: Add enum bit width for a typed enum
801
+ * @param enumName Name of the enum (e.g., "EPressureType")
802
+ * @param bitWidth Bit width from backing type (e.g., 8 for uint8_t)
803
+ */
804
+ addEnumBitWidth(enumName: string, bitWidth: number): void {
805
+ this.enumBitWidth.set(enumName, bitWidth);
806
+ }
807
+
808
+ /**
809
+ * Issue #208: Get enum bit width for a typed enum
810
+ * @param enumName Name of the enum
811
+ * @returns Bit width or undefined if not a typed enum
812
+ */
813
+ getEnumBitWidth(enumName: string): number | undefined {
814
+ return this.enumBitWidth.get(enumName);
815
+ }
816
+
817
+ /**
818
+ * Issue #208: Get all enum bit widths for cache serialization
819
+ * @returns Map of enum name -> bit width
820
+ */
821
+ getAllEnumBitWidths(): Map<string, number> {
822
+ return this.enumBitWidth;
823
+ }
824
+
825
+ /**
826
+ * Issue #208: Restore enum bit widths from cache
827
+ * @param bitWidths Map of enum name -> bit width
828
+ */
829
+ restoreEnumBitWidths(bitWidths: Map<string, number>): void {
830
+ for (const [enumName, width] of bitWidths) {
831
+ this.enumBitWidth.set(enumName, width);
832
+ }
833
+ }
834
+
835
+ // ========================================================================
836
+ // External Array Dimension Resolution
837
+ // ========================================================================
838
+
464
839
  /**
465
840
  * Issue #461: Resolve external const array dimensions
466
841
  *
@@ -472,59 +847,102 @@ class SymbolTable {
472
847
  * external .cnx files that were not available during initial symbol collection.
473
848
  */
474
849
  resolveExternalArrayDimensions(): void {
475
- // Build a map of all const values from the symbol table
850
+ const constValues = this.buildConstValuesMap();
851
+ if (constValues.size === 0) {
852
+ return;
853
+ }
854
+ this.resolveArrayDimensionsWithConstants(constValues);
855
+ }
856
+
857
+ /**
858
+ * Build a map of const variable names to their integer values.
859
+ */
860
+ private buildConstValuesMap(): Map<string, number> {
476
861
  const constValues = new Map<string, number>();
477
- for (const symbol of this.getAllSymbols()) {
478
- if (
479
- symbol.kind === ESymbolKind.Variable &&
480
- symbol.isConst &&
481
- symbol.initialValue !== undefined
482
- ) {
483
- const value = LiteralUtils.parseIntegerLiteral(symbol.initialValue);
484
- if (value !== undefined) {
485
- constValues.set(symbol.name, value);
862
+ for (const symbol of this.getAllTSymbols()) {
863
+ if (symbol.kind === "variable" && symbol.isConst) {
864
+ // After kind check, symbol is narrowed to IVariableSymbol
865
+ if (symbol.initialValue !== undefined) {
866
+ const value = LiteralUtils.parseIntegerLiteral(symbol.initialValue);
867
+ if (value !== undefined) {
868
+ constValues.set(symbol.name, value);
869
+ }
486
870
  }
487
871
  }
488
872
  }
873
+ return constValues;
874
+ }
489
875
 
490
- // If no const values found, nothing to resolve
491
- if (constValues.size === 0) {
492
- return;
493
- }
494
-
495
- // Scan all variable symbols for unresolved array dimensions
496
- for (const symbol of this.getAllSymbols()) {
876
+ /**
877
+ * Resolve string array dimensions using const values lookup.
878
+ */
879
+ private resolveArrayDimensionsWithConstants(
880
+ constValues: Map<string, number>,
881
+ ): void {
882
+ for (const symbol of this.getAllTSymbols()) {
497
883
  if (
498
- symbol.kind === ESymbolKind.Variable &&
884
+ symbol.kind === "variable" &&
499
885
  symbol.isArray &&
500
886
  symbol.arrayDimensions
501
887
  ) {
502
- let modified = false;
503
- const resolvedDimensions = symbol.arrayDimensions.map((dim) => {
504
- // If dimension is numeric, keep it
505
- const numericValue = Number.parseInt(dim, 10);
506
- if (!Number.isNaN(numericValue)) {
507
- return dim;
508
- }
509
-
510
- // Try to resolve from const values
511
- const constValue = constValues.get(dim);
512
- if (constValue !== undefined) {
513
- modified = true;
514
- return String(constValue);
515
- }
516
-
517
- // Keep original (unresolved macro reference)
518
- return dim;
519
- });
888
+ // After kind check, symbol is narrowed to IVariableSymbol
889
+ this.resolveVariableArrayDimensions(symbol, constValues);
890
+ }
891
+ }
892
+ }
520
893
 
521
- if (modified) {
522
- // Update the symbol's array dimensions
523
- symbol.arrayDimensions = resolvedDimensions;
524
- }
894
+ /**
895
+ * Resolve array dimensions for a single variable symbol.
896
+ */
897
+ private resolveVariableArrayDimensions(
898
+ variable: IVariableSymbol,
899
+ constValues: Map<string, number>,
900
+ ): void {
901
+ let modified = false;
902
+ const resolvedDimensions = variable.arrayDimensions!.map((dim) => {
903
+ if (typeof dim === "number") {
904
+ return dim;
525
905
  }
906
+ const constValue = constValues.get(dim);
907
+ if (constValue !== undefined) {
908
+ modified = true;
909
+ return constValue;
910
+ }
911
+ return dim;
912
+ });
913
+
914
+ if (modified) {
915
+ // Mutate in place - symbol is already in storage, cloning would require
916
+ // updating all maps. The readonly typing prevents accidental mutations
917
+ // elsewhere; this controlled mutation is intentional during resolution.
918
+ (
919
+ variable as unknown as { arrayDimensions: (number | string)[] }
920
+ ).arrayDimensions = resolvedDimensions;
526
921
  }
527
922
  }
923
+
924
+ // ========================================================================
925
+ // Clear / Reset
926
+ // ========================================================================
927
+
928
+ /**
929
+ * Clear all symbols
930
+ */
931
+ clear(): void {
932
+ // C-Next
933
+ this.tSymbols.clear();
934
+ this.tSymbolsByFile.clear();
935
+ // C
936
+ this.cSymbols.clear();
937
+ this.cSymbolsByFile.clear();
938
+ // C++
939
+ this.cppSymbols.clear();
940
+ this.cppSymbolsByFile.clear();
941
+ // Auxiliary
942
+ this.structFields.clear();
943
+ this.needsStructKeyword.clear();
944
+ this.enumBitWidth.clear();
945
+ }
528
946
  }
529
947
 
530
948
  export default SymbolTable;