@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,36 +6,7 @@
6
6
  // optimizations and runtime behavior.
7
7
  // ---------------------------------------------------------------------------
8
8
  import { parseCppType, renderCppType, bareType } from "../api/shared/cpp-type-ir.js";
9
- /** Type sizes for common C++ types on AVR (8-bit) and ESP32 (32-bit) */
10
- const AVR_TYPE_SIZES = {
11
- bool: 1,
12
- char: 1,
13
- "unsigned char": 1,
14
- "signed char": 1,
15
- uint8_t: 1,
16
- int8_t: 1,
17
- byte: 1,
18
- short: 2,
19
- "unsigned short": 2,
20
- int16_t: 2,
21
- uint16_t: 2,
22
- int: 2,
23
- "unsigned int": 2,
24
- int32_t: 4,
25
- uint32_t: 4,
26
- long: 4,
27
- "unsigned long": 4,
28
- int64_t: 8,
29
- uint64_t: 8,
30
- float: 4,
31
- double: 4,
32
- "long long": 8,
33
- size_t: 2,
34
- ptrdiff_t: 2,
35
- pointer: 2,
36
- "char*": 2,
37
- "const char*": 2,
38
- };
9
+ /** Type sizes for common C++ types on 32-bit targets */
39
10
  const ESP32_TYPE_SIZES = {
40
11
  bool: 1,
41
12
  char: 1,
@@ -69,14 +40,6 @@ const ESP32_TYPE_SIZES = {
69
40
  * Determine the type size table based on the target architecture.
70
41
  */
71
42
  function getTypeSizes(architecture) {
72
- const arch = (architecture ?? "").toLowerCase();
73
- if (arch === "avr" || arch === "atmega328p" || arch === "atmega2560") {
74
- return AVR_TYPE_SIZES;
75
- }
76
- if (arch === "esp32" || arch === "esp32s3" || arch === "esp32c3" || arch === "esp32c6" || arch === "xtensa" || arch === "riscv32") {
77
- return ESP32_TYPE_SIZES;
78
- }
79
- // Default to ESP32 sizes (more conservative for 32-bit targets)
80
43
  return ESP32_TYPE_SIZES;
81
44
  }
82
45
  /**
@@ -335,9 +298,7 @@ export function analyzeHeapUsage(program, architecture, callGraphNodes) {
335
298
  // Add notes about approximations
336
299
  notes.push("Heap estimate is static only — dynamic allocations (malloc/new) are not tracked.");
337
300
  notes.push("String literals may be deduplicated by the compiler/linker.");
338
- notes.push(architecture === "avr"
339
- ? "AVR sizes: int=2 bytes, pointer=2 bytes, float=4 bytes."
340
- : `Default sizes: int=${typeSizes.int ?? "?"} bytes, pointer=${typeSizes.pointer ?? "?"} bytes, float=${typeSizes.float ?? "?"} bytes.`);
301
+ notes.push(`Default sizes: int=${typeSizes.int ?? "?"} bytes, pointer=${typeSizes.pointer ?? "?"} bytes, float=${typeSizes.float ?? "?"} bytes.`);
341
302
  return {
342
303
  globalVariables,
343
304
  structSizes,
@@ -252,14 +252,20 @@ export function collectStatementIdentifiers(statement) {
252
252
  }
253
253
  }
254
254
  break;
255
- case "assign":
255
+ case "assign": {
256
256
  identifiers.add(statement.target);
257
+ // An element-access target (`buf[i] = x`) references the base array;
258
+ // extract it so the buffer's var_decl survives tree-shaking (the raw
259
+ // `buf[i]` string never matches a declaration named `buf`).
260
+ addElementAccessBase(statement.target, identifiers);
257
261
  for (const id of collectExpressionIdentifiers(statement.value)) {
258
262
  identifiers.add(id);
259
263
  }
260
264
  break;
265
+ }
261
266
  case "update":
262
267
  identifiers.add(statement.target);
268
+ addElementAccessBase(statement.target, identifiers);
263
269
  break;
264
270
  case "return":
265
271
  if (statement.value) {
@@ -414,12 +420,18 @@ export function collectStatementIdentifiers(statement) {
414
420
  /**
415
421
  * Extract identifier names from a HAL operation's string fields.
416
422
  * This ensures the call graph tracks function references embedded in
417
- * semantic HAL ops (e.g. the handler name in interrupt.attach).
423
+ * semantic HAL ops (e.g. the handler name in interrupt.attach_flags).
418
424
  */
425
+ /** Record the base identifier of an element-access lvalue (`buf[i]` → `buf`). */
426
+ function addElementAccessBase(target, identifiers) {
427
+ const base = /^([A-Za-z_][A-Za-z0-9_]*)\s*\[/.exec(target);
428
+ if (base)
429
+ identifiers.add(base[1]);
430
+ }
419
431
  function collectHALOpIdentifiers(op) {
420
432
  const identifiers = new Set();
421
433
  switch (op.operation) {
422
- case "interrupt.attach":
434
+ case "interrupt.attach_flags":
423
435
  // handler is a resolved C++ function name (e.g. "myIsr" or a placeholder)
424
436
  identifiers.add(op.handler);
425
437
  break;
@@ -427,7 +439,7 @@ function collectHALOpIdentifiers(op) {
427
439
  // handler is the user's onMessage callback name (callback() resolves it to
428
440
  // a string). Without this the tree-shaker drops the function declaration —
429
441
  // the mqtt.on_message op only carries the name, so the function has no
430
- // other reference and looks unreachable. Same shape as interrupt.attach.
442
+ // other reference and looks unreachable. Same shape as interrupt.attach_flags.
431
443
  identifiers.add(op.handler);
432
444
  break;
433
445
  case "wifi.on_event":
@@ -451,22 +463,22 @@ function collectHALOpIdentifiers(op) {
451
463
  }
452
464
  // Other HAL ops have only numeric/literal fields — no identifier references
453
465
  }
454
- // wifi.* / http.* / mqtt.* ops carry resolved C++ expression texts in their
455
- // string fields (e.g. wifi.connect ssid: `WIFI_SSID` a top-level const, or
456
- // a quoted literal). Scan every string field for identifiers so referenced
457
- // globals survive tree-shaking; quoted literals are skipped.
458
- if (op.operation.startsWith("wifi.") || op.operation.startsWith("http.")
459
- || op.operation.startsWith("mqtt.")) {
460
- for (const value of Object.values(op)) {
461
- if (typeof value !== "string" || value === op.operation)
462
- continue;
463
- if (/^".*"$/.test(value.trim()))
464
- continue;
465
- const matches = value.match(/[A-Za-z_][A-Za-z0-9_]*/g);
466
- if (matches) {
467
- for (const match of matches) {
468
- identifiers.add(match);
469
- }
466
+ // HAL ops can carry resolved C++ expression texts in their string fields —
467
+ // not just wifi/http/mqtt (e.g. wifi.connect ssid: `WIFI_SSID`, a top-level
468
+ // const) but also peripheral lowerings that inline a user buffer into the
469
+ // emitted code (spi.transceive rx: `static_cast<const void*>(id)`). Scan
470
+ // every string field of every op for identifiers so referenced variables
471
+ // survive tree-shaking; quoted literals are skipped. Over-matching is safe
472
+ // (the reachability set just keeps a name no var_decl uses).
473
+ for (const value of Object.values(op)) {
474
+ if (typeof value !== "string" || value === op.operation)
475
+ continue;
476
+ if (/^".*"$/.test(value.trim()))
477
+ continue;
478
+ const matches = value.match(/[A-Za-z_][A-Za-z0-9_]*/g);
479
+ if (matches) {
480
+ for (const match of matches) {
481
+ identifiers.add(match);
470
482
  }
471
483
  }
472
484
  }
@@ -11,7 +11,7 @@
11
11
  // wifi-blocking-in-loop (warning) blocking WiFi.connect()/scan() or
12
12
  // Http send inside loop() — stalls every
13
13
  // iteration; use async/await instead.
14
- // wifi-ap-password-short (error) WiFi.startAP() with a literal WPA2
14
+ // wifi-ap-password-short (error) WiFiAP with a literal WPA2
15
15
  // password shorter than 8 characters —
16
16
  // esp_wifi rejects it at runtime.
17
17
  // http-max-body-large (warning) Http maxBody() above 64 KB — the
@@ -23,20 +23,16 @@
23
23
  import { walkProgramIR, walkNestedStatements } from "./utils/walk-ir.js";
24
24
  /** Architectures with no WiFi radio. Driven by the `architecture` board
25
25
  * constant (from the MCU package); absent data emits nothing. */
26
- const NO_RADIO_ARCHITECTURES = new Set(["avr"]);
26
+ const NO_RADIO_ARCHITECTURES = new Set();
27
27
  /** Ops that bring the WiFi link (STA or AP) up. */
28
28
  const LINK_UP_OPS = new Set([
29
- "wifi.connect",
29
+ "wifi.join",
30
30
  "wifi.connect_start",
31
- "wifi.connect_saved",
32
31
  "wifi.ap_start",
33
32
  ]);
34
33
  /** Blocking waits that stall loop() for their full duration. */
35
34
  const BLOCKING_LOOP_OPS = new Set([
36
- "wifi.connect",
37
- "wifi.connect_saved",
38
- "wifi.wait_connected",
39
- "wifi.wait_disconnected",
35
+ "wifi.join",
40
36
  "wifi.scan",
41
37
  "http.send",
42
38
  ]);
@@ -117,7 +113,7 @@ export function validateNetworkUsage(program, boardConstants) {
117
113
  severity: "error",
118
114
  code: "wifi-no-radio",
119
115
  message: `WiFi/HTTP APIs are used but the target board's architecture ('${archName}') has no WiFi radio.`,
120
- hint: "Target a WiFi-capable board (e.g. @typecad/board-esp32-devkit) or remove the WiFi/HTTP calls.",
116
+ hint: "Target a WiFi-capable board (e.g. esp32_devkitc/esp32/procpu) or remove the WiFi/HTTP calls.",
121
117
  }));
122
118
  // No point piling on the remaining checks for a board that can't radio.
123
119
  return diagnostics;
@@ -128,7 +124,7 @@ export function validateNetworkUsage(program, boardConstants) {
128
124
  severity: "warning",
129
125
  code: "http-without-wifi",
130
126
  message: "HTTP requests are made but the program never brings the WiFi link up — every request will fail at runtime.",
131
- hint: "Call WiFi.connect(ssid, password) (or WiFi.connectSaved() / WiFi.startAP()) before sending HTTP requests.",
127
+ hint: "Join a network first — new WiFi(ssid, { psk}).join() (or a WiFiAP) before sending HTTP requests.",
132
128
  }));
133
129
  }
134
130
  // ── wifi-blocking-in-loop ────────────────────────────────────────────────
@@ -161,7 +157,7 @@ export function validateNetworkUsage(program, boardConstants) {
161
157
  diagnostics.push(diagAt(stmt, {
162
158
  severity: "error",
163
159
  code: "wifi-ap-password-short",
164
- message: `WiFi.startAP() password is ${password.length} characters — WPA2 requires at least 8, and esp_wifi rejects shorter ones at runtime.`,
160
+ message: `WiFiAP password is ${password.length} characters — WPA2 requires at least 8, and the driver rejects shorter ones at runtime.`,
165
161
  hint: "Use a password of 8+ characters, or omit the password entirely for an open access point.",
166
162
  }));
167
163
  }
@@ -811,6 +811,18 @@ function validateConstSuggestions(program, diagnostics) {
811
811
  // Set.add() -> insert, Map/Set.delete() -> erase (demo #15 fix C)
812
812
  'insert', 'erase',
813
813
  ]);
814
+ // Safety wrapper types (SafeVariable/SafeInt) mutate only through method
815
+ // calls — the C++ members are non-const by design. Kept separate from
816
+ // MUTATING_METHODS because these names ('set', 'add', ...) are matched
817
+ // ONLY against receivers whose declared cppType is a safety wrapper, so
818
+ // unrelated user classes with same-named methods are unaffected.
819
+ const SAFETY_WRAPPER_MUTATING_METHODS = new Set([
820
+ // SafeVariable<T>
821
+ 'set',
822
+ // SafeInt<T> mutating chain
823
+ 'add', 'sub', 'mul', 'divide', 'mod', 'negate', 'absValue', 'reset',
824
+ ]);
825
+ const isSafetyWrapperCppType = (cppType) => typeof cppType === 'string' && (cppType.startsWith('SafeInt') || cppType.startsWith('SafeVariable'));
814
826
  // Every lexical statement body in the program. Demotion (const-content-
815
827
  // mutated) and the suggest-const global-assignment scan must reach class
816
828
  // methods, getters, setters, constructors, and namespace-scoped functions —
@@ -852,6 +864,14 @@ function validateConstSuggestions(program, diagnostics) {
852
864
  };
853
865
  for (const ns of program.namespaces)
854
866
  collectNamespaceBodies(ns);
867
+ // Callbacks registered out-of-band (interrupt handlers, Thread.start,
868
+ // watchPin / drawCanvas bodies) carry their statements on the callback
869
+ // expression rather than in a function body. A top-level `let` mutated
870
+ // only inside one must not be const-suggested — the emitted `const`
871
+ // makes g++ reject the assignment.
872
+ for (const rc of program.registeredCallbacks ?? []) {
873
+ allStatementBodies.push(rc.callbackIR.statements);
874
+ }
855
875
  // Collect every plain-identifier assignment / update target across the whole
856
876
  // program. A `let` declared in one scope may be reassigned by a *different*
857
877
  // function that closes over it (e.g. a top-level `let counter` reassigned in
@@ -1031,6 +1051,32 @@ function validateConstSuggestions(program, diagnostics) {
1031
1051
  });
1032
1052
  }
