@typecad/cuttlefish 1.0.0-alpha.13 → 1.0.0-alpha.15

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 (343) hide show
  1. package/README.md +82 -79
  2. package/assets/editor-extensions/typecad-debug/README.md +141 -0
  3. package/assets/editor-extensions/typecad-debug/out/extension.js +347 -0
  4. package/assets/editor-extensions/typecad-debug/out/extension.js.map +1 -0
  5. package/assets/editor-extensions/typecad-debug/package.json +76 -0
  6. package/assets/editor-extensions/typecad-ui/LICENSE +27 -0
  7. package/assets/editor-extensions/typecad-ui/README.md +52 -0
  8. package/assets/editor-extensions/typecad-ui/file-icon-dark.png +0 -0
  9. package/assets/editor-extensions/typecad-ui/file-icon-light.png +0 -0
  10. package/assets/editor-extensions/typecad-ui/icon.png +0 -0
  11. package/assets/editor-extensions/typecad-ui/language-configuration.json +43 -0
  12. package/assets/editor-extensions/typecad-ui/package.json +54 -0
  13. package/assets/editor-extensions/typecad-ui/snippets/typecad-ui.json +80 -0
  14. package/assets/editor-extensions/typecad-ui/syntaxes/markdown-ui.json +45 -0
  15. package/assets/editor-extensions/typecad-ui/syntaxes/typecad-ui.tmLanguage.json +1269 -0
  16. package/dist/api/config.d.ts +30 -27
  17. package/dist/api/schema/types.d.ts +20 -3
  18. package/dist/api/shared/async-runtime-static.d.ts +1 -1
  19. package/dist/api/shared/async-runtime-static.js +5 -5
  20. package/dist/api/shared/async-types.d.ts +3 -2
  21. package/dist/api/shared/board-catalog.d.ts +2 -0
  22. package/dist/api/shared/board-catalog.js +6 -0
  23. package/dist/api/shared/board-resolver.d.ts +4 -7
  24. package/dist/api/shared/board-resolver.js +2 -1
  25. package/dist/api/shared/coop-scheduler.d.ts +1 -1
  26. package/dist/api/shared/coop-scheduler.js +1 -1
  27. package/dist/api/shared/cpp-type-ir.d.ts +1 -1
  28. package/dist/api/shared/cpp-type-ir.js +1 -1
  29. package/dist/api/shared/display-profile.d.ts +1 -1
  30. package/dist/api/shared/display-profile.js +3 -5
  31. package/dist/api/shared/framework-manifest-registry.d.ts +1 -1
  32. package/dist/api/shared/framework-manifest-registry.js +0 -1
  33. package/dist/api/shared/framework-manifest.d.ts +65 -507
  34. package/dist/api/shared/framework-manifest.js +6 -11
  35. package/dist/api/shared/hal-op-ir.d.ts +294 -685
  36. package/dist/api/shared/hal-op-ir.js +31 -65
  37. package/dist/api/shared/index.d.ts +0 -4
  38. package/dist/api/shared/index.js +1 -7
  39. package/dist/api/shared/ir-core.d.ts +6 -0
  40. package/dist/api/shared/ir-declarations.d.ts +4 -0
  41. package/dist/api/shared/ir.d.ts +1 -3
  42. package/dist/api/shared/platform-strategy.d.ts +14 -37
  43. package/dist/api/shared/polyfill-helper-registry.js +0 -5
  44. package/dist/api/shared/polyfill-types.js +0 -27
  45. package/dist/api/shared/promise-runtime.js +3 -3
  46. package/dist/api/shared/spdx-licenses.d.ts +12 -10
  47. package/dist/api/shared/spdx-licenses.js +1 -1
  48. package/dist/api/shared/toolchain-types.d.ts +1 -1
  49. package/dist/api/shared/toolchain-types.js +3 -3
  50. package/dist/api/shared/types.d.ts +0 -3
  51. package/dist/api/shared/validate-framework-manifest.js +13 -33
  52. package/dist/board-catalog/dts-reader.d.ts +220 -0
  53. package/dist/board-catalog/dts-reader.js +1052 -0
  54. package/dist/board-catalog/index.d.ts +11 -0
  55. package/dist/board-catalog/index.js +12 -0
  56. package/dist/board-catalog/pinconfig.d.ts +48 -0
  57. package/dist/board-catalog/pinconfig.js +263 -0
  58. package/dist/board-catalog/sdk.d.ts +82 -0
  59. package/dist/board-catalog/sdk.js +180 -0
  60. package/dist/board-catalog/store.d.ts +196 -0
  61. package/dist/board-catalog/store.js +363 -0
  62. package/dist/board-catalog/types.d.ts +233 -0
  63. package/dist/board-catalog/types.js +7 -0
  64. package/dist/board-catalog/walker.d.ts +112 -0
  65. package/dist/board-catalog/walker.js +1101 -0
  66. package/dist/cli-utils.d.ts +2 -2
  67. package/dist/cli-utils.js +5 -5
  68. package/dist/cli.js +227 -244
  69. package/dist/config-loader.d.ts +14 -19
  70. package/dist/config-loader.js +242 -78
  71. package/dist/config-schema.d.ts +19 -227
  72. package/dist/config-schema.js +9 -8
  73. package/dist/contract/board-generator.d.ts +4 -4
  74. package/dist/contract/board-generator.js +16 -5
  75. package/dist/contract/contract-parser.d.ts +36 -127
  76. package/dist/contract/contract-parser.js +76 -0
  77. package/dist/contract/index.d.ts +1 -1
  78. package/dist/contract/index.js +70 -21
  79. package/dist/create/active-board-catalog.d.ts +9 -0
  80. package/dist/create/active-board-catalog.js +94 -0
  81. package/dist/create/board-catalog.generated.d.ts +96 -0
  82. package/dist/create/board-catalog.generated.js +128737 -0
  83. package/dist/create/board-search.d.ts +23 -0
  84. package/dist/create/board-search.js +88 -0
  85. package/dist/create/editor-integration.d.ts +32 -0
  86. package/dist/create/editor-integration.js +257 -0
  87. package/dist/create/eslint-rules-template.d.ts +2 -2
  88. package/dist/create/framework-catalog.d.ts +48 -8
  89. package/dist/create/framework-catalog.js +58 -44
  90. package/dist/create/index.d.ts +8 -13
  91. package/dist/create/index.js +5 -9
  92. package/dist/create/mcu-target.d.ts +39 -0
  93. package/dist/create/mcu-target.js +80 -0
  94. package/dist/create/pack-targets.d.ts +19 -0
  95. package/dist/create/pack-targets.js +56 -0
  96. package/dist/create/{init-scaffold.d.ts → scaffold.d.ts} +8 -11
  97. package/dist/create/{init-scaffold.js → scaffold.js} +28 -87
  98. package/dist/create/templates.d.ts +51 -0
  99. package/dist/create/{init-templates.js → templates.js} +135 -116
  100. package/dist/create/wizard.d.ts +19 -0
  101. package/dist/create/wizard.js +314 -0
  102. package/dist/debug/preprocessor.d.ts +5 -0
  103. package/dist/debug/preprocessor.js +31 -7
  104. package/dist/diagnostics/diagnostics-report.d.ts +1 -1
  105. package/dist/diagnostics/diagnostics-report.js +3 -11
  106. package/dist/diagnostics/json-schema.d.ts +1 -1
  107. package/dist/diagnostics/md-writer.js +2 -2
  108. package/dist/diagnostics/mermaid-builder.d.ts +1 -1
  109. package/dist/diagnostics/mermaid-builder.js +1 -1
  110. package/dist/emit/cpp-emitter.js +4 -1
  111. package/dist/emit/emitters/class-emitter.js +32 -4
  112. package/dist/emit/emitters/emitter-context.d.ts +11 -0
  113. package/dist/emit/emitters/entrypoint-synthesizer.js +1 -1
  114. package/dist/emit/emitters/function-emitter-impl.js +33 -17
  115. package/dist/emit/emitters/output-finalizer.d.ts +7 -0
  116. package/dist/emit/emitters/output-finalizer.js +31 -23
  117. package/dist/emit/emitters/setup.js +147 -63
  118. package/dist/emit/emitters/top-level-prep.js +1 -1
  119. package/dist/emit/emitters/type-decl-emitter.js +13 -8
  120. package/dist/emit/emitters/ui-emitter.js +1 -1
  121. package/dist/emit/expression-renderer.d.ts +3 -3
  122. package/dist/emit/expression-renderer.js +17 -7
  123. package/dist/emit/route-hal-op.js +17 -48
  124. package/dist/emit/snprintf-helpers.d.ts +1 -3
  125. package/dist/emit/snprintf-helpers.js +1 -39
  126. package/dist/emit/statement-renderer.d.ts +0 -4
  127. package/dist/emit/statement-renderer.js +54 -45
  128. package/dist/emit/utils/async-state-machine.d.ts +16 -9
  129. package/dist/emit/utils/async-state-machine.js +56 -54
  130. package/dist/emit/utils/comment-helpers.d.ts +0 -8
  131. package/dist/emit/utils/comment-helpers.js +1 -1
  132. package/dist/emit/utils/cpp-helpers.d.ts +2 -2
  133. package/dist/emit/utils/cpp-helpers.js +2 -2
  134. package/dist/emit/utils/hal-op-cpp-type.js +4 -6
  135. package/dist/emit/utils/index.d.ts +3 -3
  136. package/dist/emit/utils/index.js +3 -3
  137. package/dist/emit/utils/type-inference.d.ts +1 -29
  138. package/dist/emit/utils/type-inference.js +0 -75
  139. package/dist/framework-package.d.ts +3 -0
  140. package/dist/framework-package.js +23 -6
  141. package/dist/framework-registry.d.ts +5 -5
  142. package/dist/frameworks/native/graphics/terminal-preview.d.ts +5 -0
  143. package/dist/frameworks/native/graphics/terminal-preview.js +33 -0
  144. package/dist/frameworks/native/index.d.ts +3 -0
  145. package/dist/frameworks/native/index.js +15 -0
  146. package/dist/frameworks/native/native-compile.d.ts +17 -0
  147. package/dist/frameworks/native/native-compile.js +170 -0
  148. package/dist/frameworks/native/native-config.d.ts +41 -0
  149. package/dist/frameworks/native/native-config.js +7 -0
  150. package/dist/frameworks/native/strategy.d.ts +97 -0
  151. package/dist/frameworks/native/strategy.js +664 -0
  152. package/dist/ir/board-resolver.d.ts +18 -23
  153. package/dist/ir/board-resolver.js +43 -401
  154. package/dist/ir/build-ir-state.d.ts +3 -0
  155. package/dist/ir/build-ir-state.js +42 -0
  156. package/dist/ir/build-ir.d.ts +1 -1
  157. package/dist/ir/build-ir.js +64 -45
  158. package/dist/ir/declaration-builders.js +1 -0
  159. package/dist/ir/expression-to-ir.js +17 -10
  160. package/dist/ir/hal/hal-emitter.d.ts +0 -2
  161. package/dist/ir/hal/hal-emitter.js +92 -41
  162. package/dist/ir/hal/hal-parser.d.ts +5 -5
  163. package/dist/ir/hal/hal-parser.js +128 -36
  164. package/dist/ir/hal/hal-plugins.d.ts +0 -1
  165. package/dist/ir/hal/hal-plugins.js +425 -716
  166. package/dist/ir/heap-analysis.js +2 -41
  167. package/dist/ir/identifier-collector.js +32 -20
  168. package/dist/ir/network-validation.js +7 -11
  169. package/dist/ir/ownership-analysis.js +75 -13
  170. package/dist/ir/peripheral-usage.d.ts +8 -2
  171. package/dist/ir/peripheral-usage.js +78 -149
  172. package/dist/ir/peripheral-validation.js +23 -3
  173. package/dist/ir/pin-capability-validation.d.ts +12 -0
  174. package/dist/ir/pin-capability-validation.js +61 -97
  175. package/dist/ir/pin-mode-validation.js +5 -5
  176. package/dist/ir/program-analysis.d.ts +8 -15
  177. package/dist/ir/program-analysis.js +140 -323
  178. package/dist/ir/pulldown-validation.js +11 -4
  179. package/dist/ir/resource-analysis.js +15 -3
  180. package/dist/ir/statement-to-ir.js +0 -6
  181. package/dist/ir/timing-validation.js +1 -1
  182. package/dist/ir/transformers/array-methods.js +11 -5
  183. package/dist/ir/transformers/call-statement.js +20 -87
  184. package/dist/ir/transformers/callback-context-registry.d.ts +1 -1
  185. package/dist/ir/transformers/callback-context-registry.js +8 -16
  186. package/dist/ir/transformers/control-flow.js +0 -13
  187. package/dist/ir/transformers/expressions.js +10 -9
  188. package/dist/ir/transformers/hal-call-resolver.d.ts +2 -2
  189. package/dist/ir/transformers/hal-call-resolver.js +24 -10
  190. package/dist/ir/transformers/hal-emit-helpers.d.ts +2 -2
  191. package/dist/ir/transformers/hal-emit-helpers.js +2 -2
  192. package/dist/ir/transformers/namespace-methods.js +1 -1
  193. package/dist/ir/transformers/ui-callback-lowering.d.ts +0 -2
  194. package/dist/ir/transformers/ui-callback-lowering.js +0 -24
  195. package/dist/ir/transformers/variables.js +338 -42
  196. package/dist/ir/try-catch-validation.js +4 -3
  197. package/dist/ir/type-resolution.js +15 -4
  198. package/dist/ir/validation-orchestrator.js +0 -9
  199. package/dist/libdef/cpp-to-decl.d.ts +0 -9
  200. package/dist/libdef/cpp-to-decl.js +0 -72
  201. package/dist/libdef/registry.d.ts +0 -1
  202. package/dist/libdef/registry.js +1 -24
  203. package/dist/library/catalog.d.ts +35 -0
  204. package/dist/library/catalog.js +67 -0
  205. package/dist/library/cli.d.ts +2 -0
  206. package/dist/library/cli.js +168 -0
  207. package/dist/library/init.d.ts +25 -0
  208. package/dist/library/init.js +397 -0
  209. package/dist/library/install.d.ts +9 -0
  210. package/dist/library/install.js +80 -0
  211. package/dist/library/registry-search.d.ts +34 -0
  212. package/dist/library/registry-search.js +50 -0
  213. package/dist/library/validate.d.ts +17 -0
  214. package/dist/library/validate.js +175 -0
  215. package/dist/library-packages.d.ts +95 -0
  216. package/dist/library-packages.js +275 -0
  217. package/dist/mapping/peripheral-names.js +9 -4
  218. package/dist/mapping/source-map.d.ts +3 -4
  219. package/dist/mapping/source-map.js +12 -18
  220. package/dist/orchestrator/graph-builder.d.ts +3 -3
  221. package/dist/orchestrator/graph-builder.js +29 -12
  222. package/dist/orchestrator/type-checker.d.ts +3 -3
  223. package/dist/orchestrator/type-checker.js +3 -3
  224. package/dist/platform/async-runtime.js +1 -1
  225. package/dist/platform/coop-scheduler-runtime.js +2 -2
  226. package/dist/platform/generic-debug-codegen.d.ts +36 -0
  227. package/dist/platform/generic-debug-codegen.js +185 -0
  228. package/dist/platform/generic-strategy.d.ts +3 -4
  229. package/dist/platform/generic-strategy.js +5 -80
  230. package/dist/platform/index.js +1 -1
  231. package/dist/platform/registry.d.ts +2 -2
  232. package/dist/platform/registry.js +2 -2
  233. package/dist/preview/client.js +17 -3
  234. package/dist/safety/asil-decorators.d.ts +32 -0
  235. package/dist/safety/asil-decorators.js +32 -0
  236. package/dist/safety/authoring.d.ts +85 -0
  237. package/dist/safety/authoring.js +61 -0
  238. package/dist/safety/engine.d.ts +3 -0
  239. package/dist/safety/engine.js +83 -0
  240. package/dist/safety/hal/ops.d.ts +48 -0
  241. package/dist/safety/hal/ops.js +46 -0
  242. package/dist/safety/iso26262/analyze.d.ts +13 -0
  243. package/dist/safety/iso26262/analyze.js +29 -0
  244. package/dist/safety/iso26262/asil.d.ts +10 -0
  245. package/dist/safety/iso26262/asil.js +22 -0
  246. package/dist/safety/iso26262/collect.d.ts +14 -0
  247. package/dist/safety/iso26262/collect.js +137 -0
  248. package/dist/safety/iso26262/goto-checker.d.ts +10 -0
  249. package/dist/safety/iso26262/goto-checker.js +72 -0
  250. package/dist/safety/iso26262/heap-checker.d.ts +7 -0
  251. package/dist/safety/iso26262/heap-checker.js +57 -0
  252. package/dist/safety/iso26262/init-checker.d.ts +13 -0
  253. package/dist/safety/iso26262/init-checker.js +127 -0
  254. package/dist/safety/iso26262/loop-checker.d.ts +7 -0
  255. package/dist/safety/iso26262/loop-checker.js +86 -0
  256. package/dist/safety/iso26262/recursion-checker.d.ts +9 -0
  257. package/dist/safety/iso26262/recursion-checker.js +134 -0
  258. package/dist/safety/iso26262/sidecar-writer.d.ts +25 -0
  259. package/dist/safety/iso26262/sidecar-writer.js +13 -0
  260. package/dist/safety/passes/pinMode-intercept.d.ts +3 -0
  261. package/dist/safety/passes/pinMode-intercept.js +60 -0
  262. package/dist/safety/runtime/mode-table.d.ts +5 -0
  263. package/dist/safety/runtime/mode-table.js +55 -0
  264. package/dist/safety/runtime/polyfills.d.ts +6 -0
  265. package/dist/safety/runtime/polyfills.js +12 -0
  266. package/dist/safety/runtime/result-struct.d.ts +11 -0
  267. package/dist/safety/runtime/result-struct.js +98 -0
  268. package/dist/safety/runtime/safe-int.d.ts +33 -0
  269. package/dist/safety/runtime/safe-int.js +170 -0
  270. package/dist/safety/runtime/safe-traits.d.ts +4 -0
  271. package/dist/safety/runtime/safe-traits.js +95 -0
  272. package/dist/safety/runtime/safe-variable.d.ts +39 -0
  273. package/dist/safety/runtime/safe-variable.js +226 -0
  274. package/dist/safety/runtime/vote.d.ts +8 -0
  275. package/dist/safety/runtime/vote.js +92 -0
  276. package/dist/safety/runtime/write-verify.d.ts +8 -0
  277. package/dist/safety/runtime/write-verify.js +71 -0
  278. package/dist/safety/safe-int-types.d.ts +45 -0
  279. package/dist/safety/safe-int-types.js +25 -0
  280. package/dist/safety/safe-variable-types.d.ts +29 -0
  281. package/dist/safety/safe-variable-types.js +19 -0
  282. package/dist/safety/safety-bridge.d.ts +5 -6
  283. package/dist/safety/safety-bridge.js +15 -28
  284. package/dist/safety/sidecar-bridge.d.ts +1 -3
  285. package/dist/safety/sidecar-bridge.js +3 -20
  286. package/dist/safety/specifiers.d.ts +6 -0
  287. package/dist/safety/specifiers.js +14 -0
  288. package/dist/safety-hook.d.ts +8 -7
  289. package/dist/safety-hook.js +12 -13
  290. package/dist/testing.d.ts +5 -6
  291. package/dist/testing.js +5 -5
  292. package/dist/transpile/resolution.d.ts +1 -1
  293. package/dist/transpile/resolution.js +18 -9
  294. package/dist/transpile/test-pins.d.ts +18 -0
  295. package/dist/transpile/test-pins.js +142 -0
  296. package/dist/transpile.d.ts +1 -2
  297. package/dist/transpile.js +90 -29
  298. package/dist/types.d.ts +45 -26
  299. package/dist/ui-hook.d.ts +1 -1
  300. package/dist/utils/cli.d.ts +2 -2
  301. package/dist/utils/cli.js +160 -157
  302. package/dist/utils/fs.d.ts +3 -4
  303. package/dist/utils/fs.js +4 -5
  304. package/dist/utils/strings.d.ts +0 -1
  305. package/dist/utils/strings.js +0 -8
  306. package/dist/utils/ui.d.ts +5 -2
  307. package/dist/utils/ui.js +13 -3
  308. package/package.json +158 -149
  309. package/dist/add-preset.d.ts +0 -4
  310. package/dist/add-preset.js +0 -74
  311. package/dist/api/shared/async-symbol-detector.d.ts +0 -11
  312. package/dist/api/shared/async-symbol-detector.js +0 -140
  313. package/dist/api/shared/native-display-op-resolver.d.ts +0 -10
  314. package/dist/api/shared/native-display-op-resolver.js +0 -64
  315. package/dist/create/board-checklist.d.ts +0 -2
  316. package/dist/create/board-checklist.js +0 -52
  317. package/dist/create/board-codegen.d.ts +0 -9
  318. package/dist/create/board-codegen.js +0 -238
  319. package/dist/create/board-generators.d.ts +0 -12
  320. package/dist/create/board-generators.js +0 -651
  321. package/dist/create/board-spec.d.ts +0 -637
  322. package/dist/create/board-spec.js +0 -214
  323. package/dist/create/init-templates.d.ts +0 -28
  324. package/dist/create/init-wizard.d.ts +0 -8
  325. package/dist/create/init-wizard.js +0 -182
  326. package/dist/install/framework-catalog.d.ts +0 -53
  327. package/dist/install/framework-catalog.js +0 -107
  328. package/dist/install/handle-install.d.ts +0 -35
  329. package/dist/install/handle-install.js +0 -177
  330. package/dist/install/index.d.ts +0 -4
  331. package/dist/install/index.js +0 -3
  332. package/dist/ir/pin-state-tracking.d.ts +0 -58
  333. package/dist/ir/pin-state-tracking.js +0 -182
  334. package/dist/ir/pwm-timer-sharing.d.ts +0 -4
  335. package/dist/ir/pwm-timer-sharing.js +0 -94
  336. package/dist/ir/timer0-pwm-timing-conflict.d.ts +0 -4
  337. package/dist/ir/timer0-pwm-timing-conflict.js +0 -72
  338. package/dist/libdef/component-decls.d.ts +0 -2
  339. package/dist/libdef/component-decls.js +0 -6
  340. package/dist/libdef/component-discovery.d.ts +0 -43
  341. package/dist/libdef/component-discovery.js +0 -83
  342. package/dist/theme-tokens.d.ts +0 -22
  343. package/dist/theme-tokens.js +0 -172
