@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
@@ -188,8 +188,8 @@ export declare class ExpressionRenderer {
188
188
  * String-enum operands are passed through unchanged (they're `const char*`).
189
189
  *
190
190
  * This is the assignment/argument-site counterpart to the operator-level
191
- * enum wrapping in renderBinary. SUPPORT_MATRIX §1.7: enum values used as
192
- * integers need an explicit cast in C++.
191
+ * enum wrapping in renderBinary. Enum values used as integers need an
192
+ * explicit cast in C++.
193
193
  */
194
194
  renderEnumSafeValue(expr: ExpressionIR, knownVariableTypes?: Map<string, KnownVariableInfo>): string;
195
195
  /**
@@ -206,7 +206,7 @@ export declare class ExpressionRenderer {
206
206
  * operand → `static_cast<EnumType>(value)` (int → enum). C++ `enum
207
207
  * class` does not implicitly convert FROM an integral storage type
208
208
  * either, so reading an `int`/`uint8_t` cell back into an enum-typed
209
- * local needs the reverse cast. SUPPORT_MATRIX §1.7.
209
+ * local needs the reverse cast.
210
210
  *
211
211
  * This closes the "enum↔integral storage boundary" family — the previous
212
212
  * point-specific casts handled enum-as-array-index (demo #28 E) and
@@ -179,8 +179,17 @@ export class ExpressionRenderer {
179
179
  break;
180
180
  case "hal-expr": {
181
181
  const resolved = routeHALOp(expr.operation, this.strategy);
182
+ // A method body's preceding side-effect ops (bus transactions, pin
183
+ // configures) must run even in expression position — wrap them with
184
+ // the value in a GCC statement-expression.
185
+ const prefix = (expr.prefixOps ?? [])
186
+ .map((op) => routeHALOp(op, this.strategy))
187
+ .map((r) => r?.code ?? `/* unhandled hal-op prefix: dropped */`)
188
+ .join(' ');
182
189
  if (resolved?.expression) {
183
- rendered = resolved.expression;
190
+ rendered = prefix
191
+ ? `({ ${prefix} ${resolved.expression}; })`
192
+ : resolved.expression;
184
193
  }
185
194
  else if (resolved?.code) {
186
195
  // Strip trailing semicolon and a leading `return ` for expression
@@ -189,7 +198,8 @@ export class ExpressionRenderer {
189
198
  // `return` keyword is invalid (avr-g++: "expected primary-expression
190
199
  // before 'return'") and would leak as
191
200
  // `strcmp(return Preferences.getString(...), ...)`. Demo #33 Finding C.
192
- rendered = resolved.code.replace(/;\s*$/, "").replace(/^\s*return\s+/, "");
201
+ const asExpr = resolved.code.replace(/;\s*$/, "").replace(/^\s*return\s+/, "");
202
+ rendered = prefix ? `({ ${prefix} ${asExpr}; })` : asExpr;
193
203
  }
194
204
  else {
195
205
  // Unregistered HAL op: surface as a warning so the user sees it, but
@@ -862,7 +872,7 @@ export class ExpressionRenderer {
862
872
  // must be cast to an integral type — a C++ `enum class` does not
863
873
  // implicitly convert to `size_t`, so `vector[enumValue]` fails to compile.
864
874
  // `renderEnumSafeValue` already wraps numeric-enum operands in
865
- // `static_cast<int>(...)` (SUPPORT_MATRIX §1.7); route the index through it
875
+ // `static_cast<int>(...)`; route the index through it
866
876
  // (with the in-scope variable types so a bare enum-typed identifier
867
877
  // resolves) so enum indices lower correctly. Non-enum indices are passed
868
878
  // through unchanged. Demo #28 Finding E.
@@ -886,8 +896,8 @@ export class ExpressionRenderer {
886
896
  * String-enum operands are passed through unchanged (they're `const char*`).
887
897
  *
888
898
  * This is the assignment/argument-site counterpart to the operator-level
889
- * enum wrapping in renderBinary. SUPPORT_MATRIX §1.7: enum values used as
890
- * integers need an explicit cast in C++.
899
+ * enum wrapping in renderBinary. Enum values used as integers need an
900
+ * explicit cast in C++.
891
901
  */
892
902
  renderEnumSafeValue(expr, knownVariableTypes) {
893
903
  const rendered = this.render(expr, undefined, knownVariableTypes);
@@ -919,7 +929,7 @@ export class ExpressionRenderer {
919
929
  * operand → `static_cast<EnumType>(value)` (int → enum). C++ `enum
920
930
  * class` does not implicitly convert FROM an integral storage type
921
931
  * either, so reading an `int`/`uint8_t` cell back into an enum-typed
922
- * local needs the reverse cast. SUPPORT_MATRIX §1.7.
932
+ * local needs the reverse cast.
923
933
  *
924
934
  * This closes the "enum↔integral storage boundary" family — the previous
925
935
  * point-specific casts handled enum-as-array-index (demo #28 E) and
@@ -1155,7 +1165,7 @@ export class ExpressionRenderer {
1155
1165
  // Wrap enum-class operands in static_cast<int>() for arithmetic operators
1156
1166
  // (+, -, *, /) and bitwise operators (&, |, ^, <<, >>). C++ enum class
1157
1167
  // values don't interoperate with int implicitly — `trophic - 1`, `a | b`,
1158
- // `x & MASK` all fail without the cast. SUPPORT_MATRIX §1.7/§5.1. The
1168
+ // `x & MASK` all fail without the cast. The
1159
1169
  // shared castEnumOperandsForOperator helper handles detection + defensive
1160
1170
  // symmetry in one place.
1161
1171
  const numericOps = new Set(["+", "-", "*", "/", "&", "|", "^", "<<", ">>"]);
@@ -11,70 +11,39 @@
11
11
  //
12
12
  // Output-pin state tracking is also handled here, centrally, so every
13
13
  // strategy benefits without per-strategy changes:
14
- // - gpio.read with `trackedValue` never reaches the strategy (a hardware
15
- // read of a direction-only output is not portable, e.g. Zephyr); it folds
16
- // to a constant or the tracked shadow variable.
17
- // - gpio.write / gpio.toggle flagged `updatesShadow` get the shadow variable
14
+ // - (pin-state-tracking removed: every gpio.* op lowers through the strategy)
18
15
  // update appended to whatever the strategy produced. The flag is baked
19
16
  // into the op at IR-build time (markShadowUpdatingOps) — emit must not
20
17
  // consult live tracker state, because all files build (each resetting the
21
18
  // tracker) before any file emits.
22
19
  // ---------------------------------------------------------------------------
23
20
  import { getSafetyHook } from "../safety-hook.js";
24
- import { pinShadowVarName } from "../ir/pin-state-tracking.js";
21
+ import { markHalOpResolved } from "../ir/build-ir-state.js";
25
22
  export function routeHALOp(op, strategy) {
23
+ // An op resolved here during IR-build-time method inlining may never exist
24
+ // as an IR node (its text is baked into the calling method's emit lines),
25
+ // so record it for program-analysis's peripheral usage flags — every
26
+ // branch, matching the IR-node paths (display.* sets usesGPIO/usesDisplay,
27
+ // safety.* maps the __tc_safety_* helpers).
26
28
  if (typeof op.operation === "string") {
27
29
  if (op.operation.startsWith("display.")) {
28
- return strategy.resolveDisplayOp?.(op);
30
+ const r = strategy.resolveDisplayOp?.(op);
31
+ if (r)
32
+ markHalOpResolved(op.operation);
33
+ return r;
29
34
  }
30
35
  if (op.operation.startsWith("safety.")) {
31
36
  // Safety ops are resolved by the @typecad/safety package via hook.
32
37
  // Returns undefined if the package is not loaded (caller emits an
33
38
  // unhandled-op warning).
34
- return getSafetyHook()?.resolveSafetyOp?.(op);
39
+ const r = getSafetyHook()?.resolveSafetyOp?.(op);
40
+ if (r)
41
+ markHalOpResolved(op.operation);
42
+ return r;
35
43
  }
36
44
  }
37
- if (op.operation === "gpio.read" && op.trackedValue) {
38
- // Tracked OUTPUT-pin read: software truth, never a hardware read.
39
- if (op.trackedValue === "high")
40
- return { expression: "true" };
41
- if (op.trackedValue === "low")
42
- return { expression: "false" };
43
- return { expression: pinShadowVarName(op.pin) };
44
- }
45
45
  const resolved = strategy.resolveHALOperation?.(op);
46
- // Toggle on a shadow-tracked pin must not use the strategy's default
47
- // read-modify-write form (e.g. digitalWrite(p, digitalRead(p) ...) on
48
- // Arduino) — reading the pin back is exactly what tracking avoids. Lower
49
- // it as a write of the shadow's current value, then flip the shadow.
50
- if (op.operation === "gpio.toggle" && op.updatesShadow) {
51
- const varName = pinShadowVarName(op.pin);
52
- const writeOp = {
53
- operation: "gpio.write",
54
- pin: op.pin,
55
- value: varName,
56
- ...(op.port !== undefined ? { port: op.port } : {}),
57
- };
58
- const writeResolved = strategy.resolveHALOperation?.(writeOp);
59
- const flip = `${varName} = (!${varName});`;
60
- if (writeResolved?.code) {
61
- return { ...writeResolved, code: `${writeResolved.code}\n${flip}` };
62
- }
63
- if (writeResolved?.expression) {
64
- return { ...writeResolved, expression: `${writeResolved.expression}, ${flip}` };
65
- }
66
- return { code: flip };
67
- }
68
- if (op.operation === "gpio.write" && op.updatesShadow) {
69
- const varName = pinShadowVarName(op.pin);
70
- const update = `${varName} = ((${op.value}) != 0);`;
71
- if (resolved?.code) {
72
- return { ...resolved, code: `${resolved.code}\n${update}` };
73
- }
74
- if (resolved?.expression) {
75
- return { ...resolved, expression: `${resolved.expression}, ${update}` };
76
- }
77
- return { code: update };
78
- }
46
+ if (resolved)
47
+ markHalOpResolved(op.operation);
79
48
  return resolved;
80
49
  }
@@ -1,4 +1,4 @@
1
- import type { AssignmentIR, ExpressionIR, StatementIR, VariableDeclarationIR } from "../api/shared/index.js";
1
+ import type { ExpressionIR, StatementIR, VariableDeclarationIR } from "../api/shared/index.js";
2
2
  import type { PlatformStrategy } from "../api/shared/index.js";
3
3
  import type { KnownVariableInfo, SnprintfArgRenderResult, SnprintfRenderResult, EmissionScopeState, SnprintfExpressionRenderer } from "../api/shared/index.js";
4
4
  import { escapeCppStringLiteral } from "../utils/strings.js";
@@ -12,6 +12,4 @@ export declare function createChildEmissionScope(baseScope: EmissionScopeState,
12
12
  export declare function recordVariableType(statement: VariableDeclarationIR, scopeState: EmissionScopeState): void;
13
13
  export { escapeCppStringLiteral };
14
14
  export declare function inferSnprintfArg(expr: ExpressionIR, strategy: PlatformStrategy, scopeState: EmissionScopeState, renderExpression: SnprintfExpressionRenderer, pointerVarTypes?: Map<string, string>, knownFunctionReturnTypes?: Map<string, string>, stringVarNames?: Set<string>): SnprintfArgRenderResult | undefined;
15
- export declare function buildSnprintfRenderResult(expr: ExpressionIR, strategy: PlatformStrategy, scopeState: EmissionScopeState, renderExpression: SnprintfExpressionRenderer, pointerVarTypes?: Map<string, string>, knownFunctionReturnTypes?: Map<string, string>, stringVarNames?: Set<string>): SnprintfRenderResult | undefined;
16
- export declare function shouldUseSnprintfForString(statement: VariableDeclarationIR | AssignmentIR, strategy: PlatformStrategy): boolean;
17
15
  export declare function statementNeedsSnprintf(statement: StatementIR, strategy: PlatformStrategy): boolean;
@@ -7,7 +7,7 @@
7
7
  // All logic lives in the CLI; no framework package dependency.
8
8
  // Types are imported from @typecad/cuttlefish/api/shared.
9
9
  // ---------------------------------------------------------------------------
10
- import { escapeCppStringLiteral, escapeSnprintfFormatFragment } from "../utils/strings.js";
10
+ import { escapeCppStringLiteral } from "../utils/strings.js";
11
11
  import { cppTypeForHalOp } from "./utils/hal-op-cpp-type.js";
12
12
  import { parsedElementString, parsedIsStringLike } from "../api/shared/cpp-type-ir.js";
13
13
  // ---------------------------------------------------------------------------
@@ -387,46 +387,8 @@ export function inferSnprintfArg(expr, strategy, scopeState, renderExpression, p
387
387
  }
388
388
  }
389
389
  // ---------------------------------------------------------------------------
390
- // Snprintf render result builder
391
- // ---------------------------------------------------------------------------
392
- export function buildSnprintfRenderResult(expr, strategy, scopeState, renderExpression, pointerVarTypes, knownFunctionReturnTypes, stringVarNames) {
393
- if (expr.kind !== "string_concat") {
394
- return undefined;
395
- }
396
- let formatString = "";
397
- const args = [];
398
- let estimatedLength = 1;
399
- const preludeLines = [];
400
- for (const part of expr.parts) {
401
- if (part.kind === "string") {
402
- // These literal parts are concatenated into the snprintf *format* string,
403
- // so any embedded `%` must be doubled or snprintf misreads it on hardware.
404
- formatString += escapeSnprintfFormatFragment(part.value);
405
- estimatedLength += part.value.length;
406
- continue;
407
- }
408
- const innerExpr = part.kind === "template_string" ? part.expression : part;
409
- const arg = inferSnprintfArg(innerExpr, strategy, scopeState, renderExpression, pointerVarTypes, knownFunctionReturnTypes, stringVarNames);
410
- if (!arg) {
411
- return undefined;
412
- }
413
- formatString += arg.format;
414
- args.push(arg.arg);
415
- estimatedLength += arg.estimatedLength;
416
- preludeLines.push(...arg.preludeLines);
417
- }
418
- return { formatString, args, estimatedLength: Math.max(estimatedLength, 16), preludeLines };
419
- }
420
- // ---------------------------------------------------------------------------
421
390
  // Snprintf usage detection
422
391
  // ---------------------------------------------------------------------------
423
- export function shouldUseSnprintfForString(statement, strategy) {
424
- if (!strategy.useSnprintfForStrings()) {
425
- return false;
426
- }
427
- const value = statement.kind === "var_decl" ? statement.initializer : statement.value;
428
- return value?.kind === "string_concat";
429
- }
430
392
  export function statementNeedsSnprintf(statement, strategy) {
431
393
  if (!strategy.useSnprintfForStrings()) {
432
394
  return false;
@@ -171,10 +171,6 @@ export declare class StatementRenderer {
171
171
  mapReturnTypeForEmit(fnName: string, returnType: string): string;
172
172
  private normalizeCppType;
173
173
  private inferFieldType;
174
- /**
175
- * Transform console.log/error/warn calls based on target platform.
176
- */
177
- private transformConsoleCall;
178
174
  private renderEmitArg;
179
175
  /**
180
176
  * Map a function name to its platform-specific name.
@@ -6,7 +6,7 @@
6
6
  import { routeHALOp } from "./route-hal-op.js";
7
7
  import { activeNamespaceNames } from "../ir/build-ir-state.js";
8
8
  import { ExpressionRenderer, transformTypeName, normalizeRawExpression } from "./expression-renderer.js";
9
- import { isConsoleCall, getConsoleMethod, inferObjectFieldType, collectNestedStructDefs } from "./utils/index.js";
9
+ import { inferObjectFieldType, collectNestedStructDefs } from "./utils/index.js";
10
10
  import { escapeCppKeyword, escapeTrailingMember } from "../utils/strings.js";
11
11
  import { accessorGetterName, accessorSetterName } from "./utils/cpp-helpers.js";
12
12
  import { parseCppType, bareType, parsedIsPointer, parsedIsVector, parsedElementString, parsedIsPlainStructType } from "../api/shared/cpp-type-ir.js";
@@ -270,7 +270,7 @@ export class StatementRenderer {
270
270
  // `return nullptr;` / `return CUTTLEFISH_UNDEFINED;` — those are
271
271
  // integer/pointer literals that won't convert to the struct type.
272
272
  // Lower to a value-initialized `return {};` instead. The `T | null`
273
- // union already strips to `T` (SUPPORT_MATRIX §1.8), so the function
273
+ // union already strips to `T`, so the function
274
274
  // signature really does return the struct. Demo #14 Finding A.
275
275
  const retType = statement.functionReturnType;
276
276
  if (retType && isStructReturnType(retType, this.strategy) && isNullishReturnValue(statement.value)) {
@@ -383,29 +383,46 @@ export class StatementRenderer {
383
383
  return "co_yield;";
384
384
  }
385
385
  if (statement.kind === "block") {
386
- return `{`;
386
+ // Blocks reach the single-line renderer as async state-machine segment
387
+ // pre-statements (chained HAL calls lower to a block of hal-ops). The
388
+ // former bare `{` dropped the block body AND emitted an unbalanced
389
+ // brace. Mirrors the line-appender's block emission: empty body →
390
+ // no-op, otherwise brace + rendered statements.
391
+ const bodyLines = statement.body
392
+ .map((nested) => this.render(nested, forHeader, calleeTransformer, knownVariableTypes))
393
+ .filter((line) => line.length > 0);
394
+ if (bodyLines.length === 0) {
395
+ return "";
396
+ }
397
+ return ["{", ...bodyLines, "}"].join("\n");
387
398
  }
388
399
  if (statement.kind === "hal-op") {
389
400
  const resolved = routeHALOp(statement.operation, this.strategy);
390
- if (resolved?.code) {
391
- // Strip leading 'return ' from raw hal-op code when emitted as a
392
- // standalone statement. The HAL definition includes `return` because
393
- // the TypeScript stub returns a value, but the C++ statement context
394
- // (e.g. inside void setup()) does not expect it.
395
- let code = resolved.code;
396
- if (code.startsWith('return '))
397
- code = code.slice('return '.length);
398
- // A raw hal-op statement (e.g. `Async.sleep(10)`
399
- // `__cuttlefish_async_sleep(10)`) is a complete C++ statement and
400
- // needs a terminating semicolon, unless it already ends with one or
401
- // with `}` (a compound block).
402
- if (!forHeader && !code.endsWith(';') && !code.endsWith('}')) {
403
- code = code + ';';
401
+ if (resolved) {
402
+ // `{ code: '' }` is a registered op's deliberate elision (sentinel
403
+ // facts an absent request body, insecure=false) — emit nothing and
404
+ // do NOT fall through to the unregistered-op warning.
405
+ if (resolved.code) {
406
+ // Strip leading 'return ' from raw hal-op code when emitted as a
407
+ // standalone statement. The HAL definition includes `return` because
408
+ // the TypeScript stub returns a value, but the C++ statement context
409
+ // (e.g. inside void setup()) does not expect it.
410
+ let code = resolved.code;
411
+ if (code.startsWith('return '))
412
+ code = code.slice('return '.length);
413
+ // A raw hal-op statement (e.g. `Async.sleep(10)`
414
+ // `__cuttlefish_async_sleep(10)`) is a complete C++ statement and
415
+ // needs a terminating semicolon, unless it already ends with one or
416
+ // with `}` (a compound block).
417
+ if (!forHeader && !code.endsWith(';') && !code.endsWith('}')) {
418
+ code = code + ';';
419
+ }
420
+ return code;
404
421
  }
405
- return code;
406
- }
407
- if (resolved?.expression) {
408
- return forHeader ? resolved.expression : `${resolved.expression};`;
422
+ if (resolved.expression) {
423
+ return forHeader ? resolved.expression : `${resolved.expression};`;
424
+ }
425
+ return "";
409
426
  }
410
427
  // Unregistered HAL op: surface as a warning so the user sees it, but
411
428
  // keep HAL as an extensibility point. The bare comment is retained as
@@ -506,6 +523,11 @@ export class StatementRenderer {
506
523
  if (code) {
507
524
  return forHeader ? code.replace(/;$/, "") : code;
508
525
  }
526
+ // A resolved op with no code/expression is a deliberate elision
527
+ // (sentinel facts) — emit nothing, no placeholder comment.
528
+ if (resolved) {
529
+ return "";
530
+ }
509
531
  return `/* unhandled awaited hal-op: ${statement.args[0].operation.operation} */`;
510
532
  }
511
533
  // Handle emit() — compile-time C++ injection
@@ -513,9 +535,16 @@ export class StatementRenderer {
513
535
  const rawText = statement.args.map(arg => this.renderEmitArg(arg)).join("");
514
536
  return forHeader ? rawText : `${rawText.endsWith(';') ? rawText : rawText + ';'}`;
515
537
  }
516
- // Handle console.* calls specially
517
- if (isConsoleCall(statement.callee)) {
518
- return this.transformConsoleCall(statement.callee, statement.args, forHeader, knownVariableTypes);
538
+ // console.* is not a supported API — it was a TypeScript carry-over whose
539
+ // lowering (platform print + a config section routing it) cost more than
540
+ // it bought. Programs write to a serial console explicitly instead.
541
+ if (statement.callee.startsWith("console.")) {
542
+ this._diagnostics.push({
543
+ severity: "error",
544
+ code: "console-unsupported",
545
+ message: `console.${statement.callee.slice("console.".length)}() is not supported — write to a serial console instead: \`USB0.writeLine(...)\` (USB CDC) or \`UART0.writeLine(...)\` from the board module.`,
546
+ });
547
+ return "";
519
548
  }
