@typecad/cuttlefish 1.0.0-alpha.14 → 1.0.0-alpha.16

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 (315) hide show
  1. package/README.md +82 -79
  2. package/assets/editor-extensions/typecad-debug/README.md +25 -26
  3. package/dist/api/config.d.ts +22 -26
  4. package/dist/api/schema/types.d.ts +20 -3
  5. package/dist/api/shared/async-runtime-static.d.ts +1 -1
  6. package/dist/api/shared/async-runtime-static.js +5 -5
  7. package/dist/api/shared/async-types.d.ts +3 -2
  8. package/dist/api/shared/board-catalog.d.ts +2 -0
  9. package/dist/api/shared/board-catalog.js +6 -0
  10. package/dist/api/shared/board-resolver.d.ts +4 -7
  11. package/dist/api/shared/board-resolver.js +2 -1
  12. package/dist/api/shared/coop-scheduler.d.ts +1 -1
  13. package/dist/api/shared/coop-scheduler.js +1 -1
  14. package/dist/api/shared/cpp-type-ir.d.ts +1 -1
  15. package/dist/api/shared/cpp-type-ir.js +1 -1
  16. package/dist/api/shared/display-profile.d.ts +1 -1
  17. package/dist/api/shared/display-profile.js +3 -5
  18. package/dist/api/shared/framework-manifest-registry.d.ts +1 -1
  19. package/dist/api/shared/framework-manifest-registry.js +0 -1
  20. package/dist/api/shared/framework-manifest.d.ts +7 -6
  21. package/dist/api/shared/framework-manifest.js +6 -11
  22. package/dist/api/shared/hal-op-ir.d.ts +294 -685
  23. package/dist/api/shared/hal-op-ir.js +31 -65
  24. package/dist/api/shared/index.d.ts +0 -4
  25. package/dist/api/shared/index.js +1 -7
  26. package/dist/api/shared/ir-core.d.ts +6 -0
  27. package/dist/api/shared/ir-declarations.d.ts +4 -0
  28. package/dist/api/shared/ir.d.ts +1 -3
  29. package/dist/api/shared/platform-strategy.d.ts +14 -37
  30. package/dist/api/shared/polyfill-helper-registry.js +0 -5
  31. package/dist/api/shared/polyfill-types.js +0 -27
  32. package/dist/api/shared/promise-runtime.js +3 -3
  33. package/dist/api/shared/spdx-licenses.d.ts +12 -10
  34. package/dist/api/shared/spdx-licenses.js +1 -1
  35. package/dist/api/shared/toolchain-types.d.ts +1 -1
  36. package/dist/api/shared/toolchain-types.js +3 -3
  37. package/dist/api/shared/types.d.ts +0 -3
  38. package/dist/api/shared/validate-framework-manifest.js +13 -33
  39. package/dist/board-catalog/dts-reader.d.ts +220 -0
  40. package/dist/board-catalog/dts-reader.js +1052 -0
  41. package/dist/board-catalog/index.d.ts +11 -0
  42. package/dist/board-catalog/index.js +12 -0
  43. package/dist/board-catalog/pinconfig.d.ts +48 -0
  44. package/dist/board-catalog/pinconfig.js +263 -0
  45. package/dist/board-catalog/sdk.d.ts +82 -0
  46. package/dist/board-catalog/sdk.js +180 -0
  47. package/dist/board-catalog/store.d.ts +196 -0
  48. package/dist/board-catalog/store.js +363 -0
  49. package/dist/board-catalog/types.d.ts +233 -0
  50. package/dist/board-catalog/types.js +7 -0
  51. package/dist/board-catalog/walker.d.ts +112 -0
  52. package/dist/board-catalog/walker.js +1101 -0
  53. package/dist/cli-utils.d.ts +2 -2
  54. package/dist/cli-utils.js +5 -5
  55. package/dist/cli.js +219 -242
  56. package/dist/config-loader.d.ts +14 -19
  57. package/dist/config-loader.js +240 -78
  58. package/dist/config-schema.d.ts +3 -5
  59. package/dist/config-schema.js +8 -8
  60. package/dist/contract/board-generator.d.ts +4 -4
  61. package/dist/contract/board-generator.js +16 -5
  62. package/dist/contract/contract-parser.d.ts +27 -0
  63. package/dist/contract/contract-parser.js +76 -0
  64. package/dist/contract/index.d.ts +1 -1
  65. package/dist/contract/index.js +70 -21
  66. package/dist/create/active-board-catalog.d.ts +9 -0
  67. package/dist/create/active-board-catalog.js +94 -0
  68. package/dist/create/board-catalog.generated.d.ts +96 -0
  69. package/dist/create/board-catalog.generated.js +128737 -0
  70. package/dist/create/board-search.d.ts +23 -0
  71. package/dist/create/board-search.js +88 -0
  72. package/dist/create/editor-integration.d.ts +4 -2
  73. package/dist/create/editor-integration.js +41 -2
  74. package/dist/create/framework-catalog.d.ts +57 -9
  75. package/dist/create/framework-catalog.js +76 -57
  76. package/dist/create/index.d.ts +5 -11
  77. package/dist/create/index.js +3 -8
  78. package/dist/create/mcu-target.d.ts +39 -0
  79. package/dist/create/mcu-target.js +80 -0
  80. package/dist/create/pack-targets.d.ts +19 -0
  81. package/dist/create/pack-targets.js +56 -0
  82. package/dist/create/scaffold.d.ts +4 -7
  83. package/dist/create/scaffold.js +19 -109
  84. package/dist/create/templates.d.ts +32 -5
  85. package/dist/create/templates.js +130 -116
  86. package/dist/create/wizard.d.ts +12 -1
  87. package/dist/create/wizard.js +168 -38
  88. package/dist/debug/preprocessor.d.ts +5 -0
  89. package/dist/debug/preprocessor.js +31 -7
  90. package/dist/diagnostics/diagnostics-report.d.ts +1 -1
  91. package/dist/diagnostics/diagnostics-report.js +3 -11
  92. package/dist/diagnostics/json-schema.d.ts +1 -1
  93. package/dist/diagnostics/md-writer.js +2 -2
  94. package/dist/diagnostics/mermaid-builder.d.ts +1 -1
  95. package/dist/diagnostics/mermaid-builder.js +1 -1
  96. package/dist/emit/cpp-emitter.js +4 -1
  97. package/dist/emit/emitters/class-emitter.js +32 -4
  98. package/dist/emit/emitters/emitter-context.d.ts +11 -0
  99. package/dist/emit/emitters/entrypoint-synthesizer.js +1 -1
  100. package/dist/emit/emitters/function-emitter-impl.js +33 -17
  101. package/dist/emit/emitters/output-finalizer.d.ts +7 -0
  102. package/dist/emit/emitters/output-finalizer.js +31 -23
  103. package/dist/emit/emitters/setup.js +125 -63
  104. package/dist/emit/emitters/top-level-prep.js +1 -1
  105. package/dist/emit/emitters/type-decl-emitter.js +13 -8
  106. package/dist/emit/emitters/ui-emitter.js +1 -1
  107. package/dist/emit/expression-renderer.d.ts +3 -3
  108. package/dist/emit/expression-renderer.js +17 -7
  109. package/dist/emit/route-hal-op.js +17 -48
  110. package/dist/emit/snprintf-helpers.d.ts +1 -3
  111. package/dist/emit/snprintf-helpers.js +1 -39
  112. package/dist/emit/statement-renderer.d.ts +0 -4
  113. package/dist/emit/statement-renderer.js +54 -45
  114. package/dist/emit/utils/async-state-machine.d.ts +16 -9
  115. package/dist/emit/utils/async-state-machine.js +56 -54
  116. package/dist/emit/utils/comment-helpers.d.ts +0 -8
  117. package/dist/emit/utils/comment-helpers.js +1 -1
  118. package/dist/emit/utils/cpp-helpers.d.ts +2 -2
  119. package/dist/emit/utils/cpp-helpers.js +2 -2
  120. package/dist/emit/utils/hal-op-cpp-type.js +4 -6
  121. package/dist/emit/utils/index.d.ts +3 -3
  122. package/dist/emit/utils/index.js +3 -3
  123. package/dist/emit/utils/type-inference.d.ts +1 -29
  124. package/dist/emit/utils/type-inference.js +0 -75
  125. package/dist/framework-package.d.ts +3 -0
  126. package/dist/framework-package.js +23 -6
  127. package/dist/framework-registry.d.ts +5 -5
  128. package/dist/frameworks/native/graphics/terminal-preview.d.ts +5 -0
  129. package/dist/frameworks/native/graphics/terminal-preview.js +33 -0
  130. package/dist/frameworks/native/index.d.ts +3 -0
  131. package/dist/frameworks/native/index.js +15 -0
  132. package/dist/frameworks/native/native-compile.d.ts +17 -0
  133. package/dist/frameworks/native/native-compile.js +170 -0
  134. package/dist/frameworks/native/native-config.d.ts +41 -0
  135. package/dist/frameworks/native/native-config.js +7 -0
  136. package/dist/frameworks/native/strategy.d.ts +97 -0
  137. package/dist/frameworks/native/strategy.js +664 -0
  138. package/dist/ir/board-resolver.d.ts +18 -23
  139. package/dist/ir/board-resolver.js +43 -401
  140. package/dist/ir/build-ir-state.d.ts +3 -0
  141. package/dist/ir/build-ir-state.js +42 -0
  142. package/dist/ir/build-ir.d.ts +1 -1
  143. package/dist/ir/build-ir.js +40 -42
  144. package/dist/ir/declaration-builders.js +1 -0
  145. package/dist/ir/expression-to-ir.js +17 -10
  146. package/dist/ir/hal/hal-emitter.d.ts +0 -2
  147. package/dist/ir/hal/hal-emitter.js +92 -41
  148. package/dist/ir/hal/hal-parser.d.ts +5 -5
  149. package/dist/ir/hal/hal-parser.js +128 -36
  150. package/dist/ir/hal/hal-plugins.d.ts +0 -1
  151. package/dist/ir/hal/hal-plugins.js +425 -716
  152. package/dist/ir/heap-analysis.js +2 -41
  153. package/dist/ir/identifier-collector.js +32 -20
  154. package/dist/ir/network-validation.js +7 -11
  155. package/dist/ir/ownership-analysis.js +75 -13
  156. package/dist/ir/peripheral-usage.d.ts +8 -2
  157. package/dist/ir/peripheral-usage.js +78 -149
  158. package/dist/ir/peripheral-validation.js +23 -3
  159. package/dist/ir/pin-capability-validation.d.ts +12 -0
  160. package/dist/ir/pin-capability-validation.js +61 -97
  161. package/dist/ir/pin-mode-validation.js +5 -5
  162. package/dist/ir/program-analysis.d.ts +8 -15
  163. package/dist/ir/program-analysis.js +140 -323
  164. package/dist/ir/pulldown-validation.js +11 -4
  165. package/dist/ir/resource-analysis.js +15 -3
  166. package/dist/ir/statement-to-ir.js +0 -6
  167. package/dist/ir/timing-validation.js +1 -1
  168. package/dist/ir/transformers/array-methods.js +11 -5
  169. package/dist/ir/transformers/call-statement.js +20 -87
  170. package/dist/ir/transformers/callback-context-registry.d.ts +1 -1
  171. package/dist/ir/transformers/callback-context-registry.js +8 -16
  172. package/dist/ir/transformers/control-flow.js +0 -13
  173. package/dist/ir/transformers/expressions.js +10 -9
  174. package/dist/ir/transformers/hal-call-resolver.d.ts +2 -2
  175. package/dist/ir/transformers/hal-call-resolver.js +24 -10
  176. package/dist/ir/transformers/hal-emit-helpers.d.ts +2 -2
  177. package/dist/ir/transformers/hal-emit-helpers.js +2 -2
  178. package/dist/ir/transformers/namespace-methods.js +1 -1
  179. package/dist/ir/transformers/ui-callback-lowering.d.ts +0 -2
  180. package/dist/ir/transformers/ui-callback-lowering.js +0 -24
  181. package/dist/ir/transformers/variables.js +338 -42
  182. package/dist/ir/try-catch-validation.js +4 -3
  183. package/dist/ir/type-resolution.js +15 -4
  184. package/dist/ir/validation-orchestrator.js +0 -9
  185. package/dist/libdef/cpp-to-decl.d.ts +0 -9
  186. package/dist/libdef/cpp-to-decl.js +0 -72
  187. package/dist/libdef/registry.d.ts +0 -1
  188. package/dist/libdef/registry.js +1 -24
  189. package/dist/library/init.d.ts +1 -1
  190. package/dist/library/init.js +137 -137
  191. package/dist/library-packages.d.ts +1 -1
  192. package/dist/library-packages.js +1 -1
  193. package/dist/mapping/peripheral-names.js +9 -4
  194. package/dist/mapping/source-map.d.ts +3 -4
  195. package/dist/mapping/source-map.js +12 -18
  196. package/dist/orchestrator/graph-builder.d.ts +3 -3
  197. package/dist/orchestrator/graph-builder.js +13 -12
  198. package/dist/orchestrator/type-checker.d.ts +3 -3
  199. package/dist/orchestrator/type-checker.js +3 -3
  200. package/dist/platform/async-runtime.js +1 -1
  201. package/dist/platform/coop-scheduler-runtime.js +2 -2
  202. package/dist/platform/generic-debug-codegen.d.ts +36 -0
  203. package/dist/platform/generic-debug-codegen.js +185 -0
  204. package/dist/platform/generic-strategy.d.ts +3 -4
  205. package/dist/platform/generic-strategy.js +5 -80
  206. package/dist/platform/index.js +1 -1
  207. package/dist/platform/registry.d.ts +2 -2
  208. package/dist/platform/registry.js +2 -2
  209. package/dist/safety/asil-decorators.d.ts +32 -0
  210. package/dist/safety/asil-decorators.js +32 -0
  211. package/dist/safety/authoring.d.ts +85 -0
  212. package/dist/safety/authoring.js +61 -0
  213. package/dist/safety/engine.d.ts +3 -0
  214. package/dist/safety/engine.js +83 -0
  215. package/dist/safety/hal/ops.d.ts +48 -0
  216. package/dist/safety/hal/ops.js +46 -0
  217. package/dist/safety/iso26262/analyze.d.ts +13 -0
  218. package/dist/safety/iso26262/analyze.js +29 -0
  219. package/dist/safety/iso26262/asil.d.ts +10 -0
  220. package/dist/safety/iso26262/asil.js +22 -0
  221. package/dist/safety/iso26262/collect.d.ts +14 -0
  222. package/dist/safety/iso26262/collect.js +137 -0
  223. package/dist/safety/iso26262/goto-checker.d.ts +10 -0
  224. package/dist/safety/iso26262/goto-checker.js +72 -0
  225. package/dist/safety/iso26262/heap-checker.d.ts +7 -0
  226. package/dist/safety/iso26262/heap-checker.js +57 -0
  227. package/dist/safety/iso26262/init-checker.d.ts +13 -0
  228. package/dist/safety/iso26262/init-checker.js +127 -0
  229. package/dist/safety/iso26262/loop-checker.d.ts +7 -0
  230. package/dist/safety/iso26262/loop-checker.js +86 -0
  231. package/dist/safety/iso26262/recursion-checker.d.ts +9 -0
  232. package/dist/safety/iso26262/recursion-checker.js +134 -0
  233. package/dist/safety/iso26262/sidecar-writer.d.ts +25 -0
  234. package/dist/safety/iso26262/sidecar-writer.js +13 -0
  235. package/dist/safety/passes/pinMode-intercept.d.ts +3 -0
  236. package/dist/safety/passes/pinMode-intercept.js +60 -0
  237. package/dist/safety/runtime/mode-table.d.ts +5 -0
  238. package/dist/safety/runtime/mode-table.js +55 -0
  239. package/dist/safety/runtime/polyfills.d.ts +6 -0
  240. package/dist/safety/runtime/polyfills.js +12 -0
  241. package/dist/safety/runtime/result-struct.d.ts +11 -0
  242. package/dist/safety/runtime/result-struct.js +98 -0
  243. package/dist/safety/runtime/safe-int.d.ts +33 -0
  244. package/dist/safety/runtime/safe-int.js +170 -0
  245. package/dist/safety/runtime/safe-traits.d.ts +4 -0
  246. package/dist/safety/runtime/safe-traits.js +95 -0
  247. package/dist/safety/runtime/safe-variable.d.ts +39 -0
  248. package/dist/safety/runtime/safe-variable.js +226 -0
  249. package/dist/safety/runtime/vote.d.ts +8 -0
  250. package/dist/safety/runtime/vote.js +92 -0
  251. package/dist/safety/runtime/write-verify.d.ts +8 -0
  252. package/dist/safety/runtime/write-verify.js +71 -0
  253. package/dist/safety/safe-int-types.d.ts +45 -0
  254. package/dist/safety/safe-int-types.js +25 -0
  255. package/dist/safety/safe-variable-types.d.ts +29 -0
  256. package/dist/safety/safe-variable-types.js +19 -0
  257. package/dist/safety/safety-bridge.d.ts +5 -6
  258. package/dist/safety/safety-bridge.js +15 -28
  259. package/dist/safety/sidecar-bridge.d.ts +1 -3
  260. package/dist/safety/sidecar-bridge.js +3 -20
  261. package/dist/safety/specifiers.d.ts +6 -0
  262. package/dist/safety/specifiers.js +14 -0
  263. package/dist/safety-hook.d.ts +8 -7
  264. package/dist/safety-hook.js +12 -13
  265. package/dist/testing.d.ts +4 -5
  266. package/dist/testing.js +5 -5
  267. package/dist/transpile/resolution.d.ts +1 -1
  268. package/dist/transpile/resolution.js +18 -9
  269. package/dist/transpile/test-pins.d.ts +18 -0
  270. package/dist/transpile/test-pins.js +142 -0
  271. package/dist/transpile.d.ts +1 -2
  272. package/dist/transpile.js +36 -30
  273. package/dist/types.d.ts +26 -26
  274. package/dist/ui-hook.d.ts +1 -1
  275. package/dist/utils/cli.d.ts +2 -2
  276. package/dist/utils/cli.js +92 -154
  277. package/dist/utils/fs.d.ts +3 -4
  278. package/dist/utils/fs.js +4 -5
  279. package/dist/utils/strings.d.ts +0 -1
  280. package/dist/utils/strings.js +0 -8
  281. package/dist/utils/ui.d.ts +5 -2
  282. package/dist/utils/ui.js +13 -3
  283. package/package.json +158 -157
  284. package/dist/add-preset.d.ts +0 -4
  285. package/dist/add-preset.js +0 -74
  286. package/dist/api/shared/async-symbol-detector.d.ts +0 -11
  287. package/dist/api/shared/async-symbol-detector.js +0 -140
  288. package/dist/api/shared/native-display-op-resolver.d.ts +0 -10
  289. package/dist/api/shared/native-display-op-resolver.js +0 -64
  290. package/dist/create/board-checklist.d.ts +0 -2
  291. package/dist/create/board-checklist.js +0 -52
  292. package/dist/create/board-codegen.d.ts +0 -9
  293. package/dist/create/board-codegen.js +0 -238
  294. package/dist/create/board-generators.d.ts +0 -12
  295. package/dist/create/board-generators.js +0 -651
  296. package/dist/create/board-spec.d.ts +0 -181
  297. package/dist/create/board-spec.js +0 -214
  298. package/dist/install/framework-catalog.d.ts +0 -53
  299. package/dist/install/framework-catalog.js +0 -107
  300. package/dist/install/handle-install.d.ts +0 -35
  301. package/dist/install/handle-install.js +0 -177
  302. package/dist/install/index.d.ts +0 -4
  303. package/dist/install/index.js +0 -3
  304. package/dist/ir/pin-state-tracking.d.ts +0 -58
  305. package/dist/ir/pin-state-tracking.js +0 -182
  306. package/dist/ir/pwm-timer-sharing.d.ts +0 -4
  307. package/dist/ir/pwm-timer-sharing.js +0 -94
  308. package/dist/ir/timer0-pwm-timing-conflict.d.ts +0 -4
  309. package/dist/ir/timer0-pwm-timing-conflict.js +0 -72
  310. package/dist/libdef/component-decls.d.ts +0 -2
  311. package/dist/libdef/component-decls.js +0 -6
  312. package/dist/libdef/component-discovery.d.ts +0 -43
  313. package/dist/libdef/component-discovery.js +0 -83
  314. package/dist/theme-tokens.d.ts +0 -22
  315. package/dist/theme-tokens.js +0 -172
