@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,672 @@
1
+ // ---------------------------------------------------------------------------
2
+ // CppTypeIR — structured representation of a C++ type
3
+ //
4
+ // Replaces the stringly-typed `CppType = string` / `CppTypeHint` template-literal
5
+ // union. A C++ type is parsed once into this discriminated union and inspected by
6
+ // `kind` thereafter; the only place a type string is reconstructed is
7
+ // `renderCppType`. This eliminates the ~60+ ad-hoc `startsWith("std::vector<")` /
8
+ // `endsWith("*")` / `slice(len, -1)` sites scattered across `ir/` and `emit/`.
9
+ //
10
+ // ## Design notes
11
+ //
12
+ // - **Qualifiers are orthogonal wrappers.** `const`, `&`, and `*` are separate
13
+ // variants (`qualified` / `reference` / `pointer`) rather than baked into a
14
+ // string. This matches how they actually compose in `const std::vector<T>&`
15
+ // and lets consumers peel one layer at a time.
16
+ // - **Byte-identical round trip.** `renderCppType(parseCppType(s)) === s` for
17
+ // every type string the transpiler produces (verified by
18
+ // `tests/packages/cuttlefish/cpp-type-ir.test.ts`). The renderer must preserve
19
+ // the exact spelling the codebase already emits, including whitespace inside
20
+ // template argument lists (e.g. `std::variant<double, std::string>` keeps its
21
+ // ", " separator).
22
+ // - **Pseudo-types are first-class.** `__tc_StaticArray<T,N>`, `__tc_str_ptr`,
23
+ // `__tc_Generator<T>` all get explicit kinds so they can be matched without
24
+ // re-parsing. The transient value-level sentinel `__TYPED_ARRAY__:elem:size`
25
+ // is *not* a cppType (it lives in HAL return values) and is therefore not
26
+ // modeled here; the `T[N]` C-array it lowers to is modeled as `staticArray`.
27
+ // - **Class types are always pointers.** Per the producer's convention
28
+ // (type-resolution.ts:417-428) a TypeScript class reference is emitted as
29
+ // `ClassName*` so `new X()` never assigns to a value-typed `X`. The parser
30
+ // preserves this; it does not "unwrap" pointers.
31
+ //
32
+ // ## Out of scope
33
+ //
34
+ // `libdef/cpp-to-decl.ts` parses raw C++ *source text* (not IR `CppType`) along
35
+ // a separate pipeline; it is unaffected by and does not consume this module.
36
+ // ---------------------------------------------------------------------------
37
+ // ---------------------------------------------------------------------------
38
+ // Known spellings
39
+ // ---------------------------------------------------------------------------
40
+ const PRIMITIVE_NAMES = new Set([
41
+ "int", "long", "long long",
42
+ "unsigned int", "unsigned long", "unsigned long long",
43
+ "short", "unsigned short",
44
+ "float", "double", "long double",
45
+ "bool", "void",
46
+ "char", "signed char", "unsigned char",
47
+ "size_t", "ssize_t", "intptr_t", "uintptr_t", "ptrdiff_t",
48
+ "int8_t", "int16_t", "int32_t", "int64_t",
49
+ "uint8_t", "uint16_t", "uint32_t", "uint64_t",
50
+ ]);
51
+ function isPrimitiveName(s) {
52
+ return PRIMITIVE_NAMES.has(s);
53
+ }
54
+ // ---------------------------------------------------------------------------
55
+ // splitTemplateArgs — the one correct nested-template-argument splitter
56
+ //
57
+ // Promoted from its private definition in type-resolution.ts. Splits a template
58
+ // argument list on top-level commas (depth-0), respecting nested `<>`. Returns
59
+ // the args with surrounding whitespace preserved (callers `.trim()` when they
60
+ // want canonical form). This is the only splitter in the codebase that handles
61
+ // `std::map<K, V>` and nested templates correctly — the half-dozen inline
62
+ // `slice(len, -1).split(",")` copies do not.
63
+ // ---------------------------------------------------------------------------
64
+ export function splitTemplateArgs(inner) {
65
+ const parts = [];
66
+ let depth = 0;
67
+ let start = 0;
68
+ for (let i = 0; i < inner.length; i++) {
69
+ const ch = inner[i];
70
+ if (ch === "<")
71
+ depth++;
72
+ else if (ch === ">")
73
+ depth--;
74
+ else if (ch === "," && depth === 0) {
75
+ parts.push(inner.slice(start, i));
76
+ start = i + 1;
77
+ }
78
+ }
79
+ parts.push(inner.slice(start));
80
+ return parts;
81
+ }
82
+ // ---------------------------------------------------------------------------
83
+ // parseCppType — the single parser
84
+ //
85
+ // Peels `const` (prefix and suffix), `&`, `*`, smart pointers, and the
86
+ // `std::` / `__tc_` template wrappers from the outside in, then recurses into
87
+ // the template arguments.
88
+ //
89
+ // Returns `opaque` for any input it cannot classify, so unknown spellings
90
+ // survive a round trip rather than throwing.
91
+ // ---------------------------------------------------------------------------
92
+ export function parseCppType(s) {
93
+ const trimmed = s.trim();
94
+ if (trimmed === "") {
95
+ return { kind: "opaque", raw: s };
96
+ }
97
+ // Direct primitive hit.
98
+ if (isPrimitiveName(trimmed)) {
99
+ return { kind: "primitive", name: trimmed };
100
+ }
101
+ // Pointer suffix `T*` (greedy: collapse trailing `**`? — codebase only uses
102
+ // single indirection, but be conservative and peel one level).
103
+ if (trimmed.endsWith("*")) {
104
+ return { kind: "pointer", base: parseCppType(trimmed.slice(0, -1).trim()) };
105
+ }
106
+ // Reference suffix `T&`.
107
+ if (trimmed.endsWith("&")) {
108
+ const base = parseCppType(trimmed.slice(0, -1).trim());
109
+ return { kind: "reference", base, isConst: isConstQualified(base) };
110
+ }
111
+ // `const` prefix: `const T`. (Also matches `const T&` already peeled above.)
112
+ // We must be careful: `const char*` parses as `pointer(const char)`, not
113
+ // `qualified(const, pointer(char))`. So only peel `const ` when it is the
114
+ // outermost token AND the remainder is not itself a pointer/array.
115
+ {
116
+ const afterConst = peelConstPrefix(trimmed);
117
+ if (afterConst !== null) {
118
+ const inner = afterConst.trim();
119
+ // If peeling const leaves a pointer/reference, the const binds to the
120
+ // pointee (`const char*`), so don't peel — recurse into pointer branch.
121
+ if (!endsWithPointerOrRef(inner)) {
122
+ return { kind: "qualified", base: parseCppType(inner), isConst: true };
123
+ }
124
+ }
125
+ }
126
+ // `const` suffix: `T const` (rare in this codebase, but legal C++).
127
+ {
128
+ const beforeSuffixConst = peelConstSuffix(trimmed);
129
+ if (beforeSuffixConst !== null) {
130
+ return { kind: "qualified", base: parseCppType(beforeSuffixConst.trim()), isConst: true };
131
+ }
132
+ }
133
+ // Template form `Name<...>`: dispatch on the head name.
134
+ const templ = matchTemplate(trimmed);
135
+ if (templ) {
136
+ const { head, inner } = templ;
137
+ switch (head) {
138
+ case "std::vector":
139
+ return { kind: "vector", element: parseCppType(splitTemplateArgs(inner)[0].trim()) };
140
+ case "std::set":
141
+ case "std::unordered_set":
142
+ return { kind: "set", element: parseCppType(splitTemplateArgs(inner)[0].trim()) };
143
+ case "std::map":
144
+ case "std::unordered_map": {
145
+ const args = splitTemplateArgs(inner).map((a) => parseCppType(a.trim()));
146
+ return { kind: "map", key: args[0] ?? { kind: "opaque", raw: "" }, value: args[1] ?? { kind: "opaque", raw: "" } };
147
+ }
148
+ case "std::tuple":
149
+ return { kind: "tuple", elements: splitTemplateArgs(inner).map((a) => parseCppType(a.trim())) };
150
+ case "std::variant":
151
+ return { kind: "variant", members: splitTemplateArgs(inner).map((a) => parseCppType(a.trim())) };
152
+ case "std::function":
153
+ return parseStdFunction(inner);
154
+ case "std::shared_ptr":
155
+ case "std::unique_ptr":
156
+ return { kind: "smartPointer", wrapper: head, inner: parseCppType(splitTemplateArgs(inner)[0].trim()) };
157
+ case "__tc_StaticArray": {
158
+ const args = splitTemplateArgs(inner).map((a) => parseCppType(a.trim()));
159
+ const sizeNode = args[1];
160
+ const size = sizeNode && sizeNode.kind === "opaque" && /^\d+$/.test(sizeNode.raw.trim())
161
+ ? Number(sizeNode.raw.trim())
162
+ : undefined;
163
+ return { kind: "staticArray", element: args[0] ?? { kind: "opaque", raw: "" }, size };
164
+ }
165
+ case "__tc_Generator":
166
+ return { kind: "generator", yieldType: parseCppType(splitTemplateArgs(inner)[0].trim()) };
167
+ default:
168
+ // Generic user template: `MyClass<T, U>` or `std::something_unmodeled<…>`.
169
+ return { kind: "named", name: head, args: splitTemplateArgs(inner).map((a) => parseCppType(a.trim())) };
170
+ }
171
+ }
172
+ // `__tc_str_ptr` — may carry no argument in current usage.
173
+ if (trimmed === "__tc_str_ptr") {
174
+ return { kind: "strPtr" };
175
+ }
176
+ // `__tc_str_ptr(inner)` form (value-level wrap; the inner is an expression,
177
+ // not a type, so we keep it opaque).
178
+ if (trimmed.startsWith("__tc_str_ptr(") && trimmed.endsWith(")")) {
179
+ return { kind: "strPtr" };
180
+ }
181
+ // `std::string` literal.
182
+ if (trimmed === "std::string") {
183
+ return { kind: "string" };
184
+ }
185
+ if (trimmed === "auto") {
186
+ return { kind: "auto" };
187
+ }
188
+ // `const char*` — common enough to model explicitly as pointer(primitive char)
189
+ // qualified const; but to keep round-tripping byte-identical, prefer letting
190
+ // the named-with-const-prefix path handle it. We land here for the bare
191
+ // `char` case via the named branch below.
192
+ // C-array forms `T[N]` / `T[]` (e.g. `uint8_t[16]`, `int[]`). These are
193
+ // emitted by HAL lowering (variables.ts) and parsed by element-access code.
194
+ {
195
+ const arr = matchCArray(trimmed);
196
+ if (arr) {
197
+ const { element, size } = arr;
198
+ // Use `staticArray` when a concrete size is present (matches the
199
+ // existing `T[N]` lowering), `cArray` when it's `T[]`.
200
+ return size !== undefined
201
+ ? { kind: "staticArray", element: parseCppType(element), size }
202
+ : { kind: "cArray", element: parseCppType(element) };
203
+ }
204
+ }
205
+ // Otherwise: a bare named type (struct/class/enum/typedef/typename).
206
+ // Allow identifier-ish names including `::` scopes (e.g. `std::string`
207
+ // already handled above; `Foo::Bar` is a named type).
208
+ if (isValidTypeName(trimmed)) {
209
+ return { kind: "named", name: trimmed };
210
+ }
211
+ // Last resort: preserve verbatim.
212
+ return { kind: "opaque", raw: s };
213
+ }
214
+ function parseStdFunction(inner) {
215
+ // `inner` is `R(P, Q, ...)` where `R` itself may be a function type.
216
+ // Find the *last* top-level `(` so the head is the return type and the
217
+ // tail is the parameter list.
218
+ let depth = 0;
219
+ let parenIdx = -1;
220
+ for (let i = inner.length - 1; i >= 0; i--) {
221
+ const ch = inner[i];
222
+ if (ch === ")")
223
+ depth++;
224
+ else if (ch === "(") {
225
+ depth--;
226
+ if (depth === 0) {
227
+ parenIdx = i;
228
+ break;
229
+ }
230
+ }
231
+ }
232
+ if (parenIdx < 0) {
233
+ return { kind: "function", returnType: parseCppType(inner.trim()), params: [] };
234
+ }
235
+ const returnTypeStr = inner.slice(0, parenIdx).trim();
236
+ const paramsStr = inner.slice(parenIdx + 1, inner.lastIndexOf(")")).trim();
237
+ const params = paramsStr === ""
238
+ ? []
239
+ : splitFunctionParams(paramsStr).map((p) => parseCppType(p.trim()));
240
+ return { kind: "function", returnType: parseCppType(returnTypeStr), params };
241
+ }
242
+ /** Split a function parameter list on top-level commas, respecting `()` and `<>`. */
243
+ function splitFunctionParams(s) {
244
+ const parts = [];
245
+ let depth = 0;
246
+ let start = 0;
247
+ for (let i = 0; i < s.length; i++) {
248
+ const ch = s[i];
249
+ if (ch === "(" || ch === "<")
250
+ depth++;
251
+ else if (ch === ")" || ch === ">")
252
+ depth--;
253
+ else if (ch === "," && depth === 0) {
254
+ parts.push(s.slice(start, i));
255
+ start = i + 1;
256
+ }
257
+ }
258
+ parts.push(s.slice(start));
259
+ return parts;
260
+ }
261
+ /** If `s` ends with `>` and has a top-level `<`, split into `head` and the
262
+ * raw inner string (whitespace preserved). Returns null otherwise. */
263
+ function matchTemplate(s) {
264
+ if (!s.endsWith(">"))
265
+ return null;
266
+ // Locate the *matching* opening `<` for the final `>`.
267
+ let depth = 0;
268
+ let openIdx = -1;
269
+ for (let i = s.length - 1; i >= 0; i--) {
270
+ const ch = s[i];
271
+ if (ch === ">")
272
+ depth++;
273
+ else if (ch === "<") {
274
+ depth--;
275
+ if (depth === 0) {
276
+ openIdx = i;
277
+ break;
278
+ }
279
+ }
280
+ }
281
+ if (openIdx < 0)
282
+ return null;
283
+ const head = s.slice(0, openIdx);
284
+ // Reject `head` that itself looks like a pointer/array tail, e.g. `int*<…>`.
285
+ if (!isValidTypeName(head.trim()))
286
+ return null;
287
+ const inner = s.slice(openIdx + 1, s.length - 1);
288
+ return { head: head.trim(), inner };
289
+ }
290
+ function matchCArray(s) {
291
+ // `T[N]` or `T[]`. Use the *last* `[` to find the array suffix.
292
+ if (!s.endsWith("]"))
293
+ return null;
294
+ const openIdx = s.lastIndexOf("[");
295
+ if (openIdx < 0)
296
+ return null;
297
+ const element = s.slice(0, openIdx).trim();
298
+ const sizeStr = s.slice(openIdx + 1, s.length - 1).trim();
299
+ if (sizeStr === "")
300
+ return { element };
301
+ if (/^\d+$/.test(sizeStr))
302
+ return { element, size: Number(sizeStr) };
303
+ return null;
304
+ }
305
+ function peelConstPrefix(s) {
306
+ return s.startsWith("const ") ? s.slice("const ".length) : null;
307
+ }
308
+ function peelConstSuffix(s) {
309
+ return s.endsWith(" const") ? s.slice(0, -" const".length) : null;
310
+ }
311
+ function endsWithPointerOrRef(s) {
312
+ return s.endsWith("*") || s.endsWith("&");
313
+ }
314
+ function isConstQualified(ir) {
315
+ return ir.kind === "qualified" && ir.isConst;
316
+ }
317
+ function isValidTypeName(s) {
318
+ // Identifier-ish, possibly scoped with `::`. Used only to decide whether to
319
+ // accept a `head` or `bare` token as a type name.
320
+ return /^(?:[A-Za-z_][A-Za-z0-9_]*)(?:::[A-Za-z_][A-Za-z0-9_]*)*$/.test(s);
321
+ }
322
+ // ---------------------------------------------------------------------------
323
+ // renderCppType — the single renderer
324
+ //
325
+ // Must be byte-identical to the historical spelling for every type string the
326
+ // transpiler emits. In particular:
327
+ // - template args are joined with ", "
328
+ // - `vector`/`map`/`set`/`tuple`/`variant` use the `std::` prefix
329
+ // - `__tc_StaticArray<T, N>` joins element and size with ", "
330
+ // - pointers print as `${base}*` (no space); references as `${base}&`
331
+ // - qualified-const prints as `const ${base}` (prefix form, matching producer)
332
+ // ---------------------------------------------------------------------------
333
+ export function renderCppType(ir) {
334
+ switch (ir.kind) {
335
+ case "primitive": return ir.name;
336
+ case "auto": return "auto";
337
+ case "string": return "std::string";
338
+ case "strPtr": return "__tc_str_ptr";
339
+ case "opaque": return ir.raw;
340
+ case "named":
341
+ return ir.args && ir.args.length > 0
342
+ ? `${ir.name}<${ir.args.map(renderCppType).join(", ")}>`
343
+ : ir.name;
344
+ case "pointer": return `${renderCppType(ir.base)}*`;
345
+ case "reference": return `${renderCppType(ir.base)}&`;
346
+ case "qualified": return ir.isConst ? `const ${renderCppType(ir.base)}` : renderCppType(ir.base);
347
+ case "vector": return `std::vector<${renderCppType(ir.element)}>`;
348
+ case "set": return `std::set<${renderCppType(ir.element)}>`;
349
+ case "map": return `std::map<${renderCppType(ir.key)}, ${renderCppType(ir.value)}>`;
350
+ case "tuple": return `std::tuple<${ir.elements.map(renderCppType).join(", ")}>`;
351
+ case "variant": return `std::variant<${ir.members.map(renderCppType).join(", ")}>`;
352
+ case "function": {
353
+ const params = ir.params.map(renderCppType).join(", ");
354
+ return `std::function<${renderCppType(ir.returnType)}(${params})>`;
355
+ }
356
+ case "staticArray":
357
+ return ir.size !== undefined
358
+ ? `__tc_StaticArray<${renderCppType(ir.element)}, ${ir.size}>`
359
+ : `__tc_StaticArray<${renderCppType(ir.element)}>`;
360
+ case "cArray":
361
+ return ir.size !== undefined
362
+ ? `${renderCppType(ir.element)}[${ir.size}]`
363
+ : `${renderCppType(ir.element)}[]`;
364
+ case "generator": return `__tc_Generator<${renderCppType(ir.yieldType)}>`;
365
+ case "smartPointer": return `${ir.wrapper}<${renderCppType(ir.inner)}>`;
366
+ default: {
367
+ // Exhaustiveness guard.
368
+ const _exhaustive = ir;
369
+ void _exhaustive;
370
+ return "";
371
+ }
372
+ }
373
+ }
374
+ // ---------------------------------------------------------------------------
375
+ // Predicate helpers — thin wrappers that replace inline string inspection.
376
+ //
377
+ // These cover the recurring idioms found across `ir/` and `emit/`:
378
+ // `endsWith("*")` → `isPointer`; `startsWith("std::vector<")` → `isVector`;
379
+ // `startsWith("std::map<") || startsWith("std::set<")` → `isAssociative`;
380
+ // etc.
381
+ // ---------------------------------------------------------------------------
382
+ /** True for `T*` (any depth of indirection). */
383
+ export function isPointer(ir) {
384
+ return ir.kind === "pointer";
385
+ }
386
+ /** True for `T&` (and `const T&`). */
387
+ export function isReference(ir) {
388
+ return ir.kind === "reference";
389
+ }
390
+ /** True for any container that supports element/index access:
391
+ * vector, set, map, staticArray, cArray. */
392
+ export function isContainer(ir) {
393
+ return ir.kind === "vector" || ir.kind === "set" || ir.kind === "map"
394
+ || ir.kind === "staticArray" || ir.kind === "cArray";
395
+ }
396
+ export function isVector(ir) { return ir.kind === "vector"; }
397
+ export function isMap(ir) { return ir.kind === "map"; }
398
+ export function isSet(ir) { return ir.kind === "set"; }
399
+ export function isTuple(ir) { return ir.kind === "tuple"; }
400
+ export function isVariant(ir) { return ir.kind === "variant"; }
401
+ export function isStdFunction(ir) { return ir.kind === "function"; }
402
+ export function isStaticArray(ir) { return ir.kind === "staticArray"; }
403
+ export function isCArray(ir) { return ir.kind === "cArray"; }
404
+ /** True for `std::string` / `__tc_str_ptr` / `const char*`-ish string types.
405
+ * Does NOT consult platform strategy — callers that need platform-aware string
406
+ * detection (e.g. Arduino `String`) should still call `strategy.isStringLikeType`. */
407
+ export function isStringLike(ir) {
408
+ if (ir.kind === "string" || ir.kind === "strPtr")
409
+ return true;
410
+ if (ir.kind === "pointer") {
411
+ const pointee = ir.base.kind === "qualified" ? ir.base.base : ir.base;
412
+ return pointee.kind === "primitive"
413
+ && (pointee.name === "char" || pointee.name === "signed char" || pointee.name === "unsigned char");
414
+ }
415
+ return false;
416
+ }
417
+ /** True for builtin scalars (`int`, `double`, …) and `std::string`/`bool`.
418
+ * Corresponds to the `isPrimitiveCppType` helpers in statement-renderer. */
419
+ export function isPrimitive(ir) {
420
+ if (ir.kind === "primitive")
421
+ return true;
422
+ if (ir.kind === "qualified")
423
+ return isPrimitive(ir.base);
424
+ return false;
425
+ }
426
+ /** Peel pointer/reference/const qualification and return the underlying type.
427
+ * `Foo*` → `Foo`, `const Bar&` → `Bar`, `std::vector<T>*` → `std::vector<T>`.
428
+ * Corresponds to the `replace(/\*$/, "").replace(/^const\s+/, "").trim()`
429
+ * idiom scattered through expression-renderer / setup. */
430
+ export function bareType(ir) {
431
+ let cur = ir;
432
+ while (true) {
433
+ if (cur.kind === "pointer" || cur.kind === "reference") {
434
+ cur = cur.base;
435
+ }
436
+ else if (cur.kind === "qualified") {
437
+ cur = cur.base;
438
+ }
439
+ else {
440
+ return cur;
441
+ }
442
+ }
443
+ }
444
+ /** Element type of a vector/set/staticArray/cArray, or the value type of a map.
445
+ * Returns undefined for non-containers. Replaces the duplicated
446
+ * `slice("std::vector<".length, -1).trim()` copies. */
447
+ export function elementOf(ir) {
448
+ switch (ir.kind) {
449
+ case "vector":
450
+ case "set":
451
+ case "staticArray":
452
+ case "cArray":
453
+ return ir.element;
454
+ case "map":
455
+ return ir.value;
456
+ default:
457
+ return undefined;
458
+ }
459
+ }
460
+ export function formatKindOf(ir) {
461
+ // `char*` / `const char*` are C-strings (%s), not single chars (%c).
462
+ // Must be checked BEFORE the generic pointer branch.
463
+ if (isCharPointer(ir))
464
+ return "string";
465
+ // Any other pointer → %p-ish dispatch bucket. Checked before bareType()
466
+ // strips the pointer.
467
+ if (ir.kind === "pointer")
468
+ return "pointer";
469
+ const bare = bareType(ir);
470
+ if (bare.kind === "string" || bare.kind === "strPtr")
471
+ return "string";
472
+ if (bare.kind === "primitive") {
473
+ switch (bare.name) {
474
+ case "bool": return "bool";
475
+ case "char":
476
+ case "signed char":
477
+ case "unsigned char": return "char";
478
+ case "float":
479
+ case "double":
480
+ case "long double": return "float";
481
+ case "int":
482
+ case "short": return "int";
483
+ case "unsigned int":
484
+ case "unsigned short":
485
+ case "uint8_t":
486
+ case "uint16_t": return "uint";
487
+ case "long":
488
+ case "int32_t":
489
+ case "int64_t": return "long";
490
+ case "unsigned long":
491
+ case "unsigned long long":
492
+ case "long long":
493
+ case "uint32_t":
494
+ case "uint64_t":
495
+ case "size_t":
496
+ case "uintptr_t": return "ulong";
497
+ default: return "other";
498
+ }
499
+ }
500
+ return "other";
501
+ }
502
+ /** True for `char*`, `const char*`, `signed char*`, etc. — C-strings, not
503
+ * pointers-to-single-chars. Drives `%s` formatting in snprintf dispatch. */
504
+ function isCharPointer(ir) {
505
+ if (ir.kind !== "pointer")
506
+ return false;
507
+ const pointee = ir.base.kind === "qualified" ? ir.base.base : ir.base;
508
+ return pointee.kind === "primitive"
509
+ && (pointee.name === "char" || pointee.name === "signed char" || pointee.name === "unsigned char");
510
+ }
511
+ // ---------------------------------------------------------------------------
512
+ // Builder helpers — replace inline `${x}*` / `std::vector<${x}>` construction.
513
+ // ---------------------------------------------------------------------------
514
+ export const CppTypeIR = {
515
+ primitive: (name) => ({ kind: "primitive", name }),
516
+ auto: () => ({ kind: "auto" }),
517
+ string: () => ({ kind: "string" }),
518
+ bool: () => ({ kind: "primitive", name: "bool" }),
519
+ void: () => ({ kind: "primitive", name: "void" }),
520
+ int: () => ({ kind: "primitive", name: "int" }),
521
+ double: () => ({ kind: "primitive", name: "double" }),
522
+ named: (name, args) => ({ kind: "named", name, args }),
523
+ pointer: (base) => ({ kind: "pointer", base }),
524
+ reference: (base, isConst = false) => ({ kind: "reference", base, isConst }),
525
+ const_: (base) => ({ kind: "qualified", base, isConst: true }),
526
+ vector: (element) => ({ kind: "vector", element }),
527
+ set: (element) => ({ kind: "set", element }),
528
+ map: (key, value) => ({ kind: "map", key, value }),
529
+ tuple: (elements) => ({ kind: "tuple", elements }),
530
+ variant: (members) => ({ kind: "variant", members }),
531
+ function: (returnType, params) => ({ kind: "function", returnType, params }),
532
+ staticArray: (element, size) => ({ kind: "staticArray", element, size }),
533
+ cArray: (element, size) => ({ kind: "cArray", element, size }),
534
+ generator: (yieldType) => ({ kind: "generator", yieldType }),
535
+ smartPointer: (wrapper, inner) => ({ kind: "smartPointer", wrapper, inner }),
536
+ strPtr: () => ({ kind: "strPtr" }),
537
+ opaque: (raw) => ({ kind: "opaque", raw }),
538
+ };
539
+ // ---------------------------------------------------------------------------
540
+ // Convenience: parse-then-inspect. Lets call sites that today do
541
+ // `cppType.endsWith("*")` become `parsedIsPointer(cppType)` while `CppType`
542
+ // is still a string during the staged migration.
543
+ // ---------------------------------------------------------------------------
544
+ export function parsedIsPointer(cppType) { return isPointer(parseCppType(cppType)); }
545
+ export function parsedIsStringLike(cppType) { return isStringLike(parseCppType(cppType)); }
546
+ export function parsedIsPrimitive(cppType) { return isPrimitive(parseCppType(cppType)); }
547
+ export function parsedIsContainer(cppType) { return isContainer(parseCppType(cppType)); }
548
+ export function parsedIsVector(cppType) { return isVector(parseCppType(cppType)); }
549
+ export function parsedIsMap(cppType) { return isMap(parseCppType(cppType)); }
550
+ export function parsedIsSet(cppType) { return isSet(parseCppType(cppType)); }
551
+ export function parsedIsTuple(cppType) { return isTuple(parseCppType(cppType)); }
552
+ export function parsedIsVariant(cppType) { return isVariant(parseCppType(cppType)); }
553
+ export function parsedIsStaticArray(cppType) { return isStaticArray(parseCppType(cppType)); }
554
+ /** True for `std::string` (and `std::string&`, `const std::string`, etc.). */
555
+ export function parsedIsStdString(cppType) {
556
+ const ir = parseCppType(cppType);
557
+ return bareType(ir).kind === "string";
558
+ }
559
+ export function parsedElementOf(cppType) { return elementOf(parseCppType(cppType)); }
560
+ /** Element/value type of a container, rendered back to a string. Replaces the
561
+ * `slice("std::vector<".length, -1).trim()` idiom at consumer sites. */
562
+ export function parsedElementString(cppType) {
563
+ const e = elementOf(parseCppType(cppType));
564
+ return e ? renderCppType(e) : undefined;
565
+ }
566
+ /** Bare (pointer/const/reference-stripped) type rendered as a string. Replaces
567
+ * `cppType.replace(/\*$/, "").replace(/^const\s+/, "").trim()` at consumer sites. */
568
+ export function parsedBareString(cppType) { return renderCppType(bareType(parseCppType(cppType))); }
569
+ export function parsedBareType(cppType) { return bareType(parseCppType(cppType)); }
570
+ /**
571
+ * Collect every user-named type referenced anywhere inside a C++ type string
572
+ * (including nested template args, pointer bases, vector elements, etc.).
573
+ * Replaces the historical "match all identifiers then filter primitives"
574
+ * idiom used for dependency tracking in call-graph analysis.
575
+ *
576
+ * Returns only `named`-kind names — primitives, `std::string`, `auto`, etc.
577
+ * are excluded because they are not user-defined types.
578
+ */
579
+ export function collectNamedTypes(ir) {
580
+ const out = [];
581
+ const walk = (node) => {
582
+ switch (node.kind) {
583
+ case "named":
584
+ out.push(node.name);
585
+ if (node.args)
586
+ for (const a of node.args)
587
+ walk(a);
588
+ break;
589
+ case "pointer":
590
+ case "reference":
591
+ case "qualified":
592
+ walk(node.base);
593
+ break;
594
+ case "vector":
595
+ case "set":
596
+ case "staticArray":
597
+ case "cArray":
598
+ walk(node.element);
599
+ break;
600
+ case "generator":
601
+ walk(node.yieldType);
602
+ break;
603
+ case "smartPointer":
604
+ walk(node.inner);
605
+ break;
606
+ case "map":
607
+ walk(node.key);
608
+ walk(node.value);
609
+ break;
610
+ case "tuple":
611
+ for (const m of node.elements)
612
+ walk(m);
613
+ break;
614
+ case "variant":
615
+ for (const m of node.members)
616
+ walk(m);
617
+ break;
618
+ case "function":
619
+ walk(node.returnType);
620
+ for (const p of node.params)
621
+ walk(p);
622
+ break;
623
+ default:
624
+ // primitive, auto, string, strPtr, opaque — no named children.
625
+ break;
626
+ }
627
+ };
628
+ walk(ir);
629
+ return out;
630
+ }
631
+ /** String-in convenience for `collectNamedTypes(parseCppType(s))`. */
632
+ export function parsedCollectNamedTypes(cppType) {
633
+ return collectNamedTypes(parseCppType(cppType));
634
+ }
635
+ /** True if the type is a plain struct/class name with no template args, pointer,
636
+ * reference, array, or container wrapper — i.e. the kind of type that a
637
+ * `return null` should lower to `return {};` (value-init).
638
+ * Replaces the `!includes("<") && !endsWith("*") && !endsWith("]")` idiom. */
639
+ export function parsedIsPlainStructType(cppType) {
640
+ const ir = parseCppType(cppType);
641
+ const bare = bareType(ir);
642
+ if (bare.kind !== "named")
643
+ return false;
644
+ if (bare.args && bare.args.length > 0)
645
+ return false;
646
+ return true;
647
+ }
648
+ /**
649
+ * True for types that own a string buffer and therefore need `.c_str()` when
650
+ * passed to a C variadic (printf/snprintf): `std::string`, `__tc_str_ptr`,
651
+ * and platform string types like Arduino `String`. NOT true for `const char*`
652
+ * / `char*`, which are already C-strings.
653
+ *
654
+ * This is the structured replacement for the
655
+ * `normalized === "std::string" || normalized === "String" || normalized === "__tc_str_ptr"`
656
+ * idiom in the snprintf/expression renderers.
657
+ */
658
+ export function needsCStrForStringLike(cppType) {
659
+ const ir = parseCppType(cppType);
660
+ // A top-level pointer (char*) is already a C-string — no .c_str() needed.
661
+ if (ir.kind === "pointer")
662
+ return false;
663
+ // Peel const/reference wrappers to reach the underlying category.
664
+ let node = ir;
665
+ while (node.kind === "qualified" || node.kind === "reference") {
666
+ node = node.base;
667
+ if (node.kind === "pointer")
668
+ return false;
669
+ }
670
+ return node.kind === "string" || node.kind === "strPtr"
671
+ || (node.kind === "named" && node.name === "String");
672
+ }
@@ -0,0 +1,12 @@
1
+ import type { ResolvedDisplay } from "./display-profile.js";
2
+ export interface DisplayAdapterCode {
3
+ /** C++ #include lines (e.g. "#include <Adafruit_ILI9341.h>"). */
4
+ includes: string;
5
+ /** C++ display object declaration (e.g. "Adafruit_ILI9341 __tc_display = ..."). */
6
+ declaration: string;
7
+ /** C++ static inline adapter functions (display_init, display_fillScreen, etc.). */
8
+ functions: string;
9
+ }
10
+ export type DisplayAdapterGenerator = (display: ResolvedDisplay) => DisplayAdapterCode;
11
+ export declare function registerDisplayAdapter(driver: string, gen: DisplayAdapterGenerator): void;
12
+ export declare function generateDisplayAdapter(display: ResolvedDisplay): DisplayAdapterCode;