@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,50 @@
1
+ interface AutoWireNode {
2
+ tag: string;
3
+ id?: string;
4
+ text?: string;
5
+ children?: AutoWireNode[];
6
+ options?: Array<{
7
+ value: string;
8
+ text: string;
9
+ }>;
10
+ name?: string;
11
+ checked?: boolean;
12
+ href?: string;
13
+ /** Rich-text runs (present only for text nodes with mixed inline content).
14
+ * A run may carry an href (inline <a href>); those make the node a link
15
+ * target that needs a click handler so it's hit-testable. */
16
+ runs?: Array<{
17
+ href?: string;
18
+ }>;
19
+ /** True when text contains a `{expr}` interpolation; auto-wire synthesizes an
20
+ * implicit text binding for it (no id required — {expr} references a signal). */
21
+ hasInterpolation?: boolean;
22
+ /** Declarative on:* event handlers (named-function references). Each value
23
+ * names an exported TS function emitted as a standalone C++ function. */
24
+ events?: {
25
+ click?: string;
26
+ hold?: string;
27
+ release?: string;
28
+ change?: string;
29
+ };
30
+ /** Declarative bind:* two-way bindings (signal names). bind:text on <input>
31
+ * composes a text binding + an input binding; bind:value on <range>/<check>
32
+ * composes a value binding + a change/click handler. */
33
+ bind?: {
34
+ text?: string;
35
+ value?: string;
36
+ };
37
+ }
38
+ export declare function getRadioGroups(): Map<string, {
39
+ id: string;
40
+ nodeIndex: number;
41
+ }[]>;
42
+ /** Register a screen ID → index mapping (called during multi-screen setup). */
43
+ export declare function registerScreenId(id: string, index: number): void;
44
+ /** Resolve a href="#screenId" to a screen index, or undefined if unknown. */
45
+ export declare function resolveScreenHref(href: string | undefined): number | undefined;
46
+ /**
47
+ * Walk the styled tree and auto-wire built-in element behaviors.
48
+ */
49
+ export declare function autoWireElements(treeName: string, root: AutoWireNode, startIndex?: number): number;
50
+ export {};
@@ -0,0 +1,218 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Auto-wire built-in elements — when the transpiler encounters <check>,
3
+ // <select>, or <button> in the HTML, it automatically registers the default
4
+ // behavior (onClick handlers, visual bindings) so the author doesn't have to.
5
+ //
6
+ // Authors can still override or add to this behavior in their TS code.
7
+ // For custom elements, use <view> + <text> + manual bindings.
8
+ // ---------------------------------------------------------------------------
9
+ import { recordClickHandler, recordBinding, markRunNode, lowerInterpolationText } from "./transformers/ui-call-resolver.js";
10
+ import { recordInputBinding } from "./transformers/ui-reactive.js";
11
+ // Track radio groups for mutual exclusion
12
+ const radioGroups = new Map();
13
+ // Track screen IDs → screen indices for link navigation.
14
+ const screenIdMap = new Map();
15
+ export function getRadioGroups() { return radioGroups; }
16
+ /** Register a screen ID → index mapping (called during multi-screen setup). */
17
+ export function registerScreenId(id, index) {
18
+ screenIdMap.set(id, index);
19
+ }
20
+ /** Resolve a href="#screenId" to a screen index, or undefined if unknown. */
21
+ export function resolveScreenHref(href) {
22
+ if (!href)
23
+ return undefined;
24
+ const target = href.startsWith("#") ? href.slice(1) : href;
25
+ return screenIdMap.get(target);
26
+ }
27
+ /**
28
+ * Walk the styled tree and auto-wire built-in element behaviors.
29
+ */
30
+ export function autoWireElements(treeName, root, startIndex = 0) {
31
+ if (startIndex === 0)
32
+ radioGroups.clear();
33
+ let nodeIndex = startIndex;
34
+ const walk = (node) => {
35
+ const currentIndex = nodeIndex++;
36
+ // Record run-bearing node indices so the binding resolver can reject
37
+ // PROP_TEXT bindings on them (runs are static-only).
38
+ if (node.runs && node.runs.length > 0)
39
+ markRunNode(currentIndex);
40
+ // Auto-wire nodes with an id, <a href> links, run-bearing link nodes
41
+ // (an inline <a href> inside a paragraph makes the paragraph a tap target),
42
+ // {expr} text interpolations, and on:* declarative event handlers. The last
43
+ // two may have no id — {expr} references a signal; on:* names a function.
44
+ const hasLinkRun = !!node.runs?.some(r => r.href);
45
+ const hasEvents = !!node.events && Object.keys(node.events).length > 0;
46
+ const hasBind = !!node.bind && Object.keys(node.bind).length > 0;
47
+ if (node.id || node.href || hasLinkRun || node.hasInterpolation || hasEvents || hasBind) {
48
+ autoWireNode(treeName, node, currentIndex);
49
+ }
50
+ node.children?.forEach(walk);
51
+ };
52
+ walk(root);
53
+ return nodeIndex;
54
+ }
55
+ function autoWireNode(treeName, node, nodeIndex) {
56
+ // {expr} text interpolation → synthesize an implicit text binding. This runs
57
+ // before the id/href guard below because an interpolation node may have no id
58
+ // ({expr} references a signal, not a screen.<id> handle). recordBinding rejects
59
+ // run-bearing nodes via the run-text-binding-conflict guard, so inline+interp
60
+ // combinations are caught there rather than here.
61
+ if (node.hasInterpolation && node.text) {
62
+ const cppBody = lowerInterpolationText(node.text);
63
+ if (cppBody) {
64
+ recordBinding({
65
+ nodeIndex,
66
+ property: "text",
67
+ fnName: `__ui_interp_${nodeIndex}`,
68
+ cppBody,
69
+ });
70
+ }
71
+ }
72
+ // bind:* declarative two-way bindings → compose a read-binding (signal→node)
73
+ // with a write-callback (node→signal). bind:text on <input> uses a text
74
+ // binding + an input binding (fires on keyboard commit). bind:value on
75
+ // <range>/<check> uses a value binding + a change/click handler.
76
+ if (node.bind) {
77
+ if (node.bind.text) {
78
+ const sig = node.bind.text;
79
+ // Read: signal → node text (reuses the binding table).
80
+ recordBinding({
81
+ nodeIndex,
82
+ property: "text",
83
+ fnName: `__ui_bindtext_${nodeIndex}`,
84
+ cppBody: `snprintf(buf, size, "%s", ${sig});`,
85
+ });
86
+ // Write: keyboard commit → signal.set(text).
87
+ recordInputBinding({
88
+ nodeIndex,
89
+ cbFnName: `__ui_bindtext_cb_${nodeIndex}`,
90
+ cbFnBody: `${sig}.set(std::string(text));`,
91
+ });
92
+ }
93
+ if (node.bind.value) {
94
+ const sig = node.bind.value;
95
+ // Read: signal → node value.
96
+ recordBinding({
97
+ nodeIndex,
98
+ property: "value",
99
+ fnName: `__ui_bindval_${nodeIndex}`,
100
+ cppExpr: sig,
101
+ });
102
+ // Write: range drag / check toggle → signal.set(value).
103
+ recordClickHandler({
104
+ nodeIndex,
105
+ kind: node.tag === "check" ? "click" : "rangechange",
106
+ fnName: `__ui_bindval_cb_${nodeIndex}`,
107
+ callbackBody: `${sig}.set(__ui_nodes[${nodeIndex}].value);`,
108
+ });
109
+ }
110
+ }
111
+ // on:* declarative event handlers → record click/hold/release/change handlers
112
+ // that reference the named C++ function by name (no inlined body). The named
113
+ // function comes from the author's `export function name() {...}` in TS,
114
+ // which the transpiler emits as a standalone C++ function.
115
+ if (node.events) {
116
+ const kindMap = { click: "click", hold: "hold", release: "release", change: "change" };
117
+ for (const key of Object.keys(node.events)) {
118
+ const fnName = node.events[key];
119
+ if (fnName) {
120
+ recordClickHandler({
121
+ nodeIndex,
122
+ kind: kindMap[key],
123
+ fnName,
124
+ callbackBody: "",
125
+ isNamedRef: true,
126
+ });
127
+ }
128
+ }
129
+ }
130
+ // The check/select/radio branches generate fnNames from node.id, so they
131
+ // require one. The href (navigation) branch below works with or without id.
132
+ // Run-bearing link nodes also work without id (handler body is a no-op; the
133
+ // real navigation happens via the run hit-test in the tap path).
134
+ const hasLinkRun = !!node.runs?.some(r => r.href);
135
+ if (!node.id && !node.href && !hasLinkRun)
136
+ return;
137
+ if (node.tag === "check") {
138
+ // Auto-wire: onClick toggles value 0↔1
139
+ recordClickHandler({
140
+ nodeIndex,
141
+ kind: "click",
142
+ fnName: `__ui_${node.id}_autoclick`,
143
+ callbackBody: `__ui_nodes[${nodeIndex}].value = (__ui_nodes[${nodeIndex}].value > 0 ? 0 : 1);`,
144
+ });
145
+ }
146
+ if (node.tag === "select") {
147
+ // Use parsed options (from <option> children) or fallback to comma text
148
+ const options = node.options && node.options.length > 0
149
+ ? node.options.map(o => o.text)
150
+ : (node.text || "").split(",").map(s => s.trim()).filter(Boolean);
151
+ const count = Math.max(options.length, 2);
152
+ // Auto-wire: onClick cycles value 0..count-1
153
+ recordClickHandler({
154
+ nodeIndex,
155
+ kind: "click",
156
+ fnName: `__ui_${node.id}_autoclick`,
157
+ callbackBody: `__ui_nodes[${nodeIndex}].value = (__ui_nodes[${nodeIndex}].value + 1) % ${count};`,
158
+ });
159
+ // Auto-bind text to show the current option via snprintf if/else chain
160
+ const branches = options.map((opt, i) => {
161
+ if (i === 0)
162
+ return `if (__ui_nodes[${nodeIndex}].value == 0) { snprintf(buf, size, "%s", "${opt}"); }`;
163
+ return `else if (__ui_nodes[${nodeIndex}].value == ${i}) { snprintf(buf, size, "%s", "${opt}"); }`;
164
+ }).join(" ");
165
+ const elseBranch = `else { snprintf(buf, size, "%s", "${options[0] || ""}"); }`;
166
+ recordBinding({
167
+ nodeIndex,
168
+ property: "text",
169
+ fnName: `__ui_${node.id}_autotext`,
170
+ cppBody: branches + " " + elseBranch,
171
+ });
172
+ }
173
+ if (node.tag === "radio" && node.name) {
174
+ // Register this radio in its group
175
+ const groupName = node.name;
176
+ if (!radioGroups.has(groupName))
177
+ radioGroups.set(groupName, []);
178
+ const group = radioGroups.get(groupName);
179
+ group.push({ id: node.id, nodeIndex });
180
+ // Auto-wire: onClick clears all radios in the group, then selects this one.
181
+ // The generated C++ references the radio group table by index.
182
+ const groupIdx = Array.from(radioGroups.keys()).indexOf(groupName);
183
+ recordClickHandler({
184
+ nodeIndex,
185
+ kind: "click",
186
+ fnName: `__ui_${node.id}_autoclick`,
187
+ callbackBody: `for (uint8_t __r = 0; __r < __ui_radio_groups[${groupIdx}].count; __r++) { uint16_t __rn = __ui_radio_groups[${groupIdx}].nodeIndices[__r]; __ui_nodes[__rn].value = 0; ui_mark_dirty(__rn); } __ui_nodes[${nodeIndex}].value = 1; ui_mark_dirty(${nodeIndex});`,
188
+ });
189
+ }
190
+ // Auto-wire <a href="#screenId"> links: onClick navigates to the target screen.
191
+ if (node.href) {
192
+ const targetScreen = resolveScreenHref(node.href);
193
+ if (targetScreen !== undefined) {
194
+ recordClickHandler({
195
+ nodeIndex,
196
+ kind: "click",
197
+ fnName: `__ui_${node.id ?? "link" + nodeIndex}_nav`,
198
+ callbackBody: `ui_navigate(${targetScreen});`,
199
+ });
200
+ }
201
+ else {
202
+ console.error(`[auto-wire] WARNING: <a href="${node.href}"> (id=${node.id}) target screen not found. Known screens: ${[...screenIdMap.keys()].join(", ")}`);
203
+ }
204
+ }
205
+ else if (hasLinkRun) {
206
+ // Run-bearing link node (an inline <a href> inside a paragraph). The link
207
+ // targets live on the runs and are resolved into the model at lower time;
208
+ // the tap path calls ui_rich_link_hit / richLinkHit to pick the target.
209
+ // Register a no-op click handler so the node is hit-testable in the first
210
+ // place (hit-test only considers nodes with a registered handler).
211
+ recordClickHandler({
212
+ nodeIndex,
213
+ kind: "click",
214
+ fnName: `__ui_${node.id ?? "richlink" + nodeIndex}_nav`,
215
+ callbackBody: `/* rich-text link; target resolved by ui_rich_link_hit */`,
216
+ });
217
+ }
218
+ }
@@ -0,0 +1,12 @@
1
+ import { ProgramIR } from '../api/index.js';
2
+ import { Diagnostic } from '../types.js';
3
+ /**
4
+ * Validate peripheral config values for common unit mistakes.
5
+ *
6
+ * Scans the program IR for cuttlefish-call nodes that configure peripherals
7
+ * with bare numbers and emits warnings when values look suspicious.
8
+ *
9
+ * @param program - The program IR to validate
10
+ * @returns Array of diagnostics for suspicious peripheral config values
11
+ */
12
+ export declare function validateUnitSuspicion(program: ProgramIR): Diagnostic[];
@@ -0,0 +1,296 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Unit Suspicion Validation
3
+ //
4
+ // Warns when bare numbers passed to peripheral config methods look suspicious.
5
+ // For example, passing 9600 to an SPI frequency (which expects Hz, not baud)
6
+ // or passing 100 to I2C speed (which expects Hz, not kHz).
7
+ //
8
+ // This validator complements the two-tier peripheral config approach:
9
+ // - Enum values (BaudRate._9600, I2CSpeed.FAST, etc.) are always safe
10
+ // - Bare numbers in .config builders are validated here for common mistakes
11
+ // ---------------------------------------------------------------------------
12
+ // Standard baud rates for UART
13
+ const KNOWN_BAUD_RATES = new Set([
14
+ 300, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200,
15
+ 230400, 460800, 921600,
16
+ ]);
17
+ // Standard I2C clock speeds in Hz
18
+ const KNOWN_I2C_SPEEDS = new Set([
19
+ 100_000, // Standard (100 kHz)
20
+ 400_000, // Fast (400 kHz)
21
+ 1_000_000, // Fast Plus (1 MHz)
22
+ 3_400_000, // High Speed (3.4 MHz)
23
+ ]);
24
+ // Standard SPI clock frequencies in Hz
25
+ const KNOWN_SPI_FREQUENCIES = new Set([
26
+ 125_000, // 125 kHz
27
+ 250_000, // 250 kHz
28
+ 500_000, // 500 kHz
29
+ 1_000_000, // 1 MHz
30
+ 2_000_000, // 2 MHz
31
+ 4_000_000, // 4 MHz
32
+ 8_000_000, // 8 MHz
33
+ 16_000_000, // 16 MHz
34
+ ]);
35
+ /**
36
+ * Extract a numeric value from an expression IR node.
37
+ * Returns `undefined` if the expression is not a simple numeric literal.
38
+ */
39
+ function extractNumericValue(expr) {
40
+ if (!expr || typeof expr !== 'object')
41
+ return undefined;
42
+ // Direct numeric literal
43
+ if (expr.kind === 'number') {
44
+ return expr.value;
45
+ }
46
+ return undefined;
47
+ }
48
+ /**
49
+ * Check if a baud rate value is suspicious.
50
+ * Warns if the value is not a standard baud rate.
51
+ */
52
+ function checkBaudRate(value) {
53
+ if (KNOWN_BAUD_RATES.has(value))
54
+ return undefined;
55
+ // Check for common mistakes
56
+ // User might have intended a standard rate but typo'd
57
+ for (const known of KNOWN_BAUD_RATES) {
58
+ // Close to a standard rate (within 10%)
59
+ if (value > known * 0.9 && value < known * 1.1) {
60
+ return `Baud rate ${value} is close to standard rate ${known}. Did you mean ${known}?`;
61
+ }
62
+ }
63
+ // Very low values might be confused with kHz
64
+ if (value > 0 && value < 100) {
65
+ return `Baud rate ${value} is unusually low. UART baud rates are typically ≥ 300.`;
66
+ }
67
+ return undefined;
68
+ }
69
+ /**
70
+ * Check if an I2C speed value is suspicious.
71
+ * Warns if the value looks like it's in kHz instead of Hz.
72
+ */
73
+ function checkI2CSpeed(value) {
74
+ if (KNOWN_I2C_SPEEDS.has(value))
75
+ return undefined;
76
+ // Common mistake: passing kHz value instead of Hz
77
+ // e.g., 100 instead of 100000, 400 instead of 400000
78
+ if (value > 0 && value < 10000) {
79
+ // Check if multiplying by 1000 gives a known speed
80
+ const asHz = value * 1000;
81
+ if (KNOWN_I2C_SPEEDS.has(asHz)) {
82
+ return `I2C speed ${value} looks like a kHz value. Did you mean ${asHz} (${value} kHz)? I2C speed is specified in Hz.`;
83
+ }
84
+ }
85
+ // Check for close matches to standard speeds
86
+ for (const known of KNOWN_I2C_SPEEDS) {
87
+ if (value > known * 0.9 && value < known * 1.1) {
88
+ return `I2C speed ${value} is close to standard speed ${known}. Did you mean ${known}?`;
89
+ }
90
+ }
91
+ return undefined;
92
+ }
93
+ /**
94
+ * Check if an SPI frequency value is suspicious.
95
+ * Warns if the value looks like it's in kHz or MHz instead of Hz,
96
+ * or if it's a standard baud rate mistakenly used for SPI.
97
+ */
98
+ function checkSPIFrequency(value) {
99
+ if (KNOWN_SPI_FREQUENCIES.has(value))
100
+ return undefined;
101
+ // Common mistake: passing kHz value instead of Hz
102
+ if (value > 0 && value < 100000) {
103
+ const asHz = value * 1000;
104
+ if (KNOWN_SPI_FREQUENCIES.has(asHz)) {
105
+ return `SPI frequency ${value} looks like a kHz value. Did you mean ${asHz}? SPI frequency is specified in Hz.`;
106
+ }
107
+ }
108
+ // Common mistake: passing MHz value instead of Hz
109
+ if (value > 0 && value <= 16) {
110
+ const asHz = value * 1_000_000;
111
+ if (KNOWN_SPI_FREQUENCIES.has(asHz)) {
112
+ return `SPI frequency ${value} looks like an MHz value. Did you mean ${asHz}? SPI frequency is specified in Hz.`;
113
+ }
114
+ }
115
+ // Check if a standard baud rate was mistakenly used for SPI
116
+ if (KNOWN_BAUD_RATES.has(value)) {
117
+ return `Value ${value} is a standard UART baud rate, not a typical SPI clock frequency. SPI frequencies are usually powers-of-two divisors of the system clock.`;
118
+ }
119
+ // Check for close matches to standard frequencies
120
+ for (const known of KNOWN_SPI_FREQUENCIES) {
121
+ if (value > known * 0.9 && value < known * 1.1) {
122
+ return `SPI frequency ${value} is close to standard frequency ${known}. Did you mean ${known}?`;
123
+ }
124
+ }
125
+ return undefined;
126
+ }
127
+ /**
128
+ * Check a peripheral config value via the appropriate checker. Emits a
129
+ * diagnostic if the value looks like a unit mistake (kHz instead of Hz, a
130
+ * baud rate used as SPI freq, etc.). Only literal numbers are checked —
131
+ * expressions/variables are opaque to this validator.
132
+ */
133
+ function checkConfigValue(kind, rawValue, diagnostics) {
134
+ // HAL ops carry resolved numeric values as `number` when the source arg was
135
+ // a literal, or as `string` expression text otherwise. Only check numbers.
136
+ const value = typeof rawValue === 'number' ? rawValue
137
+ : typeof rawValue === 'string' && /^\d+$/.test(rawValue) ? parseInt(rawValue, 10)
138
+ : null;
139
+ if (value === null)
140
+ return;
141
+ const message = kind === 'baud' ? checkBaudRate(value)
142
+ : kind === 'i2c' ? checkI2CSpeed(value)
143
+ : checkSPIFrequency(value);
144
+ if (message) {
145
+ diagnostics.push({
146
+ severity: 'warning',
147
+ message,
148
+ code: 'unit-suspicion',
149
+ source: 'unit-suspicion-validation',
150
+ });
151
+ }
152
+ }
153
+ /**
154
+ * Recursively scan a statement and its children for suspicious peripheral
155
+ * config values. Recognizes the HAL ops that carry clock/baud/frequency
156
+ * values (i2c.set_clock, uart.begin, spi.begin_transaction) and call
157
+ * statements whose callee matches known config method names.
158
+ */
159
+ function scanStatement(stmt, diagnostics) {
160
+ if (!stmt || typeof stmt !== 'object')
161
+ return;
162
+ const s = stmt;
163
+ // HAL-op statements carry structured operations with resolved values.
164
+ if (stmt.kind === 'hal-op' && s.operation) {
165
+ const op = s.operation;
166
+ switch (op.operation) {
167
+ case 'i2c.set_clock':
168
+ checkConfigValue('i2c', op.hz, diagnostics);
169
+ break;
170
+ case 'uart.begin':
171
+ checkConfigValue('baud', op.baud, diagnostics);
172
+ break;
173
+ // SPI frequency flows through SPISettings construction text, which the
174
+ // HAL op carries as a string — the numeric extraction in
175
+ // checkConfigValue handles bare-digit strings.
176
+ case 'spi.begin_transaction':
177
+ if (typeof op.settings === 'string') {
178
+ // SPISettings({freq}, ...) — try to extract the leading frequency.
179
+ const m = op.settings.match(/^\s*(\d+)/);
180
+ if (m)
181
+ checkConfigValue('spi', parseInt(m[1], 10), diagnostics);
182
+ }
183
+ break;
184
+ }
185
+ }
186
+ // Call statements: match config method names with a numeric literal arg.
187
+ // This catches pre-HAL-resolution calls and library-level config helpers.
188
+ if (stmt.kind === 'call' && typeof s.callee === 'string' && Array.isArray(s.args)) {
189
+ const method = s.callee.split('.').pop() ?? s.callee;
190
+ if (method === 'setClock' && s.args.length >= 2) {
191
+ checkConfigValue('i2c', extractNumericValue(s.args[1]), diagnostics);
192
+ }
193
+ else if (method === 'setBaudRate' || method === 'begin') {
194
+ // Serial.begin(baud) / setBaudRate(baud) — last numeric arg is the baud.
195
+ for (const arg of s.args) {
196
+ const v = extractNumericValue(arg);
197
+ if (v !== undefined)
198
+ checkConfigValue('baud', v, diagnostics);
199
+ }
200
+ }
201
+ else if (method === 'setFrequency' && s.args.length >= 2) {
202
+ checkConfigValue('spi', extractNumericValue(s.args[1]), diagnostics);
203
+ }
204
+ }
205
+ // Recurse into nested statements
206
+ if (s.body && Array.isArray(s.body)) {
207
+ for (const child of s.body)
208
+ scanStatement(child, diagnostics);
209
+ }
210
+ if (s.thenBranch && Array.isArray(s.thenBranch)) {
211
+ for (const child of s.thenBranch)
212
+ scanStatement(child, diagnostics);
213
+ }
214
+ if (s.elseBranch && Array.isArray(s.elseBranch)) {
215
+ for (const child of s.elseBranch)
216
+ scanStatement(child, diagnostics);
217
+ }
218
+ if (s.statements && Array.isArray(s.statements)) {
219
+ for (const child of s.statements)
220
+ scanStatement(child, diagnostics);
221
+ }
222
+ if (s.initializer && typeof s.initializer === 'object' && s.initializer.kind) {
223
+ scanStatement(s.initializer, diagnostics);
224
+ }
225
+ if (s.increment && typeof s.increment === 'object' && s.increment.kind) {
226
+ scanStatement(s.increment, diagnostics);
227
+ }
228
+ if (s.cases && Array.isArray(s.cases)) {
229
+ for (const c of s.cases) {
230
+ if (c.body && Array.isArray(c.body)) {
231
+ for (const child of c.body)
232
+ scanStatement(child, diagnostics);
233
+ }
234
+ }
235
+ }
236
+ if (s.tryBlock && Array.isArray(s.tryBlock)) {
237
+ for (const child of s.tryBlock)
238
+ scanStatement(child, diagnostics);
239
+ }
240
+ if (s.catchBlock && Array.isArray(s.catchBlock)) {
241
+ for (const child of s.catchBlock)
242
+ scanStatement(child, diagnostics);
243
+ }
244
+ if (s.finallyBlock && Array.isArray(s.finallyBlock)) {
245
+ for (const child of s.finallyBlock)
246
+ scanStatement(child, diagnostics);
247
+ }
248
+ }
249
+ /**
250
+ * Validate peripheral config values for common unit mistakes.
251
+ *
252
+ * Scans the program IR for cuttlefish-call nodes that configure peripherals
253
+ * with bare numbers and emits warnings when values look suspicious.
254
+ *
255
+ * @param program - The program IR to validate
256
+ * @returns Array of diagnostics for suspicious peripheral config values
257
+ */
258
+ export function validateUnitSuspicion(program) {
259
+ const diagnostics = [];
260
+ // Scan top-level statements
261
+ if (program.topLevelStatements) {
262
+ for (const stmt of program.topLevelStatements) {
263
+ scanStatement(stmt, diagnostics);
264
+ }
265
+ }
266
+ // Scan function bodies
267
+ if (program.functions) {
268
+ for (const fn of program.functions) {
269
+ if (fn.statements) {
270
+ for (const stmt of fn.statements) {
271
+ scanStatement(stmt, diagnostics);
272
+ }
273
+ }
274
+ }
275
+ }
276
+ // Scan class methods
277
+ if (program.classes) {
278
+ for (const cls of program.classes) {
279
+ if (cls.methods) {
280
+ for (const method of cls.methods) {
281
+ if (method.statements) {
282
+ for (const stmt of method.statements) {
283
+ scanStatement(stmt, diagnostics);
284
+ }
285
+ }
286
+ }
287
+ }
288
+ if (cls.constructor?.statements) {
289
+ for (const stmt of cls.constructor.statements) {
290
+ scanStatement(stmt, diagnostics);
291
+ }
292
+ }
293
+ }
294
+ }
295
+ return diagnostics;
296
+ }
@@ -0,0 +1,6 @@
1
+ import type { StatementIR, ExpressionIR, ProgramIR } from "../../api/index.js";
2
+ export declare function walkNestedStatements(stmt: StatementIR, visitor: (s: StatementIR) => void): void;
3
+ export declare function walkStatements(stmts: StatementIR[], visitor: (stmt: StatementIR) => void): void;
4
+ export declare function walkExpressionsInExpression(expr: ExpressionIR, visitor: (expr: ExpressionIR) => void): void;
5
+ export declare function walkExpressions(stmts: StatementIR[], visitor: (expr: ExpressionIR) => void): void;
6
+ export declare function walkProgramIR(program: ProgramIR, visitor: (stmt: StatementIR) => void): void;