@@ -6,31 +6,26 @@ export type { BoardConstants };
6
6
  */
7
7
  export declare function getDefaultBoardConstants(): BoardConstants;
8
8
  /**
9
- * Parse a TypeScript board-definition source file and return a flat map of
10
- * all compile-time constant scalar values exported as a `BoardDefinition`.
11
- *
12
- * Properties whose values are arrays, spread elements, or other non-literal
13
- * expressions are silently skipped (no partial constant maps for board pins
14
- * etc. are needed by the emitter).
15
- *
16
- * @param defFilePath Absolute path to the board definition `index.ts`.
9
+ * Locate the project-local generated board module by walking up from a
10
+ * source file. A project carries `.cuttlefish/board.ts` + `board.json`
11
+ * (generated by the framework's board generator — see boardgen in
12
+ * framework-zephyr) instead of a board package.
17
13
  */
18
- export declare function resolveBoardConstants(defFilePath: string): BoardConstants;
14
+ export declare function findGeneratedBoard(fromFile: string): {
15
+ boardTs: string;
16
+ boardJson: string;
17
+ } | undefined;
19
18
  /**
20
- * Given a source file path and a relative import module specifier, check
21
- * whether the import resolves to a TypeCAD board-definition package
22
- * (path pattern: /code/board-*\/index.ts).
23
- *
24
- * Returns the absolute path to the board index.ts on match, otherwise
25
- * undefined.
19
+ * Read a generated board.json manifest into BoardConstants. The manifest is
20
+ * `{ version, identifier, soc, tier, pinNames, constants: {dot-path → value} }`
21
+ * the `constants` object IS the flat map.
26
22
  */
