@typecad/cuttlefish 0.1.0-alpha.1

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 (377) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +79 -0
  3. package/dist/api/board-types.d.ts +1 -0
  4. package/dist/api/board-types.js +4 -0
  5. package/dist/api/capabilities.d.ts +12 -0
  6. package/dist/api/capabilities.js +1 -0
  7. package/dist/api/config.d.ts +120 -0
  8. package/dist/api/config.js +7 -0
  9. package/dist/api/index.d.ts +5 -0
  10. package/dist/api/index.js +2 -0
  11. package/dist/api/schema/builder.d.ts +14 -0
  12. package/dist/api/schema/builder.js +15 -0
  13. package/dist/api/schema/index.d.ts +2 -0
  14. package/dist/api/schema/index.js +1 -0
  15. package/dist/api/schema/types.d.ts +257 -0
  16. package/dist/api/schema/types.js +4 -0
  17. package/dist/api/shared/async-runtime-static.d.ts +8 -0
  18. package/dist/api/shared/async-runtime-static.js +201 -0
  19. package/dist/api/shared/async-types.d.ts +42 -0
  20. package/dist/api/shared/async-types.js +8 -0
  21. package/dist/api/shared/board-resolver.d.ts +12 -0
  22. package/dist/api/shared/board-resolver.js +7 -0
  23. package/dist/api/shared/cpp-type-ir.d.ts +229 -0
  24. package/dist/api/shared/cpp-type-ir.js +672 -0
  25. package/dist/api/shared/display-adapter.d.ts +12 -0
  26. package/dist/api/shared/display-adapter.js +145 -0
  27. package/dist/api/shared/display-adapters/eink-mono.d.ts +2 -0
  28. package/dist/api/shared/display-adapters/eink-mono.js +53 -0
  29. package/dist/api/shared/display-adapters/sdl.d.ts +2 -0
  30. package/dist/api/shared/display-adapters/sdl.js +452 -0
  31. package/dist/api/shared/display-adapters/ssd1309.d.ts +2 -0
  32. package/dist/api/shared/display-adapters/ssd1309.js +136 -0
  33. package/dist/api/shared/display-adapters/st7796.d.ts +2 -0
  34. package/dist/api/shared/display-adapters/st7796.js +132 -0
  35. package/dist/api/shared/display-capabilities.d.ts +45 -0
  36. package/dist/api/shared/display-capabilities.js +54 -0
  37. package/dist/api/shared/display-op-ir.d.ts +62 -0
  38. package/dist/api/shared/display-op-ir.js +19 -0
  39. package/dist/api/shared/display-profile.d.ts +265 -0
  40. package/dist/api/shared/display-profile.js +338 -0
  41. package/dist/api/shared/graphics-strategy.d.ts +29 -0
  42. package/dist/api/shared/graphics-strategy.js +11 -0
  43. package/dist/api/shared/hal-op-ir.d.ts +393 -0
  44. package/dist/api/shared/hal-op-ir.js +18 -0
  45. package/dist/api/shared/index.d.ts +26 -0
  46. package/dist/api/shared/index.js +21 -0
  47. package/dist/api/shared/ir-core.d.ts +363 -0
  48. package/dist/api/shared/ir-core.js +8 -0
  49. package/dist/api/shared/ir-declarations.d.ts +201 -0
  50. package/dist/api/shared/ir-declarations.js +26 -0
  51. package/dist/api/shared/ir.d.ts +85 -0
  52. package/dist/api/shared/ir.js +13 -0
  53. package/dist/api/shared/platform-strategy.d.ts +402 -0
  54. package/dist/api/shared/platform-strategy.js +14 -0
  55. package/dist/api/shared/polyfill-helper-registry.d.ts +11 -0
  56. package/dist/api/shared/polyfill-helper-registry.js +86 -0
  57. package/dist/api/shared/polyfill-types.d.ts +33 -0
  58. package/dist/api/shared/polyfill-types.js +76 -0
  59. package/dist/api/shared/promise-runtime.d.ts +10 -0
  60. package/dist/api/shared/promise-runtime.js +244 -0
  61. package/dist/api/shared/snprintf-types.d.ts +29 -0
  62. package/dist/api/shared/snprintf-types.js +8 -0
  63. package/dist/api/shared/string-method-registry.d.ts +53 -0
  64. package/dist/api/shared/string-method-registry.js +168 -0
  65. package/dist/api/shared/toolchain-types.d.ts +63 -0
  66. package/dist/api/shared/toolchain-types.js +71 -0
  67. package/dist/api/shared/types.d.ts +50 -0
  68. package/dist/api/shared/types.js +6 -0
  69. package/dist/ast/parse.d.ts +2 -0
  70. package/dist/ast/parse.js +4 -0
  71. package/dist/cache.d.ts +26 -0
  72. package/dist/cache.js +95 -0
  73. package/dist/cli-utils.d.ts +37 -0
  74. package/dist/cli-utils.js +250 -0
  75. package/dist/cli.d.ts +2 -0
  76. package/dist/cli.js +635 -0
  77. package/dist/config-loader.d.ts +78 -0
  78. package/dist/config-loader.js +508 -0
  79. package/dist/config-schema.d.ts +233 -0
  80. package/dist/config-schema.js +83 -0
  81. package/dist/create/board-checklist.d.ts +2 -0
  82. package/dist/create/board-checklist.js +52 -0
  83. package/dist/create/board-codegen.d.ts +9 -0
  84. package/dist/create/board-codegen.js +238 -0
  85. package/dist/create/board-generators.d.ts +12 -0
  86. package/dist/create/board-generators.js +652 -0
  87. package/dist/create/board-spec.d.ts +640 -0
  88. package/dist/create/board-spec.js +215 -0
  89. package/dist/create/eslint-rules-template.d.ts +2 -0
  90. package/dist/create/eslint-rules-template.js +672 -0
  91. package/dist/create/index.d.ts +11 -0
  92. package/dist/create/index.js +8 -0
  93. package/dist/create/init-scaffold.d.ts +27 -0
  94. package/dist/create/init-scaffold.js +150 -0
  95. package/dist/create/init-templates.d.ts +24 -0
  96. package/dist/create/init-templates.js +379 -0
  97. package/dist/create/init-wizard.d.ts +8 -0
  98. package/dist/create/init-wizard.js +168 -0
  99. package/dist/debug/breakpoint-loader.d.ts +24 -0
  100. package/dist/debug/breakpoint-loader.js +137 -0
  101. package/dist/debug/index.d.ts +3 -0
  102. package/dist/debug/index.js +7 -0
  103. package/dist/debug/preprocessor.d.ts +9 -0
  104. package/dist/debug/preprocessor.js +214 -0
  105. package/dist/debug/types.d.ts +32 -0
  106. package/dist/debug/types.js +6 -0
  107. package/dist/diagnostics/diagnostics-report.d.ts +51 -0
  108. package/dist/diagnostics/diagnostics-report.js +333 -0
  109. package/dist/diagnostics/json-schema.d.ts +138 -0
  110. package/dist/diagnostics/json-schema.js +27 -0
  111. package/dist/diagnostics/md-writer.d.ts +10 -0
  112. package/dist/diagnostics/md-writer.js +336 -0
  113. package/dist/diagnostics/mermaid-builder.d.ts +65 -0
  114. package/dist/diagnostics/mermaid-builder.js +681 -0
  115. package/dist/emit/cpp-emitter.d.ts +6 -0
  116. package/dist/emit/cpp-emitter.js +48 -0
  117. package/dist/emit/emitters/class-emitter.d.ts +2 -0
  118. package/dist/emit/emitters/class-emitter.js +523 -0
  119. package/dist/emit/emitters/emitter-context.d.ts +174 -0
  120. package/dist/emit/emitters/emitter-context.js +1 -0
  121. package/dist/emit/emitters/entrypoint-synthesizer.d.ts +2 -0
  122. package/dist/emit/emitters/entrypoint-synthesizer.js +175 -0
  123. package/dist/emit/emitters/function-emitter-impl.d.ts +19 -0
  124. package/dist/emit/emitters/function-emitter-impl.js +428 -0
  125. package/dist/emit/emitters/line-appender.d.ts +15 -0
  126. package/dist/emit/emitters/line-appender.js +344 -0
  127. package/dist/emit/emitters/namespace-emitter.d.ts +2 -0
  128. package/dist/emit/emitters/namespace-emitter.js +324 -0
  129. package/dist/emit/emitters/output-finalizer.d.ts +4 -0
  130. package/dist/emit/emitters/output-finalizer.js +267 -0
  131. package/dist/emit/emitters/setup.d.ts +3 -0
  132. package/dist/emit/emitters/setup.js +851 -0
  133. package/dist/emit/emitters/top-level-prep.d.ts +2 -0
  134. package/dist/emit/emitters/top-level-prep.js +706 -0
  135. package/dist/emit/emitters/type-decl-emitter.d.ts +2 -0
  136. package/dist/emit/emitters/type-decl-emitter.js +251 -0
  137. package/dist/emit/emitters/ui-emitter.d.ts +21 -0
  138. package/dist/emit/emitters/ui-emitter.js +564 -0
  139. package/dist/emit/enum-emitter.d.ts +1 -0
  140. package/dist/emit/enum-emitter.js +1 -0
  141. package/dist/emit/expression-renderer.d.ts +283 -0
  142. package/dist/emit/expression-renderer.js +1477 -0
  143. package/dist/emit/native-helpers-emitter.d.ts +11 -0
  144. package/dist/emit/native-helpers-emitter.js +34 -0
  145. package/dist/emit/route-hal-op.d.ts +5 -0
  146. package/dist/emit/route-hal-op.js +13 -0
  147. package/dist/emit/snprintf-helpers.d.ts +17 -0
  148. package/dist/emit/snprintf-helpers.js +462 -0
  149. package/dist/emit/statement-renderer.d.ts +189 -0
  150. package/dist/emit/statement-renderer.js +948 -0
  151. package/dist/emit/utils/async-state-machine.d.ts +42 -0
  152. package/dist/emit/utils/async-state-machine.js +343 -0
  153. package/dist/emit/utils/comment-helpers.d.ts +20 -0
  154. package/dist/emit/utils/comment-helpers.js +31 -0
  155. package/dist/emit/utils/cpp-helpers.d.ts +47 -0
  156. package/dist/emit/utils/cpp-helpers.js +85 -0
  157. package/dist/emit/utils/include-resolver.d.ts +58 -0
  158. package/dist/emit/utils/include-resolver.js +155 -0
  159. package/dist/emit/utils/index.d.ts +8 -0
  160. package/dist/emit/utils/index.js +12 -0
  161. package/dist/emit/utils/type-inference.d.ts +159 -0
  162. package/dist/emit/utils/type-inference.js +559 -0
  163. package/dist/eslint-check.d.ts +10 -0
  164. package/dist/eslint-check.js +102 -0
  165. package/dist/framework-package.d.ts +10 -0
  166. package/dist/framework-package.js +58 -0
  167. package/dist/framework-registry.d.ts +39 -0
  168. package/dist/framework-registry.js +30 -0
  169. package/dist/incremental-cache.d.ts +116 -0
  170. package/dist/incremental-cache.js +335 -0
  171. package/dist/ir/adc-range-validation.d.ts +11 -0
  172. package/dist/ir/adc-range-validation.js +250 -0
  173. package/dist/ir/ast-node-utils.d.ts +8 -0
  174. package/dist/ir/ast-node-utils.js +32 -0
  175. package/dist/ir/board-pin-utils.d.ts +13 -0
  176. package/dist/ir/board-pin-utils.js +65 -0
  177. package/dist/ir/board-resolver.d.ts +36 -0
  178. package/dist/ir/board-resolver.js +437 -0
  179. package/dist/ir/build-ir-state.d.ts +167 -0
  180. package/dist/ir/build-ir-state.js +306 -0
  181. package/dist/ir/build-ir.d.ts +2 -0
  182. package/dist/ir/build-ir.js +808 -0
  183. package/dist/ir/call-graph.d.ts +35 -0
  184. package/dist/ir/call-graph.js +194 -0
  185. package/dist/ir/compile-time-only.d.ts +2 -0
  186. package/dist/ir/compile-time-only.js +16 -0
  187. package/dist/ir/declaration-builders.d.ts +9 -0
  188. package/dist/ir/declaration-builders.js +608 -0
  189. package/dist/ir/entry-points.d.ts +30 -0
  190. package/dist/ir/entry-points.js +191 -0
  191. package/dist/ir/expression-to-ir.d.ts +5 -0
  192. package/dist/ir/expression-to-ir.js +2249 -0
  193. package/dist/ir/extract-property-chain.d.ts +10 -0
  194. package/dist/ir/extract-property-chain.js +30 -0
  195. package/dist/ir/feature-prescan.d.ts +3 -0
  196. package/dist/ir/feature-prescan.js +43 -0
  197. package/dist/ir/feature-registry.d.ts +30 -0
  198. package/dist/ir/feature-registry.js +816 -0
  199. package/dist/ir/filter.d.ts +7 -0
  200. package/dist/ir/filter.js +85 -0
  201. package/dist/ir/function-builder.d.ts +19 -0
  202. package/dist/ir/function-builder.js +670 -0
  203. package/dist/ir/hal/hal-emitter.d.ts +62 -0
  204. package/dist/ir/hal/hal-emitter.js +735 -0
  205. package/dist/ir/hal/hal-parser.d.ts +61 -0
  206. package/dist/ir/hal/hal-parser.js +473 -0
  207. package/dist/ir/hal/hal-plugins.d.ts +34 -0
  208. package/dist/ir/hal/hal-plugins.js +706 -0
  209. package/dist/ir/hal-resolver.d.ts +5 -0
  210. package/dist/ir/hal-resolver.js +5 -0
  211. package/dist/ir/heap-analysis.d.ts +8 -0
  212. package/dist/ir/heap-analysis.js +350 -0
  213. package/dist/ir/heap-array-validation.d.ts +24 -0
  214. package/dist/ir/heap-array-validation.js +29 -0
  215. package/dist/ir/identifier-collector.d.ts +18 -0
  216. package/dist/ir/identifier-collector.js +439 -0
  217. package/dist/ir/interrupt-analysis.d.ts +39 -0
  218. package/dist/ir/interrupt-analysis.js +467 -0
  219. package/dist/ir/memory-budget-validation.d.ts +10 -0
  220. package/dist/ir/memory-budget-validation.js +86 -0
  221. package/dist/ir/namespace-builder.d.ts +7 -0
  222. package/dist/ir/namespace-builder.js +152 -0
  223. package/dist/ir/ownership-analysis.d.ts +9 -0
  224. package/dist/ir/ownership-analysis.js +1207 -0
  225. package/dist/ir/peripheral-ownership.d.ts +3 -0
  226. package/dist/ir/peripheral-ownership.js +152 -0
  227. package/dist/ir/peripheral-symbols.d.ts +7 -0
  228. package/dist/ir/peripheral-symbols.js +57 -0
  229. package/dist/ir/peripheral-usage.d.ts +54 -0
  230. package/dist/ir/peripheral-usage.js +691 -0
  231. package/dist/ir/peripheral-validation.d.ts +8 -0
  232. package/dist/ir/peripheral-validation.js +77 -0
  233. package/dist/ir/pin-alias-conflict.d.ts +4 -0
  234. package/dist/ir/pin-alias-conflict.js +34 -0
  235. package/dist/ir/pin-capability-validation.d.ts +6 -0
  236. package/dist/ir/pin-capability-validation.js +413 -0
  237. package/dist/ir/pin-mode-validation.d.ts +10 -0
  238. package/dist/ir/pin-mode-validation.js +301 -0
  239. package/dist/ir/pin-safety.d.ts +11 -0
  240. package/dist/ir/pin-safety.js +58 -0
  241. package/dist/ir/program-analysis.d.ts +44 -0
  242. package/dist/ir/program-analysis.js +589 -0
  243. package/dist/ir/pulldown-validation.d.ts +7 -0
  244. package/dist/ir/pulldown-validation.js +49 -0
  245. package/dist/ir/pwm-timer-sharing.d.ts +4 -0
  246. package/dist/ir/pwm-timer-sharing.js +93 -0
  247. package/dist/ir/reachability.d.ts +68 -0
  248. package/dist/ir/reachability.js +224 -0
  249. package/dist/ir/register-decorators.d.ts +6 -0
  250. package/dist/ir/register-decorators.js +49 -0
  251. package/dist/ir/render-expr.d.ts +4 -0
  252. package/dist/ir/render-expr.js +127 -0
  253. package/dist/ir/resource-analysis.d.ts +19 -0
  254. package/dist/ir/resource-analysis.js +153 -0
  255. package/dist/ir/statement-to-ir.d.ts +23 -0
  256. package/dist/ir/statement-to-ir.js +349 -0
  257. package/dist/ir/symbol-table.d.ts +68 -0
  258. package/dist/ir/symbol-table.js +179 -0
  259. package/dist/ir/symbol-types.d.ts +56 -0
  260. package/dist/ir/symbol-types.js +107 -0
  261. package/dist/ir/timer0-pwm-timing-conflict.d.ts +4 -0
  262. package/dist/ir/timer0-pwm-timing-conflict.js +71 -0
  263. package/dist/ir/timing-validation.d.ts +7 -0
  264. package/dist/ir/timing-validation.js +95 -0
  265. package/dist/ir/transformers/array-methods.d.ts +8 -0
  266. package/dist/ir/transformers/array-methods.js +493 -0
  267. package/dist/ir/transformers/call-statement.d.ts +5 -0
  268. package/dist/ir/transformers/call-statement.js +758 -0
  269. package/dist/ir/transformers/callback-context-registry.d.ts +20 -0
  270. package/dist/ir/transformers/callback-context-registry.js +55 -0
  271. package/dist/ir/transformers/canvas-lowering.d.ts +42 -0
  272. package/dist/ir/transformers/canvas-lowering.js +249 -0
  273. package/dist/ir/transformers/control-flow.d.ts +8 -0
  274. package/dist/ir/transformers/control-flow.js +508 -0
  275. package/dist/ir/transformers/expressions.d.ts +7 -0
  276. package/dist/ir/transformers/expressions.js +406 -0
  277. package/dist/ir/transformers/hal-call-resolver.d.ts +29 -0
  278. package/dist/ir/transformers/hal-call-resolver.js +274 -0
  279. package/dist/ir/transformers/hal-emit-helpers.d.ts +14 -0
  280. package/dist/ir/transformers/hal-emit-helpers.js +63 -0
  281. package/dist/ir/transformers/namespace-methods.d.ts +20 -0
  282. package/dist/ir/transformers/namespace-methods.js +110 -0
  283. package/dist/ir/transformers/register-assignment.d.ts +5 -0
  284. package/dist/ir/transformers/register-assignment.js +56 -0
  285. package/dist/ir/transformers/ui-call-resolver.d.ts +149 -0
  286. package/dist/ir/transformers/ui-call-resolver.js +1136 -0
  287. package/dist/ir/transformers/ui-callback-lowering.d.ts +62 -0
  288. package/dist/ir/transformers/ui-callback-lowering.js +623 -0
  289. package/dist/ir/transformers/ui-mount.d.ts +20 -0
  290. package/dist/ir/transformers/ui-mount.js +35 -0
  291. package/dist/ir/transformers/ui-reactive.d.ts +68 -0
  292. package/dist/ir/transformers/ui-reactive.js +129 -0
  293. package/dist/ir/transformers/variables.d.ts +14 -0
  294. package/dist/ir/transformers/variables.js +1045 -0
  295. package/dist/ir/try-catch-validation.d.ts +26 -0
  296. package/dist/ir/try-catch-validation.js +128 -0
  297. package/dist/ir/type-resolution.d.ts +31 -0
  298. package/dist/ir/type-resolution.js +977 -0
  299. package/dist/ir/ui-element-auto-wire.d.ts +50 -0
  300. package/dist/ir/ui-element-auto-wire.js +218 -0
  301. package/dist/ir/unit-suspicion-validation.d.ts +12 -0
  302. package/dist/ir/unit-suspicion-validation.js +296 -0
  303. package/dist/ir/utils/walk-ir.d.ts +6 -0
  304. package/dist/ir/utils/walk-ir.js +162 -0
  305. package/dist/ir/validation-orchestrator.d.ts +4 -0
  306. package/dist/ir/validation-orchestrator.js +45 -0
  307. package/dist/libdef/base-class-resolver.d.ts +23 -0
  308. package/dist/libdef/base-class-resolver.js +50 -0
  309. package/dist/libdef/cpp-to-decl.d.ts +34 -0
  310. package/dist/libdef/cpp-to-decl.js +584 -0
  311. package/dist/libdef/header-parser.d.ts +53 -0
  312. package/dist/libdef/header-parser.js +269 -0
  313. package/dist/libdef/registry.d.ts +10 -0
  314. package/dist/libdef/registry.js +142 -0
  315. package/dist/mapping/peripheral-names.d.ts +23 -0
  316. package/dist/mapping/peripheral-names.js +63 -0
  317. package/dist/mapping/source-map.d.ts +46 -0
  318. package/dist/mapping/source-map.js +207 -0
  319. package/dist/orchestrator/dts-generator.d.ts +17 -0
  320. package/dist/orchestrator/dts-generator.js +83 -0
  321. package/dist/orchestrator/graph-builder.d.ts +18 -0
  322. package/dist/orchestrator/graph-builder.js +218 -0
  323. package/dist/orchestrator/semantic-facts-verifier.d.ts +38 -0
  324. package/dist/orchestrator/semantic-facts-verifier.js +121 -0
  325. package/dist/orchestrator/semantic-facts.d.ts +141 -0
  326. package/dist/orchestrator/semantic-facts.js +652 -0
  327. package/dist/orchestrator/type-checker.d.ts +39 -0
  328. package/dist/orchestrator/type-checker.js +760 -0
  329. package/dist/platform/async-runtime.d.ts +8 -0
  330. package/dist/platform/async-runtime.js +26 -0
  331. package/dist/platform/generic-strategy.d.ts +101 -0
  332. package/dist/platform/generic-strategy.js +289 -0
  333. package/dist/platform/index.d.ts +4 -0
  334. package/dist/platform/index.js +9 -0
  335. package/dist/platform/registry.d.ts +21 -0
  336. package/dist/platform/registry.js +42 -0
  337. package/dist/platform/toolchain.d.ts +4 -0
  338. package/dist/platform/toolchain.js +43 -0
  339. package/dist/preview/client.d.ts +1 -0
  340. package/dist/preview/client.js +137 -0
  341. package/dist/preview/server.d.ts +5 -0
  342. package/dist/preview/server.js +199 -0
  343. package/dist/profiler/index.d.ts +28 -0
  344. package/dist/profiler/index.js +28 -0
  345. package/dist/profiler/profiler.d.ts +95 -0
  346. package/dist/profiler/profiler.js +338 -0
  347. package/dist/profiler/types.d.ts +87 -0
  348. package/dist/profiler/types.js +12 -0
  349. package/dist/stores/display-profile-store.d.ts +16 -0
  350. package/dist/stores/display-profile-store.js +48 -0
  351. package/dist/stores/theme-store.d.ts +13 -0
  352. package/dist/stores/theme-store.js +30 -0
  353. package/dist/testing.d.ts +45 -0
  354. package/dist/testing.js +47 -0
  355. package/dist/transpile/resolution.d.ts +29 -0
  356. package/dist/transpile/resolution.js +282 -0
  357. package/dist/transpile.d.ts +3 -0
  358. package/dist/transpile.js +722 -0
  359. package/dist/types.d.ts +217 -0
  360. package/dist/types.js +1 -0
  361. package/dist/ui/ui-bridge.d.ts +4 -0
  362. package/dist/ui/ui-bridge.js +34 -0
  363. package/dist/ui-hook.d.ts +84 -0
  364. package/dist/ui-hook.js +45 -0
  365. package/dist/utils/cli.d.ts +3 -0
  366. package/dist/utils/cli.js +463 -0
  367. package/dist/utils/fs.d.ts +4 -0
  368. package/dist/utils/fs.js +23 -0
  369. package/dist/utils/logger.d.ts +2 -0
  370. package/dist/utils/logger.js +8 -0
  371. package/dist/utils/strings.d.ts +35 -0
  372. package/dist/utils/strings.js +142 -0
  373. package/dist/utils/ui.d.ts +66 -0
  374. package/dist/utils/ui.js +149 -0
  375. package/dist/watch.d.ts +35 -0
  376. package/dist/watch.js +111 -0
  377. package/package.json +127 -0
