@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,61 @@
1
+ import ts from "typescript";
2
+ export interface HALInstance {
3
+ className: string;
4
+ fieldValues: Map<string, string>;
5
+ _spreadParamName?: string;
6
+ /** When a bus alias comes from `const x = I2C0.take()`, tracks the singleton name for ownership IR. */
7
+ canonicalBusName?: string;
8
+ [key: string]: unknown;
9
+ }
10
+ export interface HALMethodEntry {
11
+ methodNode: ts.MethodDeclaration;
12
+ paramNames: string[];
13
+ spreadParamName?: string;
14
+ paramDefaults: Map<string, string>;
15
+ }
16
+ export interface HALClassEntry {
17
+ ctorFieldMap: Map<string, string>;
18
+ ctorDefaults: Map<string, string>;
19
+ methods: Map<string, HALMethodEntry>;
20
+ }
21
+ export declare const halClassRegistry: Map<string, HALClassEntry>;
22
+ export declare const halGlobalFunctions: Map<string, HALMethodEntry>;
23
+ export declare const halSingletons: Map<string, {
24
+ className: string;
25
+ fieldValues: Map<string, string>;
26
+ includes?: string[];
27
+ }>;
28
+ export declare const halCtorIncludes: Map<string, string[]>;
29
+ export declare let halModulesLoaded: boolean;
30
+ /** Check if an identifier name refers to a known HAL singleton or mapped peripheral. */
31
+ export declare function isHALSingleton(name: string): boolean;
32
+ /** Resolve the HAL source directory. */
33
+ export declare function resolveHALSourceDir(): string;
34
+ /** Extract constructor field mappings: which `this._field = param` assignments exist. */
35
+ export declare function extractCtorFieldMap(ctor: ts.ConstructorDeclaration): {
36
+ fieldMap: Map<string, string>;
37
+ defaults: Map<string, string>;
38
+ };
39
+ /** Extract include() calls from a constructor body. */
40
+ export declare function extractCtorIncludes(ctor: ts.ConstructorDeclaration | undefined): string[];
41
+ /** Extract parameter names and defaults from a function-like node. */
42
+ export declare function extractParams(node: ts.FunctionLikeDeclarationBase): {
43
+ paramNames: string[];
44
+ spreadParamName?: string;
45
+ paramDefaults: Map<string, string>;
46
+ };
47
+ /** Extract method entries from a class declaration. */
48
+ export declare function extractMethods(cls: ts.ClassDeclaration): Map<string, HALMethodEntry>;
49
+ /** Load and parse all HAL source files. Dynamic discovery. */
50
+ export declare function loadHALModules(force?: boolean): void;
51
+ /** Get constructor includes for a HAL class. */
52
+ export declare function getCtorIncludes(className: string): string[];
53
+ /** Resolve a call receiver to a tracked HAL instance. */
54
+ export declare function resolveHALReceiver(receiver: ts.Expression): HALInstance | null;
55
+ /** Build field values from constructor arguments using the field mapping.
56
+ * Falls back to literal defaults from the constructor body when no arg is provided. */
57
+ export declare function resolveCtorFieldValues(ctorFieldMap: Map<string, string>, args: ts.NodeArray<ts.Expression> | undefined, ctorDefaults?: Map<string, string>): Map<string, string> | null;
58
+ /** Check if a class name is a known HAL class in the registry. */
59
+ export declare function isKnownHALClass(className: string): boolean;
60
+ /** Get the constructor field map for a HAL class. */
61
+ export declare function getHALCtorFieldMap(className: string): Map<string, string> | undefined;
@@ -0,0 +1,473 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { createRequire } from "node:module";
4
+ import { fileURLToPath } from "node:url";
5
+ import ts from "typescript";
6
+ import { parseSource } from "../../ast/parse.js";
7
+ import { requiredIncludes, getCurrentBoardConstants, mcuPinForwardMap, mcuPinReverseMap, halInstances, topLevelAliasReceivers } from "../build-ir-state.js";
8
+ import { mapPeripheralName } from "../../mapping/peripheral-names.js";
9
+ import { escapeCppStringLiteral } from "../../utils/strings.js";
10
+ const require = createRequire(import.meta.url);
11
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
12
+ // Registry of HAL class method ASTs, keyed by class name
13
+ export const halClassRegistry = new Map();
14
+ export const halGlobalFunctions = new Map();
15
+ export const halSingletons = new Map();
16
+ export const halCtorIncludes = new Map();
17
+ // Guard: only load once per process
18
+ export let halModulesLoaded = false;
19
+ /** Check if an identifier name refers to a known HAL singleton or mapped peripheral. */
20
+ export function isHALSingleton(name) {
21
+ if (halSingletons.has(name))
22
+ return true;
23
+ if (mapPeripheralName(name) !== undefined)
24
+ return true;
25
+ return false;
26
+ }
27
+ /** Resolve the HAL source directory. */
28
+ export function resolveHALSourceDir() {
29
+ const monoPath = path.resolve(__dirname, "..", "..", "..", "..", "hal", "src");
30
+ let res = "";
31
+ if (fs.existsSync(path.join(monoPath, "gpio.ts"))) {
32
+ res = monoPath;
33
+ }
34
+ else {
35
+ try {
36
+ const pkgDir = path.dirname(require.resolve("@typecad/hal/package.json"));
37
+ res = path.join(pkgDir, "src");
38
+ }
39
+ catch { }
40
+ }
41
+ if (!res)
42
+ throw new Error("Could not resolve @typecad/hal/src/");
43
+ return res;
44
+ }
45
+ /** Extract constructor field mappings: which `this._field = param` assignments exist. */
46
+ export function extractCtorFieldMap(ctor) {
47
+ const fieldMap = new Map();
48
+ const defaults = new Map();
49
+ if (!ctor.body)
50
+ return { fieldMap, defaults };
51
+ for (const stmt of ctor.body.statements) {
52
+ if (ts.isExpressionStatement(stmt) &&
53
+ ts.isBinaryExpression(stmt.expression) &&
54
+ stmt.expression.operatorToken.kind === ts.SyntaxKind.EqualsToken) {
55
+ const left = stmt.expression.left;
56
+ const right = stmt.expression.right;
57
+ if (ts.isPropertyAccessExpression(left) &&
58
+ (left.expression.kind === ts.SyntaxKind.ThisKeyword ||
59
+ (ts.isIdentifier(left.expression) && left.expression.text === "this"))) {
60
+ // this._field = paramName (constructor parameter)
61
+ if (ts.isIdentifier(right)) {
62
+ fieldMap.set(left.name.text, right.text);
63
+ }
64
+ // this._field = "stringLiteral" (default value)
65
+ if (ts.isStringLiteral(right)) {
66
+ fieldMap.set(left.name.text, "__literal__" + right.text);
67
+ defaults.set(left.name.text, right.text);
68
+ }
69
+ }
70
+ }
71
+ // include("...") in constructor body
72
+ if (ts.isExpressionStatement(stmt) &&
73
+ ts.isCallExpression(stmt.expression) &&
74
+ ts.isIdentifier(stmt.expression.expression) &&
75
+ stmt.expression.expression.text === "include") {
76
+ const firstArg = stmt.expression.arguments[0];
77
+ if (firstArg && ts.isStringLiteral(firstArg)) {
78
+ // Constructor includes are registered when instances are created
79
+ // Store as a special field so processCtorIncludes can find them
80
+ }
81
+ }
82
+ }
83
+ return { fieldMap, defaults };
84
+ }
85
+ /** Extract include() calls from a constructor body. */
86
+ export function extractCtorIncludes(ctor) {
87
+ const includes = [];
88
+ if (!ctor?.body)
89
+ return includes;
90
+ for (const stmt of ctor.body.statements) {
91
+ if (ts.isExpressionStatement(stmt) &&
92
+ ts.isCallExpression(stmt.expression) &&
93
+ ts.isIdentifier(stmt.expression.expression) &&
94
+ stmt.expression.expression.text === "include") {
95
+ const firstArg = stmt.expression.arguments[0];
96
+ if (firstArg && ts.isStringLiteral(firstArg)) {
97
+ includes.push(firstArg.text);
98
+ }
99
+ }
100
+ }
101
+ return includes;
102
+ }
103
+ /** Extract parameter names and defaults from a function-like node. */
104
+ export function extractParams(node) {
105
+ const paramNames = [];
106
+ const paramDefaults = new Map();
107
+ for (const p of node.parameters) {
108
+ if (ts.isIdentifier(p.name)) {
109
+ const name = p.name.text;
110
+ paramNames.push(name);
111
+ if (p.initializer) {
112
+ if (ts.isNumericLiteral(p.initializer))
113
+ paramDefaults.set(name, p.initializer.text);
114
+ else if (ts.isStringLiteral(p.initializer))
115
+ paramDefaults.set(name, `"${escapeCppStringLiteral(p.initializer.text)}"`);
116
+ else if (p.initializer.kind === ts.SyntaxKind.TrueKeyword)
117
+ paramDefaults.set(name, "true");
118
+ else if (p.initializer.kind === ts.SyntaxKind.FalseKeyword)
119
+ paramDefaults.set(name, "false");
120
+ }
121
+ }
122
+ }
123
+ const spreadParam = node.parameters.find(p => !!p.dotDotDotToken);
124
+ const spreadParamName = spreadParam && ts.isIdentifier(spreadParam.name) ? spreadParam.name.text : undefined;
125
+ return { paramNames, spreadParamName, paramDefaults };
126
+ }
127
+ /** Extract method entries from a class declaration. */
128
+ export function extractMethods(cls) {
129
+ const methods = new Map();
130
+ for (const member of cls.members) {
131
+ if (ts.isMethodDeclaration(member) && member.name && ts.isIdentifier(member.name)) {
132
+ const methodName = member.name.text;
133
+ const { paramNames, spreadParamName, paramDefaults } = extractParams(member);
134
+ methods.set(methodName, { methodNode: member, paramNames, spreadParamName, paramDefaults });
135
+ }
136
+ }
137
+ return methods;
138
+ }
139
+ /** Load and parse all HAL source files. Dynamic discovery. */
140
+ export function loadHALModules(force = false) {
141
+ if (halModulesLoaded && !force)
142
+ return;
143
+ halModulesLoaded = true;
144
+ if (force) {
145
+ halClassRegistry.clear();
146
+ halCtorIncludes.clear();
147
+ halSingletons.clear();
148
+ halGlobalFunctions.clear();
149
+ }
150
+ try {
151
+ const srcDir = resolveHALSourceDir();
152
+ const files = fs.readdirSync(srcDir).filter(f => f.endsWith(".ts") && f !== "index.ts");
153
+ for (const fileName of files) {
154
+ const filePath = path.join(srcDir, fileName);
155
+ if (!fs.existsSync(filePath))
156
+ continue;
157
+ const source = fs.readFileSync(filePath, "utf-8");
158
+ const sourceFile = parseSource(fileName, source);
159
+ for (const stmt of sourceFile.statements) {
160
+ if (ts.isClassDeclaration(stmt) && stmt.name) {
161
+ const className = stmt.name.text;
162
+ const ctor = stmt.members.find(ts.isConstructorDeclaration);
163
+ const { fieldMap: ctorFieldMap, defaults: ctorDefaults } = ctor ? extractCtorFieldMap(ctor) : { fieldMap: new Map(), defaults: new Map() };
164
+ const ctorIncludes = extractCtorIncludes(ctor);
165
+ const methods = extractMethods(stmt);
166
+ // Metadata extraction for singletons
167
+ let instanceName;
168
+ let includes;
169
+ const defaultFields = new Map();
170
+ for (const member of stmt.members) {
171
+ if (ts.isPropertyDeclaration(member) &&
172
+ member.modifiers?.some(m => m.kind === ts.SyntaxKind.StaticKeyword) &&
173
+ ts.isIdentifier(member.name)) {
174
+ if (member.name.text === "__instance_name" && member.initializer && ts.isStringLiteral(member.initializer)) {
175
+ instanceName = member.initializer.text;
176
+ }
177
+ if (member.name.text === "__includes" && member.initializer && ts.isArrayLiteralExpression(member.initializer)) {
178
+ includes = member.initializer.elements.filter(ts.isStringLiteral).map(e => e.text);
179
+ }
180
+ if (member.name.text === "__default_fields" && member.initializer && ts.isObjectLiteralExpression(member.initializer)) {
181
+ for (const prop of member.initializer.properties) {
182
+ if (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name) && ts.isStringLiteral(prop.initializer)) {
183
+ defaultFields.set(prop.name.text, prop.initializer.text);
184
+ }
185
+ }
186
+ }
187
+ }
188
+ }
189
+ halClassRegistry.set(className, { ctorFieldMap, ctorDefaults, methods });
190
+ if (instanceName) {
191
+ halSingletons.set(instanceName, { className, fieldValues: defaultFields, includes });
192
+ }
193
+ if (ctorIncludes.length > 0) {
194
+ halCtorIncludes.set(className, ctorIncludes);
195
+ }
196
+ }
197
+ else if (ts.isFunctionDeclaration(stmt) && stmt.name && stmt.body) {
198
+ const functionName = stmt.name.text;
199
+ const { paramNames, spreadParamName, paramDefaults } = extractParams(stmt);
200
+ halGlobalFunctions.set(functionName, { methodNode: stmt, paramNames, spreadParamName, paramDefaults });
201
+ }
202
+ }
203
+ }
204
+ }
205
+ catch (e) {
206
+ console.warn("[hal-resolver] Failed to load HAL modules:", e.message);
207
+ }
208
+ }
209
+ /** Get constructor includes for a HAL class. */
210
+ export function getCtorIncludes(className) {
211
+ return halCtorIncludes.get(className) ?? [];
212
+ }
213
+ /** Resolve a call receiver to a tracked HAL instance. */
214
+ export function resolveHALReceiver(receiver) {
215
+ const result = (() => {
216
+ // Variable reference: led.method()
217
+ if (ts.isIdentifier(receiver)) {
218
+ const inst = halInstances.get(receiver.text);
219
+ if (inst)
220
+ return inst;
221
+ // Metadata-driven singleton resolution (e.g., ADC, EEPROM, WDT)
222
+ const singleton = halSingletons.get(receiver.text);
223
+ if (singleton) {
224
+ if (singleton.includes) {
225
+ for (const inc of singleton.includes)
226
+ requiredIncludes.add(inc);
227
+ }
228
+ // Reuse cached instance so state updates (e.g. ADC._reference) persist
229
+ const cached = halInstances.get(receiver.text);
230
+ if (cached)
231
+ return cached;
232
+ const inst = { className: singleton.className, fieldValues: new Map(singleton.fieldValues) };
233
+ halInstances.set(receiver.text, inst);
234
+ return inst;
235
+ }
236
+ const name = receiver.text;
237
+ const bc = getCurrentBoardConstants();
238
+ // Board-defined peripheral aliases (e.g., UART0 -> Serial)
239
+ // Consolidates both canonical (UART0) and platform (Serial) names via the manifest.
240
+ const mappedName = mapPeripheralName(name);
241
+ if (mappedName) {
242
+ const canonical = name.toUpperCase();
243
+ if (canonical.startsWith("UART"))
244
+ return { className: "SerialPort", fieldValues: new Map([["_port", mappedName]]) };
245
+ if (canonical.startsWith("I2C"))
246
+ return { className: "I2CBus", fieldValues: new Map([["_bus", mappedName]]) };
247
+ if (canonical.startsWith("SPI"))
248
+ return { className: "SPIBus", fieldValues: new Map([["_bus", mappedName]]) };
249
+ }
250
+ // Bare pin resolution (D0, A0, etc.) — enriched with MCU port name
251
+ const dMatch = name.match(/^D(\d+)$/);
252
+ if (dMatch) {
253
+ const arduinoPin = dMatch[1];
254
+ const portName = mcuPinReverseMap.get(arduinoPin);
255
+ const fields = new Map([["_pin", arduinoPin]]);
256
+ if (portName)
257
+ fields.set("_port", portName);
258
+ const inst = { className: "Pin", fieldValues: fields };
259
+ halInstances.set(name, inst);
260
+ return inst;
261
+ }
262
+ const aMatch = name.match(/^A(\d+)$/);
263
+ if (aMatch) {
264
+ const offset = Number(bc.get("pins.analogOffset") ?? 0);
265
+ const pinNum = String(Number(aMatch[1]) + offset);
266
+ const portName = mcuPinReverseMap.get(pinNum);
267
+ const fields = new Map([["_pin", pinNum]]);
268
+ if (portName)
269
+ fields.set("_port", portName);
270
+ const inst = { className: "Pin", fieldValues: fields };
271
+ halInstances.set(name, inst);
272
+ return inst;
273
+ }
274
+ const timerMatch = name.match(/^Timer(\d+)$/);
275
+ if (timerMatch) {
276
+ return { className: "HardwareTimer", fieldValues: new Map([["_instance", timerMatch[1]]]) };
277
+ }
278
+ }
279
+ // Chained call result: new Pin(13).asOutput()
280
+ // Also handles static factory calls: Pin.fromPort("PB5")
281
+ if (ts.isCallExpression(receiver) && ts.isPropertyAccessExpression(receiver.expression)) {
282
+ // Static factory: Pin.fromPort("PB5") → Pin with _port field
283
+ if (ts.isIdentifier(receiver.expression.expression) &&
284
+ receiver.expression.expression.text === 'Pin' &&
285
+ receiver.expression.name.text === 'fromPort') {
286
+ const factoryArgs = receiver.arguments;
287
+ if (factoryArgs && factoryArgs.length > 0 && ts.isStringLiteral(factoryArgs[0])) {
288
+ const portName = factoryArgs[0].text;
289
+ // Resolve Arduino pin number from MCU forward map
290
+ const arduinoPin = mcuPinForwardMap.get(portName) ?? '-1';
291
+ return { className: 'Pin', fieldValues: new Map([['_port', portName], ['_pin', arduinoPin]]) };
292
+ }
293
+ }
294
+ const innerInstance = resolveHALReceiver(receiver.expression.expression);
295
+ if (innerInstance) {
296
+ const methodName = receiver.expression.name.text;
297
+ // Specialized handling for Pin chaining (Pin -> OutputPin/InputPin)
298
+ if (innerInstance.className === "Pin" && (methodName === "asOutput" || methodName === "asInput" || methodName === "asInputPullUp")) {
299
+ const returnClassName = methodName === "asOutput" ? "OutputPin" : "InputPin";
300
+ return { className: returnClassName, fieldValues: new Map(innerInstance.fieldValues) };
301
+ }
302
+ // Specialized handling for device() factory pattern (I2CBus/SPIBus -> I2CDevice/SPIDevice)
303
+ // This allows propagating the address/CS pin from the call argument to the new instance.
304
+ if (methodName === "device" && (innerInstance.className === "I2CBus" || innerInstance.className === "SPIBus") && receiver.arguments.length > 0) {
305
+ const returnClassName = innerInstance.className === "SPIBus" ? "SPIDevice" : "I2CDevice";
306
+ const fieldValues = new Map(innerInstance.fieldValues);
307
+ const arg = receiver.arguments[0];
308
+ let argVal = null;
309
+ if (ts.isNumericLiteral(arg))
310
+ argVal = arg.text;
311
+ else if (ts.isIdentifier(arg)) {
312
+ // Check halInstances first (e.g. D10)
313
+ const argInst = halInstances.get(arg.text);
314
+ if (argInst && argInst.fieldValues.has("_pin"))
315
+ argVal = argInst.fieldValues.get("_pin");
316
+ else
317
+ argVal = arg.text;
318
+ }
319
+ if (argVal) {
320
+ const fieldName = innerInstance.className === "SPIBus" ? "_cs" : "_address";
321
+ fieldValues.set(fieldName, argVal);
322
+ return { className: returnClassName, fieldValues };
323
+ }
324
+ }
325
+ // Specialized handling for tone() chaining (OutputPin -> ToneChain)
326
+ if (methodName === "tone" && innerInstance.className === "OutputPin" && receiver.arguments.length > 0) {
327
+ const fieldValues = new Map(innerInstance.fieldValues);
328
+ const arg = receiver.arguments[0];
329
+ let argVal = null;
330
+ if (ts.isNumericLiteral(arg))
331
+ argVal = arg.text;
332
+ else if (ts.isIdentifier(arg))
333
+ argVal = arg.text;
334
+ if (argVal) {
335
+ fieldValues.set("_lastFreq", argVal);
336
+ return { className: "ToneChain", fieldValues };
337
+ }
338
+ }
339
+ // General fallback: if the method is known to return another HAL class, carry over fields
340
+ const classEntry = halClassRegistry.get(innerInstance.className);
341
+ const methodEntry = classEntry?.methods.get(methodName);
342
+ if (methodEntry && methodEntry.methodNode.type && ts.isTypeReferenceNode(methodEntry.methodNode.type) && ts.isIdentifier(methodEntry.methodNode.type.typeName)) {
343
+ const returnClassName = methodEntry.methodNode.type.typeName.text;
344
+ if (halClassRegistry.has(returnClassName)) {
345
+ return { className: returnClassName, fieldValues: new Map(innerInstance.fieldValues) };
346
+ }
347
+ }
348
+ }
349
+ }
350
+ // Inline new expression: new Pin(x).method()
351
+ if (ts.isNewExpression(receiver) && ts.isIdentifier(receiver.expression)) {
352
+ const className = receiver.expression.text;
353
+ const classEntry = halClassRegistry.get(className);
354
+ if (!classEntry)
355
+ return null;
356
+ const args = receiver.arguments;
357
+ const fieldValues = resolveCtorFieldValues(classEntry.ctorFieldMap, args, classEntry.ctorDefaults);
358
+ if (fieldValues) {
359
+ return { className, fieldValues };
360
+ }
361
+ }
362
+ // Lazy top-level alias follow (demo #34 Finding C): if `receiver` is an
363
+ // identifier that names a top-level `const x = <pin>.<modeSetter>(...)`
364
+ // alias, resolve the recorded receiver name instead. This makes HAL
365
+ // resolution order-independent — a function referencing `led` resolves it
366
+ // even when declared before `const led = LED.asOutput()`. Only mode-setter
367
+ // aliases are recorded (build-ir.ts Phase 0d), so a value-bearing-read
368
+ // variable is never followed here (Finding B). Follow the chain with a
369
+ // visited-set to guard against cycles.
370
+ if (ts.isIdentifier(receiver) && topLevelAliasReceivers.has(receiver.text)) {
371
+ // Collect the full alias chain (e.g. sensor → bus → I2C0), then resolve
372
+ // the base instance and apply ALL transformations in chain order.
373
+ const chain = [];
374
+ const visited = new Set([receiver.text]);
375
+ let cur = receiver.text;
376
+ while (topLevelAliasReceivers.has(cur) && !visited.has(topLevelAliasReceivers.get(cur).receiver)) {
377
+ const entry = topLevelAliasReceivers.get(cur);
378
+ visited.add(entry.receiver);
379
+ chain.push(entry);
380
+ cur = entry.receiver;
381
+ }
382
+ // Resolve the base instance from the end of the chain.
383
+ const baseName = chain.length > 0 ? chain[chain.length - 1].receiver : receiver.text;
384
+ const baseInst = halInstances.get(baseName);
385
+ if (baseInst) {
386
+ let resolvedInst = baseInst;
387
+ // Apply each transformation in chain order (first entry = outermost call).
388
+ for (const entry of chain) {
389
+ // Pin mode-change: Pin → OutputPin/InputPin
390
+ if ((entry.method === "asOutput" || entry.method === "asInput" || entry.method === "asInputPullUp" || entry.method === "asInputPullDown" || entry.method === "output" || entry.method === "inputPullUp" || entry.method === "inputPullDown") && resolvedInst.className === "Pin") {
391
+ const returnClassName = (entry.method === "asOutput" || entry.method === "output") ? "OutputPin" : "InputPin";
392
+ resolvedInst = { className: returnClassName, fieldValues: new Map(resolvedInst.fieldValues) };
393
+ }
394
+ // I2C/SPI device factory: bus → device with address/cs from args
395
+ if (entry.method === "device" && (resolvedInst.className === "I2CBus" || resolvedInst.className === "SPIBus")) {
396
+ const returnClassName = resolvedInst.className === "SPIBus" ? "SPIDevice" : "I2CDevice";
397
+ const fieldValues = new Map(resolvedInst.fieldValues);
398
+ const fieldName = resolvedInst.className === "SPIBus" ? "_cs" : "_address";
399
+ if (entry.args && entry.args.length > 0) {
400
+ // Resolve identifier args (e.g. D10 → 10) via halInstances.
401
+ // Numeric/string args pass through unchanged.
402
+ const rawArg = entry.args[0];
403
+ const argInst = halInstances.get(rawArg);
404
+ const resolvedArg = argInst?.fieldValues.get("_pin") ?? argInst?.fieldValues.get("pin") ?? rawArg;
405
+ fieldValues.set(fieldName, resolvedArg);
406
+ }
407
+ resolvedInst = { className: returnClassName, fieldValues };
408
+ }
409
+ // Tone chain factory: OutputPin → ToneChain with frequency from args
410
+ if (entry.method === "tone" && resolvedInst.className === "OutputPin" && entry.args && entry.args.length > 0) {
411
+ const fieldValues = new Map(resolvedInst.fieldValues);
412
+ fieldValues.set("_lastFreq", entry.args[0]);
413
+ resolvedInst = { className: "ToneChain", fieldValues };
414
+ }
415
+ // begin/identity: no class change, just carry the instance forward.
416
+ }
417
+ halInstances.set(receiver.text, resolvedInst);
418
+ return resolvedInst;
419
+ }
420
+ }
421
+ return null;
422
+ })();
423
+ return result;
424
+ }
425
+ /** Build field values from constructor arguments using the field mapping.
426
+ * Falls back to literal defaults from the constructor body when no arg is provided. */
427
+ export function resolveCtorFieldValues(ctorFieldMap, args, ctorDefaults) {
428
+ const fieldValues = new Map();
429
+ const argArr = args ?? [];
430
+ // Track which param names are from literal defaults (skip them for arg matching)
431
+ const literalFields = new Set();
432
+ for (const [fieldName, paramName] of ctorFieldMap) {
433
+ if (paramName.startsWith("__literal__")) {
434
+ literalFields.add(fieldName);
435
+ const defaultVal = ctorDefaults?.get(fieldName);
436
+ if (defaultVal !== undefined) {
437
+ fieldValues.set(fieldName, defaultVal);
438
+ }
439
+ }
440
+ }
441
+ // Match remaining fields to constructor arguments
442
+ const paramFields = Array.from(ctorFieldMap.entries()).filter(([f]) => !literalFields.has(f));
443
+ for (const [fieldName, paramName] of paramFields) {
444
+ const paramIdx = paramFields.findIndex(([, p]) => p === paramName);
445
+ if (paramIdx === -1 || paramIdx >= argArr.length)
446
+ continue;
447
+ const arg = argArr[paramIdx];
448
+ if (ts.isIdentifier(arg)) {
449
+ fieldValues.set(fieldName, arg.text);
450
+ }
451
+ else if (ts.isNumericLiteral(arg)) {
452
+ fieldValues.set(fieldName, arg.text);
453
+ }
454
+ else if (ts.isStringLiteral(arg)) {
455
+ fieldValues.set(fieldName, arg.text);
456
+ }
457
+ else if (ts.isPropertyAccessExpression(arg)) {
458
+ fieldValues.set(fieldName, arg.getText());
459
+ }
460
+ else {
461
+ return null;
462
+ }
463
+ }
464
+ return fieldValues;
465
+ }
466
+ /** Check if a class name is a known HAL class in the registry. */
467
+ export function isKnownHALClass(className) {
468
+ return halClassRegistry.has(className);
469
+ }
470
+ /** Get the constructor field map for a HAL class. */
471
+ export function getHALCtorFieldMap(className) {
472
+ return halClassRegistry.get(className)?.ctorFieldMap;
473
+ }
@@ -0,0 +1,34 @@
1
+ import ts from "typescript";
2
+ import { HALOpIR } from "../../api/index.js";
3
+ import { HALInstance } from "./hal-parser.js";
4
+ import type { ExpressionIR } from "../../api/index.js";
5
+ /** Resolve a single argument from a semantic call's AST node list. */
6
+ export declare function resolveSemanticArg(args: readonly ts.Expression[], idx: number, instance: HALInstance, paramNames: string[], callArgTexts: string[], paramDefaults: Map<string, string> | undefined): string | null;
7
+ /** Resolve a numeric argument, returning its numeric value or null. */
8
+ export declare function resolveNumericArg(args: readonly ts.Expression[], idx: number, instance: HALInstance, paramNames: string[], callArgTexts: string[], paramDefaults: Map<string, string> | undefined): number | null;
9
+ /** Extract the MCU port name from the current HAL instance, if available. */
10
+ export declare function portFromInstance(instance: HALInstance): string | undefined;
11
+ /**
12
+ * Resolve a boardResolve() argument to a dot-path string.
13
+ * Handles both static string paths ("peripherals.adc.0.resolution") and
14
+ * dynamic paths ("peripherals.adc.0.referenceVoltages." + this._reference).
15
+ */
16
+ export declare function tryResolveBoardResolveArg(args: ts.NodeArray<ts.Expression>, instance: HALInstance, paramNames: string[], callArgTexts: string[], paramDefaults: Map<string, string> | undefined): string | null;
17
+ /**
18
+ * Recursively flatten a `+`-concatenation / template-literal expression into a
19
+ * board-resolve dot-path string. Returns null if any operand cannot be
20
+ * resolved to a concrete string fragment.
21
+ */
22
+ export declare function resolveConcatPath(expr: ts.Expression, instance: HALInstance, paramNames: string[], callArgTexts: string[], paramDefaults: Map<string, string> | undefined): string | null;
23
+ /**
24
+ * Try to resolve a compound return expression that contains semantic calls.
25
+ * For example, `(gpioRead(this._pin) === HIGH)` should produce a halOp for
26
+ * `gpioRead` and return a combined expression with the strategy-resolved form.
27
+ * Returns the resolved text with placeholders, or null if no semantic calls found.
28
+ */
29
+ export declare function tryResolveCompoundSemanticReturn(expr: ts.Expression, instance: HALInstance, paramNames: string[], callArgTexts: string[], paramDefaults: Map<string, string> | undefined, halOps: HALOpIR[], callArgs: any[]): string | null;
30
+ /**
31
+ * Try to resolve a semantic HAL function call to a HALOpIR node.
32
+ * Returns the HALOpIR if the function name is recognized, or null.
33
+ */
34
+ export declare function tryResolveSemanticCall(fnName: string, args: readonly ts.Expression[], instance: HALInstance, paramNames: string[], callArgTexts: string[], paramDefaults: Map<string, string> | undefined, callArgs?: ExpressionIR[]): HALOpIR | null;