@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,681 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Mermaid Diagram Builder
3
+ //
4
+ // Generates Mermaid.js diagram markup strings from diagnostic data.
5
+ // Used by the Markdown report writer to embed visualizations.
6
+ // ---------------------------------------------------------------------------
7
+ // ── Helpers ─────────────────────────────────────────────────────────────────
8
+ /** Escape Mermaid labels to avoid syntax issues */
9
+ function esc(label) {
10
+ return label
11
+ .replace(/"/g, "#quot;")
12
+ .replace(/\n/g, " ")
13
+ .replace(/\\/g, "/")
14
+ .trim();
15
+ }
16
+ /**
17
+ * Wrap a label for use in Mermaid bracket syntax.
18
+ * If the label contains characters that confuse the parser
19
+ * (parentheses, brackets, etc.), wraps it in double-quote form.
20
+ */
21
+ function safeLabel(label) {
22
+ const safe = esc(label);
23
+ // Always use quotes if the label contains any non-alphanumeric characters
24
+ // (except spaces), to avoid confusing the Mermaid parser.
25
+ if (/[^a-zA-Z0-9 ]/.test(safe)) {
26
+ return `["${safe}"]`;
27
+ }
28
+ return `[${safe}]`;
29
+ }
30
+ function indent(level, str) {
31
+ return " ".repeat(level) + str;
32
+ }
33
+ // ── Symbol classification (shared across diagram builders) ──────────────────
34
+ /** Symbols that are low-value leaf nodes — filter them out of diagrams. */
35
+ const NOISE = new Set([
36
+ "true", "false", "HIGH", "LOW", "OUTPUT", "INPUT", "INPUT_PULLUP",
37
+ "__EMIT__", "__top_level__", "LED", "LED_BUILTIN",
38
+ ]);
39
+ /** Symbols from the TypeCAD board descriptor namespace chain. */
40
+ const BOARD_CHAIN = new Set([
41
+ "TypeCAD", "Arduino", "Uno", "Nano", "Mega", "Mega2560",
42
+ "Demo", "Board", "ATmega328P", "Features", "Esp32", "DevKit",
43
+ ]);
44
+ /** Known Arduino / HAL runtime API calls. */
45
+ function isArduinoAPI(name) {
46
+ const apis = [
47
+ // GPIO
48
+ "digitalWrite", "digitalRead", "analogWrite", "analogRead", "pinMode",
49
+ // Serial
50
+ "Serial", "println", "print", "read", "write",
51
+ // Audio
52
+ "tone", "noTone",
53
+ // Timing
54
+ "millis", "micros", "delay", "delayMicroseconds",
55
+ // Interrupts
56
+ "attachInterrupt", "detachInterrupt",
57
+ // SPI / Shift
58
+ "shiftOut", "shiftIn", "pulseIn",
59
+ // HAL event tokens (from Button, etc.)
60
+ "pressed", "released", "input",
61
+ ];
62
+ return apis.includes(name);
63
+ }
64
+ // ── Execution Flow Diagram ──────────────────────────────────────────────────
65
+ /**
66
+ * Build a categorized architecture diagram showing how the sketch
67
+ * is organized: entry points, HAL objects, Arduino APIs (grouped by
68
+ * subsystem), state variables, and custom functions.
69
+ *
70
+ * Noise symbols (true/false/HIGH/board chain) are filtered out.
71
+ * Nodes are laid out horizontally within subgraphs for readability.
72
+ */
73
+ export function buildExecutionFlowDiagram(flow, callGraph) {
74
+ const lines = [];
75
+ lines.push("```mermaid");
76
+ lines.push("%%{init: { 'theme': 'base', 'themeVariables': { 'primaryColor': '#e1f5fe', 'edgeColor': '#546e7a', 'fontFamily': 'Segoe UI, Roboto, Helvetica Neue, sans-serif' } } }%%");
77
+ lines.push("flowchart TD");
78
+ // ── 0. Styles ─────────────────────────────────────────────────────
79
+ lines.push(" classDef entry fill:#4caf50,stroke:#2e7d32,color:#fff,stroke-width:2px;");
80
+ lines.push(" classDef api fill:#fff9c4,stroke:#fbc02d,color:#333,stroke-width:1px;");
81
+ lines.push(" classDef var fill:#e1f5fe,stroke:#0288d1,color:#01579b,stroke-width:1px;");
82
+ lines.push(" classDef fn fill:#e8f5e9,stroke:#43a047,color:#1b5e20,stroke-width:1px;");
83
+ lines.push(" classDef obj fill:#f3e5f5,stroke:#8e24aa,color:#4a148c,stroke-width:1px;");
84
+ lines.push(" classDef board fill:#fafafa,stroke:#9e9e9e,color:#616161,stroke-width:1px,stroke-dasharray: 5 5;");
85
+ // ── 1. Walk call graph, collecting non-noise symbols ──────────────
86
+ const relevant = new Set();
87
+ const visited = new Set();
88
+ function walk(name) {
89
+ if (visited.has(name))
90
+ return;
91
+ if (name === "__top_level__")
92
+ return;
93
+ visited.add(name);
94
+ if (!NOISE.has(name) && !BOARD_CHAIN.has(name)) {
95
+ relevant.add(name);
96
+ }
97
+ const node = callGraph.nodes.get(name);
98
+ if (node) {
99
+ for (const dep of node.dependencies) {
100
+ walk(dep);
101
+ }
102
+ }
103
+ }
104
+ for (const ep of flow.entryPoints)
105
+ walk(ep);
106
+ for (const ep of flow.isrHandlers)
107
+ walk(ep);
108
+ for (const task of flow.asyncTaskNames)
109
+ walk(task);
110
+ if (relevant.size === 0) {
111
+ for (const [name] of callGraph.nodes) {
112
+ if (!NOISE.has(name) && !BOARD_CHAIN.has(name) && name !== "__top_level__") {
113
+ walk(name);
114
+ }
115
+ }
116
+ }
117
+ // Collect board chain symbols that were reached (for one collapsed node)
118
+ const boardUsed = [];
119
+ for (const name of visited) {
120
+ if (BOARD_CHAIN.has(name))
121
+ boardUsed.push(name);
122
+ }
123
+ // ── 2. Sort into semantic categories ──────────────────────────────
124
+ const entry = new Set(flow.entryPoints.filter((e) => relevant.has(e)));
125
+ const isr = new Set(flow.isrHandlers.filter((e) => relevant.has(e)));
126
+ const async = new Set(flow.asyncTaskNames.filter((e) => relevant.has(e)));
127
+ const halObjects = [];
128
+ const userVars = [];
129
+ const userFns = [];
130
+ const apis = [];
131
+ const other = [];
132
+ for (const name of relevant) {
133
+ if (entry.has(name) || isr.has(name) || async.has(name))
134
+ continue;
135
+ const node = callGraph.nodes.get(name);
136
+ if (isArduinoAPI(name)) {
137
+ apis.push(name);
138
+ }
139
+ else if (node?.kind === "function") {
140
+ userFns.push(name);
141
+ }
142
+ else if (node?.kind === "variable") {
143
+ // Heuristic: short camelCase names without Time/Phase/State suffixes
144
+ // are likely HAL objects; longer or snake_case names are state vars.
145
+ if (/^[a-z][a-zA-Z]*$/.test(name) &&
146
+ name.length <= 10 &&
147
+ !/(Time|Phase|State|Edge)$/i.test(name)) {
148
+ halObjects.push(name);
149
+ }
150
+ else {
151
+ userVars.push(name);
152
+ }
153
+ }
154
+ else if (node?.kind === "class" || node?.kind === "enum") {
155
+ other.push(name);
156
+ }
157
+ else {
158
+ // Nodes not in callGraph (leaf constants, external symbols)
159
+ other.push(name);
160
+ }
161
+ }
162
+ // ── 3. Draw categorized subgraphs ─────────────────────────────────
163
+ // --- Top: Entry Points ────────────────────────────────────────────
164
+ const hasEntry = entry.size > 0 || isr.size > 0 || async.size > 0;
165
+ if (hasEntry) {
166
+ lines.push(" subgraph Entry[\"Entry Points\"]");
167
+ lines.push(" direction LR");
168
+ for (const name of entry) {
169
+ lines.push(` ${name}([${esc(name)}]):::entry`);
170
+ }
171
+ for (const name of isr) {
172
+ lines.push(` ${name}([ISR: ${esc(name)}]):::entry`);
173
+ }
174
+ for (const name of async) {
175
+ lines.push(` ${name}([async: ${esc(name)}]):::entry`);
176
+ }
177
+ lines.push(" end");
178
+ lines.push("");
179
+ }
180
+ // --- HAL Objects ─────────────────────────────────────────────────
181
+ if (halObjects.length > 0) {
182
+ lines.push(" subgraph Objects[\"HAL Objects\"]");
183
+ lines.push(" direction LR");
184
+ for (const name of halObjects) {
185
+ lines.push(` ${name}{{${esc(name)}}}:::obj`);
186
+ }
187
+ lines.push(" end");
188
+ lines.push("");
189
+ }
190
+ // --- Arduino APIs (grouped by subsystem) ─────────────────────────
191
+ if (apis.length > 0) {
192
+ lines.push(" subgraph APIs[\"Arduino APIs\"]");
193
+ lines.push(" direction LR");
194
+ const groups = {
195
+ "GPIO": ["digitalWrite", "digitalRead", "analogWrite", "analogRead", "pinMode"],
196
+ "Serial": ["Serial", "println", "print", "read", "write"],
197
+ "Audio": ["tone", "noTone"],
198
+ "Timing": ["millis", "micros", "delay", "delayMicroseconds"],
199
+ };
200
+ const accounted = new Set();
201
+ for (const [label, members] of Object.entries(groups)) {
202
+ const present = apis.filter((a) => members.includes(a));
203
+ if (present.length > 0) {
204
+ present.forEach((p) => accounted.add(p));
205
+ lines.push(` subgraph ${label.toLowerCase()}[${label}]`);
206
+ lines.push(" direction LR");
207
+ for (const name of present) {
208
+ lines.push(` ${name}${safeLabel(name)}:::api`);
209
+ }
210
+ lines.push(" end");
211
+ }
212
+ }
213
+ const remaining = apis.filter((a) => !accounted.has(a));
214
+ if (remaining.length > 0) {
215
+ lines.push(" subgraph other[\"Other\"]");
216
+ lines.push(" direction LR");
217
+ for (const name of remaining) {
218
+ lines.push(` ${name}${safeLabel(name)}:::api`);
219
+ }
220
+ lines.push(" end");
221
+ }
222
+ lines.push(" end");
223
+ lines.push("");
224
+ }
225
+ // --- State Variables ─────────────────────────────────────────────
226
+ if (userVars.length > 0) {
227
+ lines.push(" subgraph Vars[\"State Variables\"]");
228
+ lines.push(" direction LR");
229
+ for (const name of userVars) {
230
+ lines.push(` ${name}[(${esc(name)})]:::var`);
231
+ }
232
+ lines.push(" end");
233
+ lines.push("");
234
+ }
235
+ // --- Custom Functions ────────────────────────────────────────────
236
+ if (userFns.length > 0) {
237
+ lines.push(" subgraph Fns[\"Functions\"]");
238
+ lines.push(" direction LR");
239
+ for (const name of userFns) {
240
+ lines.push(` ${name}[[${esc(name)}]]:::fn`);
241
+ }
242
+ lines.push(" end");
243
+ lines.push("");
244
+ }
245
+ // --- Other Symbols (classes, enums, external refs) ───────────────
246
+ if (other.length > 0) {
247
+ lines.push(" subgraph Misc[\"Other\"]");
248
+ lines.push(" direction LR");
249
+ for (const name of other) {
250
+ lines.push(` ${name}${safeLabel(name)}`);
251
+ }
252
+ lines.push(" end");
253
+ lines.push("");
254
+ }
255
+ // --- Board descriptor (collapsed into one node) ──────────────────
256
+ if (boardUsed.length > 0) {
257
+ const chain = boardUsed.join(" → ");
258
+ lines.push(` board_collapsed[\"Board: ${esc(chain)}\"]:::board`);
259
+ lines.push("");
260
+ }
261
+ // ── 4. Edges: cross-category only, dotted ────────────────────────
262
+ const drawnEdges = new Set();
263
+ for (const name of relevant) {
264
+ const node = callGraph.nodes.get(name);
265
+ if (!node)
266
+ continue;
267
+ for (const dep of node.dependencies) {
268
+ if (!relevant.has(dep))
269
+ continue;
270
+ if (dep === "__top_level__")
271
+ continue;
272
+ const nameCat = _category(name);
273
+ const depCat = _category(dep);
274
+ // Only draw edges that cross category boundaries.
275
+ // Intra-category edges are implicit from the subgraph containment.
276
+ if (nameCat !== depCat) {
277
+ const key = `${name}-->${dep}`;
278
+ if (!drawnEdges.has(key)) {
279
+ drawnEdges.add(key);
280
+ lines.push(` ${name} -.-> ${dep}`);
281
+ }
282
+ }
283
+ }
284
+ }
285
+ // Board chain connections
286
+ if (boardUsed.length > 0) {
287
+ for (const ep of entry) {
288
+ lines.push(` ${ep} -.-> board_collapsed`);
289
+ }
290
+ }
291
+ lines.push("```");
292
+ return lines.join("\n");
293
+ // ── local helpers ────────────────────────────────────────────────
294
+ function _category(name) {
295
+ if (entry.has(name))
296
+ return "entry";
297
+ if (isr.has(name))
298
+ return "isr";
299
+ if (async.has(name))
300
+ return "async";
301
+ if (halObjects.includes(name))
302
+ return "hal";
303
+ if (userVars.includes(name))
304
+ return "var";
305
+ if (userFns.includes(name))
306
+ return "fn";
307
+ if (apis.includes(name))
308
+ return "api";
309
+ if (other.includes(name))
310
+ return "other";
311
+ return "unknown";
312
+ }
313
+ }
314
+ /**
315
+ * Build a specialized flow diagram for ISR (Interrupt) handlers.
316
+ * Shows only the paths starting from hardware events to their deep dependencies.
317
+ */
318
+ export function buildInterruptMap(flow, callGraph) {
319
+ const isrs = flow.isrHandlers;
320
+ if (isrs.length === 0)
321
+ return "";
322
+ const lines = [];
323
+ lines.push("```mermaid");
324
+ lines.push("%%{init: { 'theme': 'base', 'themeVariables': { 'primaryColor': '#ffebee', 'edgeColor': '#c62828' } } }%%");
325
+ lines.push("flowchart LR");
326
+ lines.push(" classDef isr fill:#f44336,stroke:#b71c1c,color:#fff,font-weight:bold;");
327
+ lines.push(" classDef logic fill:#ffffff,stroke:#c62828,color:#b71c1c,stroke-width:1px;");
328
+ lines.push(" classDef api fill:#fff9c4,stroke:#fbc02d,color:#333,font-size:11px;");
329
+ const visited = new Set();
330
+ const edges = new Set();
331
+ function walk(name, isRoot = false) {
332
+ if (visited.has(name))
333
+ return;
334
+ visited.add(name);
335
+ const node = callGraph.nodes.get(name);
336
+ const style = isRoot ? ":::isr" : (isArduinoAPI(name) ? ":::api" : ":::logic");
337
+ const shape = isRoot ? `[[${esc(name)}]]` : `(${esc(name)})`;
338
+ lines.push(` ${name}${shape}${style}`);
339
+ if (node) {
340
+ for (const dep of node.dependencies) {
341
+ if (dep === "__top_level__" || NOISE.has(dep))
342
+ continue;
343
+ const edge = `${name}-->${dep}`;
344
+ if (!edges.has(edge)) {
345
+ edges.add(edge);
346
+ lines.push(` ${name} -- calls --> ${dep}`);
347
+ }
348
+ walk(dep);
349
+ }
350
+ }
351
+ }
352
+ for (const isr of isrs) {
353
+ walk(isr, true);
354
+ }
355
+ lines.push("```");
356
+ return lines.join("\n");
357
+ }
358
+ // ── Pin Usage Diagram ───────────────────────────────────────────────────────
359
+ /**
360
+ * Build a pie chart showing pin usage distribution.
361
+ */
362
+ export function buildPinUsagePie(gpio, summary) {
363
+ const lines = [];
364
+ lines.push("```mermaid");
365
+ lines.push("%%{init: { 'theme': 'base', 'themeVariables': { 'pie1': '#4caf50', 'pie2': '#2196f3', 'pie3': '#ff9800', 'pie4': '#f44336', 'pie5': '#9c27b0', 'pie6': '#795548', 'pie7': '#9e9e9e' } } }%%");
366
+ lines.push("pie showData");
367
+ lines.push(" title Pin Usage Distribution");
368
+ const modeCounts = {};
369
+ for (const pin of gpio) {
370
+ modeCounts[pin.mode] = (modeCounts[pin.mode] ?? 0) + 1;
371
+ }
372
+ const modeLabels = {
373
+ OUTPUT: "Digital Output",
374
+ INPUT: "Digital Input",
375
+ INPUT_PULLUP: "Input w/ Pullup",
376
+ INPUT_PULLDOWN: "Input w/ Pulldown",
377
+ ANALOG: "Analog Input",
378
+ PWM: "PWM Output",
379
+ };
380
+ for (const [mode, count] of Object.entries(modeCounts)) {
381
+ const label = modeLabels[mode] ?? mode;
382
+ lines.push(` "${label}" : ${count}`);
383
+ }
384
+ if (summary.unusedPins > 0) {
385
+ lines.push(` "Unused" : ${summary.unusedPins}`);
386
+ }
387
+ lines.push("```");
388
+ return lines.join("\n");
389
+ }
390
+ // ── Pin Detail Table (not a diagram, but embedded in md-writer) ────────────
391
+ /**
392
+ * Build a markdown table of individual pin assignments.
393
+ */
394
+ export function buildPinDetailTable(gpio) {
395
+ if (gpio.length === 0)
396
+ return "_No GPIO pins configured._";
397
+ const lines = [];
398
+ lines.push("| Pin | Mode | Peripheral Role |");
399
+ lines.push("|-----|------|-----------------|");
400
+ for (const pin of gpio) {
401
+ const role = pin.peripheralRole ?? "—";
402
+ lines.push(`| \`${esc(pin.pinName)}\` | ${pin.mode} | ${role} |`);
403
+ }
404
+ return lines.join("\n");
405
+ }
406
+ // ── Peripheral Allocation Diagram ───────────────────────────────────────────
407
+ /**
408
+ * Build a flowchart showing peripheral resource allocation.
409
+ */
410
+ export function buildPeripheralDiagram(peripherals) {
411
+ const lines = [];
412
+ lines.push("```mermaid");
413
+ lines.push("%%{init: { 'theme': 'base', 'themeVariables': { 'primaryColor': '#f3e5f5', 'edgeColor': '#7b1fa2' } } }%%");
414
+ lines.push("flowchart LR");
415
+ lines.push(" classDef peri fill:#f3e5f5,stroke:#8e24aa,color:#4a148c,stroke-width:1px;");
416
+ lines.push(" classDef pin fill:#ffffff,stroke:#9c27b0,color:#333,stroke-width:1px;");
417
+ const drawn = new Set();
418
+ for (const p of peripherals) {
419
+ const subgraphId = p.displayName.replace(/[^a-zA-Z0-9_]/g, "_");
420
+ if (!drawn.has(subgraphId)) {
421
+ drawn.add(subgraphId);
422
+ lines.push(indent(1, `subgraph ${subgraphId}${safeLabel(p.displayName)}`));
423
+ lines.push(indent(2, `direction LR`));
424
+ // List pins assigned to this peripheral
425
+ for (const pin of peripherals.filter((pp) => pp.displayName === p.displayName)) {
426
+ for (const pinName of pin.pins) {
427
+ const pinId = `${subgraphId}_${pinName.replace(/[^a-zA-Z0-9_]/g, "_")}`;
428
+ lines.push(indent(2, `${pinId}${safeLabel(pinName)}:::pin`));
429
+ }
430
+ }
431
+ lines.push(indent(1, "end"));
432
+ lines.push(indent(1, `${subgraphId}:::peri`));
433
+ }
434
+ }
435
+ // If no peripherals are active, show a note
436
+ if (peripherals.length === 0) {
437
+ lines.push(indent(1, "NONE[No peripherals configured]"));
438
+ }
439
+ lines.push("```");
440
+ return lines.join("\n");
441
+ }
442
+ // ── Peripheral Detail Table ─────────────────────────────────────────────────
443
+ export function buildPeripheralTable(peripherals) {
444
+ if (peripherals.length === 0)
445
+ return "_No peripherals in use._";
446
+ const lines = [];
447
+ lines.push("| Peripheral | Instance | Pins |");
448
+ lines.push("|------------|----------|------|");
449
+ for (const p of peripherals) {
450
+ const pinList = p.pins.map((n) => `\`${esc(n)}\``).join(", ") || "—";
451
+ lines.push(`| ${p.displayName} | ${p.instance} | ${pinList} |`);
452
+ }
453
+ return lines.join("\n");
454
+ }
455
+ // ── Async Task Timeline ─────────────────────────────────────────────────────
456
+ /**
457
+ * Build a Gantt chart showing async task intervals (if timing data is available).
458
+ */
459
+ export function buildAsyncTaskDiagram(tasks) {
460
+ const lines = [];
461
+ lines.push("```mermaid");
462
+ lines.push("gantt");
463
+ lines.push(" title Async Task Schedule");
464
+ lines.push(" dateFormat X");
465
+ lines.push(" axisFormat %");
466
+ for (const task of tasks) {
467
+ const intervalMs = task.intervalMs ?? 1000; // default 1000ms for unknown
468
+ // Show one "cycle" of the task
469
+ lines.push(` section ${esc(task.name)}`);
470
+ lines.push(` ${esc(task.name)} : 0, ${intervalMs}`);
471
+ }
472
+ if (tasks.length === 0) {
473
+ lines.push(" section No Async Tasks");
474
+ lines.push(" idle : 0, 1000");
475
+ }
476
+ lines.push("```");
477
+ return lines.join("\n");
478
+ }
479
+ // ── Heap Estimation Diagram ─────────────────────────────────────────────────
480
+ /**
481
+ * Build a pie chart showing static memory allocation breakdown.
482
+ */
483
+ export function buildHeapPie(heap) {
484
+ const lines = [];
485
+ lines.push("```mermaid");
486
+ lines.push("%%{init: { 'theme': 'base', 'themeVariables': { 'pie1': '#03a9f4', 'pie2': '#673ab7', 'pie3': '#ff5722', 'pie4': '#4caf50' } } }%%");
487
+ lines.push("pie showData");
488
+ lines.push(" title Static Memory Allocation (bytes)");
489
+ if (heap.globalVariables.length > 0) {
490
+ let varTotal = 0;
491
+ for (const v of heap.globalVariables)
492
+ varTotal += v.estimatedBytes;
493
+ if (varTotal > 0)
494
+ lines.push(` "Global Variables" : ${varTotal}`);
495
+ }
496
+ let structTotal = 0;
497
+ for (const [, size] of Object.entries(heap.structSizes)) {
498
+ structTotal += size;
499
+ }
500
+ if (structTotal > 0)
501
+ lines.push(` "Struct/Class Instances" : ${structTotal}`);
502
+ let strTotal = 0;
503
+ for (const sl of heap.stringLiterals) {
504
+ strTotal += sl.estimatedBytes;
505
+ }
506
+ if (strTotal > 0)
507
+ lines.push(` "String Literals" : ${strTotal}`);
508
+ if (heap.totalStaticBytes === 0) {
509
+ lines.push(` "No static allocations" : 1`);
510
+ }
511
+ lines.push("```");
512
+ // Add summary data table
513
+ lines.push("");
514
+ lines.push("| Category | Bytes |");
515
+ lines.push("|----------|-------|");
516
+ let varBytes = 0;
517
+ for (const v of heap.globalVariables)
518
+ varBytes += v.estimatedBytes;
519
+ lines.push(`| Global Variables | ${varBytes} |`);
520
+ lines.push(`| Struct/Class Sizes | ${structTotal} |`);
521
+ lines.push(`| String Literals | ${strTotal} |`);
522
+ lines.push(`| **Total Static** | **${heap.totalStaticBytes}** |`);
523
+ lines.push(`| Est. Max Stack Depth | ${heap.estimatedStackDepth} frames |`);
524
+ return lines.join("\n");
525
+ }
526
+ /**
527
+ * Build a vertical "stack" visualization of static memory allocation.
528
+ */
529
+ export function buildMemoryMap(heap) {
530
+ const lines = [];
531
+ lines.push("```mermaid");
532
+ lines.push("%%{init: { 'theme': 'base', 'themeVariables': { 'primaryColor': '#37474f', 'edgeColor': '#ffffff' } } }%%");
533
+ lines.push("flowchart TD");
534
+ lines.push(" classDef section fill:#263238,stroke:#eceff1,color:#fff,font-weight:bold;");
535
+ lines.push(" classDef item fill:#455a64,stroke:#607d8b,color:#cfd8dc,font-size:12px;");
536
+ lines.push(" classDef stack fill:#eceff1,stroke:#b0bec5,color:#455a64,stroke-dasharray: 5 5;");
537
+ lines.push(" subgraph SRAM[\"SRAM Memory Layout\"]");
538
+ lines.push(" direction TB");
539
+ // Stack section
540
+ lines.push(" subgraph StackS[\"ESTIMATED STACK\"]");
541
+ lines.push(` StackFrame[\"~${heap.estimatedStackDepth} Recursive Frames\"]:::stack`);
542
+ lines.push(" end");
543
+ lines.push(" StackS:::section");
544
+ // Globals section
545
+ if (heap.globalVariables.length > 0) {
546
+ lines.push(" subgraph GlobalsS[\"GLOBAL VARIABLES\"]");
547
+ for (const v of heap.globalVariables.slice(0, 10)) {
548
+ lines.push(` v_${v.name.replace(/[^a-zA-Z0-9]/g, "_")}[\"${esc(v.name)} (${v.estimatedBytes}b)\"]:::item`);
549
+ }
550
+ if (heap.globalVariables.length > 10) {
551
+ lines.push(` v_more[\"...and ${heap.globalVariables.length - 10} more\"]:::item`);
552
+ }
553
+ lines.push(" end");
554
+ lines.push(" GlobalsS:::section");
555
+ }
556
+ // Strings section
557
+ if (heap.stringLiterals.length > 0) {
558
+ lines.push(" subgraph StringsS[\"STRING LITERALS\"]");
559
+ for (let i = 0; i < Math.min(heap.stringLiterals.length, 5); i++) {
560
+ const s = heap.stringLiterals[i];
561
+ const preview = s.value.length > 15 ? s.value.substring(0, 12) + "..." : s.value;
562
+ lines.push(` s_${i}[\"\\\"${esc(preview)}\\\" (${s.estimatedBytes}b)\"]:::item`);
563
+ }
564
+ if (heap.stringLiterals.length > 5) {
565
+ lines.push(` s_more[\"...and ${heap.stringLiterals.length - 5} more\"]:::item`);
566
+ }
567
+ lines.push(" end");
568
+ lines.push(" StringsS:::section");
569
+ }
570
+ lines.push(" end");
571
+ lines.push("```");
572
+ return lines.join("\n");
573
+ }
574
+ /**
575
+ * Build a visualization of the deepest call paths.
576
+ */
577
+ export function buildStackPathsMap(paths) {
578
+ if (!paths || paths.length === 0)
579
+ return "_No deep call paths detected._";
580
+ const lines = [];
581
+ lines.push("```mermaid");
582
+ lines.push("%%{init: { 'theme': 'base', 'themeVariables': { 'primaryColor': '#e1f5fe', 'edgeColor': '#0288d1' } } }%%");
583
+ lines.push("flowchart LR");
584
+ lines.push(" classDef frame fill:#ffffff,stroke:#0288d1,color:#01579b,font-size:11px;");
585
+ lines.push(" classDef entry fill:#4caf50,stroke:#2e7d32,color:#fff,font-weight:bold;");
586
+ paths.forEach((path, pathIdx) => {
587
+ const pathNodes = [];
588
+ path.forEach((node, nodeIdx) => {
589
+ const id = `p${pathIdx}_n${nodeIdx}`;
590
+ const cls = nodeIdx === 0 ? ":::entry" : ":::frame";
591
+ lines.push(` ${id}[${esc(node)}]${cls}`);
592
+ pathNodes.push(id);
593
+ });
594
+ for (let i = 0; i < pathNodes.length - 1; i++) {
595
+ lines.push(` ${pathNodes[i]} --> ${pathNodes[i + 1]}`);
596
+ }
597
+ });
598
+ lines.push("```");
599
+ return lines.join("\n");
600
+ }
601
+ // ── Peripheral Conflicts ────────────────────────────────────────────────────
602
+ // ── Peripheral Conflicts ────────────────────────────────────────────────────
603
+ /**
604
+ * Build a conflict table for the markdown report.
605
+ */
606
+ export function buildConflictTable(conflicts) {
607
+ if (conflicts.length === 0)
608
+ return "_No peripheral conflicts detected._";
609
+ const lines = [];
610
+ lines.push("| Severity | Pin | Peripheral | Role | Suggestion |");
611
+ lines.push("|----------|-----|------------|------|------------|");
612
+ for (const c of conflicts) {
613
+ const sev = c.severity === "error" ? "🔴 Error" : "🟡 Warning";
614
+ lines.push(`| ${sev} | \`${esc(c.pinName)}\` | ${esc(c.peripheralName)} | ${esc(c.role)} | ${esc(c.suggestion)} |`);
615
+ }
616
+ return lines.join("\n");
617
+ }
618
+ // ── Additional Diagnostic Sections ──────────────────────────────────────────
619
+ /**
620
+ * Build a Mermaid dependency graph of imported modules.
621
+ */
622
+ export function buildModuleGraphDiagram(graph) {
623
+ if (!graph || graph.nodes.length === 0)
624
+ return "_No module data available._";
625
+ const lines = [];
626
+ lines.push("```mermaid");
627
+ lines.push("flowchart TD");
628
+ lines.push(" classDef module_file fill:#fafafa,stroke:#9e9e9e,color:#333,stroke-width:1px;");
629
+ const uniqueNodes = new Set(graph.nodes);
630
+ for (const node of uniqueNodes) {
631
+ // Ensure ID starts with a letter and contains only valid chars
632
+ let id = node.replace(/[^a-zA-Z0-9]/g, "_").replace(/^_+/, "");
633
+ if (/^[0-9]/.test(id))
634
+ id = "m" + id;
635
+ if (!id)
636
+ id = "module";
637
+ lines.push(` ${id}${safeLabel(node)}:::module_file`);
638
+ }
639
+ for (const edge of graph.edges) {
640
+ let from = edge.from.replace(/[^a-zA-Z0-9]/g, "_").replace(/^_+/, "");
641
+ if (/^[0-9]/.test(from))
642
+ from = "m" + from;
643
+ let to = edge.to.replace(/[^a-zA-Z0-9]/g, "_").replace(/^_+/, "");
644
+ if (/^[0-9]/.test(to))
645
+ to = "m" + to;
646
+ lines.push(` ${from} --> ${to}`);
647
+ }
648
+ lines.push("```");
649
+ return lines.join("\n");
650
+ }
651
+ /**
652
+ * Build a table showing symbols removed by tree shaking.
653
+ */
654
+ export function buildTreeShakingTable(report) {
655
+ if (!report || report.removedSymbols.length === 0) {
656
+ return "_No symbols were removed by tree shaking._";
657
+ }
658
+ const lines = [];
659
+ lines.push("| Removed Symbol |");
660
+ lines.push("|----------------|");
661
+ for (const sym of report.removedSymbols) {
662
+ lines.push(`| \`${esc(sym)}\` |`);
663
+ }
664
+ return lines.join("\n");
665
+ }
666
+ /**
667
+ * Build a table showing build timing phases.
668
+ */
669
+ export function buildTimingTable(timing) {
670
+ if (!timing || !timing.phases || Object.keys(timing.phases).length === 0) {
671
+ return "_No timing data available._";
672
+ }
673
+ const lines = [];
674
+ lines.push("| Phase | Time (ms) |");
675
+ lines.push("|-------|-----------|");
676
+ for (const [phase, ms] of Object.entries(timing.phases)) {
677
+ lines.push(`| ${phase} | ${ms.toFixed(2)} |`);
678
+ }
679
+ lines.push(`| **Total** | **${timing.totalMs.toFixed(2)}** |`);
680
+ return lines.join("\n");
681
+ }
@@ -0,0 +1,6 @@
1
+ import type { ProgramIR } from "../api/index.js";
2
+ import type { GeneratedOutputs } from "../types.js";
3
+ import type { EmitterOptions } from "./emitters/emitter-context.js";
4
+ export { type EmitterOptions } from "./emitters/emitter-context.js";
5
+ export declare function registerAllEnumNames(enums: any[]): void;
6
+ export declare function emitCpp(program: ProgramIR, options: EmitterOptions): GeneratedOutputs;