520
549
  let callee = statement.callee;
521
550
  if (callee.startsWith("this.")) {
@@ -781,7 +810,7 @@ export class StatementRenderer {
781
810
  ? `${arrayType} ${safeSpreadArrName}[] = { ${initializerText} }`
782
811
  : `${arrayType} ${safeSpreadArrName}[] = { ${initializerText} };`;
783
812
  }
784
- // Enum ↔ integral storage boundary (SUPPORT_MATRIX §1.7). TS lets an
813
+ // Enum ↔ integral storage boundary. TS lets an
785
814
  // enum and a number flow into each other freely (enums ARE numbers at
786
815
  // runtime), but the lowered C++ `enum class` has NO implicit conversion
787
816
  // in EITHER direction: `const n: int = Color.Red` AND
@@ -917,26 +946,6 @@ export class StatementRenderer {
917
946
  return inferObjectFieldType(value, this.pointerVarTypes, this.knownFunctionReturnTypes, undefined, undefined, undefined, // largeEnumNames - would need to pass through
918
947
  parentName, fieldName, this.strategy.defaultNumericType(this._compliance), (o, n) => this.strategy.resolvePinType?.(o, n));
919
948
  }
920
- /**
921
- * Transform console.log/error/warn calls based on target platform.
922
- */
923
- transformConsoleCall(callee, args, forHeader, knownVariableTypes) {
924
- const method = getConsoleMethod(callee);
925
- const renderedArgs = args.map((arg) => {
926
- let rendered = this.expressionRenderer.render(arg, undefined, knownVariableTypes);
927
- if (arg.kind === "identifier" && knownVariableTypes) {
928
- const varInfo = knownVariableTypes.get(arg.value);
929
- if (varInfo && this.enumNames.has(varInfo.cppType)) {
930
- rendered = `static_cast<int>(${rendered})`;
931
- }
932
- }
933
- if (arg.kind === "property-access" && arg.isEnum) {
934
- rendered = `static_cast<int>(${rendered})`;
935
- }
936
- return rendered;
937
- }).join(" << ");
938
- return this.strategy.transformConsoleCall(method, renderedArgs, forHeader);
939
- }
940
949
  renderEmitArg(arg) {
941
950
  if (arg.kind === "string")
942
951
  return arg.value;
@@ -5,14 +5,6 @@
5
5
  */
6
6
  import type { StatementIR } from "../../api/index.js";
7
7
  import type { PlatformStrategy } from "../../api/shared/index.js";
8
- /**
9
- * Converts a string to PascalCase.
10
- * Used for generating class names from function names.
11
- *
12
- * @param str The input string (e.g., "my_function" or "myFunction")
13
- * @returns PascalCase string (e.g., "MyFunction")
14
- */
15
- export declare function toPascalCaseLocal(str: string): string;
16
8
  /**
17
9
  * Result of generating an async task class.
18
10
  */
@@ -23,6 +15,21 @@ export interface AsyncTaskClassResult {
23
15
  instanceDecl: string;
24
16
  /** The task variable name for use in loop() */
25
17
  taskVarName: string;
18
+ /** For async METHODS: the definition of the starter function the in-class
19
+ * body calls (binds the owner and arms STATE_0). Emitted after the task
20
+ * class; the matching prototype must precede the owning class. */
21
+ starterDef?: string;
22
+ }
23
+ /** Options for generateAsyncTaskClass. */
24
+ export interface AsyncTaskClassOptions {
25
+ /** Owning class name for async METHODS: the task binds `this` to an owner
26
+ * pointer set by start(owner); segment code that renders `this->x` is
27
+ * rewritten to `_owner->x` by the embedding renderStatement callback. */
28
+ ownerClassName?: string;
29
+ /** Invoked for every awaited call that has no cooperative lowering (the
30
+ * call would be silently dropped). The emitter surfaces it as a
31
+ * diagnostic instead of emitting wrong code. */
32
+ onUnsupportedAwait?: (callee: string, span: StatementIR["sourceSpan"] | undefined) => void;
26
33
  }
27
34
  /**
28
35
  * Generates a cooperative state-machine class for an async function.
@@ -39,4 +46,4 @@ export interface AsyncTaskClassResult {
39
46
  * @param knownFunctionReturnTypes Map of function names to their return types
40
47
  * @returns The class definition, instance declaration, and task variable name
41
48
  */
42
- export declare function generateAsyncTaskClass(fnName: string, fnStatements: StatementIR[], strategy: PlatformStrategy, knownFunctionReturnTypes: Map<string, string>, renderStatement: (stmt: StatementIR, forHeader: boolean, strategy: PlatformStrategy, pointerVarTypes?: Map<string, string>, calleeTransformer?: (callee: string) => string, knownFunctionReturnTypes?: Map<string, string>) => string): AsyncTaskClassResult;
49
+ export declare function generateAsyncTaskClass(fnName: string, fnStatements: StatementIR[], strategy: PlatformStrategy, knownFunctionReturnTypes: Map<string, string>, renderStatement: (stmt: StatementIR, forHeader: boolean, strategy: PlatformStrategy, pointerVarTypes?: Map<string, string>, calleeTransformer?: (callee: string) => string, knownFunctionReturnTypes?: Map<string, string>) => string, options?: AsyncTaskClassOptions): AsyncTaskClassResult;