@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,62 @@
1
+ import ts from "typescript";
2
+ import { Diagnostic } from "../../types.js";
3
+ import { type CallbackContextId } from "./callback-context-registry.js";
4
+ import type { ExpressionIR, StatementIR } from "../../api/shared/ir-core.js";
5
+ /** Rewrite CSS color string literals in a rendered C++ expression. Prefer
6
+ * resolveColorIR on IR for new code. */
7
+ export declare function resolveColorLiterals(raw: string): string;
8
+ /** Walk an ExpressionIR tree and rewrite CSS color string-literal nodes into
9
+ * raw hex nodes the ExpressionRenderer emits as a bare int. */
10
+ export declare function resolveColorIR(expr: ExpressionIR): ExpressionIR;
11
+ /** Apply resolveColorIR across every expression nested in a StatementIR tree.
12
+ * When a var_decl's initializer fully resolves to color hex, retarget its
13
+ * cppType to the display color int. */
14
+ export declare function resolveColorsInStatements(statements: StatementIR[]): StatementIR[];
15
+ /** Recursively rename identifiers in a StatementIR tree (e.g. bindInput
16
+ * param → `text`, list tap param → `idx`). */
17
+ export declare function renameIdentifiersInStatements(statements: StatementIR[], from: string, to: string): StatementIR[];
18
+ export declare function noteConsoleInCallback(): void;
19
+ export declare function loweredConsoleInCallback(): boolean;
20
+ export declare function resetCallbackLoweringState(): void;
21
+ export declare function beginCanvasAmbient(ctxName: string, diagnostics: Diagnostic[], sourceText: string): void;
22
+ export declare function endCanvasAmbient(): void;
23
+ export declare function getCanvasAmbientCtx(): string | null;
24
+ export declare function getCanvasAmbientDiagnostics(): Diagnostic[] | null;
25
+ export declare function getCanvasAmbientSourceText(): string | null;
26
+ /**
27
+ * Lower a single callback-body expression to a C++ string (no trailing `;`).
28
+ * Used for concise arrow bodies and as a compact-render fallback. Block bodies
29
+ * go through lowerStatementList instead.
30
+ */
31
+ export declare function lowerCallbackExpr(expr: ts.Expression, sourceText: string, diagnostics: Diagnostic[]): string;
32
+ /**
33
+ * Lower an arrow/function-expression callback body to StatementIR[] through
34
+ * the same lowerStatementList path setInterval uses.
35
+ */
36
+ export declare function lowerCallbackStatements(cbArg: ts.ArrowFunction | ts.FunctionExpression, fileName: string, sourceText: string, diagnostics: Diagnostic[], contextId?: CallbackContextId): StatementIR[];
37
+ export type ResolvedCallbackArg = {
38
+ kind: "inline";
39
+ fn: ts.ArrowFunction | ts.FunctionExpression;
40
+ } | {
41
+ kind: "named";
42
+ name: string;
43
+ };
44
+ /** Resolve a UI callback arg to an inline arrow or a named free-function ref.
45
+ * Unresolvable identifiers produce a fatal diagnostic (fail closed). */
46
+ export declare function resolveCallbackArg(cbArg: ts.Expression | undefined, sourceFile: ts.SourceFile | undefined, diagnostics: Diagnostic[], label: string): ResolvedCallbackArg | undefined;
47
+ /**
48
+ * Resolve + lower a callback when the C++ wrapper signature may differ from
49
+ * the author's function (bindInput, list tap). Returns statements + param
50
+ * names for IR-level rename.
51
+ */
52
+ export declare function lowerNamedOrInlineCallback(cbArg: ts.Expression | undefined, fileName: string, sourceText: string, diagnostics: Diagnostic[], label: string, contextId?: CallbackContextId): {
53
+ statements: StatementIR[];
54
+ paramNames: string[];
55
+ } | undefined;
56
+ export declare function renderStatementsCompact(statements: StatementIR[]): string;
57
+ /**
58
+ * Lower an arrow/function-expression callback's body to a single C++ string.
59
+ * Routes through lowerCallbackStatements then compact-renders. Prefer storing
60
+ * bodyStatements on the handler spec and rendering at emit time.
61
+ */
62
+ export declare function lowerCallbackBody(cbArg: ts.ArrowFunction | ts.FunctionExpression, sourceText: string, diagnostics: Diagnostic[], contextId?: CallbackContextId, fileName?: string): string;
@@ -0,0 +1,623 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Shared lowering for UI callback bodies (onToggle, watchPin, onClick, …).
3
+ //
4
+ // Author callbacks lower through lowerStatementList (same IR the rest of the
5
+ // program uses) and are rendered at emit time by StatementRenderer /
6
+ // appendRenderedStatement. The old string-baking second pipeline is gone.
7
+ //
8
+ // UI-specific behaviour that still happens here:
9
+ // - signal.set(value) → assign (already in callToStatement)
10
+ // - signal() → identifier (already in expressionToIR)
11
+ // - console.* → platform transform (already at emit via StatementRenderer)
12
+ // - CSS color string literals → rgb int (resolveColorIR walk on the IR)
13
+ // - canvas ctx.* → ui_display_* (ambient canvas ctx + rewriteCanvasCall)
14
+ // ---------------------------------------------------------------------------
15
+ import ts from "typescript";
16
+ import { expressionToIR } from "../expression-to-ir.js";
17
+ import { renderExprAsText } from "../render-expr.js";
18
+ import { requireUIHook } from "../../ui-hook.js";
19
+ import { getDisplayProfile } from "../../stores/display-profile-store.js";
20
+ import { getContext } from "../build-ir-state.js";
21
+ import { makeSourceSpan } from "../ast-node-utils.js";
22
+ import { lowerStatementList } from "../statement-to-ir.js";
23
+ import { callbackContextLabel, unsupportedStatementHint, } from "./callback-context-registry.js";
24
+ import { isSignalName } from "./ui-call-resolver.js";
25
+ import { rewriteCanvasCall } from "./canvas-lowering.js";
26
+ import { resolveStrategy } from "../../platform/registry.js";
27
+ import { StatementRenderer } from "../../emit/statement-renderer.js";
28
+ import { createEmissionScopeState } from "../../emit/snprintf-helpers.js";
29
+ import { getCurrentIrTypeScope } from "../symbol-types.js";
30
+ // ── Color-literal resolution ───────────────────────────────────────────────
31
+ const COLOR_LITERAL_RE = /"(#[0-9a-fA-F]{8}|#[0-9a-fA-F]{6}|#[0-9a-fA-F]{3}|(rgb|rgba|hsl|hsla)\([^)]*\)|[A-Za-z]+)"/g;
32
+ /** Rewrite CSS color string literals in a rendered C++ expression. Prefer
33
+ * resolveColorIR on IR for new code. */
34
+ export function resolveColorLiterals(raw) {
35
+ const fmt = getDisplayProfile().colorFormat;
36
+ const resolveColorInternal = requireUIHook().resolveColorInternal;
37
+ return raw.replace(COLOR_LITERAL_RE, (match, color) => {
38
+ try {
39
+ return `0x${resolveColorInternal(color, fmt).toString(16)}`;
40
+ }
41
+ catch {
42
+ return match;
43
+ }
44
+ });
45
+ }
46
+ /** Walk an ExpressionIR tree and rewrite CSS color string-literal nodes into
47
+ * raw hex nodes the ExpressionRenderer emits as a bare int. */
48
+ export function resolveColorIR(expr) {
49
+ const fmt = getDisplayProfile().colorFormat;
50
+ const resolveColorInternal = requireUIHook().resolveColorInternal;
51
+ const walk = (e) => {
52
+ if (e.kind === "string") {
53
+ try {
54
+ const hex = resolveColorInternal(e.value, fmt);
55
+ return { kind: "raw", value: `0x${hex.toString(16)}` };
56
+ }
57
+ catch {
58
+ return e;
59
+ }
60
+ }
61
+ if (e.kind === "ternary") {
62
+ return {
63
+ ...e,
64
+ condition: walk(e.condition),
65
+ whenTrue: walk(e.whenTrue),
66
+ whenFalse: walk(e.whenFalse),
67
+ };
68
+ }
69
+ if (e.kind === "binary")
70
+ return { ...e, left: walk(e.left), right: walk(e.right) };
71
+ if (e.kind === "unary")
72
+ return { ...e, operand: walk(e.operand) };
73
+ if (e.kind === "string_concat")
74
+ return { ...e, parts: e.parts.map(walk) };
75
+ if (e.kind === "template_string")
76
+ return { ...e, expression: walk(e.expression) };
77
+ if (e.kind === "method-call")
78
+ return { ...e, args: e.args.map(walk) };
79
+ if (e.kind === "property-access")
80
+ return { ...e, object: walk(e.object) };
81
+ if (e.kind === "element-access") {
82
+ return { ...e, object: walk(e.object), index: walk(e.index) };
83
+ }
84
+ if (e.kind === "array")
85
+ return { ...e, elements: e.elements.map(walk) };
86
+ if (e.kind === "object") {
87
+ return { ...e, fields: e.fields.map((f) => ({ ...f, value: walk(f.value) })) };
88
+ }
89
+ if (e.kind === "await")
90
+ return { ...e, value: walk(e.value) };
91
+ if (e.kind === "paren")
92
+ return { ...e, inner: walk(e.inner) };
93
+ return e;
94
+ };
95
+ return walk(expr);
96
+ }
97
+ /** Apply resolveColorIR across every expression nested in a StatementIR tree.
98
+ * When a var_decl's initializer fully resolves to color hex, retarget its
99
+ * cppType to the display color int. */
100
+ export function resolveColorsInStatements(statements) {
101
+ const walkExpr = (e) => (e ? resolveColorIR(e) : undefined);
102
+ const isColorHexExpr = (e) => {
103
+ if (e.kind === "raw" && /^0x[0-9a-fA-F]+$/.test(e.value.trim()))
104
+ return true;
105
+ if (e.kind === "ternary")
106
+ return isColorHexExpr(e.whenTrue) && isColorHexExpr(e.whenFalse);
107
+ if (e.kind === "paren")
108
+ return isColorHexExpr(e.inner);
109
+ return false;
110
+ };
111
+ const colorCppType = () => {
112
+ const fmt = getDisplayProfile().colorFormat;
113
+ return fmt === "rgb888" || fmt === "rgb666" ? "uint32_t" : "uint16_t";
114
+ };
115
+ const walk = (s) => {
116
+ switch (s.kind) {
117
+ case "var_decl": {
118
+ const initializer = walkExpr(s.initializer);
119
+ if (initializer && isColorHexExpr(initializer)) {
120
+ return { ...s, initializer, cppType: colorCppType() };
121
+ }
122
+ return { ...s, initializer };
123
+ }
124
+ case "assign":
125
+ return { ...s, value: resolveColorIR(s.value) };
126
+ case "call":
127
+ return { ...s, args: s.args.map(resolveColorIR) };
128
+ case "return":
129
+ return { ...s, value: walkExpr(s.value) };
130
+ case "if":
131
+ return {
132
+ ...s,
133
+ condition: resolveColorIR(s.condition),
134
+ thenBranch: s.thenBranch.map(walk),
135
+ elseBranch: s.elseBranch?.map(walk),
136
+ };
137
+ case "while":
138
+ case "do_while":
139
+ return { ...s, condition: resolveColorIR(s.condition), body: s.body.map(walk) };
140
+ case "for":
141
+ return {
142
+ ...s,
143
+ initializer: s.initializer ? walk(s.initializer) : undefined,
144
+ condition: walkExpr(s.condition),
145
+ increment: s.increment ? walk(s.increment) : undefined,
146
+ body: s.body.map(walk),
147
+ };
148
+ case "block":
149
+ return { ...s, body: s.body.map(walk) };
150
+ default:
151
+ return s;
152
+ }
153
+ };
154
+ return statements.map(walk);
155
+ }
156
+ /** Recursively rename identifiers in a StatementIR tree (e.g. bindInput
157
+ * param → `text`, list tap param → `idx`). */
158
+ export function renameIdentifiersInStatements(statements, from, to) {
159
+ if (from === to)
160
+ return statements;
161
+ const renameExpr = (e) => {
162
+ if (e.kind === "identifier" && e.value === from)
163
+ return { ...e, value: to };
164
+ if (e.kind === "ternary") {
165
+ return {
166
+ ...e,
167
+ condition: renameExpr(e.condition),
168
+ whenTrue: renameExpr(e.whenTrue),
169
+ whenFalse: renameExpr(e.whenFalse),
170
+ };
171
+ }
172
+ if (e.kind === "binary")
173
+ return { ...e, left: renameExpr(e.left), right: renameExpr(e.right) };
174
+ if (e.kind === "unary")
175
+ return { ...e, operand: renameExpr(e.operand) };
176
+ if (e.kind === "string_concat")
177
+ return { ...e, parts: e.parts.map(renameExpr) };
178
+ if (e.kind === "template_string")
179
+ return { ...e, expression: renameExpr(e.expression) };
180
+ if (e.kind === "method-call")
181
+ return { ...e, args: e.args.map(renameExpr) };
182
+ if (e.kind === "property-access")
183
+ return { ...e, object: renameExpr(e.object) };
184
+ if (e.kind === "element-access") {
185
+ return { ...e, object: renameExpr(e.object), index: renameExpr(e.index) };
186
+ }
187
+ if (e.kind === "array")
188
+ return { ...e, elements: e.elements.map(renameExpr) };
189
+ if (e.kind === "object") {
190
+ return { ...e, fields: e.fields.map((f) => ({ ...f, value: renameExpr(f.value) })) };
191
+ }
192
+ if (e.kind === "raw" && e.value === from)
193
+ return { kind: "identifier", value: to };
194
+ if (e.kind === "await")
195
+ return { ...e, value: renameExpr(e.value) };
196
+ if (e.kind === "paren")
197
+ return { ...e, inner: renameExpr(e.inner) };
198
+ return e;
199
+ };
200
+ const renameStmt = (s) => {
201
+ switch (s.kind) {
202
+ case "var_decl":
203
+ return {
204
+ ...s,
205
+ name: s.name === from ? to : s.name,
206
+ initializer: s.initializer ? renameExpr(s.initializer) : undefined,
207
+ };
208
+ case "assign":
209
+ return {
210
+ ...s,
211
+ target: s.target === from ? to : s.target,
212
+ value: renameExpr(s.value),
213
+ };
214
+ case "call":
215
+ return { ...s, args: s.args.map(renameExpr) };
216
+ case "return":
217
+ return { ...s, value: s.value ? renameExpr(s.value) : undefined };
218
+ case "if":
219
+ return {
220
+ ...s,
221
+ condition: renameExpr(s.condition),
222
+ thenBranch: s.thenBranch.map(renameStmt),
223
+ elseBranch: s.elseBranch?.map(renameStmt),
224
+ };
225
+ case "while":
226
+ case "do_while":
227
+ return {
228
+ ...s,
229
+ condition: renameExpr(s.condition),
230
+ body: s.body.map(renameStmt),
231
+ };
232
+ case "for":
233
+ return {
234
+ ...s,
235
+ initializer: s.initializer ? renameStmt(s.initializer) : undefined,
236
+ condition: s.condition ? renameExpr(s.condition) : undefined,
237
+ increment: s.increment ? renameStmt(s.increment) : undefined,
238
+ body: s.body.map(renameStmt),
239
+ };
240
+ case "block":
241
+ return { ...s, body: s.body.map(renameStmt) };
242
+ default:
243
+ return s;
244
+ }
245
+ };
246
+ return statements.map(renameStmt);
247
+ }
248
+ // ── Console-in-callback tracking (legacy string-bake leftover) ─────────────
249
+ let _loweredConsoleInCallback = false;
250
+ export function noteConsoleInCallback() {
251
+ _loweredConsoleInCallback = true;
252
+ }
253
+ export function loweredConsoleInCallback() {
254
+ return _loweredConsoleInCallback;
255
+ }
256
+ export function resetCallbackLoweringState() {
257
+ _loweredConsoleInCallback = false;
258
+ endCanvasAmbient();
259
+ }
260
+ // ── Ambient canvas context ─────────────────────────────────────────────────
261
+ // While lowerCallbackStatements is lowering a drawCanvas body, callToStatement
262
+ // and expressionToIR consult these to rewrite ctx.* calls / ctx.width|height.
263
+ let _canvasAmbientCtx = null;
264
+ let _canvasAmbientDiagnostics = null;
265
+ let _canvasAmbientSourceText = null;
266
+ export function beginCanvasAmbient(ctxName, diagnostics, sourceText) {
267
+ _canvasAmbientCtx = ctxName;
268
+ _canvasAmbientDiagnostics = diagnostics;
269
+ _canvasAmbientSourceText = sourceText;
270
+ }
271
+ export function endCanvasAmbient() {
272
+ _canvasAmbientCtx = null;
273
+ _canvasAmbientDiagnostics = null;
274
+ _canvasAmbientSourceText = null;
275
+ }
276
+ export function getCanvasAmbientCtx() {
277
+ return _canvasAmbientCtx;
278
+ }
279
+ export function getCanvasAmbientDiagnostics() {
280
+ return _canvasAmbientDiagnostics;
281
+ }
282
+ export function getCanvasAmbientSourceText() {
283
+ return _canvasAmbientSourceText;
284
+ }
285
+ // ── Type-map seeding for callbacks ─────────────────────────────────────────
286
+ function callbackTypeMaps() {
287
+ const scope = getCurrentIrTypeScope();
288
+ const localVariableTypes = new Map();
289
+ if (scope) {
290
+ for (const [k, v] of scope.globals)
291
+ localVariableTypes.set(k, v);
292
+ for (const [k, v] of scope.locals) {
293
+ if (!localVariableTypes.has(k))
294
+ localVariableTypes.set(k, v);
295
+ }
296
+ }
297
+ const functionReturnTypes = new Map([...(getContext().activeFunctionReturnTypes ?? new Map())]);
298
+ return { functionReturnTypes, localVariableTypes, pointerVars: new Map() };
299
+ }
300
+ // ── Compact expression helper (concise-body / legacy) ──────────────────────
301
+ /**
302
+ * Lower a single callback-body expression to a C++ string (no trailing `;`).
303
+ * Used for concise arrow bodies and as a compact-render fallback. Block bodies
304
+ * go through lowerStatementList instead.
305
+ */
306
+ export function lowerCallbackExpr(expr, sourceText, diagnostics) {
307
+ if (ts.isCallExpression(expr) &&
308
+ ts.isPropertyAccessExpression(expr.expression) &&
309
+ ts.isIdentifier(expr.expression.expression) &&
310
+ expr.expression.expression.text === "console") {
311
+ const method = expr.expression.name.text;
312
+ const renderedArgs = expr.arguments
313
+ .map((arg) => renderExprAsText(expressionToIR(arg, sourceText, diagnostics)))
314
+ .join(" << ");
315
+ _loweredConsoleInCallback = true;
316
+ const strategy = getContext().activeStrategy;
317
+ if (strategy) {
318
+ return strategy.transformConsoleCall(method, renderedArgs, false).replace(/;$/, "");
319
+ }
320
+ return `std::cout << ${renderedArgs} << std::endl`;
321
+ }
322
+ if (ts.isCallExpression(expr) &&
323
+ ts.isPropertyAccessExpression(expr.expression) &&
324
+ expr.expression.name.text === "set" &&
325
+ ts.isIdentifier(expr.expression.expression) &&
326
+ isSignalName(expr.expression.expression.text)) {
327
+ const sigName = expr.expression.expression.text;
328
+ const argText = expr.arguments[0]
329
+ ? renderExprAsText(expressionToIR(expr.arguments[0], sourceText, diagnostics))
330
+ : "0";
331
+ return `${sigName} = ${argText}`;
332
+ }
333
+ if (ts.isCallExpression(expr) &&
334
+ ts.isIdentifier(expr.expression) &&
335
+ expr.arguments.length === 0 &&
336
+ isSignalName(expr.expression.text)) {
337
+ return expr.expression.text;
338
+ }
339
+ let raw = renderExprAsText(expressionToIR(expr, sourceText, diagnostics));
340
+ raw = resolveColorLiterals(raw);
341
+ return raw;
342
+ }
343
+ // ── Canvas disallowed-statement reject ─────────────────────────────────────
344
+ const CANVAS_DISALLOWED_KINDS = new Set([
345
+ "try",
346
+ "throw",
347
+ "switch",
348
+ "class",
349
+ "function",
350
+ ]);
351
+ function rejectDisallowedCanvasStatements(statements, diagnostics, sourceText) {
352
+ const walk = (s) => {
353
+ if (CANVAS_DISALLOWED_KINDS.has(s.kind)) {
354
+ diagnostics.push({
355
+ severity: "error",
356
+ code: "ui-callback-unsupported-statement",
357
+ message: `Unsupported statement in ${callbackContextLabel("ui-draw-canvas")}: '${s.kind}' cannot be lowered here.`,
358
+ hint: unsupportedStatementHint("ui-draw-canvas"),
359
+ source: sourceText.slice(0, 80),
360
+ });
361
+ return;
362
+ }
363
+ if (s.kind === "if") {
364
+ for (const n of s.thenBranch)
365
+ walk(n);
366
+ for (const n of s.elseBranch ?? [])
367
+ walk(n);
368
+ }
369
+ else if (s.kind === "while" || s.kind === "do_while" || s.kind === "for" || s.kind === "block") {
370
+ for (const n of s.body)
371
+ walk(n);
372
+ }
373
+ };
374
+ for (const s of statements)
375
+ walk(s);
376
+ }
377
+ // ── Primary IR lowering ────────────────────────────────────────────────────
378
+ /**
379
+ * Lower an arrow/function-expression callback body to StatementIR[] through
380
+ * the same lowerStatementList path setInterval uses.
381
+ */
382
+ export function lowerCallbackStatements(cbArg, fileName, sourceText, diagnostics, contextId = "ui-event-callback") {
383
+ const fnName = `__ui_cb_${contextId}`;
384
+ const isCanvas = contextId === "ui-draw-canvas";
385
+ const diagStart = diagnostics.length;
386
+ const { functionReturnTypes, localVariableTypes, pointerVars } = callbackTypeMaps();
387
+ if (isCanvas) {
388
+ const ctxName = cbArg.parameters[0]?.name.getText() ?? "ctx";
389
+ beginCanvasAmbient(ctxName, diagnostics, sourceText);
390
+ }
391
+ try {
392
+ let statements;
393
+ if (ts.isBlock(cbArg.body)) {
394
+ statements = lowerStatementList(cbArg.body.statements, fileName, sourceText, diagnostics, functionReturnTypes, localVariableTypes, fnName, undefined, pointerVars);
395
+ }
396
+ else {
397
+ let exprText;
398
+ if (isCanvas && ts.isCallExpression(cbArg.body)) {
399
+ const ctxName = cbArg.parameters[0]?.name.getText() ?? "ctx";
400
+ exprText = rewriteCanvasCall(cbArg.body, ctxName, diagnostics, sourceText) ?? "";
401
+ }
402
+ else {
403
+ exprText = lowerCallbackExpr(cbArg.body, sourceText, diagnostics);
404
+ }
405
+ statements = [{
406
+ kind: "call",
407
+ sourceSpan: makeSourceSpan(cbArg.body, fileName, sourceText),
408
+ callee: "__EMIT__",
409
+ args: [{ kind: "string", value: exprText.replace(/;$/, "") }],
410
+ }];
411
+ }
412
+ statements = resolveColorsInStatements(statements);
413
+ if (isCanvas) {
414
+ rejectDisallowedCanvasStatements(statements, diagnostics, sourceText);
415
+ }
416
+ for (let i = diagStart; i < diagnostics.length; i++) {
417
+ const d = diagnostics[i];
418
+ if (d.code === "TS2CPP_UNSUPPORTED_STMT" && d.severity === "error") {
419
+ d.code = "ui-callback-unsupported-statement";
420
+ d.message = `Unsupported statement in ${callbackContextLabel(contextId)}.`;
421
+ d.hint = unsupportedStatementHint(contextId);
422
+ }
423
+ }
424
+ return statements;
425
+ }
426
+ finally {
427
+ if (isCanvas)
428
+ endCanvasAmbient();
429
+ }
430
+ }
431
+ function findTopLevelCallable(name, sourceFile) {
432
+ for (const stmt of sourceFile.statements) {
433
+ if (ts.isFunctionDeclaration(stmt) && stmt.name?.text === name && stmt.body) {
434
+ return { kind: "function", decl: stmt };
435
+ }
436
+ if (ts.isVariableStatement(stmt)) {
437
+ for (const d of stmt.declarationList.declarations) {
438
+ if (ts.isIdentifier(d.name) &&
439
+ d.name.text === name &&
440
+ d.initializer &&
441
+ (ts.isArrowFunction(d.initializer) || ts.isFunctionExpression(d.initializer))) {
442
+ return { kind: "arrow", fn: d.initializer };
443
+ }
444
+ }
445
+ }
446
+ }
447
+ return undefined;
448
+ }
449
+ /** Resolve a UI callback arg to an inline arrow or a named free-function ref.
450
+ * Unresolvable identifiers produce a fatal diagnostic (fail closed). */
451
+ export function resolveCallbackArg(cbArg, sourceFile, diagnostics, label) {
452
+ if (!cbArg)
453
+ return undefined;
454
+ if (ts.isArrowFunction(cbArg) || ts.isFunctionExpression(cbArg)) {
455
+ return { kind: "inline", fn: cbArg };
456
+ }
457
+ if (ts.isIdentifier(cbArg)) {
458
+ const name = cbArg.text;
459
+ const sf = sourceFile ?? cbArg.getSourceFile();
460
+ if (sf && findTopLevelCallable(name, sf)) {
461
+ return { kind: "named", name };
462
+ }
463
+ diagnostics.push({
464
+ severity: "error",
465
+ code: "ui-callback-unresolved-name",
466
+ message: `${label}: cannot resolve '${name}' to a top-level function or arrow. Pass an inline arrow, or declare '${name}' at module scope.`,
467
+ hint: `Example: use an inline arrow (() => { /* ... */ }) or declare function ${name}() { ... } at top level.`,
468
+ });
469
+ return undefined;
470
+ }
471
+ diagnostics.push({
472
+ severity: "error",
473
+ code: "ui-callback-unsupported-arg",
474
+ message: `${label}: callback must be an inline arrow/function expression or a top-level function name.`,
475
+ });
476
+ return undefined;
477
+ }
478
+ /**
479
+ * Resolve + lower a callback when the C++ wrapper signature may differ from
480
+ * the author's function (bindInput, list tap). Returns statements + param
481
+ * names for IR-level rename.
482
+ */
483
+ export function lowerNamedOrInlineCallback(cbArg, fileName, sourceText, diagnostics, label, contextId = "ui-event-callback") {
484
+ if (!cbArg)
485
+ return undefined;
486
+ if (ts.isArrowFunction(cbArg) || ts.isFunctionExpression(cbArg)) {
487
+ const paramNames = cbArg.parameters
488
+ .map((p) => (ts.isIdentifier(p.name) ? p.name.text : ""))
489
+ .filter(Boolean);
490
+ return {
491
+ statements: lowerCallbackStatements(cbArg, fileName, sourceText, diagnostics, contextId),
492
+ paramNames,
493
+ };
494
+ }
495
+ if (ts.isIdentifier(cbArg)) {
496
+ const name = cbArg.text;
497
+ const sf = cbArg.getSourceFile();
498
+ const found = sf ? findTopLevelCallable(name, sf) : undefined;
499
+ if (found?.kind === "arrow") {
500
+ const paramNames = found.fn.parameters
501
+ .map((p) => (ts.isIdentifier(p.name) ? p.name.text : ""))
502
+ .filter(Boolean);
503
+ return {
504
+ statements: lowerCallbackStatements(found.fn, fileName, sourceText, diagnostics, contextId),
505
+ paramNames,
506
+ };
507
+ }
508
+ if (found?.kind === "function" && found.decl.body) {
509
+ const paramNames = found.decl.parameters
510
+ .map((p) => (ts.isIdentifier(p.name) ? p.name.text : ""))
511
+ .filter(Boolean);
512
+ const { functionReturnTypes, localVariableTypes, pointerVars } = callbackTypeMaps();
513
+ const diagStart = diagnostics.length;
514
+ const statements = resolveColorsInStatements(lowerStatementList(found.decl.body.statements, fileName, sourceText, diagnostics, functionReturnTypes, localVariableTypes, `__ui_cb_${contextId}`, undefined, pointerVars));
515
+ for (let i = diagStart; i < diagnostics.length; i++) {
516
+ const d = diagnostics[i];
517
+ if (d.code === "TS2CPP_UNSUPPORTED_STMT" && d.severity === "error") {
518
+ d.code = "ui-callback-unsupported-statement";
519
+ d.message = `Unsupported statement in ${callbackContextLabel(contextId)}.`;
520
+ d.hint = unsupportedStatementHint(contextId);
521
+ }
522
+ }
523
+ return { statements, paramNames };
524
+ }
525
+ diagnostics.push({
526
+ severity: "error",
527
+ code: "ui-callback-unresolved-name",
528
+ message: `${label}: cannot resolve '${name}' to a top-level function or arrow.`,
529
+ hint: `Pass an inline arrow, or declare '${name}' at module scope.`,
530
+ });
531
+ return undefined;
532
+ }
533
+ diagnostics.push({
534
+ severity: "error",
535
+ code: "ui-callback-unsupported-arg",
536
+ message: `${label}: callback must be an inline arrow/function expression or a top-level function name.`,
537
+ });
538
+ return undefined;
539
+ }
540
+ // ── Compact render (tests / legacy string fallbacks) ───────────────────────
541
+ export function renderStatementsCompact(statements) {
542
+ const strategy = getContext().activeStrategy ?? resolveStrategy("generic");
543
+ const { functionReturnTypes, localVariableTypes } = callbackTypeMaps();
544
+ const knownVariableTypes = new Map([...localVariableTypes].map(([k, v]) => [k, { cppType: v }]));
545
+ const renderer = new StatementRenderer({
546
+ strategy,
547
+ knownFunctionReturnTypes: functionReturnTypes,
548
+ pointerVarTypes: new Map(),
549
+ globalPointerVarTypes: new Map(),
550
+ classNameMap: new Map(),
551
+ enumNames: new Set(),
552
+ largeEnumNames: new Set(),
553
+ boardConstants: undefined,
554
+ knownVariableTypes,
555
+ stringVarNames: new Set(),
556
+ crossModuleClassNames: new Set(),
557
+ });
558
+ const scope = createEmissionScopeState();
559
+ for (const [k, v] of knownVariableTypes)
560
+ scope.knownVariableTypes.set(k, v);
561
+ const parts = [];
562
+ const renderOne = (s) => {
563
+ if (s.kind === "if") {
564
+ const { statement: head } = renderer.renderWithPrelude(s, false, undefined, scope.knownVariableTypes);
565
+ const thenParts = [];
566
+ for (const n of s.thenBranch) {
567
+ const before = parts.length;
568
+ renderOne(n);
569
+ thenParts.push(...parts.splice(before));
570
+ }
571
+ if (s.elseBranch && s.elseBranch.length > 0) {
572
+ const elseParts = [];
573
+ for (const n of s.elseBranch) {
574
+ const before = parts.length;
575
+ renderOne(n);
576
+ elseParts.push(...parts.splice(before));
577
+ }
578
+ parts.push(`${head} { ${thenParts.join(" ")} } else { ${elseParts.join(" ")} }`);
579
+ }
580
+ else {
581
+ parts.push(`${head} { ${thenParts.join(" ")} }`);
582
+ }
583
+ return;
584
+ }
585
+ if (s.kind === "for" || s.kind === "while" || s.kind === "do_while") {
586
+ const { statement: head } = renderer.renderWithPrelude(s, false, undefined, scope.knownVariableTypes);
587
+ const bodyParts = [];
588
+ for (const n of s.body) {
589
+ const before = parts.length;
590
+ renderOne(n);
591
+ bodyParts.push(...parts.splice(before));
592
+ }
593
+ if (s.kind === "do_while") {
594
+ parts.push(`do { ${bodyParts.join(" ")} } ${head}`);
595
+ }
596
+ else {
597
+ parts.push(`${head} { ${bodyParts.join(" ")} }`);
598
+ }
599
+ return;
600
+ }
601
+ if (s.kind === "block") {
602
+ for (const n of s.body)
603
+ renderOne(n);
604
+ return;
605
+ }
606
+ const { prelude, statement } = renderer.renderWithPrelude(s, false, undefined, scope.knownVariableTypes);
607
+ for (const line of prelude)
608
+ parts.push(line.endsWith(";") ? line : `${line};`);
609
+ parts.push(statement.endsWith(";") || statement.endsWith("}") ? statement : `${statement};`);
610
+ };
611
+ for (const s of statements)
612
+ renderOne(s);
613
+ return parts.join(" ");
614
+ }
615
+ /**
616
+ * Lower an arrow/function-expression callback's body to a single C++ string.
617
+ * Routes through lowerCallbackStatements then compact-renders. Prefer storing
618
+ * bodyStatements on the handler spec and rendering at emit time.
619
+ */
620
+ export function lowerCallbackBody(cbArg, sourceText, diagnostics, contextId = "ui-event-callback", fileName = "callback.ts") {
621
+ const statements = lowerCallbackStatements(cbArg, fileName, sourceText, diagnostics, contextId);
622
+ return renderStatementsCompact(statements);
623
+ }