27
- export declare function tryResolveBoardDefFile(fromFile: string, moduleSpecifier: string, boardPackage?: string): string | undefined;
23
+ export declare function readGeneratedBoardConstants(boardJsonPath: string): BoardConstants;
28
24
  /**
29
- * Resolve the framework-specific build target (e.g. Arduino FQBN) from the
30
- * board package's manifest.
31
- *
32
- * @param boardPackage Board package identifier or path.
33
- * @param configPath Path to the project config file (for relative resolution).
34
- * @param framework Target framework name (default: 'arduino').
25
+ * Given a source file path and an import module specifier, return the path
26
+ * of the generated board.json manifest the specifier refers to, or
27
+ * undefined. Only two specifiers name board data: the virtual
28
+ * `@typecad/board` module and (defensively) the config's own board target
29
+ * string. Relative-path board imports are gone with the board packages.
35
30
  */
36
- export declare function resolveBoardBuildTarget(boardPackage: string, configPath: string, framework?: string): string | undefined;
31
+ export declare function tryResolveBoardDefFile(fromFile: string, moduleSpecifier: string, boardTarget?: string): string | undefined;
@@ -1,17 +1,20 @@
1
1
  // ---------------------------------------------------------------------------
2
2
  // Board constant resolver
3
3
  //