1033
1053
  }
1054
+ // Safety wrapper mutation: match on the LEADING identifier of the
1055
+ // callee — chained calls arrive as partially-rendered callees
1056
+ // (e.g. `count.add(5).mul`) whose receiver segment is not a bare
1057
+ // identifier — and gate on the receiver's declared safety cppType
1058
+ // so same-named methods on non-safety types are untouched.
1059
+ if (SAFETY_WRAPPER_MUTATING_METHODS.has(method)) {
1060
+ const baseDot = callee.indexOf('.');
1061
+ const base = baseDot > 0 ? callee.slice(0, baseDot) : receiver;
1062
+ const letEntry = letVars.get(base);
1063
+ if (letEntry && isSafetyWrapperCppType(letEntry.stmt.cppType)) {
1064
+ letEntry.everAssigned = true;
1065
+ }
1066
+ const constEntry = constVars.get(base);
1067
+ if (constEntry && constEntry.stmt.storage === 'const' && isSafetyWrapperCppType(constEntry.stmt.cppType)) {
1068
+ constEntry.stmt.storage = 'let';
1069
+ diagnostics.push({
1070
+ severity: 'info',
1071
+ message: `'${base}' is declared 'const' but is mutated via .${method}() — demoted to non-const in C++ so the mutation compiles.`,
1072
+ line: constEntry.span.startLine,
1073
+ column: constEntry.span.startColumn,
1074
+ filePath: constEntry.span.filePath,
1075
+ code: 'ownership-const-content-mutated',
1076
+ source: 'ownership-analysis',
1077
+ });
1078
+ }
1079
+ }
1034
1080
  }