@@ -0,0 +1,153 @@
1
+ import { findBoardPinByName, formatPinReference, getBoardPins } from './board-pin-utils.js';
2
+ /**
3
+ * Unified hardware resource conflict analysis.
4
+ * Detects:
5
+ * 1. Pin Multiplexing Conflicts: Same pin used for GPIO and a Peripheral (I2C, SPI, UART).
6
+ * 2. Peripheral Instance Conflicts: Multiple peripherals sharing the same pins.
7
+ * 3. Board-Specific Hardware Warnings: Logic for specific pins (e.g. "Pin 13 has a built-in LED").
8
+ */
9
+ export function analyzeResources(program, strategy) {
10
+ const diagnostics = [];
11
+ const usage = program.peripheralUsage;
12
+ const board = program.boardConstants;
13
+ if (!usage || !board)
14
+ return diagnostics;
15
+ // 1. Build Peripheral Pin Map from board definitions
16
+ const pinMap = buildPeripheralPinMap(board);
17
+ // 2. Track reported conflicts to avoid noise
18
+ const reported = new Set();
19
+ // 3. Check for GPIO vs Peripheral conflicts
20
+ for (const [pinName, functions] of pinMap) {
21
+ const boardPin = findBoardPinByName(pinName, board);
22
+ const pinNumber = boardPin?.number;
23
+ // Check if pin is used as GPIO
24
+ const isGpio = isPinUsedAsGpio(pinName, pinNumber, usage);
25
+ for (const func of functions) {
26
+ const isActive = isPeripheralActive(func.type, func.instance, usage);
27
+ if (isActive && isGpio && func.role !== 'cs') {
28
+ const peripheralName = getPeripheralName(func.type, func.instance);
29
+ const conflictKey = `gpio:${pinName}:${peripheralName}`;
30
+ if (!reported.has(conflictKey)) {
31
+ reported.add(conflictKey);
32
+ const pinRef = formatPinReference(pinName, boardPin);
33
+ const suggestion = generateActionableSuggestion(pinName, peripheralName, func.role, board);
34
+ diagnostics.push({
35
+ severity: 'warning',
36
+ message: `${pinRef} is configured as ${peripheralName} ${func.role.toUpperCase()}. Using it as GPIO may interfere with communication.\n → ${suggestion}`,
37
+ code: 'peripheral-pin-conflict',
38
+ source: 'resource-analysis',
39
+ });
40
+ }
41
+ }
42
+ }
43
+ }
44
+ // 4. Check for Peripheral vs Peripheral conflicts (e.g. I2C0 and SPI0 sharing pins - rare but possible on some boards)
45
+ // This is partially covered by the board-definition logic, but we can detect it here if two active
46
+ // peripherals use the same canonical pin name.
47
+ const activePinsToPeripheral = new Map();
48
+ for (const [pinName, functions] of pinMap) {
49
+ for (const func of functions) {
50
+ if (isPeripheralActive(func.type, func.instance, usage)) {
51
+ const peripheralName = getPeripheralName(func.type, func.instance);
52
+ if (activePinsToPeripheral.has(pinName) && activePinsToPeripheral.get(pinName) !== peripheralName) {
53
+ const other = activePinsToPeripheral.get(pinName);
54
+ const conflictKey = `ppp:${pinName}:${peripheralName}:${other}`;
55
+ if (!reported.has(conflictKey)) {
56
+ reported.add(conflictKey);
57
+ diagnostics.push({
58
+ severity: 'error',
59
+ message: `Hardware Conflict: Pin '${pinName}' is required by both ${peripheralName} and ${other}.`,
60
+ hint: `Move one of the peripherals to different pins if your board supports remapping, or avoid using both simultaneously.`,
61
+ code: 'peripheral-peripheral-conflict',
62
+ source: 'resource-analysis',
63
+ });
64
+ }
65
+ }
66
+ activePinsToPeripheral.set(pinName, peripheralName);
67
+ }
68
+ }
69
+ }
70
+ return diagnostics;
71
+ }
72
+ /**
73
+ * Build a peripheral pin map from board constants.
74
+ */
75
+ function buildPeripheralPinMap(boardConstants) {
76
+ const map = new Map();
77
+ const boardPins = getBoardPins(boardConstants);
78
+ const pinsByCanonicalName = new Map(boardPins.map(pin => [pin.name, pin]));
79
+ function addPin(pinName, func) {
80
+ const boardPin = pinsByCanonicalName.get(pinName);
81
+ const pinNames = boardPin ? [boardPin.name, ...boardPin.aliases] : [pinName];
82
+ for (const resolvedPinName of pinNames) {
83
+ const existing = map.get(resolvedPinName) ?? [];
84
+ existing.push(func);
85
+ map.set(resolvedPinName, existing);
86
+ }
87
+ }
88
+ // Helper to parse "0:sda=A4,scl=A5;1:sda=...,scl=..."
89
+ const parseBusData = (data, type) => {
90
+ if (typeof data !== 'string' || data.length === 0)
91
+ return;
92
+ for (const busStr of data.split(';')) {
93
+ const colonIdx = busStr.indexOf(':');
94
+ if (colonIdx === -1)
95
+ continue;
96
+ const instance = parseInt(busStr.slice(0, colonIdx), 10);
97
+ const pinsStr = busStr.slice(colonIdx + 1);
98
+ for (const pair of pinsStr.split(',')) {
99
+ const eqIdx = pair.indexOf('=');
100
+ if (eqIdx === -1)
101
+ continue;
102
+ const role = pair.slice(0, eqIdx).trim();
103
+ const pinName = pair.slice(eqIdx + 1).trim();
104
+ if (pinName)
105
+ addPin(pinName, { type, instance, role });
106
+ }
107
+ }
108
+ };
109
+ parseBusData(boardConstants.get('pins.i2c'), 'i2c');
110
+ parseBusData(boardConstants.get('pins.spi'), 'spi');
111
+ parseBusData(boardConstants.get('pins.uart'), 'uart');
112
+ return map;
113
+ }
114
+ function isPinUsedAsGpio(pinName, pinNumber, usage) {
115
+ if (usage.pinsUsed.has(pinName))
116
+ return true;
117
+ if (pinNumber !== undefined) {
118
+ if (usage.outputPins.has(pinNumber) || usage.inputPins.has(pinNumber) ||
119
+ usage.inputPullupPins.has(pinNumber) || usage.inputPulldownPins.has(pinNumber)) {
120
+ return true;
121
+ }
122
+ }
123
+ return false;
124
+ }
125
+ function isPeripheralActive(type, instance, usage) {
126
+ switch (type) {
127
+ case 'i2c': return usage.i2c || usage.i2cInstancesUsed.has(instance);
128
+ case 'spi': return usage.spi || usage.spiInstancesUsed.has(instance);
129
+ case 'uart': return usage.uart || usage.uartInstancesUsed.has(instance);
130
+ default: return false;
131
+ }
132
+ }
133
+ function getPeripheralName(type, instance) {
134
+ switch (type) {
135
+ case 'i2c': return `I2C${instance}`;
136
+ case 'spi': return `SPI${instance}`;
137
+ case 'uart': return instance === 0 ? 'Serial' : `Serial${instance}`;
138
+ default: return 'Peripheral';
139
+ }
140
+ }
141
+ function generateActionableSuggestion(pinName, peripheralName, role, board) {
142
+ const roleUpper = role.toUpperCase();
143
+ if (peripheralName.startsWith('Serial')) {
144
+ return `Consider using a different pin for GPIO, or avoid calling ${peripheralName}.begin() if you need ${pinName} as GPIO.`;
145
+ }
146
+ if (roleUpper === 'SDA' || roleUpper === 'SCL') {
147
+ return `I2C requires ${roleUpper} on ${pinName}. Avoid using this pin for GPIO while I2C is active.`;
148
+ }
149
+ if (roleUpper === 'MOSI' || roleUpper === 'MISO' || roleUpper === 'SCK') {
150
+ return `SPI requires ${roleUpper} on ${pinName}. Use a different pin for GPIO, or avoid calling SPI.begin().`;
151
+ }
152
+ return `Avoid initializing ${peripheralName} if you need ${pinName} as GPIO.`;
153
+ }
@@ -0,0 +1,23 @@
1
+ import ts from "typescript";
2
+ import { Diagnostic } from "../types.js";
3
+ import { StatementIR } from "../api/index.js";
4
+ import { CppTypeHint } from "./type-resolution.js";
5
+ import { PointerTracker } from "./build-ir-state.js";
6
+ import { forInitializerToIR, incrementorToIR, lowerControlFlowStatement } from "./transformers/control-flow.js";
7
+ export { forInitializerToIR, incrementorToIR, lowerControlFlowStatement };
8
+ import { tryResolveHALMethod, resolveHALCallForVarInit, tryResolveHALExpression } from "./transformers/hal-call-resolver.js";
9
+ export { tryResolveHALMethod, resolveHALCallForVarInit, tryResolveHALExpression };
10
+ import { prescanArrayUsage, buildInlineForLoop } from "./transformers/array-methods.js";
11
+ export { prescanArrayUsage, buildInlineForLoop };
12
+ import { callToStatement } from "./transformers/call-statement.js";
13
+ export { callToStatement };
14
+ import { assignmentOperatorToString, updateLocalTypeFromAssignment, extractForInKeys, variableStatementToIR, collectPointerVars } from "./transformers/variables.js";
15
+ export { assignmentOperatorToString, updateLocalTypeFromAssignment, extractForInKeys, variableStatementToIR, collectPointerVars };
16
+ export declare function expressionStatementToIR(statement: ts.ExpressionStatement, fileName: string, sourceText: string, diagnostics: Diagnostic[], functionReturnTypes: Map<string, CppTypeHint>, localVariableTypes: Map<string, CppTypeHint>, pointerVars?: PointerTracker): StatementIR | undefined;
17
+ export declare function lowerStatement(statement: ts.Statement, fileName: string, sourceText: string, diagnostics: Diagnostic[], functionReturnTypes: Map<string, CppTypeHint>, localVariableTypes: Map<string, CppTypeHint>, functionNameForDiagnostics: string, typeAliases?: Map<string, ts.TypeNode>, pointerVars?: PointerTracker): StatementIR[] | undefined;
18
+ /**
19
+ * Hoist a nested function declaration to file scope.
20
+ * Creates a mangled name (parent__inner) and registers it in the alias map
21
+ * so that call sites within the parent function get rewritten.
22
+ */
23
+ export declare function lowerStatementList(statements: readonly ts.Statement[] | ts.NodeArray<ts.Statement>, fileName: string, sourceText: string, diagnostics: Diagnostic[], functionReturnTypes: Map<string, CppTypeHint>, localVariableTypes: Map<string, CppTypeHint>, functionNameForDiagnostics: string, typeAliases?: Map<string, ts.TypeNode>, pointerVars?: PointerTracker): StatementIR[];
@@ -0,0 +1,349 @@
1
+ import ts from "typescript";
2
+ import { isStringEnum } from "../api/shared/index.js";
3
+ import { extractNodeComments, makeDiagnostic, makeSourceSpan } from "./ast-node-utils.js";
4
+ import { isCompileTimeOnlyCallName, isCompileTimeOnlyClassName } from "./compile-time-only.js";
5
+ import { TYPED_ARRAY_ELEMENT_MAP, hoistedNestedEnums, hoistedNestedInterfaces, hoistedNestedTypeAliases, nestedFunctionAliases, nestedClassAliases, mutableArrayVars, arrayLiteralSizes, activeEnumNames, activeStringEnumNames, resetFunctionScopeState } from "./build-ir-state.js";
6
+ import { getCurrentIrTypeScope, bindIrTypeScopeLocals } from "./symbol-types.js";
7
+ import { renderExprAsText } from "./render-expr.js";
8
+ import { expressionToIR } from "./expression-to-ir.js";
9
+ import { enumDeclarationToIR, interfaceDeclarationToIR, typeAliasDeclarationToIR } from "./declaration-builders.js";
10
+ import { forInitializerToIR, incrementorToIR, lowerControlFlowStatement } from "./transformers/control-flow.js";
11
+ export { forInitializerToIR, incrementorToIR, lowerControlFlowStatement };
12
+ import { expressionStatementToIR as delegateExpressionStatementToIR } from "./transformers/expressions.js";
13
+ import { tryResolveHALMethod, resolveHALCallForVarInit, tryResolveHALExpression } from "./transformers/hal-call-resolver.js";
14
+ import { resolveElementValue } from "./transformers/ui-call-resolver.js";
15
+ export { tryResolveHALMethod, resolveHALCallForVarInit, tryResolveHALExpression };
16
+ import { hoistNestedFunction, hoistNestedClass } from "./function-builder.js";
17
+ import { prescanArrayUsage, buildInlineForLoop } from "./transformers/array-methods.js";
18
+ export { prescanArrayUsage, buildInlineForLoop };
19
+ import { callToStatement } from "./transformers/call-statement.js";
20
+ export { callToStatement };
21
+ import { assignmentOperatorToString, updateLocalTypeFromAssignment, extractForInKeys, variableStatementToIR, collectPointerVars } from "./transformers/variables.js";
22
+ export { assignmentOperatorToString, updateLocalTypeFromAssignment, extractForInKeys, variableStatementToIR, collectPointerVars };
23
+ export function expressionStatementToIR(statement, fileName, sourceText, diagnostics, functionReturnTypes, localVariableTypes, pointerVars = new Map()) {
24
+ return delegateExpressionStatementToIR(statement, fileName, sourceText, diagnostics, functionReturnTypes, localVariableTypes, pointerVars);
25
+ }
26
+ export function lowerStatement(statement, fileName, sourceText, diagnostics, functionReturnTypes, localVariableTypes, functionNameForDiagnostics, typeAliases, pointerVars = new Map()) {
27
+ if (ts.isExpressionStatement(statement)) {
28
+ // Handle arr.forEach(arrowFn) as a standalone statement → inline loop
29
+ if (ts.isCallExpression(statement.expression) &&
30
+ ts.isPropertyAccessExpression(statement.expression.expression) &&
31
+ statement.expression.expression.name.text === "forEach" &&
32
+ ts.isIdentifier(statement.expression.expression.expression)) {
33
+ const srcName = statement.expression.expression.expression.text;
34
+ const srcSize = arrayLiteralSizes.get(srcName);
35
+ const arrowFn = statement.expression.arguments[0];
36
+ if (srcSize !== undefined && arrowFn && (ts.isArrowFunction(arrowFn) || ts.isFunctionExpression(arrowFn))) {
37
+ const param = arrowFn.parameters[0];
38
+ const paramName = param && ts.isIdentifier(param.name) ? param.name.text : "__x";
39
+ const span = makeSourceSpan(statement, fileName, sourceText);
40
+ const comments = extractNodeComments(statement, sourceText);
41
+ if (!ts.isBlock(arrowFn.body)) {
42
+ // Expression body
43
+ const bodyIR = expressionToIR(arrowFn.body, sourceText, diagnostics);
44
+ return [{
45
+ kind: "for",
46
+ sourceSpan: span,
47
+ leadingComments: comments.leadingComments,
48
+ trailingComments: comments.trailingComments,
49
+ initializer: { kind: "var_decl", sourceSpan: span, name: "__tc_i", storage: "let", cppType: "int", initializer: { kind: "number", value: 0 } },
50
+ condition: { kind: "binary", left: { kind: "identifier", value: "__tc_i" }, operator: "<", right: { kind: "number", value: srcSize } },
51
+ increment: { kind: "update", sourceSpan: span, target: "__tc_i", operator: "++", prefix: false },
52
+ body: [
53
+ { kind: "var_decl", sourceSpan: span, name: paramName, storage: "const", cppType: "auto",
54
+ initializer: { kind: "raw", value: `${srcName}[__tc_i]` } },
55
+ { kind: "var_decl", sourceSpan: span, name: "__tc_result", storage: "let", cppType: "auto", initializer: bodyIR },
56
+ ],
57
+ }];
58
+ }
59
+ else {
60
+ // Block body — lower statements and prepend param decl
61
+ const blockStatements = lowerStatementList(arrowFn.body.statements, fileName, sourceText, diagnostics, functionReturnTypes, localVariableTypes, functionNameForDiagnostics, typeAliases, pointerVars);
62
+ return [{
63
+ kind: "for",
64
+ sourceSpan: span,
65
+ leadingComments: comments.leadingComments,
66
+ trailingComments: comments.trailingComments,
67
+ initializer: { kind: "var_decl", sourceSpan: span, name: "__tc_i", storage: "let", cppType: "int", initializer: { kind: "number", value: 0 } },
68
+ condition: { kind: "binary", left: { kind: "identifier", value: "__tc_i" }, operator: "<", right: { kind: "number", value: srcSize } },
69
+ increment: { kind: "update", sourceSpan: span, target: "__tc_i", operator: "++", prefix: false },
70
+ body: [
71
+ { kind: "var_decl", sourceSpan: span, name: paramName, storage: "const", cppType: "auto",
72
+ initializer: { kind: "raw", value: `${srcName}[__tc_i]` } },
73
+ ...blockStatements,
74
+ ],
75
+ }];
76
+ }
77
+ }
78
+ }
79
+ // Check for compile-time-only calls first (e.g., registerPlatformStrategy())
80
+ // These are registration calls that don't need C++ emission
81
+ if (ts.isCallExpression(statement.expression)) {
82
+ const call = statement.expression;
83
+ if (ts.isIdentifier(call.expression)) {
84
+ const calleeName = call.expression.text;
85
+ if (isCompileTimeOnlyCallName(calleeName)) {
86
+ return []; // Skip silently - no C++ emission needed
87
+ }
88
+ }
89
+ // Also check for method calls like "something.register()" that are compile-time only
90
+ if (ts.isPropertyAccessExpression(call.expression)) {
91
+ const method = call.expression.name.text;
92
+ if (isCompileTimeOnlyCallName(method)) {
93
+ return [];
94
+ }
95
+ }
96
+ }
97
+ // Check for new expressions that are compile-time only (e.g., new NativeStrategy())
98
+ if (ts.isNewExpression(statement.expression)) {
99
+ // New expressions at top level in board packages are typically compile-time only
100
+ // Check if it's a known strategy type
101
+ if (ts.isIdentifier(statement.expression.expression)) {
102
+ const className = statement.expression.expression.text;
103
+ if (isCompileTimeOnlyClassName(className)) {
104
+ return []; // Skip silently
105
+ }
106
+ }
107
+ }
108
+ // ── UI element .value write: screen.led.value = 1 ────────────────────
109
+ // Lowers to __ui_nodes[N].value = X; ui_mark_dirty(N);
110
+ if (ts.isBinaryExpression(statement.expression) &&
111
+ statement.expression.operatorToken.kind === ts.SyntaxKind.EqualsToken &&
112
+ ts.isPropertyAccessExpression(statement.expression.left) &&
113
+ statement.expression.left.name.text === "value" &&
114
+ ts.isPropertyAccessExpression(statement.expression.left.expression) &&
115
+ ts.isIdentifier(statement.expression.left.expression.expression)) {
116
+ const treeName = statement.expression.left.expression.expression.text;
117
+ const elemId = statement.expression.left.expression.name.text;
118
+ const nodeIdx = resolveElementValue(treeName, elemId);
119
+ if (nodeIdx !== undefined) {
120
+ const valIR = expressionToIR(statement.expression.right, sourceText, diagnostics, pointerVars);
121
+ const valText = renderExprAsText(valIR);
122
+ return [{
123
+ kind: "call",
124
+ sourceSpan: makeSourceSpan(statement, fileName, sourceText),
125
+ callee: `__RAW_STMT____ui_nodes[${nodeIdx}].value = ${valText}; ui_mark_dirty(${nodeIdx});`,
126
+ args: [],
127
+ }];
128
+ }
129
+ }
130
+ // ── UI element .text write: screen.ssid.text = "x" ──────────────────
131
+ // Lowers to strncpy(__ui_nodes[N].textBuffer, "x", UI_TEXT_BUF);
132
+ // __ui_nodes[N].textBuffer[UI_TEXT_BUF] = 0; ui_mark_dirty(N);
133
+ if (ts.isBinaryExpression(statement.expression) &&
134
+ statement.expression.operatorToken.kind === ts.SyntaxKind.EqualsToken &&
135
+ ts.isPropertyAccessExpression(statement.expression.left) &&
136
+ statement.expression.left.name.text === "text" &&
137
+ ts.isPropertyAccessExpression(statement.expression.left.expression) &&
138
+ ts.isIdentifier(statement.expression.left.expression.expression)) {
139
+ const treeName = statement.expression.left.expression.expression.text;
140
+ const elemId = statement.expression.left.expression.name.text;
141
+ const nodeIdx = resolveElementValue(treeName, elemId);
142
+ if (nodeIdx !== undefined) {
143
+ const valIR = expressionToIR(statement.expression.right, sourceText, diagnostics, pointerVars);
144
+ const valText = renderExprAsText(valIR);
145
+ return [{
146
+ kind: "call",
147
+ sourceSpan: makeSourceSpan(statement, fileName, sourceText),
148
+ callee: `__RAW_STMT__strncpy(__ui_nodes[${nodeIdx}].textBuffer, ${valText}, UI_TEXT_BUF); __ui_nodes[${nodeIdx}].textBuffer[UI_TEXT_BUF] = 0; ui_mark_dirty(${nodeIdx});`,
149
+ args: [],
150
+ }];
151
+ }
152
+ }
153
+ const loweredExpression = expressionStatementToIR(statement, fileName, sourceText, diagnostics, functionReturnTypes, localVariableTypes, pointerVars);
154
+ return loweredExpression ? [loweredExpression] : undefined;
155
+ }
156
+ if (ts.isVariableStatement(statement)) {
157
+ return variableStatementToIR(statement, fileName, sourceText, diagnostics, functionReturnTypes, localVariableTypes, typeAliases, pointerVars, functionNameForDiagnostics, lowerStatementList);
158
+ }
159
+ const controlFlowLowered = lowerControlFlowStatement(statement, fileName, sourceText, diagnostics, functionReturnTypes, localVariableTypes, functionNameForDiagnostics, typeAliases, pointerVars);
160
+ if (controlFlowLowered !== null) {
161
+ return controlFlowLowered;
162
+ }
163
+ diagnostics.push(makeDiagnostic(sourceText, statement.pos, `Unsupported statement in function '${functionNameForDiagnostics}'.`, "error", "TS2CPP_UNSUPPORTED_STMT"));
164
+ return undefined;
165
+ }
166
+ /**
167
+ * Hoist a nested function declaration to file scope.
168
+ * Creates a mangled name (parent__inner) and registers it in the alias map
169
+ * so that call sites within the parent function get rewritten.
170
+ */
171
+ // ---------------------------------------------------------------------------
172
+ // Array method pre-scan
173
+ // ---------------------------------------------------------------------------
174
+ // Methods that require StaticArray promotion (not all are mutating — indexOf is read-only
175
+ // but needs StaticArray since C arrays don't have an indexOf method).
176
+ export function lowerStatementList(statements, fileName, sourceText, diagnostics, functionReturnTypes, localVariableTypes, functionNameForDiagnostics, typeAliases, pointerVars = new Map()) {
177
+ const lowered = [];
178
+ const nestedNames = [];
179
+ const nestedClassNames = [];
180
+ // Phase 1: Pre-scan for nested function declarations — register aliases only.
181
+ // This ensures sibling functions can reference each other.
182
+ for (const statement of statements) {
183
+ if (ts.isFunctionDeclaration(statement) && statement.name) {
184
+ const originalName = statement.name.text;
185
+ const safeParentName = functionNameForDiagnostics.replace(/\./g, "_");
186
+ const mangledName = `${safeParentName}__${originalName}`;
187
+ nestedFunctionAliases.set(originalName, mangledName);
188
+ nestedNames.push(originalName);
189
+ }
190
+ if (ts.isClassDeclaration(statement) && statement.name) {
191
+ const originalName = statement.name.text;
192
+ const safeParentName = functionNameForDiagnostics.replace(/\./g, "_");
193
+ if (safeParentName) {
194
+ const mangledName = `${safeParentName}__${originalName}`;
195
+ nestedClassAliases.set(originalName, mangledName);
196
+ nestedClassNames.push(originalName);
197
+ }
198
+ }
199
+ }
200
+ // Phase 1.5: Collect local type aliases into the shared map so that
201
+ // nested function return types can resolve generic mapped types etc.
202
+ if (typeAliases) {
203
+ for (const statement of statements) {
204
+ if (ts.isTypeAliasDeclaration(statement)) {
205
+ typeAliases.set(statement.name.text, statement.type);
206
+ }
207
+ }
208
+ }
209
+ // Phase 1.6: Pre-scan for enum declarations (top-level within this scope and
210
+ // nested inside functions) so that string-concat chain detection during
211
+ // lowering knows which enum-typed variables are string-bearing (string enums
212
+ // lower to const char*). Must run BEFORE hoisting/lowers.
213
+ for (const statement of statements) {
214
+ const collectEnums = (node) => {
215
+ if (ts.isEnumDeclaration(node) && node.name) {
216
+ activeEnumNames.add(node.name.text);
217
+ // Determine string-enum-ness from the declaration.
218
+ let allString = true;
219
+ let any = false;
220
+ for (const member of node.members) {
221
+ if (member.initializer && ts.isStringLiteral(member.initializer)) {
222
+ any = true;
223
+ }
224
+ else if (member.initializer && !ts.isStringLiteral(member.initializer)) {
225
+ allString = false;
226
+ }
227
+ else {
228
+ allString = false;
229
+ }
230
+ }
231
+ if (any && allString) {
232
+ activeStringEnumNames.add(node.name.text);
233
+ }
234
+ }
235
+ };
236
+ collectEnums(statement);
237
+ ts.forEachChild(statement, collectEnums);
238
+ }
239
+ // Phase 2: Hoist nested functions (process their bodies).
240
+ for (const statement of statements) {
241
+ if (ts.isFunctionDeclaration(statement) && statement.name) {
242
+ hoistNestedFunction(statement, fileName, sourceText, diagnostics, functionReturnTypes, functionNameForDiagnostics, typeAliases, pointerVars, lowerStatementList);
243
+ }
244
+ }
245
+ // Phase 2.5: Hoist nested class declarations.
246
+ for (const statement of statements) {
247
+ if (ts.isClassDeclaration(statement) && statement.name) {
248
+ hoistNestedClass(statement, fileName, sourceText, diagnostics, functionReturnTypes, functionNameForDiagnostics, typeAliases, pointerVars, lowerStatementList);
249
+ }
250
+ }
251
+ // Phase 2.6: Hoist nested enum declarations.
252
+ for (const statement of statements) {
253
+ if (ts.isEnumDeclaration(statement)) {
254
+ const enumIR = enumDeclarationToIR(statement, fileName, sourceText);
255
+ if (enumIR && !hoistedNestedEnums.some(e => e.name === enumIR.name)) {
256
+ hoistedNestedEnums.push(enumIR);
257
+ // Register string-enum-ness so concat-chain detection (expression-to-ir)
258
+ // recognizes variables of this type as string-bearing.
259
+ if (isStringEnum(enumIR)) {
260
+ activeStringEnumNames.add(enumIR.name);
261
+ }
262
+ }
263
+ }
264
+ }
265
+ // Phase 2.6b: Hoist local interface and type alias declarations.
266
+ // These are type-only but needed for C++ struct generation when used as return types.
267
+ const scopeName = functionNameForDiagnostics
268
+ ? `${functionNameForDiagnostics.replace(/\./g, "_")}__types`
269
+ : undefined;
270
+ for (const statement of statements) {
271
+ if (ts.isInterfaceDeclaration(statement) && statement.name) {
272
+ const ifaceIR = interfaceDeclarationToIR(statement, fileName, sourceText, typeAliases ?? new Map());
273
+ if (ifaceIR && !hoistedNestedInterfaces.some(i => i.name === ifaceIR.name)) {
274
+ if (scopeName)
275
+ ifaceIR.parentScope = scopeName;
276
+ hoistedNestedInterfaces.push(ifaceIR);
277
+ }
278
+ }
279
+ if (ts.isTypeAliasDeclaration(statement)) {
280
+ const aliasIR = typeAliasDeclarationToIR(statement, fileName, sourceText, typeAliases ?? new Map());
281
+ if (aliasIR && !hoistedNestedTypeAliases.some(a => a.name === aliasIR.name)) {
282
+ hoistedNestedTypeAliases.push(aliasIR);
283
+ }
284
+ }
285
+ }
286
+ // Collect pointer variables from this scope (vars initialized with 'new')
287
+ const scopePointerVars = new Map();
288
+ for (const statement of statements) {
289
+ if (ts.isVariableStatement(statement)) {
290
+ for (const decl of statement.declarationList.declarations) {
291
+ if (ts.isIdentifier(decl.name) && decl.initializer && ts.isNewExpression(decl.initializer)) {
292
+ const ctorText = decl.initializer.expression && ts.isIdentifier(decl.initializer.expression)
293
+ ? decl.initializer.expression.text : "";
294
+ if (!TYPED_ARRAY_ELEMENT_MAP[ctorText]) {
295
+ scopePointerVars.set(decl.name.text, ctorText);
296
+ }
297
+ }
298
+ }
299
+ }
300
+ }
301
+ // Phase 2.7: Pre-scan for array methods requiring StaticArray promotion.
302
+ // Clear function-scoped state so variables from previous functions don't leak,
303
+ // but preserve file-level mutable array tracking (populated by build-ir.ts pre-scan).
304
+ const savedMutableArrayVars = new Set(mutableArrayVars);
305
+ const savedArrayLiteralSizes = new Map(arrayLiteralSizes);
306
+ resetFunctionScopeState();
307
+ for (const v of savedMutableArrayVars)
308
+ mutableArrayVars.add(v);
309
+ for (const [k, v] of savedArrayLiteralSizes)
310
+ arrayLiteralSizes.set(k, v);
311
+ // resetFunctionScopeState re-seeded scope.locals from classFields. Now bind
312
+ // the threaded localVariableTypes map as the scope's locals storage (folding
313
+ // both the re-seeded classFields entries and any entries the threaded map
314
+ // already carried, e.g. function parameters). After this, the threaded
315
+ // `localVariableTypes` param and getCurrentIrTypeScope().locals are the SAME
316
+ // Map, so writes through either are visible to both — eliminating the old
317
+ // shadow-sync that copied localVariableTypes into the global activeLocalTypes.
318
+ const scope = getCurrentIrTypeScope();
319
+ if (scope) {
320
+ bindIrTypeScopeLocals(scope, localVariableTypes);
321
+ }
322
+ for (const statement of statements) {
323
+ prescanArrayUsage(statement);
324
+ }
325
+ // Phase 3: Process remaining (non-function, non-class) statements.
326
+ for (const statement of statements) {
327
+ if (ts.isFunctionDeclaration(statement)) {
328
+ continue; // Already hoisted
329
+ }
330
+ if (ts.isClassDeclaration(statement)) {
331
+ continue; // Already hoisted
332
+ }
333
+ if (ts.isEnumDeclaration(statement)) {
334
+ continue; // Already hoisted
335
+ }
336
+ const result = lowerStatement(statement, fileName, sourceText, diagnostics, functionReturnTypes, localVariableTypes, functionNameForDiagnostics, typeAliases, scopePointerVars);
337
+ if (result) {
338
+ lowered.push(...result);
339
+ }
340
+ }
341
+ // Phase 4: Clean up aliases so they don't leak to sibling scopes.
342
+ for (const name of nestedNames) {
343
+ nestedFunctionAliases.delete(name);
344
+ }
345
+ for (const name of nestedClassNames) {
346
+ nestedClassAliases.delete(name);
347
+ }
348
+ return lowered;
349
+ }
@@ -0,0 +1,68 @@
1
+ import type { ProgramIR } from "../api/index.js";
2
+ /**
3
+ * Per-class accessor map: member name → whether it is a getter, setter, or
4
+ * both. Keyed by class name, matching the old allClassAccessors shape.
5
+ */
6
+ export type ClassAccessors = Map<string, "getter" | "setter" | "both">;
7
+ export interface SymbolTable {
8
+ /** className/interfaceName → fieldName → cppType. Replaces allClassFieldTypes
9
+ * and the per-file interfaceFieldTypes cross-module portion. Includes
10
+ * extendsClass-inherited fields once resolveInheritance runs. */
11
+ classFieldTypes: Map<string, Map<string, string>>;
12
+ /** className → accessor map. Replaces allClassAccessors. */
13
+ classAccessors: Map<string, ClassAccessors>;
14
+ /** function name → return cppType. Replaces allFunctionReturnTypes. */
15
+ functionReturnTypes: Map<string, string>;
16
+ /** top-level variable name → cppType (non-"auto" only). Replaces
17
+ * allVariableTypes. */
18
+ variableTypes: Map<string, string>;
19
+ /** All class names across the aggregated files. Replaces allClassNames. */
20
+ classNames: Set<string>;
21
+ /** className → parent class name (the `extends X` target). Needed by
22
+ * resolveInheritance to copy parent fields into children; not present in
23
+ * the old ad-hoc maps (it was read from programIR.classes in the second
24
+ * pass) so it is retained here to keep inheritance resolvable from the
25
+ * aggregated table alone. */
26
+ extends: Map<string, string>;
27
+ }
28
+ export declare function createSymbolTable(): SymbolTable;
29
+ /**
30
+ * Build a SymbolTable from a single file's ProgramIR. This is the per-file
31
+ * view; cross-file aggregation is done by mergeSymbolTable.
32
+ *
33
+ * Mirrors the old transpile.ts:612-666 first pass:
34
+ * - class fields, interface fields, accessors, function return types, and
35
+ * non-"auto" top-level variable types are collected
36
+ * - extendsClass relationships are recorded for the post-merge inheritance
37
+ * pass (the old code read them from programIR.classes directly)
38
+ * Accessor kind merge rule: getter+setter on the same name → "both".
39
+ *
40
+ * Does NOT fold parent fields into children yet — that happens once, after
41
+ * all files are merged, in resolveInheritance (mirroring the old two-pass
42
+ * structure where the second pass ran after the first pass over all files).
43
+ */
44
+ export declare function buildSymbolTable(program: ProgramIR): SymbolTable;
45
+ /**
46
+ * Fold one SymbolTable into an accumulating cross-module table. This is the
47
+ * merge used during Pass 1 of transpile.ts to build the cross-file view from
48
+ * every file's per-file table.
49
+ *
50
+ * Field-type and accessor entries are merged (later files add to existing
51
+ * class entries); function return types and variable types are last-write-wins
52
+ * (matching the old Map.set behavior); class names are unioned; extends
53
+ * relationships are last-write-wins.
54
+ */
55
+ export declare function mergeSymbolTable(target: SymbolTable, source: SymbolTable): SymbolTable;
56
+ /**
57
+ * Apply extendsClass field inheritance across an aggregated SymbolTable.
58
+ * Mirrors the old transpile.ts:668-688 SECOND pass: for each class that
59
+ * extends a parent present in the table, copy any parent fields the child does
60
+ * not already declare. Must run AFTER all files have been merged so cross-file
61
+ * parents are visible.
62
+ *
63
+ * Merge rule (preserved exactly): `!childFields.has(fname)` — a child's own
64
+ * field declaration wins over the parent's. If the child has no field entry at
65
+ * all but the parent does, a fresh entry seeded entirely from the parent is
66
+ * created (mirroring the old `else if (parentFields && !childFields)` branch).
67
+ */
68
+ export declare function resolveInheritance(table: SymbolTable): void;