4
- // Parses a TypeScript board-definition file (e.g. code/board-arduino-uno/index.ts)
5
- // using the TypeScript compiler API and extracts all compile-time scalar values
6
- // from the exported `BoardDefinition` object into a flat dot-path map.
4
+ // Board data comes from the project-local generated board module: boardgen
5
+ // (in framework-zephyr) materializes `.cuttlefish/board.ts` + `board.json`
6
+ // above the user's sources, and `board.json` carries the flat dot-path
7
+ // constant map read here. The legacy @typecad/board-* / @typecad/mcu-*
8
+ // packages and their TypeScript BoardDefinition manifests are gone, so there
9
+ // is no AST path — the JSON manifest is the only board source.
7
10
  //
8
11
  // The result is stored in `ProgramIR.boardConstants` and used by the C++
9
- // emitter to fold `Board.definition.*` property accesses into inline literals
10
- // without maintaining a separate hard-coded copy of the manifest.
12
+ // emitter to fold board constant lookups (`board("pins.led")` and friends)
13
+ // into inline literals — without maintaining a separate hard-coded copy of
14
+ // the manifest.
11
15
  // ---------------------------------------------------------------------------
12
16
  import path from "node:path";
13
17
  import fs from "node:fs";
14
- import ts from "typescript";
15
18
  /**
16
19
  * Returns a set of default board constants (standard Arduino Uno-like)
17
20
  * used as a fallback when no specific board manifest is loaded.
@@ -19,419 +22,58 @@ import ts from "typescript";
19
22
  export function getDefaultBoardConstants() {
20
23
  const result = new Map();
21
24
  result.set("pins.analogOffset", 14);
22
- result.set("peripherals.aliases.UART0", "Serial");
23
- result.set("peripherals.aliases.I2C0", "Wire");
24
- result.set("peripherals.aliases.SPI0", "SPI");
25
+ result.set("peripherals.aliases.UART0", "UART0");
26
+ result.set("peripherals.aliases.I2C0", "I2C0");
27
+ result.set("peripherals.aliases.SPI0", "SPI0");
25
28
  return result;
26
29
  }
27
30
  /**
28
- * Parse a TypeScript board-definition source file and return a flat map of
29
- * all compile-time constant scalar values exported as a `BoardDefinition`.
30
- *
31
- * Properties whose values are arrays, spread elements, or other non-literal
32
- * expressions are silently skipped (no partial constant maps for board pins
33
- * etc. are needed by the emitter).
34
- *
35
- * @param defFilePath Absolute path to the board definition `index.ts`.
31
+ * Locate the project-local generated board module by walking up from a
32
+ * source file. A project carries `.cuttlefish/board.ts` + `board.json`
33
+ * (generated by the framework's board generator — see boardgen in
34
+ * framework-zephyr) instead of a board package.
36
35
  */
