@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,428 @@
1
+ import { emitCommentLines, isRuntimeExpression, collectNestedStructDefs, inferObjectFieldType } from "../utils/index.js";
2
+ import { appendSourceLine, appendHeaderLine, appendRenderedStatement } from "./line-appender.js";
3
+ import { createChildEmissionScope } from "../snprintf-helpers.js";
4
+ import { escapeCppKeyword } from "../../utils/strings.js";
5
+ import { parsedIsPlainStructType } from "../../api/shared/cpp-type-ir.js";
6
+ import { entryHasUI } from "../../ui-hook.js";
7
+ import { activeNamespaceNames } from "../../ir/build-ir-state.js";
8
+ export function emitPostClassDeclarations(ctx) {
9
+ const { strategy, effectiveEmitMode, mappedFunctions, isEntryFile, topLevelScope } = ctx;
10
+ const platformReservedNames = strategy.reservedNames();
11
+ const normalizeCppTypeForTarget = (cppType) => strategy.normalizeCppType(cppType);
12
+ // Runtime variable declarations AFTER classes (for non-entry files)
13
+ if (!isEntryFile) {
14
+ for (const statement of ctx.emittedTopLevelStatements) {
15
+ if (statement.kind === "var_decl" && statement.initializer && isRuntimeExpression(statement.initializer)) {
16
+ appendRenderedStatement(ctx, statement, "", topLevelScope);
17
+ }
18
+ }
19
+ }
20
+ // Forward declarations for promoted runtime var_decls.
21
+ //
22
+ // A promoted top-level variable (one classified runtime AND referenced by a
23
+ // free function, so it must live at file scope) is forward-declared here and
24
+ // assigned its real initializer inside the entrypoint. The default
25
+ // initializer must be value-initialization (`{}`), which is valid for every
26
+ // C++ type: scalars/pointers zero/null-initialize, class types
27
+ // (std::string, std::vector, std::map, user structs) default-construct.
28
+ // Previously this emitted `= 0` for every non-pointer type, which is invalid
29
+ // for class types (`std::vector<...>` has no implicit conversion from int)
30
+ // and failed at g++ time. Demo #28 Finding B.
31
+ if (ctx.promotedVarDecls.size > 0) {
32
+ for (const [varName, info] of ctx.promotedVarDecls) {
33
+ appendSourceLine(ctx, `${info.cppType} ${escapeCppKeyword(varName, platformReservedNames)} = {};`);
34
+ }
35
+ appendSourceLine(ctx, "");
36
+ }
37
+ // Object literal struct definitions (split mode)
38
+ const { program, exprRenderer } = ctx;
39
+ const renderExpression = (expr, calleeTransformer) => exprRenderer.render(expr, calleeTransformer);
40
+ for (const statement of ctx.emittedTopLevelStatements) {
41
+ if (effectiveEmitMode === "split" &&
42
+ statement.kind === "var_decl" &&
43
+ statement.initializer?.kind === "object") {
44
+ // When the source annotation names a concrete type (e.g. an exported
45
+ // interface referenced across modules: `const cfg: ThresholdConfig = {...}`),
46
+ // the variable's cppType already is that interface/struct name. The struct
47
+ // itself is declared by the interface declaration, and the extern + cpp
48
+ // definition are emitted by emitTypeDeclarations (via the extern block and
49
+ // appendRenderedStatement respectively). So we must skip synthesizing a
50
+ // local `_name_t` struct here — otherwise we'd emit a second, conflicting
51
+ // struct definition and a duplicate extern/definition.
52
+ const placeholderStructName = `_${statement.name}_t`;
53
+ // Compile-time-only namespace values (e.g. the `ui` handle) emit nothing.
54
+ if (activeNamespaceNames.has(statement.name)) {
55
+ return;
56
+ }
57
+ const declaredCppType = statement.cppType;
58
+ const hasExplicitNamedType = !!declaredCppType &&
59
+ declaredCppType !== "auto" &&
60
+ declaredCppType !== placeholderStructName &&
61
+ parsedIsPlainStructType(declaredCppType);
62
+ // Still register the field types so downstream rendering (e.g. string-concat
63
+ // wrapping via interfaceFieldTypes) can resolve property accesses on the var.
64
+ const fieldTypeEntries = statement.initializer.fields.map((field) => {
65
+ const inferred = inferObjectFieldType(field.value, ctx.globalPointerVarTypes, ctx.knownFunctionReturnTypes, ctx.knownTopLevelObjectTypes, ctx.knownTopLevelObjectFields, ctx.largeEnumNames, statement.name, field.name, strategy.defaultNumericType(), (o, n) => strategy.resolvePinType?.(o, n));
66
+ return [field.name, inferred];
67
+ });
68
+ if (hasExplicitNamedType) {
69
+ const namedType = declaredCppType;
70
+ ctx.knownTopLevelObjectTypes.set(statement.name, namedType);
71
+ ctx.knownTopLevelObjectFields.set(statement.name, new Map(fieldTypeEntries));
72
+ continue;
73
+ }
74
+ const structName = placeholderStructName;
75
+ const nestedStructs = collectNestedStructDefs(statement.initializer, statement.name, ctx.globalPointerVarTypes, ctx.knownFunctionReturnTypes, ctx.knownTopLevelObjectTypes, ctx.knownTopLevelObjectFields, ctx.largeEnumNames);
76
+ for (const ns of nestedStructs) {
77
+ const nestedFieldDefs = ns.fields
78
+ .map((f) => `${f.type} ${strategy.renameStructField(f.name)};`)
79
+ .join(" ");
80
+ appendHeaderLine(ctx, `struct ${ns.structName} { ${nestedFieldDefs} };`);
81
+ }
82
+ const fieldDefs = fieldTypeEntries
83
+ .map(([fieldName, inferredType]) => {
84
+ const safeFieldName = strategy.renameStructField(fieldName);
85
+ return `${inferredType} ${safeFieldName};`;
86
+ })
87
+ .join(" ");
88
+ const initValues = statement.initializer.fields
89
+ .map((field) => {
90
+ const renderExpr = (e) => renderExpression(e, ctx.fixPointerFieldAccess);
91
+ const overridden = strategy.objectFieldInitializer(field.value, renderExpr);
92
+ if (overridden !== undefined)
93
+ return overridden;
94
+ const structInit = strategy.structFieldInitializer(field.value, ctx.compiletimeVarNames, renderExpr);
95
+ if (structInit !== undefined)
96
+ return structInit;
97
+ return renderExpression(field.value, ctx.fixPointerFieldAccess);
98
+ })
99
+ .join(", ");
100
+ ctx.knownTopLevelObjectTypes.set(statement.name, structName);
101
+ ctx.knownTopLevelObjectFields.set(statement.name, new Map(fieldTypeEntries));
102
+ emitCommentLines(statement.leadingComments, "", (line) => appendHeaderLine(ctx, line));
103
+ appendHeaderLine(ctx, `struct ${structName} { ${fieldDefs} };`);
104
+ appendHeaderLine(ctx, `extern ${structName} ${statement.name};`);
105
+ emitCommentLines(statement.trailingComments, "", (line) => appendHeaderLine(ctx, line));
106
+ emitCommentLines(statement.leadingComments, "", (line) => appendSourceLine(ctx, line));
107
+ appendSourceLine(ctx, `${structName} ${statement.name} = { ${initValues} };`, {
108
+ tsSpan: statement.sourceSpan,
109
+ nodeKind: statement.kind,
110
+ });
111
+ emitCommentLines(statement.trailingComments, "", (line) => appendSourceLine(ctx, line));
112
+ }
113
+ }
114
+ if (ctx.emittedTopLevelStatements.some(s => s.kind === "var_decl" && s.initializer?.kind === "object")) {
115
+ appendSourceLine(ctx, "");
116
+ }
117
+ }
118
+ export function emitCallbackFunctions(ctx) {
119
+ const { strategy, effectiveEmitMode, topLevelScope } = ctx;
120
+ // NOTE: forward declarations for callbacks and free functions are now emitted
121
+ // BEFORE class bodies by emitFunctionForwardDeclarations (cpp-emitter step
122
+ // 6.5). This function emits only the callback DEFINITIONS (plus split-mode
123
+ // header prototypes, which belong with the public API).
124
+ // Emit callback functions
125
+ for (const callback of ctx.callbackFunctions) {
126
+ if (callback.debounceMs !== undefined && callback.debounceMs > 0) {
127
+ appendSourceLine(ctx, `volatile unsigned long ${callback.name}_lastTime = 0;`);
128
+ appendSourceLine(ctx, `const unsigned long ${callback.name}_debounce = ${callback.debounceMs};`);
129
+ appendSourceLine(ctx, "");
130
+ }
131
+ appendSourceLine(ctx, `${strategy.isrFunctionAttribute?.() ?? ""}${renderCallbackSignature(callback)} {`);
132
+ if (callback.debounceMs !== undefined && callback.debounceMs > 0) {
133
+ appendSourceLine(ctx, ` volatile unsigned long now = ${strategy.currentTimeMillis()};`);
134
+ appendSourceLine(ctx, ` if (now - ${callback.name}_lastTime < ${callback.name}_debounce) return;`);
135
+ appendSourceLine(ctx, ` ${callback.name}_lastTime = now;`);
136
+ }
137
+ const callbackScope = createChildEmissionScope(topLevelScope, callback.typedParams);
138
+ for (const stmt of callback.statements) {
139
+ appendRenderedStatement(ctx, stmt, " ", callbackScope);
140
+ }
141
+ appendSourceLine(ctx, "}");
142
+ appendSourceLine(ctx, "");
143
+ }
144
+ // Split-mode ISR callback forward declarations in header
145
+ if (effectiveEmitMode === "split") {
146
+ for (const callback of ctx.callbackFunctions) {
147
+ appendHeaderLine(ctx, `${strategy.isrFunctionAttribute?.() ?? ""}${renderCallbackSignature(callback)};`);
148
+ }
149
+ }
150
+ }
151
+ /**
152
+ * Render the C++ signature of a synthesized callback (ISR) free function.
153
+ *
154
+ * Historically every hoisted callback emitted as `void name()` — fine for
155
+ * parameter-less ISRs (the `onFalling(() => {...})` case) but wrong for a
156
+ * typed lambda passed as a `std::function<R(args)>` argument, where the
157
+ * function must carry the same return type and parameter list. We fall back
158
+ * to the historical `void name()` shape when the callback carries no
159
+ * returnType/typedParams (the common ISR path that populates neither).
160
+ */
161
+ function renderCallbackSignature(callback) {
162
+ const ret = callback.returnType && callback.returnType !== "void" ? callback.returnType : "void";
163
+ const params = (callback.typedParams ?? []).map(p => `${p.cppType} ${p.name}`).join(", ");
164
+ return `${ret} ${callback.name}(${params})`;
165
+ }
166
+ export function emitFunctions(ctx) {
167
+ const { strategy, effectiveEmitMode, mappedFunctions, topLevelScope, hasPromiseRuntime, asyncTaskClasses, usesTimers } = ctx;
168
+ // NOTE: source-level forward declarations (non-split free fns + split-mode
169
+ // static fns) are now emitted BEFORE class bodies by
170
+ // emitFunctionForwardDeclarations (cpp-emitter step 6.5). This function
171
+ // emits function DEFINITIONS and the split-mode header prototypes for
172
+ // exported functions (which ride along with their definition below).
173
+ for (let fi = 0; fi < mappedFunctions.length; fi++) {
174
+ const fn = mappedFunctions[fi];
175
+ const declarationParameterList = ctx.statementRenderer.renderParameters(fn.parameters, true);
176
+ const definitionParameterList = ctx.statementRenderer.renderParameters(fn.parameters, false);
177
+ const readonlyPrefix = fn.isReadonlyReturnType ? "const " : "";
178
+ const isExported = fn.isExported === true;
179
+ // A function is an entrypoint if it is the strategy's primary entrypoint
180
+ // (e.g. `setup` on Arduino, `main` on native) OR one of the platform's
181
+ // reserved entrypoint names the strategy excludes from forward declarations
182
+ // (e.g. `loop` on Arduino, whose `void loop(void)` is forward-declared
183
+ // extern by the Arduino core — emitting `static void loop()` redeclares it
184
+ // with conflicting linkage, which ESP32's GCC rejects; see
185
+ // arduino-loop-linkage.test.ts). Treating these as entrypoints drops the
186
+ // `static` qualifier, matching how `setup`/`main` already emit.
187
+ const platformEntrypoints = strategy.forwardDeclarationExclusions?.() ?? [];
188
+ const isEntrypoint = fn.name === strategy.entrypointFunctionName() ||
189
+ platformEntrypoints.includes(fn.name);
190
+ // Demo #18 Finding B: a non-exported free function that is CALLED from a
191
+ // class method body must be visible in the header (inline method bodies
192
+ // live there in split mode) and defined non-static in the .cpp (a `static`
193
+ // definition would clash with the header's extern prototype). The header
194
+ // prototype is emitted in emitFunctionForwardDeclarations (which runs
195
+ // before classes); here we only drop the `static` from the definition.
196
+ const calledFromClassMethod = ctx.freeFunctionsCalledFromClassMethods.has(fn.name);
197
+ const needsStatic = !isExported && !isEntrypoint && !calledFromClassMethod;
198
+ if (effectiveEmitMode === "split") {
199
+ if (isExported) {
200
+ emitCommentLines(fn.leadingComments, "", (line) => appendHeaderLine(ctx, line));
201
+ if (fn.typeParameters && fn.typeParameters.length > 0) {
202
+ appendHeaderLine(ctx, `template<typename ${fn.typeParameters.join(", typename ")}>`);
203
+ }
204
+ appendHeaderLine(ctx, `${readonlyPrefix}${ctx.statementRenderer.mapReturnTypeForEmit(fn.name, fn.returnType)} ${fn.name}(${declarationParameterList});`, {
205
+ tsSpan: fn.sourceSpan,
206
+ nodeKind: "function_declaration",
207
+ symbolName: fn.name,
208
+ });
209
+ emitCommentLines(fn.trailingComments, "", (line) => appendHeaderLine(ctx, line));
210
+ }
211
+ }
212
+ // Generic (templated) functions must be DEFINED in the header — a C++
213
+ // template definition in a .cpp is not visible to other translation
214
+ // units, producing `undefined reference` at link time. So for an exported
215
+ // generic function in split mode we route the full definition (template
216
+ // line + signature + body) into the header. We use the same buffer-swap
217
+ // trick the class emitter uses (class-emitter.ts:13-18), so that
218
+ // appendSourceLine / appendRenderedStatement (which are hardwired to the
219
+ // source buffer) write to the header while the swap is active. Non-generic
220
+ // exported functions keep their historical decl-in-.h / def-in-.cpp split.
221
+ const isExportedGeneric = effectiveEmitMode === "split" &&
222
+ isExported &&
223
+ !!fn.typeParameters && fn.typeParameters.length > 0 &&
224
+ !fn.isAsync; // async functions are driven via task classes, not templates
225
+ if (isExportedGeneric) {
226
+ const _swapLines = ctx.sourceLines;
227
+ ctx.sourceLines = ctx.headerLines;
228
+ ctx.headerLines = _swapLines;
229
+ const _swapMaps = ctx.sourceMapEntries;
230
+ ctx.sourceMapEntries = ctx.headerMapEntries;
231
+ ctx.headerMapEntries = _swapMaps;
232
+ }
233
+ emitCommentLines(fn.leadingComments, "", (line) => appendSourceLine(ctx, line));
234
+ if (fn.typeParameters && fn.typeParameters.length > 0) {
235
+ appendSourceLine(ctx, `template<typename ${fn.typeParameters.join(", typename ")}>`);
236
+ }
237
+ const fnReturnType = fn.isGenerator ? `__tc_Generator<${fn.returnType === "void" ? "void" : ctx.statementRenderer.mapReturnTypeForEmit(fn.name, fn.returnType)}>` : `${readonlyPrefix}${ctx.statementRenderer.mapReturnTypeForEmit(fn.name, fn.returnType)}`;
238
+ const linkagePrefix = needsStatic ? "static " : "";
239
+ appendSourceLine(ctx, `${linkagePrefix}${fnReturnType} ${fn.name}(${definitionParameterList})`, {
240
+ tsSpan: fn.sourceSpan,
241
+ nodeKind: "function_definition",
242
+ symbolName: fn.name,
243
+ });
244
+ appendSourceLine(ctx, "{");
245
+ const asyncDriverFn = strategy.asyncDriverFunctionName();
246
+ if (hasPromiseRuntime && fn.name === asyncDriverFn) {
247
+ appendSourceLine(ctx, " cuttlefish_pump_microtasks();");
248
+ }
249
+ if (fn.isAsync && ctx.hasAsyncRuntime) {
250
+ appendSourceLine(ctx, ` // driven as cooperative task in ${asyncDriverFn}()`);
251
+ }
252
+ else {
253
+ if (fn.typeParameterConstraints) {
254
+ for (const [param, expr] of fn.typeParameterConstraints) {
255
+ appendSourceLine(ctx, ` static_assert(${expr}, "${param} constraint violated");`);
256
+ }
257
+ }
258
+ const functionScope = createChildEmissionScope(topLevelScope, fn.parameters);
259
+ ctx.cArrayVarNames = ctx.fnCArrayVarNames.get(String(fi)) ?? new Set();
260
+ const isLoopDriver = fn.name === asyncDriverFn;
261
+ const lastStmt = fn.statements.length > 0 ? fn.statements[fn.statements.length - 1] : null;
262
+ const lastIsReturn = lastStmt?.kind === "return";
263
+ const stmtsToEmit = (isLoopDriver && lastIsReturn)
264
+ ? fn.statements.slice(0, -1)
265
+ : fn.statements;
266
+ for (const statement of stmtsToEmit) {
267
+ appendRenderedStatement(ctx, statement, " ", functionScope);
268
+ }
269
+ // Drive the UI runtime each frame. Fires only in the driver function when
270
+ // a UI is mounted (entryHasUI). Uses a separate gate from the async pump
271
+ // so a pure-UI program (no async/timers) still animates. When the strategy
272
+ // provides hostEventLoop, the per-frame work runs inside a while loop so a
273
+ // host target (SDL) can pump events and present between ticks. Emitted
274
+ // AFTER the function's init statements (ui_init/display_init/touch_init)
275
+ // so initialization precedes the loop.
276
+ if (entryHasUI() && fn.name === asyncDriverFn) {
277
+ const loop = strategy.hostEventLoop?.();
278
+ if (loop) {
279
+ appendSourceLine(ctx, ` bool ${loop.flagName} = true;`);
280
+ appendSourceLine(ctx, ` while (${loop.continueCondition}) {`);
281
+ appendSourceLine(ctx, ` ${loop.preIteration}`);
282
+ }
283
+ appendSourceLine(ctx, ` uint32_t __tc_ui_now = (uint32_t)${strategy.currentTimeMillis()};`);
284
+ appendSourceLine(ctx, " static uint32_t __tc_ui_last_tick = __tc_ui_now;");
285
+ appendSourceLine(ctx, " uint32_t __tc_ui_delta = __tc_ui_now - __tc_ui_last_tick;");
286
+ appendSourceLine(ctx, " __tc_ui_last_tick = __tc_ui_now;");
287
+ appendSourceLine(ctx, " if (__tc_ui_delta > 250) __tc_ui_delta = 250;");
288
+ appendSourceLine(ctx, " ui_tick((uint16_t)__tc_ui_delta);");
289
+ if (loop) {
290
+ appendSourceLine(ctx, ` ${loop.postIteration}`);
291
+ appendSourceLine(ctx, ` }`);
292
+ }
293
+ }
294
+ if (isLoopDriver && (hasPromiseRuntime || asyncTaskClasses.length > 0 || usesTimers)) {
295
+ const taskNames = asyncTaskClasses.map(t => t.taskVarName);
296
+ const asyncConfig = strategy.getAsyncRuntimeConfig();
297
+ asyncConfig.hasPromiseRuntime = hasPromiseRuntime;
298
+ asyncConfig.hasTimers = usesTimers;
299
+ const injectionLines = strategy.asyncLoopInjection(taskNames, asyncConfig);
300
+ for (const line of injectionLines) {
301
+ appendSourceLine(ctx, ` ${line}`);
302
+ }
303
+ }
304
+ if (isLoopDriver && lastIsReturn) {
305
+ appendRenderedStatement(ctx, lastStmt, " ", functionScope);
306
+ }
307
+ }
308
+ appendSourceLine(ctx, "}");
309
+ emitCommentLines(fn.trailingComments, "", (line) => appendSourceLine(ctx, line));
310
+ appendSourceLine(ctx, "");
311
+ // Restore the buffer swap we applied for exported generic functions (see
312
+ // isExportedGeneric above). After this point sourceLines/headerLines are
313
+ // back to their normal roles for the next function in the loop.
314
+ if (isExportedGeneric) {
315
+ const _swapLines = ctx.sourceLines;
316
+ ctx.sourceLines = ctx.headerLines;
317
+ ctx.headerLines = _swapLines;
318
+ const _swapMaps = ctx.sourceMapEntries;
319
+ ctx.sourceMapEntries = ctx.headerMapEntries;
320
+ ctx.headerMapEntries = _swapMaps;
321
+ }
322
+ }
323
+ }
324
+ /**
325
+ * Emit forward declarations for ALL free functions (and ISR callbacks) BEFORE
326
+ * class bodies. A class method may call a free function declared later in the
327
+ * same source file; if that function's forward declaration only appears after
328
+ * the class (as it did historically via emitCallbackFunctions/emitFunctions),
329
+ * g++ reports "'fn' was not declared in this scope" inside the class body.
330
+ *
331
+ * This runs at cpp-emitter.ts step 6.5, ahead of emitClasses (step 7). The
332
+ * definition-only emission in emitCallbackFunctions/emitFunctions below no
333
+ * longer re-emits these declarations (they are dropped there to avoid
334
+ * duplicates). Template/generic functions get template prototypes here so
335
+ * earlier functions can call them before their definitions later in the same
336
+ * translation unit.
337
+ */
338
+ export function emitFunctionForwardDeclarations(ctx) {
339
+ const { strategy, effectiveEmitMode } = ctx;
340
+ const excludedNames = new Set(strategy.forwardDeclarationExclusions?.() ?? []);
341
+ // ISR callback forward declarations.
342
+ if (effectiveEmitMode !== "split") {
343
+ for (const callback of ctx.callbackFunctions) {
344
+ appendSourceLine(ctx, `${strategy.isrFunctionAttribute?.() ?? ""}${renderCallbackSignature(callback)};`);
345
+ }
346
+ }
347
+ let emittedAnyFn = false;
348
+ for (const fn of ctx.mappedFunctions) {
349
+ if (excludedNames.has(fn.name))
350
+ continue;
351
+ const isExported = fn.isExported === true;
352
+ // A function is an entrypoint if it is the strategy's primary entrypoint
353
+ // (e.g. `setup` on Arduino, `main` on native) OR one of the platform's
354
+ // reserved entrypoint names the strategy excludes from forward declarations
355
+ // (e.g. `loop` on Arduino, whose `void loop(void)` is forward-declared
356
+ // extern by the Arduino core — emitting `static void loop()` redeclares it
357
+ // with conflicting linkage, which ESP32's GCC rejects; see
358
+ // arduino-loop-linkage.test.ts). Treating these as entrypoints drops the
359
+ // `static` qualifier, matching how `setup`/`main` already emit.
360
+ const platformEntrypoints = strategy.forwardDeclarationExclusions?.() ?? [];
361
+ const isEntrypoint = fn.name === strategy.entrypointFunctionName() ||
362
+ platformEntrypoints.includes(fn.name);
363
+ // Demo #18 Finding B: a free function called from a class method body is
364
+ // forward-declared in the HEADER (like an exported function) — this step
365
+ // runs BEFORE emitClasses, so the prototype precedes the class body that
366
+ // references it. It must NOT also get a `static` source-level forward decl.
367
+ const calledFromClassMethod = ctx.freeFunctionsCalledFromClassMethods.has(fn.name);
368
+ // Exported functions and class-method-called free functions are forward-
369
+ // declared in the HEADER (above). Only static (non-exported) functions
370
+ // that are NOT called from a class method need a source-level forward decl.
371
+ if (effectiveEmitMode === "split" && calledFromClassMethod) {
372
+ const declarationParameterList = ctx.statementRenderer.renderParameters(fn.parameters, true);
373
+ const readonlyPrefix = fn.isReadonlyReturnType ? "const " : "";
374
+ const fnReturnType = fn.isGenerator
375
+ ? `__tc_Generator<${fn.returnType === "void" ? "void" : ctx.statementRenderer.mapTypeForEmit(fn.returnType)}>`
376
+ : `${readonlyPrefix}${ctx.statementRenderer.mapReturnTypeForEmit(fn.name, fn.returnType)}`;
377
+ if (fn.typeParameters && fn.typeParameters.length > 0) {
378
+ const typeParams = fn.typeParameters.join(", typename ");
379
+ appendHeaderLine(ctx, `template<typename ${typeParams}>`);
380
+ }
381
+ appendHeaderLine(ctx, `${fnReturnType} ${fn.name}(${declarationParameterList});`, {
382
+ tsSpan: fn.sourceSpan,
383
+ nodeKind: "function_declaration",
384
+ symbolName: fn.name,
385
+ });
386
+ emittedAnyFn = true;
387
+ continue;
388
+ }
389
+ if (effectiveEmitMode === "split" && (isExported || isEntrypoint))
390
+ continue;
391
+ const declarationParameterList = ctx.statementRenderer.renderParameters(fn.parameters, true);
392
+ const readonlyPrefix = fn.isReadonlyReturnType ? "const " : "";
393
+ const fnReturnType = fn.isGenerator
394
+ ? `__tc_Generator<${fn.returnType === "void" ? "void" : ctx.statementRenderer.mapTypeForEmit(fn.returnType)}>`
395
+ : `${readonlyPrefix}${ctx.statementRenderer.mapReturnTypeForEmit(fn.name, fn.returnType)}`;
396
+ if (fn.typeParameters && fn.typeParameters.length > 0) {
397
+ const fnNeedsStatic = !isExported && !isEntrypoint;
398
+ const typeParams = fn.typeParameters.join(", typename ");
399
+ appendSourceLine(ctx, `template<typename ${typeParams}>`);
400
+ appendSourceLine(ctx, `${fnNeedsStatic ? "static " : ""}${fnReturnType} ${fn.name}(${declarationParameterList});`, {
401
+ tsSpan: fn.sourceSpan,
402
+ nodeKind: "function_declaration",
403
+ symbolName: fn.name,
404
+ });
405
+ emittedAnyFn = true;
406
+ continue;
407
+ }
408
+ if (effectiveEmitMode === "split") {
409
+ appendSourceLine(ctx, `static ${fnReturnType} ${fn.name}(${declarationParameterList});`, {
410
+ tsSpan: fn.sourceSpan,
411
+ nodeKind: "function_declaration",
412
+ symbolName: fn.name,
413
+ });
414
+ }
415
+ else {
416
+ const fnNeedsStatic = !isExported && !isEntrypoint;
417
+ appendSourceLine(ctx, `${fnNeedsStatic ? "static " : ""}${fnReturnType} ${fn.name}(${declarationParameterList});`, {
418
+ tsSpan: fn.sourceSpan,
419
+ nodeKind: "function_declaration",
420
+ symbolName: fn.name,
421
+ });
422
+ }
423
+ emittedAnyFn = true;
424
+ }
425
+ if (ctx.callbackFunctions.length > 0 || emittedAnyFn) {
426
+ appendSourceLine(ctx, "");
427
+ }
428
+ }
@@ -0,0 +1,15 @@
1
+ import type { StatementIR } from "../../api/index.js";
2
+ import type { SourceSpan } from "../../types.js";
3
+ import type { EmissionScopeState } from "../snprintf-helpers.js";
4
+ import type { EmitterContext } from "./emitter-context.js";
5
+ export declare function appendSourceLine(ctx: EmitterContext, line: string, entry?: {
6
+ tsSpan: SourceSpan;
7
+ nodeKind: string;
8
+ symbolName?: string;
9
+ }): void;
10
+ export declare function appendHeaderLine(ctx: EmitterContext, line: string, entry?: {
11
+ tsSpan: SourceSpan;
12
+ nodeKind: string;
13
+ symbolName?: string;
14
+ }): void;
15
+ export declare function appendRenderedStatement(ctx: EmitterContext, statement: StatementIR, indent: string, scopeState: EmissionScopeState): void;