1035
1081
  }
1036
1082
  // Recurse into nested statements (shares this scope's maps — a nested
@@ -1045,24 +1091,40 @@ function validateConstSuggestions(program, diagnostics) {
1045
1091
  // Promote `let` bindings that are never reassigned (in this scope or any
1046
1092
  // other) to `const` in the emitted C++. The transpiler's whole-program
1047
1093
  // reassignment analysis proves the binding is never written after init —
1048
- // information avr-gcc cannot recover across translation units. Emitting
1094
+ // information the compiler cannot recover across translation units. Emitting
1049
1095
  // `const` lets the compiler place the value in flash/ROM and enables
1050
1096
  // constant folding. The inverse demotion (const→let when a member is
1051
1097
  // mutated) already mutates `.storage` the same way (see above), so the
1052
1098
  // emit path already handles both directions.
1053
1099
  for (const entry of letVars.values()) {
1054
- if (!entry.everAssigned && !globallyAssignedNames.has(entry.name)) {
1055
- entry.stmt.storage = 'const';
1056
- diagnostics.push({
1057
- severity: 'info',
1058
- message: `'${entry.name}' is never reassignedemitted as \`const\` so the C++ compiler can place it in ROM and fold it.`,
1059
- line: entry.span.startLine,
1060
- column: entry.span.startColumn,
1061
- filePath: entry.span.filePath,
1062
- code: 'ownership-suggest-const',
1063
- source: 'ownership-analysis',
1064
- });
1065
- }
1100
+ if (entry.everAssigned || globallyAssignedNames.has(entry.name))
1101
+ continue;
1102
+ // Safety wrapper declarations mutate exclusively through method calls
1103
+ // (.set/.add/...), and chained mutating calls render as callee text the
1104
+ // reassignment walk cannot fully parse non-mutation cannot be proven
1105
+ // for these types, so they are never promoted (a promoted `const
1106
+ // SafeVariable` / `const SafeInt` rejects every mutating member in g++).
1107
+ if (isSafetyWrapperCppType(entry.stmt.cppType))
1108
+ continue;
1109
+ // A typed-array buffer (`const id = new Uint8Array(N)`, forced to let at
1110
+ // IR build) lowers with a pointer cppType + array initializer. HAL fills
1111
+ // write through it opaquely — the lowered C++ embeds the buffer name in
1112
+ // hal-op text (e.g. spi.transceive's rx), which the reassignment walk
1113
+ // above cannot see. Promoting it to const would make the HAL fill
1114
+ // undefined behavior and disagree with the array-shaped definition.
1115
+ const bufferInit = entry.stmt.initializer;
1116
+ if (bufferInit?.kind === 'array' && /\*\s*$/.test(entry.stmt.cppType ?? ''))
1117
+ continue;
1118
+ entry.stmt.storage = 'const';
1119
+ diagnostics.push({
1120
+ severity: 'info',
1121
+ message: `'${entry.name}' is never reassigned — emitted as \`const\` so the C++ compiler can place it in ROM and fold it.`,
1122
+ line: entry.span.startLine,
1123
+ column: entry.span.startColumn,
1124
+ filePath: entry.span.filePath,
1125
+ code: 'ownership-suggest-const',
1126
+ source: 'ownership-analysis',
1127
+ });
1066
1128
  }
1067
1129
  };