37
- export function resolveBoardConstants(defFilePath) {
38
- const result = new Map();
39
- // Build a minimal TypeScript program just to get a parsed AST with type
40
- // information for the target file. We don't need emit or diagnostics.
41
- const program = ts.createProgram([defFilePath], {
42
- noEmit: true,
43
- skipLibCheck: true,
44
- strict: false,
45
- target: ts.ScriptTarget.ES2020,
46
- });
47
- // The source file may be keyed with either Windows or POSIX separators.
48
- const sourceFile = program.getSourceFile(defFilePath) ??
49
- program.getSourceFile(defFilePath.replace(/\\/g, "/"));
50
- if (!sourceFile)
51
- return result;
52
- // Find exported variable declarations — both object literals (board/MCU defs)
53
- // and arrays of objects (peripheral instance lists).
54
- ts.forEachChild(sourceFile, (node) => {
55
- if (!ts.isVariableStatement(node))
56
- return;
57
- const isExported = node.modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword);
58
- if (!isExported)
59
- return;
60
- for (const decl of node.declarationList.declarations) {
61
- if (!ts.isIdentifier(decl.name))
62
- continue;
63
- const varName = decl.name.text;
64
- const init = decl.initializer;
65
- // Object literal — walk normally (board/MCU definitions)
66
- let walkInit = init;
67
- // Unwrap `as const` / type assertions
68
- while (walkInit && ts.isAsExpression(walkInit))
69
- walkInit = walkInit.expression;
70
- if (walkInit && ts.isObjectLiteralExpression(walkInit)) {
71
- // Peripheral capability objects (e.g. PWM_CAPABILITIES → peripherals.pwm.*)
72
- // are namespaced so HAL lookups like board("peripherals.pwm.resolution")
73
- // resolve. Other object literals (board/MCU definitions) walk with no prefix.
74
- if (varName.endsWith("_CAPABILITIES")) {
75
- const baseName = varName.replace("_CAPABILITIES", "").toLowerCase();
76
- walkObjectLiteral(walkInit, `peripherals.${baseName}`, result);
77
- }
78
- else {
79
- walkObjectLiteral(walkInit, "", result);
80
- }
81
- }
82
- // Array of objects — walk for peripheral instance data
83
- // (e.g., ADC_INSTANCES → peripherals.adc.0.*)
84
- if (walkInit && ts.isArrayLiteralExpression(walkInit)) {
85
- if (varName.endsWith("_INSTANCES")) {
86
- const baseName = varName.replace("_INSTANCES", "").toLowerCase();
87
- const prefix = `peripherals.${baseName}`;
88
- walkArrayLiteral(walkInit, prefix, result);
89
- }
90
- }
91
- }
92
- });
93
- // After parsing the board file, check for MCU imports and merge pin data.
94
- // Board definitions often use `...MCU.pins` spread which the AST walker
95
- // cannot handle, but the MCU file has static pin data we can parse.
96
- resolveAndMergeMCUConstants(defFilePath, result);
97
- return result;
98
- }
99
- /**
100
- * Detect MCU package imports in a board definition file, resolve the MCU
101
- * definition file, parse its pin/peripheral constants, and merge them into
102
- * the board constants. This handles the common pattern where board definitions
103
- * use spread operators (`...ATmega328P.pins`) that the AST walker can't parse.
104
- */
105
- function resolveAndMergeMCUConstants(boardFilePath, boardConstants) {
106
- // Only proceed if the board file didn't produce pin.all entries on its own
107
- let hasPinData = false;
108
- for (const key of boardConstants.keys()) {
109
- if (key.startsWith("pins.all.")) {
110
- hasPinData = true;
111
- break;
112
- }
113
- }
114
- if (hasPinData)
115
- return;
116
- // Parse the board file to find MCU imports
117
- const sourceText = fs.readFileSync(boardFilePath, "utf-8");
118
- const sourceFile = ts.createSourceFile(boardFilePath, sourceText, ts.ScriptTarget.Latest, true);
119
- let mcuSpecifier;
120
- for (const stmt of sourceFile.statements) {
121
- if (!ts.isImportDeclaration(stmt))
122
- continue;
123
- const spec = stmt.moduleSpecifier;
124
- if (!ts.isStringLiteral(spec))
125
- continue;
126
- if (spec.text.startsWith("@typecad/mcu-")) {
127
- mcuSpecifier = spec.text;
128
- break;
129
- }
130
- }
131
- if (!mcuSpecifier)
132
- return;
133
- // Resolve the MCU package file path
134
- const parts = mcuSpecifier.split("/");
135
- const pkgName = parts[1]; // e.g. "mcu-atmega328p"
136
- const mcuFileNames = ["mcu.ts", "index.ts"];
137
- let dir = path.dirname(boardFilePath);
138
- while (true) {
139
- for (const mcuFileName of mcuFileNames) {
140
- const nmCandidate = path.join(dir, "node_modules", "@typecad", pkgName, "src", mcuFileName);
141
- if (fs.existsSync(nmCandidate)) {
142
- mergeMCUConstants(nmCandidate, boardConstants);
143
- return;
144
- }
145
- const pkgCandidate = path.join(dir, "packages", pkgName, "src", mcuFileName);
146
- if (fs.existsSync(pkgCandidate)) {
147
- mergeMCUConstants(pkgCandidate, boardConstants);
148
- return;
149
- }
36
+ export function findGeneratedBoard(fromFile) {
37
+ let dir = path.dirname(path.resolve(fromFile));
38
+ for (let i = 0; i < 8; i++) {
39
+ const boardJson = path.join(dir, ".cuttlefish", "board.json");
40
+ const boardTs = path.join(dir, ".cuttlefish", "board.ts");
41
+ if (fs.existsSync(boardJson) && fs.existsSync(boardTs)) {
42
+ return { boardTs, boardJson };
150
43
  }
151
44
  const parent = path.dirname(dir);
152
45
  if (parent === dir)
153
46
  break;
154
47
  dir = parent;
155
48
  }
156
- }
157
- /**
158
- * Parse an MCU definition file and merge its pin data into the board constants.
159
- */
160
- function mergeMCUConstants(mcuFilePath, boardConstants) {
161
- const mcuConstants = resolveBoardConstants(mcuFilePath);
162
- // Merge MCU pin data and peripheral constants into board constants.
163
- // Don't overwrite existing board-specific values
164
- for (const [key, value] of mcuConstants.entries()) {
165
- if (key.startsWith("pins.") || key.startsWith("peripherals.")) {
166
- if (!boardConstants.has(key)) {
167
- boardConstants.set(key, value);
168
- }
169
- }
170
- }
171
- // Copy architecture if the MCU has it and the board doesn't
172
- if (mcuConstants.has("architecture") && !boardConstants.has("architecture")) {
173
- boardConstants.set("architecture", mcuConstants.get("architecture"));
174
- }
175
- // Also parse the MCU peripherals file for ADC/PWM/Timer data that the MCU
176
- // definition references via import (e.g., `peripherals: MCU_PERIPHERALS`).
177
- const mcuDir = path.dirname(mcuFilePath);
178
- const periphFile = path.join(mcuDir, "peripherals.ts");
179
- if (fs.existsSync(periphFile)) {
180
- const periphConstants = resolveBoardConstants(periphFile);
181
- for (const [key, value] of periphConstants.entries()) {
182
- if (!boardConstants.has(key)) {
183
- boardConstants.set(key, value);
184
- }
185
- }
186
- }
187
- }
188
- // ---------------------------------------------------------------------------
189
- // Helpers
190
- // ---------------------------------------------------------------------------
191
- /**
192
- * Recursively walk an `ObjectLiteralExpression`, adding scalar leaf values
193
- * to `out` keyed by their dot-separated path.
194
- *
195
- * @param obj Current object literal to visit.
196
- * @param prefix Dot-path accumulated so far (empty string at top level).
197
- * @param out Accumulator map.
198
- */
199
- function walkObjectLiteral(obj, prefix, out) {
200
- for (const prop of obj.properties) {
201
- // Only handle plain `key: value` assignments.
202
- // Shorthand, spread, methods, and getters are ignored.
203
- if (!ts.isPropertyAssignment(prop))
204
- continue;
205
- const keyNode = prop.name;
206
- const key = ts.isIdentifier(keyNode) || ts.isStringLiteral(keyNode) || ts.isNumericLiteral(keyNode)
207
- ? keyNode.text
208
- : undefined;
209
- if (!key)
210
- continue;
211
- const fullPath = prefix ? `${prefix}.${key}` : key;
212
- const init = prop.initializer;
213
- const scalar = resolveScalar(init);
214
- if (scalar !== undefined) {
215
- out.set(fullPath, scalar);
216
- }
217
- else if (ts.isObjectLiteralExpression(init)) {
218
- // Recurse into nested objects (e.g. `memory: { flash: 32_768, ... }`).
219
- walkObjectLiteral(init, fullPath, out);
220
- }
221
- else if (ts.isArrayLiteralExpression(init)) {
222
- // Capture string arrays (e.g. `pins.unsafe: ['D0', 'D1']`)
223
- const arrValues = [];
224
- for (const elem of init.elements) {
225
- if (ts.isStringLiteral(elem)) {
226
- arrValues.push(elem.text);
227
- }
228
- }
229
- if (arrValues.length > 0) {
230
- out.set(fullPath, arrValues.join(','));
231
- }
232
- else {
233
- walkArrayLiteral(init, fullPath, out);
234
- }
235
- }
236
- // Encode peripheral pin maps in a compact parseable format.
237
- // pins.i2c = { 0: { sda: 'A4', scl: 'A5' } } -> "0:sda=A4,scl=A5"
238
- // pins.spi = { 0: { mosi: 'D11', miso: 'D12', sck: 'D13', cs: 'D10' } } -> "0:mosi=D11,miso=D12,sck=D13,cs=D10"
239
- // pins.uart = { 0: { tx: 'D1', rx: 'D0' } } -> "0:tx=D1,rx=D0"
240
- if (ts.isObjectLiteralExpression(init)) {
241
- const encoded = tryEncodePeripheralPinMap(key, init);
242
- if (encoded) {
243
- out.set(fullPath, encoded);
244
- }
245
- }
246
- // Other complex expressions are silently ignored.
247
- }
248
- }
249
- function walkArrayLiteral(arr, prefix, out) {
250
- arr.elements.forEach((elem, index) => {
251
- const fullPath = `${prefix}.${index}`;
252
- const scalar = resolveScalar(elem);
253
- if (scalar !== undefined) {
254
- out.set(fullPath, scalar);
255
- return;
256
- }
257
- if (ts.isObjectLiteralExpression(elem)) {
258
- walkObjectLiteral(elem, fullPath, out);
259
- return;
260
- }
261
- if (ts.isArrayLiteralExpression(elem)) {
262
- const arrValues = [];
263
- for (const nested of elem.elements) {
264
- if (ts.isStringLiteral(nested)) {
265
- arrValues.push(nested.text);
266
- }
267
- }
268
- if (arrValues.length > 0) {
269
- out.set(fullPath, arrValues.join(','));
270
- }
271
- }
272
- });
273
- }
274
- /**
275
- * Try to evaluate a simple literal expression to a scalar JS value.
276
- * Returns `undefined` for anything that is not a plain, directly readable
277
- * literal (string, number, boolean, negative-number).
278
- */
279
- function resolveScalar(expr) {
280
- // Strip `as const` / `as T` type assertions — recurse on the inner expression.
281
- if (ts.isAsExpression(expr))
282
- return resolveScalar(expr.expression);
283
- // String literal
284
- if (ts.isStringLiteral(expr))
285
- return expr.text;
286
- // Numeric literal — TypeScript preserves underscore separators in `.text`
287
- // (e.g. 32_768), so we strip them before converting.
288
- if (ts.isNumericLiteral(expr)) {
289
- return Number(expr.text.replace(/_/g, ""));
290
- }
291
- // Boolean keywords
292
- if (expr.kind === ts.SyntaxKind.TrueKeyword)
293
- return true;
294
- if (expr.kind === ts.SyntaxKind.FalseKeyword)
295
- return false;
296
- // Negative numeric literals: -32768 or -1_024
297
- if (ts.isPrefixUnaryExpression(expr) &&
298
- expr.operator === ts.SyntaxKind.MinusToken &&
299
- ts.isNumericLiteral(expr.operand)) {
300
- return -Number(expr.operand.text.replace(/_/g, ""));
301
- }
302
49
  return undefined;
303
50
  }
304
- // ---------------------------------------------------------------------------
305
- // Peripheral pin map encoding
306
- // ---------------------------------------------------------------------------
307
51
  /**
308
- * Try to encode a peripheral pin map object into a compact string format.
309
- * Handles pins.i2c, pins.spi, pins.uart structures.
310
- *
311
- * Input: { 0: { sda: 'A4', scl: 'A5' } }
312
- * Output: "0:sda=A4,scl=A5"
313
- *
314
- * Input: { 0: { mosi: 'D11', miso: 'D12', sck: 'D13', cs: 'D10' } }
315
- * Output: "0:mosi=D11,miso=D12,sck=D13,cs=D10"
52
+ * Read a generated board.json manifest into BoardConstants. The manifest is
53
+ * `{ version, identifier, soc, tier, pinNames, constants: {dot-path → value} }`
54
+ * — the `constants` object IS the flat map.
316
55
  */
317
- function tryEncodePeripheralPinMap(key, obj) {
318
- // Only encode known peripheral pin structures
319
- if (key !== 'i2c' && key !== 'spi' && key !== 'uart')
320
- return undefined;
321
- const instances = [];
322
- for (const prop of obj.properties) {
323
- if (!ts.isPropertyAssignment(prop))
324
- continue;
325
- const keyNode = prop.name;
326
- if (!ts.isIdentifier(keyNode) && !ts.isStringLiteral(keyNode) && !ts.isNumericLiteral(keyNode))
327
- continue;
328
- const instanceKey = keyNode.text;
329
- const value = prop.initializer;
330
- if (!ts.isObjectLiteralExpression(value))
331
- continue;
332
- // Parse the inner object { sda: 'A4', scl: 'A5' } etc.
333
- const fields = [];
334
- for (const field of value.properties) {
335
- if (!ts.isPropertyAssignment(field))
336
- continue;
337
- const fieldKey = field.name;
338
- if (!ts.isIdentifier(fieldKey) && !ts.isStringLiteral(fieldKey) && !ts.isNumericLiteral(fieldKey))
339
- continue;
340
- const fieldValue = field.initializer;
341
- if (!ts.isStringLiteral(fieldValue))
342
- continue;
343
- fields.push(`${fieldKey.text}=${fieldValue.text}`);
344
- }
345
- if (fields.length > 0) {
346
- instances.push(`${instanceKey}:${fields.join(',')}`);
347
- }
348
- }
349
- if (instances.length > 0) {
350
- return instances.join(';');
56
+ export function readGeneratedBoardConstants(boardJsonPath) {
57
+ const manifest = JSON.parse(fs.readFileSync(boardJsonPath, "utf-8"));
58
+ const result = new Map();
59
+ for (const [k, v] of Object.entries(manifest.constants ?? {})) {
60
+ result.set(k, v);
351
61
  }
352
- return undefined;
62
+ return result;
353
63
  }
354
64
  /**
355
- * Given a source file path and a relative import module specifier, check
356
- * whether the import resolves to a TypeCAD board-definition package
357
- * (path pattern: /code/board-*\/index.ts).
358
- *
359
- * Returns the absolute path to the board index.ts on match, otherwise
360
- * undefined.
65
+ * Given a source file path and an import module specifier, return the path
66
+ * of the generated board.json manifest the specifier refers to, or
67
+ * undefined. Only two specifiers name board data: the virtual
68
+ * `@typecad/board` module and (defensively) the config's own board target
69
+ * string. Relative-path board imports are gone with the board packages.
361
70
  */
362
- export function tryResolveBoardDefFile(fromFile, moduleSpecifier, boardPackage) {
363
- // Handle the "@typecad/board" virtual import — rewrite to the concrete board
364
- // package so the rest of the resolution logic works unchanged.
365
- // (Case-insensitive so the documented mixed-case form resolves identically.)
366
- let effectiveSpecifier = moduleSpecifier;
367
- if (moduleSpecifier.toLowerCase() === "@typecad/board" && boardPackage) {
368
- effectiveSpecifier = boardPackage;
369
- }
370
- // Handle relative imports (e.g. "../code/board-arduino-uno/pins")
371
- if (effectiveSpecifier.startsWith(".")) {
372
- const dir = path.dirname(fromFile);
373
- const base = path.resolve(dir, moduleSpecifier);
374
- // Candidates: bare path, +.ts, or /index.ts
375
- const candidates = [
376
- base,
377
- `${base}.ts`,
378
- path.join(base, "index.ts"),
379
- ];
380
- for (const candidate of candidates) {
381
- if (!fs.existsSync(candidate))
382
- continue;
383
- const normalized = candidate.replace(/\\/g, "/");
384
- if (/[\\/]board-/.test(normalized)) {
385
- // Always redirect to index.ts in the board package root so we parse the
386
- // BoardDefinition manifest regardless of which file was actually imported
387
- // (e.g. board.ts, pins.ts, etc.).
388
- const boardDir = path.dirname(candidate);
389
- const indexTs = path.join(boardDir, "index.ts");
390
- return fs.existsSync(indexTs) ? indexTs : candidate;
391
- }
392
- }
393
- return undefined;
394
- }
395
- // Handle npm-scoped board package imports (e.g. "@typecad/board-esp32-devkit")
396
- if (effectiveSpecifier.startsWith("@typecad/board-")) {
397
- const parts = effectiveSpecifier.split("/");
398
- const pkgName = parts[1]; // "board-esp32-devkit"
399
- // Walk up from the importing file's directory to find node_modules OR a packages directory (monorepo)
400
- let dir = path.dirname(fromFile);
401
- while (true) {
402
- // 1. Try node_modules
403
- const nmCandidate = path.join(dir, "node_modules", "@typecad", pkgName, "src", "index.ts");
404
- if (fs.existsSync(nmCandidate))
405
- return nmCandidate;
406
- // 2. Try packages/ directory (monorepo layout)
407
- const pkgCandidate = path.join(dir, "packages", pkgName, "src", "index.ts");
408
- if (fs.existsSync(pkgCandidate))
409
- return pkgCandidate;
410
- // 3. Try sibling packages directory (if fromFile is inside a package)
411
- const siblingPkgCandidate = path.join(path.dirname(dir), "packages", pkgName, "src", "index.ts");
412
- if (fs.existsSync(siblingPkgCandidate))
413
- return siblingPkgCandidate;
414
- const parent = path.dirname(dir);
415
- if (parent === dir)
416
- break; // reached filesystem root
417
- dir = parent;
418
- }
71
+ export function tryResolveBoardDefFile(fromFile, moduleSpecifier, boardTarget) {
72
+ const isVirtualBoardSpecifier = moduleSpecifier.toLowerCase() === "@typecad/board";
73
+ if (isVirtualBoardSpecifier || moduleSpecifier === boardTarget) {
74
+ const generated = findGeneratedBoard(fromFile);
75
+ if (generated)
76
+ return generated.boardJson;
419
77
  }
420
78
  return undefined;
421
79
  }
422
- /**
423
- * Resolve the framework-specific build target (e.g. Arduino FQBN) from the
424
- * board package's manifest.
425
- *
426
- * @param boardPackage Board package identifier or path.
427
- * @param configPath Path to the project config file (for relative resolution).
428
- * @param framework Target framework name (default: 'arduino').
429
- */
430
- export function resolveBoardBuildTarget(boardPackage, configPath, framework = "arduino") {
431
- const defFile = tryResolveBoardDefFile(configPath, boardPackage);
432
- if (!defFile)
433
- return undefined;
434
- const constants = resolveBoardConstants(defFile);
435
- const target = constants.get(`build.frameworks.${framework}`);
436
- return typeof target === "string" ? target : undefined;
437
- }
@@ -165,4 +165,7 @@ export declare const TYPED_ARRAY_ELEMENT_MAP: Record<string, string>;
165
165
  export declare function getCurrentBoardConstants(): BoardConstants;
166
166
  export declare function setCurrentBoardConstants(v: BoardConstants | undefined): void;
167
167
  export declare function resetBuildState(): void;
168
+ export declare function markHalOpResolved(opName: string): void;
169
+ export declare function getTranspileResolvedHalOps(): ReadonlySet<string>;
170
+ export declare function resetTranspileResolvedHalOps(): void;
168
171
  export declare function resetFunctionScopeState(): void;
@@ -217,6 +217,14 @@ export function setCurrentBoardConstants(v) {
217
217
  const ctx = getContext();
218
218
  ctx._currentBoardConstants = v;
219
219
  if (v) {
220
+ // Framework strategies that resolve per-program chip data (framework-zephyr's
221
+ // prepareChip) must see the board constants at IR-build time: HAL method
222
+ // bodies lower to C++ text during the build, before the emitter's
223
+ // prepareChip call (emit/emitters/setup.ts) ever runs — without this, the
224
+ // lowering resolves every op against the NO_BOARD_CHIP defaults.
225
+ // Mirrors that duck-typed call.
226
+ ctx.activeStrategy
227
+ ?.prepareChip?.({ boardConstants: v }, undefined);
220
228
  // Populate peripheral aliases (e.g. UART0 -> Serial, I2C0 -> Wire)
221
229
  for (const [key, value] of v.entries()) {
222
230
  if (key.startsWith("peripherals.aliases.")) {
@@ -262,6 +270,19 @@ export function setCurrentBoardConstants(v) {
262
270
  }
263
271
  }
264
272
  }
273
+ // Board-module pin aliases (pins.aliases.<NAME> → pin name): the
274
+ // generated board module exports LED/BUTTON (and silkscreen labels) as
275
+ // aliases of datasheet-named pins. Map them through to numbers so
276
+ // resolveHALReceiver treats them as Pin constants.
277
+ for (const [key, value] of v.entries()) {
278
+ const aliasMatch = key.match(/^pins\.aliases\.([A-Za-z_][A-Za-z0-9_]*)$/);
279
+ if (aliasMatch && typeof value === 'string') {
280
+ const num = mcuPinForwardMap.get(value);
281
+ if (num !== undefined) {
282
+ pinAliasMap.set(aliasMatch[1], num);
283
+ }
284
+ }
285
+ }
265
286
  }
266
287
  }
267
288
  // 6. State management hooks
@@ -300,6 +321,27 @@ export function resetBuildState() {
300
321
  activeFunctionReturnTypes.clear();
301
322
  getContext()._currentBoardConstants = undefined;
302
323
  }
324
+ // ── Transpile-resolved HAL ops ──────────────────────────────────────────────
325
+ // HAL ops the transpiler resolves to C++ TEXT while inlining one HAL method
326
+ // inside another (e.g. `sense.readMillivolts()` in the argument of
327
+ // `USB0.writeLine(...)`) never appear as hal-op/hal-expr IR nodes, so the
328
+ // statement walk in program-analysis can't see them. routeHALOp and
329
+ // resolveHALExprToText record every op they successfully resolve here, and
330
+ // analyzeProgram merges these names into the peripheral usage flags.
331
+ // Deliberately NOT cleared by
332
+ // resetBuildState (per-file): the ops resolve while building whichever file
333
+ // inlines them, and analyzeProgram runs later, at emit. resetTranspileResolvedHalOps
334
+ // clears it once per transpile run.
335
+ const transpileResolvedHalOps = new Set();
336
+ export function markHalOpResolved(opName) {
337
+ transpileResolvedHalOps.add(opName);
338
+ }
339
+ export function getTranspileResolvedHalOps() {
340
+ return transpileResolvedHalOps;
341
+ }
342
+ export function resetTranspileResolvedHalOps() {
343
+ transpileResolvedHalOps.clear();
344
+ }
303
345
  export function resetFunctionScopeState() {
304
346
  activeCArrayVars.clear();
305
347
  activeArrayLiteralVars.clear();
@@ -1,2 +1,2 @@
1
1
  import { ClassIR, ProgramIR } from "../api/index.js";
2
- export declare function buildProgramIR(fileName: string, sourceText: string, boardPackage?: string, prebuiltClassMap?: Map<string, ClassIR>): ProgramIR;
2
+ export declare function buildProgramIR(fileName: string, sourceText: string, boardTarget?: string, prebuiltClassMap?: Map<string, ClassIR>): ProgramIR;