@@ -0,0 +1,142 @@
1
+ // ---------------------------------------------------------------------------
2
+ // @typecad/test-pins — board test-pin role data
3
+ //
4
+ // Boards describe their testable pins declaratively in a `test-pins.json`
5
+ // shipped next to their package.json. Test suites import stable role names
6
+ // from the '@typecad/test-pins' virtual module:
7
+ //
8
+ // import { GPIO_OUT, PWM_PIN } from '@typecad/test-pins';
9
+ //
10
+ // At hardware-test time the @typecad/expect preprocessor substitutes each
11
+ // role identifier in the test source with the board's real pin symbol (and
12
+ // each fact with its numeric literal), rewriting the import to
13
+ // '@typecad/board' — the exact lowering path hand-written per-board tests
14
+ // use. This module provides the schema, the JSON reader, and the
15
+ // editor-support generator (config-loader writes .cuttlefish/test-pins.ts
16
+ // so the language server resolves the specifier).
17
+ //
18
+ // Schema (all fields optional — a board only declares what it can test;
19
+ // suites gate themselves on role availability via `@typecad-requires-roles`):
20
+ //
21
+ // {
22
+ // "pins": {
23
+ // "gpioOut": "PB5", -> GPIO_OUT
24
+ // "gpioIn": "PB0", -> GPIO_IN
25
+ // "pwm": "PB6", -> PWM_PIN
26
+ // "pwmAlt": "PB7", -> PWM_ALT
27
+ // "cs": "PA4", -> CS_PIN
28
+ // "interrupt": "PA0", -> INT_PIN
29
+ // "led": "PC13", -> LED_PIN
30
+ // "button": "PA0" -> BUTTON_PIN
31
+ // },
32
+ // "facts": {
33
+ // "adcMax": 4095 -> ADC_MAX
34
+ // },
35
+ // "usb": { -> port discovery (host side only):
36
+ // "vid": "2FE3", multi-board test rigs match the
37
+ // "pid": "0001", console/upload port by USB identity
38
+ // "serial": "…" (optional) instead of tracking COM/tty numbers;
39
+ // } Zephyr CDC boards all enumerate at
40
+ // } the default 2FE3:0001 — run one CDC
41
+ // board at a time (see the expect
42
+ // README's "USB port discovery")
43
+ // }
44
+ // ---------------------------------------------------------------------------
45
+ import fs from "node:fs";
46
+ import path from "node:path";
47
+ /** Pin role -> exported const name. Single source for generator + env typing. */
48
+ const PIN_ROLES = {
49
+ gpioOut: "GPIO_OUT",
50
+ gpioIn: "GPIO_IN",
51
+ pwm: "PWM_PIN",
52
+ pwmAlt: "PWM_ALT",
53
+ adcPin: "ADC_PIN",
54
+ adcPinAlt: "ADC_PIN_ALT",
55
+ cs: "CS_PIN",
56
+ interrupt: "INT_PIN",
57
+ led: "LED_PIN",
58
+ button: "BUTTON_PIN",
59
+ // Bus selector roles carry a quoted instance name ('I2C0'), not a pin
60
+ // symbol — they export as string literals and substitute inline the same
61
+ // way (the value text already includes the quotes).
62
+ i2cBus: "I2C_BUS",
63
+ };
64
+ /** Fact role -> exported const name. */
65
+ const FACT_ROLES = {
66
+ adcMax: "ADC_MAX",
67
+ };
68
+ const IDENTIFIER_RE = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
69
+ /** Read and parse a project's test-pins.json. Returns undefined when absent. */
70
+ export function readTestPinsFile(projectDir) {
71
+ const jsonPath = path.join(projectDir, "test-pins.json");
72
+ if (!fs.existsSync(jsonPath))
73
+ return undefined;
74
+ try {
75
+ return JSON.parse(fs.readFileSync(jsonPath, "utf8"));
76
+ }
77
+ catch (e) {
78
+ console.error(`[test-pins] Failed to parse ${jsonPath}: ${e.message}`);
79
+ return undefined;
80
+ }
81
+ }
82
+ /**
83
+ * Build the generated module's source: role consts re-exported from the
84
+ * board package. Used by the editor-support generator
85
+ * (.cuttlefish/test-pins.ts — see config-loader's generateVirtualTypeDeclaration)
86
+ * so the language server resolves the '@typecad/test-pins' specifier.
87
+ * Hardware runs do NOT transpile this module: the @typecad/expect
88
+ * preprocessor substitutes role identifiers in test sources with the
89
+ * board's real pin symbols before the transpiler runs (the HAL resolves
90
+ * pins through board-package metadata, not through transpiled modules).
91
+ * Returns undefined when the board declares no usable roles.
92
+ */
93
+ export function buildTestPinsModuleContent(boardTarget, data) {
94
+ const lines = [
95
+ `// Generated from ${boardTarget}/test-pins.json by the '@typecad/test-pins'`,
96
+ `// resolver. Do not edit — regenerated on every transpile.`,
97
+ `import {`,
98
+ ];
99
+ const importedPins = [];
100
+ const exports = [];
101
+ for (const [role, constName] of Object.entries(PIN_ROLES)) {
102
+ const value = data.pins?.[role];
103
+ if (value === undefined)
104
+ continue;
105
+ if (Array.isArray(value)) {
106
+ const names = value.filter((n) => typeof n === "string" && IDENTIFIER_RE.test(n));
107
+ if (names.length === 0)
108
+ continue;
109
+ importedPins.push(...names);
110
+ exports.push(`export const ${constName} = [${names.join(", ")}];`);
111
+ }
112
+ else if (typeof value === "string" && IDENTIFIER_RE.test(value)) {
113
+ importedPins.push(value);
114
+ exports.push(`export const ${constName} = ${value};`);
115
+ }
116
+ else if (typeof value === "string" && /^'[^']*'$/.test(value)) {
117
+ // Quoted selector text (a bus instance name) — export as-is; no board
118
+ // pin import needed.
119
+ exports.push(`export const ${constName} = ${value};`);
120
+ }
121
+ else {
122
+ console.error(`[test-pins] Ignoring invalid pin role '${role}' in test-pins.json`);
123
+ }
124
+ }
125
+ for (const [role, constName] of Object.entries(FACT_ROLES)) {
126
+ const value = data.facts?.[role];
127
+ if (typeof value !== "number" || !Number.isFinite(value))
128
+ continue;
129
+ exports.push(`export const ${constName} = ${value};`);
130
+ }
131
+ if (importedPins.length === 0 && exports.length === 0)
132
+ return undefined;
133
+ for (const name of [...new Set(importedPins)].sort()) {
134
+ lines.push(` ${name},`);
135
+ }
136
+ // Pin symbols live in the generated board module (the .cuttlefish sibling).
137
+ lines.push(`} from './board.js';`);
138
+ lines.push("");
139
+ lines.push(...exports);
140
+ lines.push("");
141
+ return lines.join("\n");
142
+ }
@@ -1,6 +1,5 @@
1
- import { GenerateLibdefOptions, GeneratedOutputs, TranspileOptions } from "./types.js";
1
+ import { GeneratedOutputs, TranspileOptions } from "./types.js";
2
2
  import { loadFrameworkPackage } from "./framework-package.js";