1068
1130
  for (const body of allStatementBodies)
@@ -9,8 +9,6 @@ export interface PeripheralUsage {
9
9
  pwm: boolean;
10
10
  /** External interrupts are used (attachInterrupt on D2, D3) */
11
11
  externalInterrupts: boolean;
12
- /** Timer0-based timing is used (millis, micros) */
13
- timer0: boolean;
14
12
  /** I2C bus is used */
15
13
  i2c: boolean;
16
14
  /** SPI bus is used */
@@ -31,6 +29,14 @@ export interface PeripheralUsage {
31
29
  inputPulldownPins: Set<number>;
32
30
  /** Specific I2C bus instances used (0 for I2C0, 1 for I2C1, etc.) */
33
31
  i2cInstancesUsed: Set<number>;
32
+ /** DT-bound sensor parts used (generic catalog, hal/sensor.ts) */
33
+ sensor: boolean;
34
+ /** Distinct sensors used: `${part}|${busInstance}|${address}` keys — feeds
35
+ * the framework's per-sensor DT node + device-handle emission. */
36
+ sensorPartsUsed: Set<string>;
37
+ /** Distinct thin SPI targets used: `${bus}|${cs}|${hz}|${mode}` keys —
38
+ * feeds the per-target DT child node + spi_dt_spec emission. */
39
+ spiTargetsUsed: Set<string>;
34
40
  /** Specific SPI bus instances used (0 for SPI0, 1 for SPI1, etc.) */
35
41
  spiInstancesUsed: Set<number>;
36
42
  /** Specific UART instances used (0 for UART0/Serial, 1 for UART1/Serial1, etc.) */