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
@@ -0,0 +1,742 @@
1
+ /**
2
+ * Pass-By-Value Analyzer
3
+ *
4
+ * Extracted from CodeGenerator.ts (Issue #269, #558, #566, #579)
5
+ *
6
+ * Performs three-phase analysis to determine which function parameters
7
+ * can be passed by value (as opposed to pointer):
8
+ *
9
+ * Phase 1: Collect function parameter lists and direct modifications
10
+ * Phase 2: Transitive modification propagation (via TransitiveModificationPropagator)
11
+ * Phase 3: Determine which parameters can pass by value
12
+ *
13
+ * A parameter can pass by value if:
14
+ * 1. It's a small primitive type (u8, i8, u16, i16, u32, i32, u64, i64, bool)
15
+ * 2. It's not modified (directly or transitively)
16
+ * 3. It's not an array, struct, string, or callback
17
+ * 4. It's not accessed via subscript (Issue #579)
18
+ */
19
+
20
+ import * as Parser from "../parser/grammar/CNextParser";
21
+ import CodeGenState from "../../state/CodeGenState";
22
+ import SymbolRegistry from "../../state/SymbolRegistry";
23
+ import FunctionUtils from "../../../utils/FunctionUtils";
24
+ import TransitiveModificationPropagator from "./helpers/TransitiveModificationPropagator";
25
+ import StatementExpressionCollector from "./helpers/StatementExpressionCollector";
26
+ import ChildStatementCollector from "./helpers/ChildStatementCollector";
27
+ import AssignmentTargetExtractor from "./helpers/AssignmentTargetExtractor";
28
+ import ExpressionUtils from "../../../utils/ExpressionUtils";
29
+
30
+ /**
31
+ * Small primitive types that are eligible for pass-by-value optimization.
32
+ */
33
+ const SMALL_PRIMITIVES = new Set([
34
+ "u8",
35
+ "i8",
36
+ "u16",
37
+ "i16",
38
+ "u32",
39
+ "i32",
40
+ "u64",
41
+ "i64",
42
+ "bool",
43
+ ]);
44
+
45
+ /**
46
+ * Static analyzer for determining pass-by-value eligibility.
47
+ * All state is stored in CodeGenState - this class contains pure analysis logic.
48
+ */
49
+ class PassByValueAnalyzer {
50
+ /**
51
+ * Main entry point: Analyze a program tree to determine pass-by-value parameters.
52
+ * Updates CodeGenState with analysis results.
53
+ */
54
+ static analyze(tree: Parser.ProgramContext): void {
55
+ // Reset analysis state
56
+ CodeGenState.modifiedParameters.clear();
57
+ CodeGenState.passByValueParams.clear();
58
+ CodeGenState.functionCallGraph.clear();
59
+ CodeGenState.functionParamLists.clear();
60
+
61
+ // Phase 1: Collect function parameter lists and direct modifications
62
+ PassByValueAnalyzer.collectFunctionParametersAndModifications(tree);
63
+
64
+ // Issue #558: Inject cross-file data before transitive propagation
65
+ PassByValueAnalyzer.injectCrossFileModifications();
66
+ PassByValueAnalyzer.injectCrossFileParamLists();
67
+
68
+ // Phase 2: Fixed-point iteration for transitive modifications
69
+ TransitiveModificationPropagator.propagate(
70
+ CodeGenState.functionCallGraph,
71
+ CodeGenState.functionParamLists,
72
+ CodeGenState.modifiedParameters,
73
+ );
74
+
75
+ // Phase 3: Determine which parameters can pass by value
76
+ PassByValueAnalyzer.computePassByValueParams();
77
+ }
78
+
79
+ /**
80
+ * Inject cross-file modification data into modifiedParameters.
81
+ * SonarCloud S3776: Extracted from analyze().
82
+ */
83
+ private static injectCrossFileModifications(): void {
84
+ if (!CodeGenState.pendingCrossFileModifications) return;
85
+
86
+ for (const [
87
+ funcName,
88
+ params,
89
+ ] of CodeGenState.pendingCrossFileModifications) {
90
+ const existing = CodeGenState.modifiedParameters.get(funcName);
91
+ if (existing) {
92
+ for (const param of params) {
93
+ existing.add(param);
94
+ }
95
+ } else {
96
+ CodeGenState.modifiedParameters.set(funcName, new Set(params));
97
+ }
98
+ }
99
+ CodeGenState.pendingCrossFileModifications = null; // Clear after use
100
+ }
101
+
102
+ /**
103
+ * Inject cross-file parameter lists into functionParamLists.
104
+ * SonarCloud S3776: Extracted from analyze().
105
+ */
106
+ private static injectCrossFileParamLists(): void {
107
+ if (!CodeGenState.pendingCrossFileParamLists) return;
108
+
109
+ for (const [funcName, params] of CodeGenState.pendingCrossFileParamLists) {
110
+ if (!CodeGenState.functionParamLists.has(funcName)) {
111
+ CodeGenState.functionParamLists.set(funcName, [...params]);
112
+ }
113
+ }
114
+ CodeGenState.pendingCrossFileParamLists = null; // Clear after use
115
+ }
116
+
117
+ /**
118
+ * Phase 1: Walk all functions to collect:
119
+ * - Parameter lists (for call graph resolution)
120
+ * - Direct modifications (param <- value)
121
+ * - Function calls where params are passed as arguments
122
+ *
123
+ * Exposed as public for use by CodeGenerator.analyzeModificationsOnly()
124
+ * which needs to run just this phase for cross-file analysis.
125
+ */
126
+ static collectFunctionParametersAndModifications(
127
+ tree: Parser.ProgramContext,
128
+ ): void {
129
+ for (const decl of tree.declaration()) {
130
+ // Handle scope-level functions
131
+ if (decl.scopeDeclaration()) {
132
+ const scopeDecl = decl.scopeDeclaration()!;
133
+ const scopeName = scopeDecl.IDENTIFIER().getText();
134
+
135
+ for (const member of scopeDecl.scopeMember()) {
136
+ if (member.functionDeclaration()) {
137
+ const funcDecl = member.functionDeclaration()!;
138
+ const funcName = funcDecl.IDENTIFIER().getText();
139
+ const fullName = `${scopeName}_${funcName}`;
140
+ PassByValueAnalyzer.analyzeFunctionForModifications(
141
+ fullName,
142
+ funcDecl,
143
+ );
144
+ }
145
+ }
146
+ }
147
+
148
+ // Handle top-level functions
149
+ if (decl.functionDeclaration()) {
150
+ const funcDecl = decl.functionDeclaration()!;
151
+ const name = funcDecl.IDENTIFIER().getText();
152
+ PassByValueAnalyzer.analyzeFunctionForModifications(name, funcDecl);
153
+ }
154
+ }
155
+ }
156
+
157
+ /**
158
+ * Analyze a single function for parameter modifications and call graph edges.
159
+ */
160
+ private static analyzeFunctionForModifications(
161
+ funcName: string,
162
+ funcDecl: Parser.FunctionDeclarationContext,
163
+ ): void {
164
+ // Collect parameter names
165
+ const paramNames: string[] = [];
166
+ const paramList = funcDecl.parameterList();
167
+ if (paramList) {
168
+ for (const param of paramList.parameter()) {
169
+ paramNames.push(param.IDENTIFIER().getText());
170
+ }
171
+ }
172
+ CodeGenState.functionParamLists.set(funcName, paramNames);
173
+
174
+ // Initialize modified set
175
+ CodeGenState.modifiedParameters.set(funcName, new Set());
176
+ // Issue #579: Initialize subscript access tracking
177
+ CodeGenState.subscriptAccessedParameters.set(funcName, new Set());
178
+ CodeGenState.functionCallGraph.set(funcName, []);
179
+
180
+ // Walk the function body to find modifications and calls
181
+ const block = funcDecl.block();
182
+ if (block) {
183
+ PassByValueAnalyzer.walkBlockForModifications(
184
+ funcName,
185
+ paramNames,
186
+ block,
187
+ );
188
+ }
189
+ }
190
+
191
+ /**
192
+ * Walk a block to find parameter modifications and function calls.
193
+ */
194
+ private static walkBlockForModifications(
195
+ funcName: string,
196
+ paramNames: string[],
197
+ block: Parser.BlockContext,
198
+ ): void {
199
+ const paramSet = new Set(paramNames);
200
+
201
+ for (const stmt of block.statement()) {
202
+ PassByValueAnalyzer.walkStatementForModifications(
203
+ funcName,
204
+ paramSet,
205
+ stmt,
206
+ );
207
+ }
208
+ }
209
+
210
+ /**
211
+ * Walk a statement recursively looking for modifications and calls.
212
+ * Issue #566: Refactored to use helper methods for expression and child collection.
213
+ */
214
+ private static walkStatementForModifications(
215
+ funcName: string,
216
+ paramSet: Set<string>,
217
+ stmt: Parser.StatementContext,
218
+ ): void {
219
+ // 1. Check for parameter modifications via assignment targets
220
+ if (stmt.assignmentStatement()) {
221
+ PassByValueAnalyzer.trackAssignmentModifications(
222
+ funcName,
223
+ paramSet,
224
+ stmt,
225
+ );
226
+ }
227
+
228
+ // 2. Walk all expressions in this statement for function calls and subscript access
229
+ for (const expr of StatementExpressionCollector.collectAll(stmt)) {
230
+ PassByValueAnalyzer.walkExpressionForCalls(funcName, paramSet, expr);
231
+ // Issue #579: Also track subscript read access on parameters
232
+ PassByValueAnalyzer.walkExpressionForSubscriptAccess(
233
+ funcName,
234
+ paramSet,
235
+ expr,
236
+ );
237
+ }
238
+
239
+ // 3. Recurse into child statements and blocks
240
+ const { statements, blocks } = ChildStatementCollector.collectAll(stmt);
241
+ for (const childStmt of statements) {
242
+ PassByValueAnalyzer.walkStatementForModifications(
243
+ funcName,
244
+ paramSet,
245
+ childStmt,
246
+ );
247
+ }
248
+ for (const block of blocks) {
249
+ PassByValueAnalyzer.walkBlockForModifications(
250
+ funcName,
251
+ [...paramSet],
252
+ block,
253
+ );
254
+ }
255
+ }
256
+
257
+ /**
258
+ * Track assignment modifications for parameter const inference.
259
+ * SonarCloud S3776: Extracted from walkStatementForModifications().
260
+ */
261
+ private static trackAssignmentModifications(
262
+ funcName: string,
263
+ paramSet: Set<string>,
264
+ stmt: Parser.StatementContext,
265
+ ): void {
266
+ const assign = stmt.assignmentStatement()!;
267
+ const target = assign.assignmentTarget();
268
+
269
+ const { baseIdentifier, hasSingleIndexSubscript } =
270
+ AssignmentTargetExtractor.extract(target);
271
+
272
+ // Issue #579: Track subscript access on parameters (for write path)
273
+ if (
274
+ hasSingleIndexSubscript &&
275
+ baseIdentifier &&
276
+ paramSet.has(baseIdentifier)
277
+ ) {
278
+ CodeGenState.subscriptAccessedParameters
279
+ .get(funcName)!
280
+ .add(baseIdentifier);
281
+ }
282
+
283
+ // Track as modified parameter
284
+ if (baseIdentifier && paramSet.has(baseIdentifier)) {
285
+ CodeGenState.modifiedParameters.get(funcName)!.add(baseIdentifier);
286
+ }
287
+ }
288
+
289
+ /**
290
+ * Walk an expression tree to find function calls where parameters are passed.
291
+ * Uses recursive descent through the expression hierarchy.
292
+ */
293
+ private static walkExpressionForCalls(
294
+ funcName: string,
295
+ paramSet: Set<string>,
296
+ expr: Parser.ExpressionContext,
297
+ ): void {
298
+ // Expression -> TernaryExpression -> OrExpression -> ... -> PostfixExpression
299
+ const ternary = expr.ternaryExpression();
300
+ if (ternary) {
301
+ // Walk all orExpression children
302
+ for (const orExpr of ternary.orExpression()) {
303
+ PassByValueAnalyzer.walkOrExpressionForCalls(
304
+ funcName,
305
+ paramSet,
306
+ orExpr,
307
+ );
308
+ }
309
+ }
310
+ }
311
+
312
+ /**
313
+ * Issue #579: Walk an expression tree to find subscript access on parameters.
314
+ * This tracks read access like `buf[i]` where buf is a parameter.
315
+ * Parameters with subscript access must become pointers.
316
+ */
317
+ private static walkExpressionForSubscriptAccess(
318
+ funcName: string,
319
+ paramSet: Set<string>,
320
+ expr: Parser.ExpressionContext,
321
+ ): void {
322
+ const ternary = expr.ternaryExpression();
323
+ if (ternary) {
324
+ for (const orExpr of ternary.orExpression()) {
325
+ PassByValueAnalyzer.walkOrExpression(orExpr, (unaryExpr) => {
326
+ PassByValueAnalyzer.handleSubscriptAccess(
327
+ funcName,
328
+ paramSet,
329
+ unaryExpr,
330
+ );
331
+ });
332
+ }
333
+ }
334
+ }
335
+
336
+ /**
337
+ * Issue #579: Handle subscript access on a unary expression.
338
+ * Only tracks single-index subscript access (which could be array access).
339
+ * Two-index subscript (e.g., value[start, width]) is always bit extraction,
340
+ * so it doesn't require the parameter to become a pointer.
341
+ */
342
+ private static handleSubscriptAccess(
343
+ funcName: string,
344
+ paramSet: Set<string>,
345
+ unaryExpr: Parser.UnaryExpressionContext,
346
+ ): void {
347
+ const postfixExpr = unaryExpr.postfixExpression();
348
+ if (!postfixExpr) return;
349
+
350
+ const primary = postfixExpr.primaryExpression();
351
+ const ops = postfixExpr.postfixOp();
352
+
353
+ // Check if primary is a parameter and there's subscript access
354
+ const primaryId = primary.IDENTIFIER()?.getText();
355
+ if (!primaryId || !paramSet.has(primaryId)) {
356
+ return;
357
+ }
358
+
359
+ // Only track SINGLE-index subscript access (potential array access)
360
+ // Two-index subscript like value[0, 8] is bit extraction, not array access
361
+ const hasSingleIndexSubscript = ops.some(
362
+ (op) => op.expression().length === 1,
363
+ );
364
+ if (hasSingleIndexSubscript) {
365
+ CodeGenState.subscriptAccessedParameters.get(funcName)!.add(primaryId);
366
+ }
367
+ }
368
+
369
+ /**
370
+ * Generic walker for orExpression trees.
371
+ * Walks through the expression hierarchy and calls the handler for each unaryExpression.
372
+ * Used by both function call tracking and subscript access tracking.
373
+ */
374
+ private static walkOrExpression(
375
+ orExpr: Parser.OrExpressionContext,
376
+ handler: (unaryExpr: Parser.UnaryExpressionContext) => void,
377
+ ): void {
378
+ orExpr
379
+ .andExpression()
380
+ .flatMap((and) => and.equalityExpression())
381
+ .flatMap((eq) => eq.relationalExpression())
382
+ .flatMap((rel) => rel.bitwiseOrExpression())
383
+ .flatMap((bor) => bor.bitwiseXorExpression())
384
+ .flatMap((bxor) => bxor.bitwiseAndExpression())
385
+ .flatMap((band) => band.shiftExpression())
386
+ .flatMap((shift) => shift.additiveExpression())
387
+ .flatMap((add) => add.multiplicativeExpression())
388
+ .flatMap((mul) => mul.unaryExpression())
389
+ .forEach(handler);
390
+ }
391
+
392
+ /**
393
+ * Walk an orExpression tree for function calls.
394
+ */
395
+ private static walkOrExpressionForCalls(
396
+ funcName: string,
397
+ paramSet: Set<string>,
398
+ orExpr: Parser.OrExpressionContext,
399
+ ): void {
400
+ PassByValueAnalyzer.walkOrExpression(orExpr, (unaryExpr) => {
401
+ PassByValueAnalyzer.walkUnaryExpressionForCalls(
402
+ funcName,
403
+ paramSet,
404
+ unaryExpr,
405
+ );
406
+ });
407
+ }
408
+
409
+ /**
410
+ * Walk a unaryExpression tree for function calls.
411
+ */
412
+ private static walkUnaryExpressionForCalls(
413
+ funcName: string,
414
+ paramSet: Set<string>,
415
+ unaryExpr: Parser.UnaryExpressionContext,
416
+ ): void {
417
+ // Recurse into nested unary
418
+ if (unaryExpr.unaryExpression()) {
419
+ PassByValueAnalyzer.walkUnaryExpressionForCalls(
420
+ funcName,
421
+ paramSet,
422
+ unaryExpr.unaryExpression()!,
423
+ );
424
+ return;
425
+ }
426
+
427
+ // Check postfix expression
428
+ const postfix = unaryExpr.postfixExpression();
429
+ if (postfix) {
430
+ PassByValueAnalyzer.walkPostfixExpressionForCalls(
431
+ funcName,
432
+ paramSet,
433
+ postfix,
434
+ );
435
+ }
436
+ }
437
+
438
+ /**
439
+ * Walk a postfixExpression for function calls.
440
+ * This is where function calls are found: primaryExpr followed by '(' args ')'
441
+ */
442
+ private static walkPostfixExpressionForCalls(
443
+ funcName: string,
444
+ paramSet: Set<string>,
445
+ postfix: Parser.PostfixExpressionContext,
446
+ ): void {
447
+ const primary = postfix.primaryExpression();
448
+ const postfixOps = postfix.postfixOp();
449
+
450
+ // Handle simple function calls: IDENTIFIER followed by '(' ... ')'
451
+ PassByValueAnalyzer.handleSimpleFunctionCall(
452
+ funcName,
453
+ paramSet,
454
+ primary,
455
+ postfixOps,
456
+ );
457
+
458
+ // Issue #365: Handle scope-qualified calls: Scope.method(...) or global.Scope.method(...)
459
+ PassByValueAnalyzer.handleScopeQualifiedCalls(
460
+ funcName,
461
+ paramSet,
462
+ primary,
463
+ postfixOps,
464
+ );
465
+
466
+ // Recurse into primary expression if it's a parenthesized expression
467
+ if (primary.expression()) {
468
+ PassByValueAnalyzer.walkExpressionForCalls(
469
+ funcName,
470
+ paramSet,
471
+ primary.expression()!,
472
+ );
473
+ }
474
+
475
+ // Walk arguments in any postfix function call ops (for nested calls)
476
+ PassByValueAnalyzer.walkPostfixOpsRecursively(
477
+ funcName,
478
+ paramSet,
479
+ postfixOps,
480
+ );
481
+ }
482
+
483
+ /**
484
+ * Handle simple function calls: IDENTIFIER followed by '(' ... ')'
485
+ * Issue #797: Resolve bare function names to scope-qualified names when inside a scope.
486
+ */
487
+ private static handleSimpleFunctionCall(
488
+ funcName: string,
489
+ paramSet: Set<string>,
490
+ primary: Parser.PrimaryExpressionContext,
491
+ postfixOps: Parser.PostfixOpContext[],
492
+ ): void {
493
+ if (!primary.IDENTIFIER() || postfixOps.length === 0) return;
494
+
495
+ const firstOp = postfixOps[0];
496
+ if (!firstOp.LPAREN()) return;
497
+
498
+ const bareCalleeName = primary.IDENTIFIER()!.getText();
499
+ const resolvedCalleeName = PassByValueAnalyzer.resolveCalleeNameInScope(
500
+ funcName,
501
+ bareCalleeName,
502
+ );
503
+ PassByValueAnalyzer.recordCallsFromArgList(
504
+ funcName,
505
+ paramSet,
506
+ resolvedCalleeName,
507
+ firstOp,
508
+ );
509
+ }
510
+
511
+ /**
512
+ * Issue #797: Resolve a bare function name to its scope-qualified name.
513
+ * When inside a scope, bare calls like `fillData()` should resolve to `Scope_fillData`.
514
+ *
515
+ * Uses SymbolRegistry for proper scope-aware resolution instead of string parsing.
516
+ */
517
+ private static resolveCalleeNameInScope(
518
+ callerFuncName: string,
519
+ bareCalleeName: string,
520
+ ): string {
521
+ // Try to resolve using SymbolRegistry (new type system)
522
+ const callerScope =
523
+ SymbolRegistry.getScopeByMangledFunctionName(callerFuncName);
524
+ if (callerScope) {
525
+ // Use SymbolRegistry.resolveFunction to find the callee in scope chain
526
+ const callee = SymbolRegistry.resolveFunction(
527
+ bareCalleeName,
528
+ callerScope,
529
+ );
530
+ if (callee) {
531
+ // Use FunctionUtils to get the C-mangled name (types layer, not output layer)
532
+ return FunctionUtils.getCMangledName(callee);
533
+ }
534
+ }
535
+
536
+ // Fallback to legacy string-based lookup for backward compatibility
537
+ // (handles functions from C headers, external functions, etc.)
538
+ const underscoreIndex = callerFuncName.indexOf("_");
539
+ if (underscoreIndex === -1) {
540
+ return bareCalleeName;
541
+ }
542
+
543
+ const scopePrefix = callerFuncName.substring(0, underscoreIndex + 1);
544
+ const qualifiedName = scopePrefix + bareCalleeName;
545
+
546
+ if (CodeGenState.functionParamLists.has(qualifiedName)) {
547
+ return qualifiedName;
548
+ }
549
+
550
+ return bareCalleeName;
551
+ }
552
+
553
+ /**
554
+ * Handle scope-qualified calls: Scope.method(...) or global.Scope.method(...)
555
+ * Track member accesses to build the mangled callee name (e.g., Storage_load)
556
+ */
557
+ private static handleScopeQualifiedCalls(
558
+ funcName: string,
559
+ paramSet: Set<string>,
560
+ primary: Parser.PrimaryExpressionContext,
561
+ postfixOps: Parser.PostfixOpContext[],
562
+ ): void {
563
+ if (postfixOps.length === 0) return;
564
+
565
+ const memberNames = PassByValueAnalyzer.collectInitialMemberNames(
566
+ funcName,
567
+ primary,
568
+ );
569
+
570
+ for (const op of postfixOps) {
571
+ if (op.IDENTIFIER()) {
572
+ memberNames.push(op.IDENTIFIER()!.getText());
573
+ } else if (op.LPAREN() && memberNames.length >= 1) {
574
+ const calleeName = memberNames.join("_");
575
+ PassByValueAnalyzer.recordCallsFromArgList(
576
+ funcName,
577
+ paramSet,
578
+ calleeName,
579
+ op,
580
+ );
581
+ memberNames.length = 0; // Reset for potential chained calls
582
+ } else if (op.expression().length > 0) {
583
+ memberNames.length = 0; // Array subscript breaks scope chain
584
+ }
585
+ }
586
+ }
587
+
588
+ /**
589
+ * Collect initial member names from primary expression for scope resolution.
590
+ * Issue #561: When 'this' is used, resolve to the current scope name from funcName.
591
+ */
592
+ private static collectInitialMemberNames(
593
+ funcName: string,
594
+ primary: Parser.PrimaryExpressionContext,
595
+ ): string[] {
596
+ const memberNames: string[] = [];
597
+ const primaryId = primary.IDENTIFIER()?.getText();
598
+
599
+ if (primaryId && primaryId !== "global") {
600
+ memberNames.push(primaryId);
601
+ } else if (primary.THIS()) {
602
+ const scopeName = funcName.split("_")[0];
603
+ if (scopeName && scopeName !== funcName) {
604
+ memberNames.push(scopeName);
605
+ }
606
+ }
607
+ return memberNames;
608
+ }
609
+
610
+ /**
611
+ * Record function calls to the call graph from an argument list.
612
+ * Also recurses into argument expressions.
613
+ */
614
+ private static recordCallsFromArgList(
615
+ funcName: string,
616
+ paramSet: Set<string>,
617
+ calleeName: string,
618
+ op: Parser.PostfixOpContext,
619
+ ): void {
620
+ const argList = op.argumentList();
621
+ if (!argList) return;
622
+
623
+ const args = argList.expression();
624
+ for (let i = 0; i < args.length; i++) {
625
+ const arg = args[i];
626
+ const argName = ExpressionUtils.extractIdentifier(arg);
627
+ if (argName && paramSet.has(argName)) {
628
+ CodeGenState.functionCallGraph.get(funcName)!.push({
629
+ callee: calleeName,
630
+ paramIndex: i,
631
+ argParamName: argName,
632
+ });
633
+ }
634
+ PassByValueAnalyzer.walkExpressionForCalls(funcName, paramSet, arg);
635
+ }
636
+ }
637
+
638
+ /**
639
+ * Walk postfix ops recursively for nested calls and array subscripts.
640
+ */
641
+ private static walkPostfixOpsRecursively(
642
+ funcName: string,
643
+ paramSet: Set<string>,
644
+ postfixOps: Parser.PostfixOpContext[],
645
+ ): void {
646
+ for (const op of postfixOps) {
647
+ if (op.argumentList()) {
648
+ for (const argExpr of op.argumentList()!.expression()) {
649
+ PassByValueAnalyzer.walkExpressionForCalls(
650
+ funcName,
651
+ paramSet,
652
+ argExpr,
653
+ );
654
+ }
655
+ }
656
+ for (const expr of op.expression()) {
657
+ PassByValueAnalyzer.walkExpressionForCalls(funcName, paramSet, expr);
658
+ }
659
+ }
660
+ }
661
+
662
+ /**
663
+ * Phase 3: Determine which parameters can pass by value.
664
+ * A parameter passes by value if:
665
+ * 1. It's a small primitive type (u8, i8, u16, i16, u32, i32, u64, i64, bool)
666
+ * 2. It's not modified (directly or transitively)
667
+ * 3. It's not an array, struct, string, or callback
668
+ */
669
+ private static computePassByValueParams(): void {
670
+ for (const [funcName, paramNames] of CodeGenState.functionParamLists) {
671
+ const passByValue = new Set<string>();
672
+ const modified =
673
+ CodeGenState.modifiedParameters.get(funcName) ?? new Set();
674
+
675
+ // Get function declaration to check parameter types
676
+ const funcSig = CodeGenState.functionSignatures.get(funcName);
677
+ if (funcSig) {
678
+ for (let i = 0; i < paramNames.length; i++) {
679
+ const paramName = paramNames[i];
680
+ const paramSig = funcSig.parameters[i];
681
+
682
+ if (!paramSig) continue;
683
+
684
+ // Check if eligible for pass-by-value:
685
+ // - Is a small primitive type
686
+ // - Not an array
687
+ // - Not modified
688
+ // - Not accessed via subscript (Issue #579)
689
+ const isSmallPrimitive = SMALL_PRIMITIVES.has(paramSig.baseType);
690
+ const isArray = paramSig.isArray ?? false;
691
+ const isModified = modified.has(paramName);
692
+ // Issue #579: Parameters with subscript access must become pointers
693
+ const hasSubscriptAccess =
694
+ CodeGenState.subscriptAccessedParameters
695
+ .get(funcName)
696
+ ?.has(paramName) ?? false;
697
+
698
+ if (
699
+ isSmallPrimitive &&
700
+ !isArray &&
701
+ !isModified &&
702
+ !hasSubscriptAccess
703
+ ) {
704
+ passByValue.add(paramName);
705
+ }
706
+ }
707
+ }
708
+
709
+ CodeGenState.passByValueParams.set(funcName, passByValue);
710
+ }
711
+ }
712
+
713
+ /**
714
+ * Check if a parameter should be passed by value (by name).
715
+ * Used internally during code generation.
716
+ */
717
+ static isParameterPassByValueByName(
718
+ funcName: string,
719
+ paramName: string,
720
+ ): boolean {
721
+ const passByValue = CodeGenState.passByValueParams.get(funcName);
722
+ return passByValue?.has(paramName) ?? false;
723
+ }
724
+
725
+ /**
726
+ * Issue #269: Check if a parameter should be passed by value (by index).
727
+ * Part of IOrchestrator interface - used by CallExprGenerator.
728
+ */
729
+ static isParameterPassByValue(funcName: string, paramIndex: number): boolean {
730
+ const paramList = CodeGenState.functionParamLists.get(funcName);
731
+ if (!paramList || paramIndex < 0 || paramIndex >= paramList.length) {
732
+ return false;
733
+ }
734
+ const paramName = paramList[paramIndex];
735
+ return PassByValueAnalyzer.isParameterPassByValueByName(
736
+ funcName,
737
+ paramName,
738
+ );
739
+ }
740
+ }
741
+
742
+ export default PassByValueAnalyzer;