3
3
  export { loadFrameworkPackage };
4
4
  export { getLoadedFramework, hasLoadedFramework } from "./framework-registry.js";
5
5
  export declare function transpileFile(options: TranspileOptions): Promise<GeneratedOutputs>;
6
- export declare function generateLibraryDefinitions(options: GenerateLibdefOptions): string[];
package/dist/transpile.js CHANGED
@@ -20,19 +20,21 @@ const CUTTLEFISH_VERSION = (() => {
20
20
  }
21
21
  })();
22
22
  import { buildProgramIR } from "./ir/build-ir.js";
23
+ import { resetTranspileResolvedHalOps } from "./ir/build-ir-state.js";
23
24
  import { classDeclarationToIR } from "./ir/declaration-builders.js";
24
25
  import { clickHandlers } from "./ir/transformers/ui-call-resolver.js";
25
26
  import { requireUIHook, hasUIHook } from "./ui-hook.js";
26
27
  import { loadUIEngine } from "./ui/ui-bridge.js";
27
28
  import { hasSafetyHook, requireSafetyHook } from "./safety-hook.js";
28
29
  import { loadSafetyEngine } from "./safety/safety-bridge.js";
30
+ import { isSafetyImportSpecifier } from "./safety/specifiers.js";
29
31
  import { setDisplayProfile, resetDisplayProfile, getDisplayProfile } from "./stores/display-profile-store.js";
30
32
  import { setThemeCss, resetThemeCss, setThemeClass } from "./stores/theme-store.js";
31
33
  import { emitCpp, registerAllEnumNames } from "./emit/cpp-emitter.js";
32
- import { readText, writeText, resetWrittenFiles, wasWrittenThisRun } from "./utils/fs.js";
34
+ import { writeText, resetWrittenFiles, wasWrittenThisRun } from "./utils/fs.js";
33
35
  import { debug as logDebug, info } from "./utils/logger.js";
34
36
  import { printDebugStrategy } from "./utils/ui.js";
35
- import { loadLibraryDefinitions, generateLibdefStubs } from "./libdef/registry.js";
37
+ import { loadLibraryDefinitions } from "./libdef/registry.js";
36
38
  import { resetCuttlefishLibraries, validateCuttlefishLibraries, cuttlefishLibraryLibdefs, libraryDefinitionKey, writeCuttlefishLibraryArtifacts, } from "./library-packages.js";
37
39
  import { buildCallGraph } from "./ir/call-graph.js";
38
40
  import { clearCaches, } from "./cache.js";
@@ -70,7 +72,7 @@ function loadExpectPreprocessor() {
70
72
  function cleanOutput(_entryDir, outDir) {
71
73
  // The out dir is NOT wiped: writeText skips writing when content is
72
74
  // identical, so keeping it lets downstream build tools (idf.py/ninja,
73
- // arduino-cli) reuse their build caches. Stale generated SOURCES are handled
75
+ // west) reuse their build caches. Stale generated SOURCES are handled
74
76
  // precisely instead — after emission, sweepStaleGeneratedSources() removes
75
77
  // compiled-source files in the out dir that this run did not write (e.g. a
76
78
  // main.cpp left behind by the old emit naming next to the current src.cpp;
@@ -80,7 +82,7 @@ function cleanOutput(_entryDir, outDir) {
80
82
  void outDir;
81
83
  resetWrittenFiles();
82
84
  }
83
- const GENERATED_SOURCE_EXTENSIONS = [".cpp", ".cc", ".c", ".h", ".ino"];
85
+ const GENERATED_SOURCE_EXTENSIONS = [".cpp", ".cc", ".c", ".h"];
84
86
  /**
85
87
  * Remove stale generated source files from the out dir: compiled-source files
86
88
  * that THIS transpile run did not write. Sweeps only the source layouts the
@@ -122,13 +124,13 @@ function sweepStaleGeneratedSources(outDir) {
122
124
  * Returns list of generated files.
123
125
  */
124
126
  /**
125
- * True iff the program imports `@typecad/safety` anywhere. The safety
126
- * transform pass uses this as its fast no-op guard — when no file imports
127
- * safety, the pass returns the program unchanged.
127
+ * True iff the program imports the safety authoring surface anywhere. The
128
+ * safety transform pass uses this as its fast no-op guard — when no file
129
+ * imports safety, the pass returns the program unchanged.
128
130
  */
129
131
  function entryImportsSafety(program) {
130
132
  for (const imp of program.imports) {
131
- if (imp.moduleSpecifier === "@typecad/safety")
133
+ if (isSafetyImportSpecifier(imp.moduleSpecifier))
132
134
  return true;
133
135
  }
134
136
  return false;
@@ -259,7 +261,7 @@ function throwIfFatalDiagnostics(entries) {
259
261
  * doesn't export a FrameworkStrategy, allowing emitCpp to fall back to
260
262
  * target-based resolution via the platform registry.
261
263
  */
262
- function loadPlatformStrategy(frameworkPackage, _boardPackage, fromDir, debug) {
264
+ function loadPlatformStrategy(frameworkPackage, _boardTarget, fromDir, debug) {
263
265
  if (!frameworkPackage) {
264
266
  if (debug) {
265
267
  logDebug(`No framework package configured, will use target-based resolution`, true);
@@ -312,12 +314,12 @@ export async function transpileFile(options) {
312
314
  const entryFile = path.resolve(options.inputFile);
313
315
  const entryDir = path.dirname(entryFile);
314
316
  const sourceDir = entryDir;
315
- const sketchBaseName = path.basename(entryFile).replace(/\.[^.]+$/, "");
317
+ const entryBaseName = path.basename(entryFile).replace(/\.[^.]+$/, "");
316
318
  const outBaseDir = options.outDir ?? sourceDir;
317
319
  profiler.endTimer("setup:caches");
318
320
  profiler.startTimer("setup:load-strategy");
319
321
  // Load platform strategy from framework or board package, or use target-based resolution
320
- const boardStrategy = loadPlatformStrategy(options.frameworkPackage, options.boardPackage, entryDir, options.debug);
322
+ const boardStrategy = loadPlatformStrategy(options.frameworkPackage, options.boardTarget, entryDir, options.debug);
321
323
  profiler.endTimer("setup:load-strategy");
322
324
  // Use the framework-loaded strategy for output path computation if available,
323
325
  // otherwise fall back to target-based resolution. This ensures a single
@@ -331,7 +333,7 @@ export async function transpileFile(options) {
331
333
  if (configDisplay) {
332
334
  const { resolveDisplayProfile } = await import("./api/shared/display-profile.js");
333
335
  // Build the named-profile registry. Prefer the strategy's hook (per-framework
334
- // canonical profiles — Arduino returns its BUILT_IN_PROFILES, Zephyr returns
336
+ // canonical profiles — the framework returns its BUILT_IN_PROFILES
335
337
  // its DT-binding profiles). Fall back to the legacy dynamic import of the
336
338
  // framework's displays/ili9341-spi module when the strategy provides none.
337
339
  // The registry maps a config `profile` name (e.g. "st7796-zephyr") to its
@@ -361,7 +363,7 @@ export async function transpileFile(options) {
361
363
  setThemeClass(configDisplay.themeClass);
362
364
  }
363
365
  }
364
- const outDir = path.join(outBaseDir, strategy.outputSubdirectory(sketchBaseName));
366
+ const outDir = path.join(outBaseDir, strategy.outputSubdirectory(entryBaseName));
365
367
  // Start fresh: clean the output directory. (Incremental builds are disabled —
366
368
  // see incremental-cache.ts — so we always transpile the full graph.)
367
369
  cleanOutput(entryDir, outDir);
@@ -379,7 +381,7 @@ export async function transpileFile(options) {
379
381
  }
380
382
  })();
381
383
  resetCuttlefishLibraries();
382
- const graphResult = await collectTranspileGraph(entryFile, options.boardPackage, imageDecodeMax);
384
+ const graphResult = await collectTranspileGraph(entryFile, options.boardTarget, imageDecodeMax);
383
385
  profiler.endTimer("graph:collect");
384
386
  // Cuttlefish library packages registered during the graph walk — validate
385
387
  // them against the loaded framework (and build target, when known) before
@@ -392,7 +394,7 @@ export async function transpileFile(options) {
392
394
  let typeCheckProgram;
393
395
  if (options.skipTypeCheck !== true && transpileFiles.length > 0) {
394
396
  profiler.startTimer("typecheck:full");
395
- let typeCheckResult = typeCheckFiles(transpileFiles, options.boardPackage, entryFile);
397
+ let typeCheckResult = typeCheckFiles(transpileFiles, options.boardTarget, entryFile);
396
398
  // If type-checking failed, try to auto-generate missing .d.ts files from C++ sources
397
399
  if (!typeCheckResult.success) {
398
400
  profiler.startTimer("typecheck:autogen-decls");
@@ -401,7 +403,7 @@ export async function transpileFile(options) {
401
403
  // If we generated any declaration files, retry type-checking
402
404
  if (generatedDecls.length > 0) {
403
405
  profiler.startTimer("typecheck:retry");
404
- typeCheckResult = typeCheckFiles(transpileFiles, options.boardPackage, entryFile);
406
+ typeCheckResult = typeCheckFiles(transpileFiles, options.boardTarget, entryFile);
405
407
  profiler.endTimer("typecheck:retry");
406
408
  }
407
409
  }
@@ -592,7 +594,9 @@ export async function transpileFile(options) {
592
594
  // Printf instrumentation runs only in printf debug mode. In gdb mode
593
595
  // (e.g. ESP32-S3), --debug emits #line markers at the emit stage and
594
596
  // uses VS Code native breakpoints; the printf preprocessor is skipped
595
- // so the source reaches IR/emit unmodified.
597
+ // so the source reaches IR/emit unmodified. The preprocessor instruments
598
+ // with the SAME strategy that emits below — its debug dialect must match
599
+ // the runtime the generated code links against.
596
600
  const buildTarget = options.platformContext?.frameworkData?.buildTarget;
597
601
  const debugMode = strategy.debugMode?.(buildTarget) ?? 'printf';
598
602
  if (options.debug && breakpoints && debugMode === 'printf') {
@@ -600,11 +604,12 @@ export async function transpileFile(options) {
600
604
  fileName: filePath,
601
605
  breakpoints,
602
606
  source: sourceText,
607
+ strategy,
603
608
  });
604
609
  sourceText = instrumented;
605
610
  }
606
611
  profiler.startTimer(`ir:build-ir:${fileBasename}`);
607
- const programIR = buildProgramIR(filePath, sourceText, options.boardPackage, prebuiltClassMap);
612
+ const programIR = buildProgramIR(filePath, sourceText, options.boardTarget, prebuiltClassMap);
608
613
  profiler.endTimer(`ir:build-ir:${fileBasename}`);
609
614
  const npmPackage = npmPackages.get(filePath);
610
615
  profiler.endTimer(`ir:build:${fileBasename}`);
@@ -621,6 +626,11 @@ export async function transpileFile(options) {
621
626
  profiler.startTimer("ir:load-hal");
622
627
  loadHALModules(true);
623
628
  profiler.endTimer("ir:load-hal");
629
+ // Fresh run, fresh resolved-op set: the lowering seams record every HAL op
630
+ // they resolve (some never become IR nodes); analyzeProgram merges them into
631
+ // the peripheral usage flags at emit. Without this reset, a watch-mode
632
+ // rebuild in the same process would carry the previous program's ops over.
633
+ resetTranspileResolvedHalOps();
624
634
  const rawIRArray = await Promise.all(filesToProcess.map(buildRawIR));
625
635
  profiler.captureMemorySnapshot("ir:post-build");
626
636
  profiler.endTimer("ir:build-all");
@@ -661,7 +671,7 @@ export async function transpileFile(options) {
661
671
  for (const { filePath, programIR } of rawIRArray) {
662
672
  for (const imp of programIR.imports) {
663
673
  // Resolve the import to find which file it comes from
664
- const resolved = resolveImport(filePath, imp.moduleSpecifier, options.boardPackage);
674
+ const resolved = resolveImport(filePath, imp.moduleSpecifier, options.boardTarget);
665
675
  if (!resolved)
666
676
  continue;
667
677
  const targetFile = resolved.sourcePath;
@@ -888,10 +898,11 @@ export async function transpileFile(options) {
888
898
  profiler.startTimer("post:native-modules");
889
899
  const nativeModuleOutputs = [];
890
900
  for (const [moduleSpecifier, nativeModule] of graphResult.nativeModules) {
891
- // Skip copying — Arduino's library system provides both .h and .cpp.
892
- // Copying either causes conflicts: the .cpp merges into the .ino (duplicate
893
- // definitions), and the .h shadows the library's own header (link failures).
894
- // The gen-decls .d.ts files are sufficient for TypeScript type-checking.
901
+ // Skip copying — framework libraries provide both .h and .cpp.
902
+ // Copying either causes conflicts: the .cpp merges into the entry source
903
+ // (duplicate definitions), and the .h shadows the library's own header
904
+ // (link failures). The gen-decls .d.ts files are sufficient for TS
905
+ // type-checking.
895
906
  info(`Native module (library-managed): ${moduleSpecifier}`);
896
907
  }
897
908
  profiler.endTimer("post:native-modules");
@@ -929,7 +940,7 @@ export async function transpileFile(options) {
929
940
  asyncTaskNames: entryOutputs.asyncTaskNames ?? [],
930
941
  usesTimers: entryOutputs.usesTimers ?? false,
931
942
  target: options.target,
932
- boardPackage: options.boardPackage,
943
+ boardTarget: options.boardTarget,
933
944
  frameworkPackage: options.frameworkPackage,
934
945
  outDir,
935
946
  outputFile: entryOutputs.sourcePath,
@@ -980,7 +991,7 @@ export async function transpileFile(options) {
980
991
  }
981
992
  // ── Cuttlefish library packages: shims + libraries.json sidecar ─────────
982
993
  // Shims are written next to the emitted sources (the framework scaffold's
983
- // CMake/sketch regen compiles them); the sidecar records the used
994
+ // CMake/program regen compiles them); the sidecar records the used
984
995
  // libraries' build contributions (Kconfig lines, overlay fragments) for
985
996
  // the framework toolchain — the board-constants.json convention.
986
997
  try {
@@ -996,8 +1007,3 @@ export async function transpileFile(options) {
996
1007
  diagnosticsReportPath,
997
1008
  };
998
1009
  }
999
- export function generateLibraryDefinitions(options) {
1000
- const sourceText = readText(options.inputFile);
1001
- const programIR = buildProgramIR(options.inputFile, sourceText);
1002
- return generateLibdefStubs(options.inputFile, programIR.imports, options.outDir);
1003
- }
package/dist/types.d.ts CHANGED
@@ -55,15 +55,15 @@ export interface TranspileOptions {
55
55
  /** Tree-shaking options for dead code elimination */
56
56
  treeShaking?: TreeShakingOptions;
57
57
  /**
58
- * Board package specifier resolved from `cuttlefish.config.ts`.
59
- * When present, `@typecad/board` imports are rewritten to this package
60
- * (e.g. `'@typecad/board-arduino-uno'`).
58
+ * Zephyr board target resolved from `cuttlefish.config.ts` (e.g.
59
+ * `'esp32s3_devkitc/esp32s3/procpu'`). When a generated board module is
60
+ * absent, `@typecad/board` imports resolve through it.
61
61
  */
62
- boardPackage?: string;
62
+ boardTarget?: string;
63
63
  /**
64
64
  * Framework package for code generation strategy.
65
- * Can be any framework package path, e.g. '@typecad/framework-arduino',
66
- * '@typecad/framework-avr', or a custom local path.
65
+ * Can be any framework package path, e.g. '@typecad/framework-zephyr',
66
+ * '@typecad/framework-native', or a custom local path.
67
67
  * When not specified, the GenericStrategy (standard C++) is used.
68
68
  */
69
69
  frameworkPackage?: string;
@@ -121,7 +121,7 @@ export interface LibraryDefinition {
121
121
  variants?: LibraryDefinitionVariant[];
122
122
  }
123
123
  export interface CommandLineOptions {
124
- command: "default" | "build" | "gen-libdefs" | "gen-decls" | "map-error" | "preview" | "doctor" | "licenses";
124
+ command: "default" | "build" | "gen-decls" | "preview" | "doctor" | "licenses";
125
125
  /** For `licenses`: treat unknown/missing licenses as failures (exit 1). */
126
126
  strict?: boolean;
127
127
  /** For `licenses`: scan all installed libraries (default: this project's only). */
@@ -141,26 +141,23 @@ export interface CommandLineOptions {
141
141
  monitor: boolean;
142
142
  /** Serial port for upload and monitor (e.g. COM4 or /dev/ttyACM0) */
143
143
  port?: string;
144
+ /** One-off probe-method override (a board probeMethods id) for --upload
145
+ * and --debug. Wins over zephyr.probe in cuttlefish.config.ts; Zephyr-only. */
146
+ probe?: string;
144
147
  /** Baud rate for monitor. Undefined when --baud is absent so the consumer
145
- * can fall back to config.console.baudRate (the framework monitor default
146
- * applies only when neither is set). */
148
+ * can fall through to the framework monitor default. */
147
149
  baud?: number;
148
150
  platformContext?: PlatformContext;
149
- mapFile?: string;
150
- cppFile?: string;
151
- cppLine?: number;
152
- cppColumn?: number;
153
- message?: string;
154
151
  /** Tree-shaking options */
155
152
  treeShaking?: TreeShakingOptions;
156
153
  /**
157
154
  * Board package specifier resolved from `cuttlefish.config.ts`.
158
155
  * When present, `@typecad/board` imports are rewritten to this package.
159
156
  */
160
- boardPackage?: string;
157
+ boardTarget?: string;
161
158
  /**
162
159
  * Framework package for code generation strategy.
163
- * Can be '@typecad/framework-arduino', '@typecad/framework-avr', or a custom path.
160
+ * Can be '@typecad/framework-zephyr', '@typecad/framework-native', or a custom path.
164
161
  */
165
162
  frameworkPackage?: string;
166
163
  /** Enable debug mode - inject breakpoint instrumentation */
@@ -188,11 +185,6 @@ export interface CommandLineOptions {
188
185
  /** Project root (dir of cuttlefish.config.ts); passed to transpileFile for the ESLint gate. */
189
186
  projectRoot?: string;
190
187
  }
191
- export interface GenerateLibdefOptions {
192
- inputFile: string;
193
- outDir: string;
194
- }
195
- /** `cuttlefish add <preset>` — scaffold a copy-and-own asset into the project. */
196
188
  export interface GeneratedOutputs {
197
189
  headerPath?: string;
198
190
  sourcePath: string;
@@ -228,15 +220,23 @@ export interface CreateCommandOptions {
228
220
  target?: string;
229
221
  framework?: string;
230
222
  baud?: number;
231
- noSketch?: boolean;
223
+ noStarter?: boolean;
232
224
  outDir?: string;
233
225
  /** Skip the automatic `npm install` in the scaffolded project. */
234
226
  noInstall?: boolean;
227
+ /** Probe method id (board probeMethods table) — skips the wizard question
228
+ * and writes zephyr.probe into the scaffolded config. Zephyr-only. */
229
+ probe?: string;
230
+ /** Serial port the board is attached to (COMx / /dev/tty*) — skips the
231
+ * wizard question and seeds test.port in the config. */
232
+ port?: string;
235
233
  }
236
- export interface BoardAddCommandOptions {
237
- command: "board-add";
238
- specPath: string;
239
- force?: boolean;
234
+ /** Parsed `cuttlefish board <subcommand>` options. */
235
+ export interface BoardCommandOptions {
236
+ command: "board";
237
+ subcommand: "regen" | "sync";
238
+ /** sync: optional explicit Zephyr checkout path to walk. */
239
+ zephyrBase?: string;
240
240
  }
241
241
  /** Parsed `cuttlefish library <subcommand>` options. */
242
242
  export interface LibraryCommandOptions {
package/dist/ui-hook.d.ts CHANGED
@@ -62,7 +62,7 @@ export interface TranspilerUIHook {
62
62
  * native display paths). Called separately from emitRuntimeHeader so the
63
63
  * class can be emitted BEFORE display adapter declarations that
64
64
  * instantiate CuttlefishGFX by value. Returns "" when active is false
65
- * (Arduino path).
65
+ * (console path).
66
66
  */
67
67
  emitCuttlefishGfx(active: boolean): string;
68
68
  /**
@@ -1,3 +1,3 @@
1
- import { CommandLineOptions, CreateCommandOptions, BoardAddCommandOptions, LibraryCommandOptions } from "../types.js";
1
+ import { CommandLineOptions, CreateCommandOptions, LibraryCommandOptions, BoardCommandOptions } from "../types.js";
2
2
  export declare function printHelp(): void;
3
- export declare function parseCommandLine(argv: string[]): CommandLineOptions | CreateCommandOptions | BoardAddCommandOptions | LibraryCommandOptions | "help";
3
+ export declare function parseCommandLine(argv: string[]): CommandLineOptions | CreateCommandOptions | LibraryCommandOptions | BoardCommandOptions | "help";