@typecad/cuttlefish 0.1.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (377) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +79 -0
  3. package/dist/api/board-types.d.ts +1 -0
  4. package/dist/api/board-types.js +4 -0
  5. package/dist/api/capabilities.d.ts +12 -0
  6. package/dist/api/capabilities.js +1 -0
  7. package/dist/api/config.d.ts +120 -0
  8. package/dist/api/config.js +7 -0
  9. package/dist/api/index.d.ts +5 -0
  10. package/dist/api/index.js +2 -0
  11. package/dist/api/schema/builder.d.ts +14 -0
  12. package/dist/api/schema/builder.js +15 -0
  13. package/dist/api/schema/index.d.ts +2 -0
  14. package/dist/api/schema/index.js +1 -0
  15. package/dist/api/schema/types.d.ts +257 -0
  16. package/dist/api/schema/types.js +4 -0
  17. package/dist/api/shared/async-runtime-static.d.ts +8 -0
  18. package/dist/api/shared/async-runtime-static.js +201 -0
  19. package/dist/api/shared/async-types.d.ts +42 -0
  20. package/dist/api/shared/async-types.js +8 -0
  21. package/dist/api/shared/board-resolver.d.ts +12 -0
  22. package/dist/api/shared/board-resolver.js +7 -0
  23. package/dist/api/shared/cpp-type-ir.d.ts +229 -0
  24. package/dist/api/shared/cpp-type-ir.js +672 -0
  25. package/dist/api/shared/display-adapter.d.ts +12 -0
  26. package/dist/api/shared/display-adapter.js +145 -0
  27. package/dist/api/shared/display-adapters/eink-mono.d.ts +2 -0
  28. package/dist/api/shared/display-adapters/eink-mono.js +53 -0
  29. package/dist/api/shared/display-adapters/sdl.d.ts +2 -0
  30. package/dist/api/shared/display-adapters/sdl.js +452 -0
  31. package/dist/api/shared/display-adapters/ssd1309.d.ts +2 -0
  32. package/dist/api/shared/display-adapters/ssd1309.js +136 -0
  33. package/dist/api/shared/display-adapters/st7796.d.ts +2 -0
  34. package/dist/api/shared/display-adapters/st7796.js +132 -0
  35. package/dist/api/shared/display-capabilities.d.ts +45 -0
  36. package/dist/api/shared/display-capabilities.js +54 -0
  37. package/dist/api/shared/display-op-ir.d.ts +62 -0
  38. package/dist/api/shared/display-op-ir.js +19 -0
  39. package/dist/api/shared/display-profile.d.ts +265 -0
  40. package/dist/api/shared/display-profile.js +338 -0
  41. package/dist/api/shared/graphics-strategy.d.ts +29 -0
  42. package/dist/api/shared/graphics-strategy.js +11 -0
  43. package/dist/api/shared/hal-op-ir.d.ts +393 -0
  44. package/dist/api/shared/hal-op-ir.js +18 -0
  45. package/dist/api/shared/index.d.ts +26 -0
  46. package/dist/api/shared/index.js +21 -0
  47. package/dist/api/shared/ir-core.d.ts +363 -0
  48. package/dist/api/shared/ir-core.js +8 -0
  49. package/dist/api/shared/ir-declarations.d.ts +201 -0
  50. package/dist/api/shared/ir-declarations.js +26 -0
  51. package/dist/api/shared/ir.d.ts +85 -0
  52. package/dist/api/shared/ir.js +13 -0
  53. package/dist/api/shared/platform-strategy.d.ts +402 -0
  54. package/dist/api/shared/platform-strategy.js +14 -0
  55. package/dist/api/shared/polyfill-helper-registry.d.ts +11 -0
  56. package/dist/api/shared/polyfill-helper-registry.js +86 -0
  57. package/dist/api/shared/polyfill-types.d.ts +33 -0
  58. package/dist/api/shared/polyfill-types.js +76 -0
  59. package/dist/api/shared/promise-runtime.d.ts +10 -0
  60. package/dist/api/shared/promise-runtime.js +244 -0
  61. package/dist/api/shared/snprintf-types.d.ts +29 -0
  62. package/dist/api/shared/snprintf-types.js +8 -0
  63. package/dist/api/shared/string-method-registry.d.ts +53 -0
  64. package/dist/api/shared/string-method-registry.js +168 -0
  65. package/dist/api/shared/toolchain-types.d.ts +63 -0
  66. package/dist/api/shared/toolchain-types.js +71 -0
  67. package/dist/api/shared/types.d.ts +50 -0
  68. package/dist/api/shared/types.js +6 -0
  69. package/dist/ast/parse.d.ts +2 -0
  70. package/dist/ast/parse.js +4 -0
  71. package/dist/cache.d.ts +26 -0
  72. package/dist/cache.js +95 -0
  73. package/dist/cli-utils.d.ts +37 -0
  74. package/dist/cli-utils.js +250 -0
  75. package/dist/cli.d.ts +2 -0
  76. package/dist/cli.js +635 -0
  77. package/dist/config-loader.d.ts +78 -0
  78. package/dist/config-loader.js +508 -0
  79. package/dist/config-schema.d.ts +233 -0
  80. package/dist/config-schema.js +83 -0
  81. package/dist/create/board-checklist.d.ts +2 -0
  82. package/dist/create/board-checklist.js +52 -0
  83. package/dist/create/board-codegen.d.ts +9 -0
  84. package/dist/create/board-codegen.js +238 -0
  85. package/dist/create/board-generators.d.ts +12 -0
  86. package/dist/create/board-generators.js +652 -0
  87. package/dist/create/board-spec.d.ts +640 -0
  88. package/dist/create/board-spec.js +215 -0
  89. package/dist/create/eslint-rules-template.d.ts +2 -0
  90. package/dist/create/eslint-rules-template.js +672 -0
  91. package/dist/create/index.d.ts +11 -0
  92. package/dist/create/index.js +8 -0
  93. package/dist/create/init-scaffold.d.ts +27 -0
  94. package/dist/create/init-scaffold.js +150 -0
  95. package/dist/create/init-templates.d.ts +24 -0
  96. package/dist/create/init-templates.js +379 -0
  97. package/dist/create/init-wizard.d.ts +8 -0
  98. package/dist/create/init-wizard.js +168 -0
  99. package/dist/debug/breakpoint-loader.d.ts +24 -0
  100. package/dist/debug/breakpoint-loader.js +137 -0
  101. package/dist/debug/index.d.ts +3 -0
  102. package/dist/debug/index.js +7 -0
  103. package/dist/debug/preprocessor.d.ts +9 -0
  104. package/dist/debug/preprocessor.js +214 -0
  105. package/dist/debug/types.d.ts +32 -0
  106. package/dist/debug/types.js +6 -0
  107. package/dist/diagnostics/diagnostics-report.d.ts +51 -0
  108. package/dist/diagnostics/diagnostics-report.js +333 -0
  109. package/dist/diagnostics/json-schema.d.ts +138 -0
  110. package/dist/diagnostics/json-schema.js +27 -0
  111. package/dist/diagnostics/md-writer.d.ts +10 -0
  112. package/dist/diagnostics/md-writer.js +336 -0
  113. package/dist/diagnostics/mermaid-builder.d.ts +65 -0
  114. package/dist/diagnostics/mermaid-builder.js +681 -0
  115. package/dist/emit/cpp-emitter.d.ts +6 -0
  116. package/dist/emit/cpp-emitter.js +48 -0
  117. package/dist/emit/emitters/class-emitter.d.ts +2 -0
  118. package/dist/emit/emitters/class-emitter.js +523 -0
  119. package/dist/emit/emitters/emitter-context.d.ts +174 -0
  120. package/dist/emit/emitters/emitter-context.js +1 -0
  121. package/dist/emit/emitters/entrypoint-synthesizer.d.ts +2 -0
  122. package/dist/emit/emitters/entrypoint-synthesizer.js +175 -0
  123. package/dist/emit/emitters/function-emitter-impl.d.ts +19 -0
  124. package/dist/emit/emitters/function-emitter-impl.js +428 -0
  125. package/dist/emit/emitters/line-appender.d.ts +15 -0
  126. package/dist/emit/emitters/line-appender.js +344 -0
  127. package/dist/emit/emitters/namespace-emitter.d.ts +2 -0
  128. package/dist/emit/emitters/namespace-emitter.js +324 -0
  129. package/dist/emit/emitters/output-finalizer.d.ts +4 -0
  130. package/dist/emit/emitters/output-finalizer.js +267 -0
  131. package/dist/emit/emitters/setup.d.ts +3 -0
  132. package/dist/emit/emitters/setup.js +851 -0
  133. package/dist/emit/emitters/top-level-prep.d.ts +2 -0
  134. package/dist/emit/emitters/top-level-prep.js +706 -0
  135. package/dist/emit/emitters/type-decl-emitter.d.ts +2 -0
  136. package/dist/emit/emitters/type-decl-emitter.js +251 -0
  137. package/dist/emit/emitters/ui-emitter.d.ts +21 -0
  138. package/dist/emit/emitters/ui-emitter.js +564 -0
  139. package/dist/emit/enum-emitter.d.ts +1 -0
  140. package/dist/emit/enum-emitter.js +1 -0
  141. package/dist/emit/expression-renderer.d.ts +283 -0
  142. package/dist/emit/expression-renderer.js +1477 -0
  143. package/dist/emit/native-helpers-emitter.d.ts +11 -0
  144. package/dist/emit/native-helpers-emitter.js +34 -0
  145. package/dist/emit/route-hal-op.d.ts +5 -0
  146. package/dist/emit/route-hal-op.js +13 -0
  147. package/dist/emit/snprintf-helpers.d.ts +17 -0
  148. package/dist/emit/snprintf-helpers.js +462 -0
  149. package/dist/emit/statement-renderer.d.ts +189 -0
  150. package/dist/emit/statement-renderer.js +948 -0
  151. package/dist/emit/utils/async-state-machine.d.ts +42 -0
  152. package/dist/emit/utils/async-state-machine.js +343 -0
  153. package/dist/emit/utils/comment-helpers.d.ts +20 -0
  154. package/dist/emit/utils/comment-helpers.js +31 -0
  155. package/dist/emit/utils/cpp-helpers.d.ts +47 -0
  156. package/dist/emit/utils/cpp-helpers.js +85 -0
  157. package/dist/emit/utils/include-resolver.d.ts +58 -0
  158. package/dist/emit/utils/include-resolver.js +155 -0
  159. package/dist/emit/utils/index.d.ts +8 -0
  160. package/dist/emit/utils/index.js +12 -0
  161. package/dist/emit/utils/type-inference.d.ts +159 -0
  162. package/dist/emit/utils/type-inference.js +559 -0
  163. package/dist/eslint-check.d.ts +10 -0
  164. package/dist/eslint-check.js +102 -0
  165. package/dist/framework-package.d.ts +10 -0
  166. package/dist/framework-package.js +58 -0
  167. package/dist/framework-registry.d.ts +39 -0
  168. package/dist/framework-registry.js +30 -0
  169. package/dist/incremental-cache.d.ts +116 -0
  170. package/dist/incremental-cache.js +335 -0
  171. package/dist/ir/adc-range-validation.d.ts +11 -0
  172. package/dist/ir/adc-range-validation.js +250 -0
  173. package/dist/ir/ast-node-utils.d.ts +8 -0
  174. package/dist/ir/ast-node-utils.js +32 -0
  175. package/dist/ir/board-pin-utils.d.ts +13 -0
  176. package/dist/ir/board-pin-utils.js +65 -0
  177. package/dist/ir/board-resolver.d.ts +36 -0
  178. package/dist/ir/board-resolver.js +437 -0
  179. package/dist/ir/build-ir-state.d.ts +167 -0
  180. package/dist/ir/build-ir-state.js +306 -0
  181. package/dist/ir/build-ir.d.ts +2 -0
  182. package/dist/ir/build-ir.js +808 -0
  183. package/dist/ir/call-graph.d.ts +35 -0
  184. package/dist/ir/call-graph.js +194 -0
  185. package/dist/ir/compile-time-only.d.ts +2 -0
  186. package/dist/ir/compile-time-only.js +16 -0
  187. package/dist/ir/declaration-builders.d.ts +9 -0
  188. package/dist/ir/declaration-builders.js +608 -0
  189. package/dist/ir/entry-points.d.ts +30 -0
  190. package/dist/ir/entry-points.js +191 -0
  191. package/dist/ir/expression-to-ir.d.ts +5 -0
  192. package/dist/ir/expression-to-ir.js +2249 -0
  193. package/dist/ir/extract-property-chain.d.ts +10 -0
  194. package/dist/ir/extract-property-chain.js +30 -0
  195. package/dist/ir/feature-prescan.d.ts +3 -0
  196. package/dist/ir/feature-prescan.js +43 -0
  197. package/dist/ir/feature-registry.d.ts +30 -0
  198. package/dist/ir/feature-registry.js +816 -0
  199. package/dist/ir/filter.d.ts +7 -0
  200. package/dist/ir/filter.js +85 -0
  201. package/dist/ir/function-builder.d.ts +19 -0
  202. package/dist/ir/function-builder.js +670 -0
  203. package/dist/ir/hal/hal-emitter.d.ts +62 -0
  204. package/dist/ir/hal/hal-emitter.js +735 -0
  205. package/dist/ir/hal/hal-parser.d.ts +61 -0
  206. package/dist/ir/hal/hal-parser.js +473 -0
  207. package/dist/ir/hal/hal-plugins.d.ts +34 -0
  208. package/dist/ir/hal/hal-plugins.js +706 -0
  209. package/dist/ir/hal-resolver.d.ts +5 -0
  210. package/dist/ir/hal-resolver.js +5 -0
  211. package/dist/ir/heap-analysis.d.ts +8 -0
  212. package/dist/ir/heap-analysis.js +350 -0
  213. package/dist/ir/heap-array-validation.d.ts +24 -0
  214. package/dist/ir/heap-array-validation.js +29 -0
  215. package/dist/ir/identifier-collector.d.ts +18 -0
  216. package/dist/ir/identifier-collector.js +439 -0
  217. package/dist/ir/interrupt-analysis.d.ts +39 -0
  218. package/dist/ir/interrupt-analysis.js +467 -0
  219. package/dist/ir/memory-budget-validation.d.ts +10 -0
  220. package/dist/ir/memory-budget-validation.js +86 -0
  221. package/dist/ir/namespace-builder.d.ts +7 -0
  222. package/dist/ir/namespace-builder.js +152 -0
  223. package/dist/ir/ownership-analysis.d.ts +9 -0
  224. package/dist/ir/ownership-analysis.js +1207 -0
  225. package/dist/ir/peripheral-ownership.d.ts +3 -0
  226. package/dist/ir/peripheral-ownership.js +152 -0
  227. package/dist/ir/peripheral-symbols.d.ts +7 -0
  228. package/dist/ir/peripheral-symbols.js +57 -0
  229. package/dist/ir/peripheral-usage.d.ts +54 -0
  230. package/dist/ir/peripheral-usage.js +691 -0
  231. package/dist/ir/peripheral-validation.d.ts +8 -0
  232. package/dist/ir/peripheral-validation.js +77 -0
  233. package/dist/ir/pin-alias-conflict.d.ts +4 -0
  234. package/dist/ir/pin-alias-conflict.js +34 -0
  235. package/dist/ir/pin-capability-validation.d.ts +6 -0
  236. package/dist/ir/pin-capability-validation.js +413 -0
  237. package/dist/ir/pin-mode-validation.d.ts +10 -0
  238. package/dist/ir/pin-mode-validation.js +301 -0
  239. package/dist/ir/pin-safety.d.ts +11 -0
  240. package/dist/ir/pin-safety.js +58 -0
  241. package/dist/ir/program-analysis.d.ts +44 -0
  242. package/dist/ir/program-analysis.js +589 -0
  243. package/dist/ir/pulldown-validation.d.ts +7 -0
  244. package/dist/ir/pulldown-validation.js +49 -0
  245. package/dist/ir/pwm-timer-sharing.d.ts +4 -0
  246. package/dist/ir/pwm-timer-sharing.js +93 -0
  247. package/dist/ir/reachability.d.ts +68 -0
  248. package/dist/ir/reachability.js +224 -0
  249. package/dist/ir/register-decorators.d.ts +6 -0
  250. package/dist/ir/register-decorators.js +49 -0
  251. package/dist/ir/render-expr.d.ts +4 -0
  252. package/dist/ir/render-expr.js +127 -0
  253. package/dist/ir/resource-analysis.d.ts +19 -0
  254. package/dist/ir/resource-analysis.js +153 -0
  255. package/dist/ir/statement-to-ir.d.ts +23 -0
  256. package/dist/ir/statement-to-ir.js +349 -0
  257. package/dist/ir/symbol-table.d.ts +68 -0
  258. package/dist/ir/symbol-table.js +179 -0
  259. package/dist/ir/symbol-types.d.ts +56 -0
  260. package/dist/ir/symbol-types.js +107 -0
  261. package/dist/ir/timer0-pwm-timing-conflict.d.ts +4 -0
  262. package/dist/ir/timer0-pwm-timing-conflict.js +71 -0
  263. package/dist/ir/timing-validation.d.ts +7 -0
  264. package/dist/ir/timing-validation.js +95 -0
  265. package/dist/ir/transformers/array-methods.d.ts +8 -0
  266. package/dist/ir/transformers/array-methods.js +493 -0
  267. package/dist/ir/transformers/call-statement.d.ts +5 -0
  268. package/dist/ir/transformers/call-statement.js +758 -0
  269. package/dist/ir/transformers/callback-context-registry.d.ts +20 -0
  270. package/dist/ir/transformers/callback-context-registry.js +55 -0
  271. package/dist/ir/transformers/canvas-lowering.d.ts +42 -0
  272. package/dist/ir/transformers/canvas-lowering.js +249 -0
  273. package/dist/ir/transformers/control-flow.d.ts +8 -0
  274. package/dist/ir/transformers/control-flow.js +508 -0
  275. package/dist/ir/transformers/expressions.d.ts +7 -0
  276. package/dist/ir/transformers/expressions.js +406 -0
  277. package/dist/ir/transformers/hal-call-resolver.d.ts +29 -0
  278. package/dist/ir/transformers/hal-call-resolver.js +274 -0
  279. package/dist/ir/transformers/hal-emit-helpers.d.ts +14 -0
  280. package/dist/ir/transformers/hal-emit-helpers.js +63 -0
  281. package/dist/ir/transformers/namespace-methods.d.ts +20 -0
  282. package/dist/ir/transformers/namespace-methods.js +110 -0
  283. package/dist/ir/transformers/register-assignment.d.ts +5 -0
  284. package/dist/ir/transformers/register-assignment.js +56 -0
  285. package/dist/ir/transformers/ui-call-resolver.d.ts +149 -0
  286. package/dist/ir/transformers/ui-call-resolver.js +1136 -0
  287. package/dist/ir/transformers/ui-callback-lowering.d.ts +62 -0
  288. package/dist/ir/transformers/ui-callback-lowering.js +623 -0
  289. package/dist/ir/transformers/ui-mount.d.ts +20 -0
  290. package/dist/ir/transformers/ui-mount.js +35 -0
  291. package/dist/ir/transformers/ui-reactive.d.ts +68 -0
  292. package/dist/ir/transformers/ui-reactive.js +129 -0
  293. package/dist/ir/transformers/variables.d.ts +14 -0
  294. package/dist/ir/transformers/variables.js +1045 -0
  295. package/dist/ir/try-catch-validation.d.ts +26 -0
  296. package/dist/ir/try-catch-validation.js +128 -0
  297. package/dist/ir/type-resolution.d.ts +31 -0
  298. package/dist/ir/type-resolution.js +977 -0
  299. package/dist/ir/ui-element-auto-wire.d.ts +50 -0
  300. package/dist/ir/ui-element-auto-wire.js +218 -0
  301. package/dist/ir/unit-suspicion-validation.d.ts +12 -0
  302. package/dist/ir/unit-suspicion-validation.js +296 -0
  303. package/dist/ir/utils/walk-ir.d.ts +6 -0
  304. package/dist/ir/utils/walk-ir.js +162 -0
  305. package/dist/ir/validation-orchestrator.d.ts +4 -0
  306. package/dist/ir/validation-orchestrator.js +45 -0
  307. package/dist/libdef/base-class-resolver.d.ts +23 -0
  308. package/dist/libdef/base-class-resolver.js +50 -0
  309. package/dist/libdef/cpp-to-decl.d.ts +34 -0
  310. package/dist/libdef/cpp-to-decl.js +584 -0
  311. package/dist/libdef/header-parser.d.ts +53 -0
  312. package/dist/libdef/header-parser.js +269 -0
  313. package/dist/libdef/registry.d.ts +10 -0
  314. package/dist/libdef/registry.js +142 -0
  315. package/dist/mapping/peripheral-names.d.ts +23 -0
  316. package/dist/mapping/peripheral-names.js +63 -0
  317. package/dist/mapping/source-map.d.ts +46 -0
  318. package/dist/mapping/source-map.js +207 -0
  319. package/dist/orchestrator/dts-generator.d.ts +17 -0
  320. package/dist/orchestrator/dts-generator.js +83 -0
  321. package/dist/orchestrator/graph-builder.d.ts +18 -0
  322. package/dist/orchestrator/graph-builder.js +218 -0
  323. package/dist/orchestrator/semantic-facts-verifier.d.ts +38 -0
  324. package/dist/orchestrator/semantic-facts-verifier.js +121 -0
  325. package/dist/orchestrator/semantic-facts.d.ts +141 -0
  326. package/dist/orchestrator/semantic-facts.js +652 -0
  327. package/dist/orchestrator/type-checker.d.ts +39 -0
  328. package/dist/orchestrator/type-checker.js +760 -0
  329. package/dist/platform/async-runtime.d.ts +8 -0
  330. package/dist/platform/async-runtime.js +26 -0
  331. package/dist/platform/generic-strategy.d.ts +101 -0
  332. package/dist/platform/generic-strategy.js +289 -0
  333. package/dist/platform/index.d.ts +4 -0
  334. package/dist/platform/index.js +9 -0
  335. package/dist/platform/registry.d.ts +21 -0
  336. package/dist/platform/registry.js +42 -0
  337. package/dist/platform/toolchain.d.ts +4 -0
  338. package/dist/platform/toolchain.js +43 -0
  339. package/dist/preview/client.d.ts +1 -0
  340. package/dist/preview/client.js +137 -0
  341. package/dist/preview/server.d.ts +5 -0
  342. package/dist/preview/server.js +199 -0
  343. package/dist/profiler/index.d.ts +28 -0
  344. package/dist/profiler/index.js +28 -0
  345. package/dist/profiler/profiler.d.ts +95 -0
  346. package/dist/profiler/profiler.js +338 -0
  347. package/dist/profiler/types.d.ts +87 -0
  348. package/dist/profiler/types.js +12 -0
  349. package/dist/stores/display-profile-store.d.ts +16 -0
  350. package/dist/stores/display-profile-store.js +48 -0
  351. package/dist/stores/theme-store.d.ts +13 -0
  352. package/dist/stores/theme-store.js +30 -0
  353. package/dist/testing.d.ts +45 -0
  354. package/dist/testing.js +47 -0
  355. package/dist/transpile/resolution.d.ts +29 -0
  356. package/dist/transpile/resolution.js +282 -0
  357. package/dist/transpile.d.ts +3 -0
  358. package/dist/transpile.js +722 -0
  359. package/dist/types.d.ts +217 -0
  360. package/dist/types.js +1 -0
  361. package/dist/ui/ui-bridge.d.ts +4 -0
  362. package/dist/ui/ui-bridge.js +34 -0
  363. package/dist/ui-hook.d.ts +84 -0
  364. package/dist/ui-hook.js +45 -0
  365. package/dist/utils/cli.d.ts +3 -0
  366. package/dist/utils/cli.js +463 -0
  367. package/dist/utils/fs.d.ts +4 -0
  368. package/dist/utils/fs.js +23 -0
  369. package/dist/utils/logger.d.ts +2 -0
  370. package/dist/utils/logger.js +8 -0
  371. package/dist/utils/strings.d.ts +35 -0
  372. package/dist/utils/strings.js +142 -0
  373. package/dist/utils/ui.d.ts +66 -0
  374. package/dist/utils/ui.js +149 -0
  375. package/dist/watch.d.ts +35 -0
  376. package/dist/watch.js +111 -0
  377. package/package.json +127 -0
@@ -0,0 +1,706 @@
1
+ import { applySymbolMap, statementRequiresRuntime, collectPointerVarTypes, collectExpressionIdentifiers, } from "../utils/index.js";
2
+ function exprContainsTimingCall(expr, timingVarNames) {
3
+ if (!expr || typeof expr !== 'object' || !expr.kind)
4
+ return false;
5
+ switch (expr.kind) {
6
+ case "method-call":
7
+ return /\bmillis\b/.test(expr.callee) || /\bmicros\b/.test(expr.callee);
8
+ case "raw":
9
+ return /\bmillis\s*\(/.test(expr.value) || /\bmicros\s*\(/.test(expr.value);
10
+ case "identifier":
11
+ return timingVarNames.has(expr.value);
12
+ case "binary":
13
+ return exprContainsTimingCall(expr.left, timingVarNames) || exprContainsTimingCall(expr.right, timingVarNames);
14
+ case "unary":
15
+ return exprContainsTimingCall(expr.operand, timingVarNames);
16
+ case "paren":
17
+ return exprContainsTimingCall(expr.inner, timingVarNames);
18
+ case "ternary":
19
+ return exprContainsTimingCall(expr.condition, timingVarNames) || exprContainsTimingCall(expr.whenTrue, timingVarNames) || exprContainsTimingCall(expr.whenFalse, timingVarNames);
20
+ case "property-access":
21
+ return exprContainsTimingCall(expr.object, timingVarNames);
22
+ case "element-access":
23
+ return exprContainsTimingCall(expr.object, timingVarNames) || exprContainsTimingCall(expr.index, timingVarNames);
24
+ default:
25
+ return false;
26
+ }
27
+ }
28
+ function scanForTimingAssignments(stmts, timingVarNames) {
29
+ for (const stmt of stmts) {
30
+ if (stmt.kind === "var_decl" && stmt.initializer && exprContainsTimingCall(stmt.initializer, timingVarNames)) {
31
+ timingVarNames.add(stmt.name);
32
+ }
33
+ if (stmt.kind === "assign" && exprContainsTimingCall(stmt.value, timingVarNames)) {
34
+ timingVarNames.add(stmt.target);
35
+ }
36
+ if ("body" in stmt && Array.isArray(stmt.body))
37
+ scanForTimingAssignments(stmt.body, timingVarNames);
38
+ if ("thenBranch" in stmt && Array.isArray(stmt.thenBranch))
39
+ scanForTimingAssignments(stmt.thenBranch, timingVarNames);
40
+ if ("elseBranch" in stmt && Array.isArray(stmt.elseBranch))
41
+ scanForTimingAssignments(stmt.elseBranch, timingVarNames);
42
+ if ("cases" in stmt && Array.isArray(stmt.cases)) {
43
+ for (const c of stmt.cases)
44
+ scanForTimingAssignments(c.body, timingVarNames);
45
+ }
46
+ if ("tryBlock" in stmt && Array.isArray(stmt.tryBlock))
47
+ scanForTimingAssignments(stmt.tryBlock, timingVarNames);
48
+ if ("catchBlock" in stmt && Array.isArray(stmt.catchBlock))
49
+ scanForTimingAssignments(stmt.catchBlock, timingVarNames);
50
+ if ("finallyBlock" in stmt && Array.isArray(stmt.finallyBlock))
51
+ scanForTimingAssignments(stmt.finallyBlock, timingVarNames);
52
+ }
53
+ }
54
+ function promoteVarDecls(stmts, timingVarNames) {
55
+ for (const stmt of stmts) {
56
+ if (stmt.kind === "var_decl" && timingVarNames.has(stmt.name)) {
57
+ const t = stmt.cppType;
58
+ if (t === "auto" || t === "int" || t === "long" || t === "unsigned int" || t === "short" || t === "unsigned short") {
59
+ stmt.cppType = "unsigned long";
60
+ }
61
+ }
62
+ if ("body" in stmt && Array.isArray(stmt.body))
63
+ promoteVarDecls(stmt.body, timingVarNames);
64
+ if ("thenBranch" in stmt && Array.isArray(stmt.thenBranch))
65
+ promoteVarDecls(stmt.thenBranch, timingVarNames);
66
+ if ("elseBranch" in stmt && Array.isArray(stmt.elseBranch))
67
+ promoteVarDecls(stmt.elseBranch, timingVarNames);
68
+ if ("cases" in stmt && Array.isArray(stmt.cases)) {
69
+ for (const c of stmt.cases)
70
+ promoteVarDecls(c.body, timingVarNames);
71
+ }
72
+ if ("tryBlock" in stmt && Array.isArray(stmt.tryBlock))
73
+ promoteVarDecls(stmt.tryBlock, timingVarNames);
74
+ if ("catchBlock" in stmt && Array.isArray(stmt.catchBlock))
75
+ promoteVarDecls(stmt.catchBlock, timingVarNames);
76
+ if ("finallyBlock" in stmt && Array.isArray(stmt.finallyBlock))
77
+ promoteVarDecls(stmt.finallyBlock, timingVarNames);
78
+ }
79
+ }
80
+ function rewriteAsIdentifier(expr, callbackName) {
81
+ expr.kind = "identifier";
82
+ expr.value = callbackName;
83
+ }
84
+ function collectCallbackFromExpression(expr, callbackFunctions, isrPrefix, counter) {
85
+ if (expr.kind === "callback") {
86
+ const callbackName = `${isrPrefix}_isr_${counter.value++}`;
87
+ callbackFunctions.push({
88
+ name: callbackName,
89
+ params: expr.params,
90
+ statements: expr.statements,
91
+ debounceMs: expr.debounceMs,
92
+ isInterruptHandler: expr.isInterruptHandler,
93
+ });
94
+ rewriteAsIdentifier(expr, callbackName);
95
+ return;
96
+ }
97
+ // Extract lambda expressions as ISR/callback functions. This is needed for
98
+ // lambdas passed to HAL methods (onFalling(() => {...})) and other callback
99
+ // registrations. The ONLY case we must NOT extract is a lambda assigned to a
100
+ // variable as a value (e.g. `const square = (x) => x*x`), because extracting
101
+ // it strips the parameter and breaks the call site. That case is guarded by
102
+ // the caller (collectCallbackFromStatement) which skips var_decl initializers.
103
+ if (expr.kind === "lambda") {
104
+ const callbackName = `${isrPrefix}_isr_${counter.value++}`;
105
+ const lam = expr;
106
+ // Preserve the lambda's return type and typed params so a
107
+ // `(x): int16_t => {...}` callback lowers to `int16_t name(int16_t)`
108
+ // rather than the default `void name()`. The historical ISR/HAL path
109
+ // leaves these unset (defaults to void()).
110
+ // Keep `auto` params (so the ISR isn't arity-stripped) and an `auto`
111
+ // return type (C++14 return-type deduction) — both let the __tc_*
112
+ // template helpers deduce types via decltype instead of failing on a
113
+ // void(auto) callable. Only drop a param when it has no cppType at all.
114
+ const lamParams = (lam.params ?? [])
115
+ .filter((p) => p && p.name && p.cppType && p.cppType !== "void");
116
+ const returnType = lam.returnType && lam.returnType !== "void"
117
+ ? lam.returnType
118
+ : undefined;
119
+ callbackFunctions.push({
120
+ name: callbackName,
121
+ params: lamParams.map((p) => p.name),
122
+ statements: lam.statements ?? lam.body ?? [],
123
+ debounceMs: lam.debounceMs,
124
+ returnType,
125
+ typedParams: lamParams,
126
+ });
127
+ rewriteAsIdentifier(expr, callbackName);
128
+ return;
129
+ }
130
+ if (expr.kind === "method-call") {
131
+ for (const arg of expr.args) {
132
+ if (arg.kind === "callback") {
133
+ const callbackName = `${isrPrefix}_isr_${counter.value++}`;
134
+ callbackFunctions.push({
135
+ name: callbackName,
136
+ params: arg.params,
137
+ statements: arg.statements,
138
+ debounceMs: arg.debounceMs,
139
+ });
140
+ rewriteAsIdentifier(arg, callbackName);
141
+ }
142
+ else {
143
+ collectCallbackFromExpression(arg, callbackFunctions, isrPrefix, counter);
144
+ }
145
+ }
146
+ }
147
+ if (expr.kind === "raw")
148
+ return;
149
+ if ("args" in expr && Array.isArray(expr.args)) {
150
+ for (const arg of expr.args) {
151
+ collectCallbackFromExpression(arg, callbackFunctions, isrPrefix, counter);
152
+ }
153
+ }
154
+ if ("initializer" in expr && expr.initializer) {
155
+ collectCallbackFromExpression(expr.initializer, callbackFunctions, isrPrefix, counter);
156
+ }
157
+ if ("value" in expr && expr.value && typeof expr.value === "object") {
158
+ collectCallbackFromExpression(expr.value, callbackFunctions, isrPrefix, counter);
159
+ }
160
+ if ("left" in expr) {
161
+ collectCallbackFromExpression(expr.left, callbackFunctions, isrPrefix, counter);
162
+ }
163
+ if ("right" in expr) {
164
+ collectCallbackFromExpression(expr.right, callbackFunctions, isrPrefix, counter);
165
+ }
166
+ if ("condition" in expr && typeof expr.condition === "object") {
167
+ collectCallbackFromExpression(expr.condition, callbackFunctions, isrPrefix, counter);
168
+ }
169
+ if ("whenTrue" in expr) {
170
+ collectCallbackFromExpression(expr.whenTrue, callbackFunctions, isrPrefix, counter);
171
+ }
172
+ if ("whenFalse" in expr) {
173
+ collectCallbackFromExpression(expr.whenFalse, callbackFunctions, isrPrefix, counter);
174
+ }
175
+ if ("inner" in expr) {
176
+ collectCallbackFromExpression(expr.inner, callbackFunctions, isrPrefix, counter);
177
+ }
178
+ if ("object" in expr && typeof expr.object === "object" && expr.kind !== "instanceof") {
179
+ collectCallbackFromExpression(expr.object, callbackFunctions, isrPrefix, counter);
180
+ }
181
+ if ("elements" in expr && Array.isArray(expr.elements)) {
182
+ for (const e of expr.elements) {
183
+ collectCallbackFromExpression(e, callbackFunctions, isrPrefix, counter);
184
+ }
185
+ }
186
+ }
187
+ function collectCallbacks(statements, callbackFunctions, isrPrefix, counter) {
188
+ for (const stmt of statements) {
189
+ if (stmt.kind === "call") {
190
+ for (const arg of stmt.args) {
191
+ collectCallbackFromExpression(arg, callbackFunctions, isrPrefix, counter);
192
+ }
193
+ }
194
+ if (stmt.kind === "var_decl" && stmt.initializer) {
195
+ // A lambda directly assigned to a variable (e.g. `const square = (x) => x*x`)
196
+ // is a VALUE, not a callback — extracting it strips its parameters and
197
+ // breaks the call site. Skip direct-lambda initializers, but still
198
+ // recurse to find callbacks nested inside (e.g. `const f = foo(() => {})`).
199
+ if (stmt.initializer.kind !== "lambda") {
200
+ collectCallbackFromExpression(stmt.initializer, callbackFunctions, isrPrefix, counter);
201
+ }
202
+ }
203
+ if ("body" in stmt && Array.isArray(stmt.body)) {
204
+ collectCallbacks(stmt.body, callbackFunctions, isrPrefix, counter);
205
+ }
206
+ if ("thenBranch" in stmt && Array.isArray(stmt.thenBranch)) {
207
+ collectCallbacks(stmt.thenBranch, callbackFunctions, isrPrefix, counter);
208
+ }
209
+ if ("elseBranch" in stmt && Array.isArray(stmt.elseBranch)) {
210
+ collectCallbacks(stmt.elseBranch, callbackFunctions, isrPrefix, counter);
211
+ }
212
+ if ("cases" in stmt && Array.isArray(stmt.cases)) {
213
+ for (const c of stmt.cases) {
214
+ collectCallbacks(c.body, callbackFunctions, isrPrefix, counter);
215
+ }
216
+ }
217
+ if ("value" in stmt && stmt.value) {
218
+ collectCallbackFromExpression(stmt.value, callbackFunctions, isrPrefix, counter);
219
+ }
220
+ }
221
+ }
222
+ function replacePlaceholderInStmt(stmt, placeholder, replacement) {
223
+ if (stmt.kind === "call" && stmt.callee === "__EMIT__" && stmt.args) {
224
+ for (const arg of stmt.args) {
225
+ if (arg.kind === "string" && typeof arg.value === "string" && arg.value.includes(placeholder)) {
226
+ arg.value = arg.value.replace(placeholder, replacement);
227
+ }
228
+ }
229
+ }
230
+ if (stmt.kind === "hal-op" && stmt.operation) {
231
+ if (stmt.operation.operation === "raw" && typeof stmt.operation.code === "string") {
232
+ stmt.operation.code = stmt.operation.code.replaceAll(placeholder, replacement);
233
+ }
234
+ else {
235
+ for (const [key, val] of Object.entries(stmt.operation)) {
236
+ if (typeof val === "string" && val.includes(placeholder)) {
237
+ stmt.operation[key] = val.replaceAll(placeholder, replacement);
238
+ }
239
+ }
240
+ }
241
+ }
242
+ for (const key of ["body", "thenBranch", "elseBranch"]) {
243
+ if (Array.isArray(stmt[key])) {
244
+ for (const s of stmt[key])
245
+ replacePlaceholderInStmt(s, placeholder, replacement);
246
+ }
247
+ }
248
+ if (stmt.cases && Array.isArray(stmt.cases)) {
249
+ for (const c of stmt.cases) {
250
+ if (c.body)
251
+ for (const s of c.body)
252
+ replacePlaceholderInStmt(s, placeholder, replacement);
253
+ }
254
+ }
255
+ if (stmt.statements && Array.isArray(stmt.statements)) {
256
+ for (const s of stmt.statements)
257
+ replacePlaceholderInStmt(s, placeholder, replacement);
258
+ }
259
+ }
260
+ function replacePlaceholderInAllStatements(statements, placeholder, replacement) {
261
+ for (const stmt of statements) {
262
+ replacePlaceholderInStmt(stmt, placeholder, replacement);
263
+ }
264
+ }
265
+ function removeShadowingVarDecls(statements, globalVarNames, isrIdentifiers) {
266
+ const result = [];
267
+ for (const stmt of statements) {
268
+ if (stmt.kind === "var_decl" && globalVarNames.has(stmt.name) && isrIdentifiers.has(stmt.name)) {
269
+ continue;
270
+ }
271
+ result.push(stmt);
272
+ // Recursively process nested statements
273
+ if ("body" in stmt && Array.isArray(stmt.body)) {
274
+ stmt.body = removeShadowingVarDecls(stmt.body, globalVarNames, isrIdentifiers);
275
+ }
276
+ if ("thenBranch" in stmt && Array.isArray(stmt.thenBranch)) {
277
+ stmt.thenBranch = removeShadowingVarDecls(stmt.thenBranch, globalVarNames, isrIdentifiers);
278
+ }
279
+ if ("elseBranch" in stmt && Array.isArray(stmt.elseBranch)) {
280
+ stmt.elseBranch = removeShadowingVarDecls(stmt.elseBranch, globalVarNames, isrIdentifiers);
281
+ }
282
+ if ("cases" in stmt && Array.isArray(stmt.cases)) {
283
+ for (const c of stmt.cases) {
284
+ if (c.body) {
285
+ c.body = removeShadowingVarDecls(c.body, globalVarNames, isrIdentifiers);
286
+ }
287
+ }
288
+ }
289
+ if ("tryBlock" in stmt && Array.isArray(stmt.tryBlock)) {
290
+ stmt.tryBlock = removeShadowingVarDecls(stmt.tryBlock, globalVarNames, isrIdentifiers);
291
+ }
292
+ if ("catchBlock" in stmt && Array.isArray(stmt.catchBlock)) {
293
+ stmt.catchBlock = removeShadowingVarDecls(stmt.catchBlock, globalVarNames, isrIdentifiers);
294
+ }
295
+ if ("finallyBlock" in stmt && Array.isArray(stmt.finallyBlock)) {
296
+ stmt.finallyBlock = removeShadowingVarDecls(stmt.finallyBlock, globalVarNames, isrIdentifiers);
297
+ }
298
+ }
299
+ return result;
300
+ }
301
+ function collectIdentifierNames(statements) {
302
+ const names = new Set();
303
+ function scanStmt(stmt) {
304
+ if (stmt.kind === "var_decl") {
305
+ names.add(stmt.name);
306
+ }
307
+ if (stmt.kind === "assign") {
308
+ names.add(stmt.target);
309
+ }
310
+ if ("body" in stmt && Array.isArray(stmt.body)) {
311
+ for (const s of stmt.body)
312
+ scanStmt(s);
313
+ }
314
+ if ("thenBranch" in stmt && Array.isArray(stmt.thenBranch)) {
315
+ for (const s of stmt.thenBranch)
316
+ scanStmt(s);
317
+ }
318
+ if ("elseBranch" in stmt && Array.isArray(stmt.elseBranch)) {
319
+ for (const s of stmt.elseBranch)
320
+ scanStmt(s);
321
+ }
322
+ if ("cases" in stmt && Array.isArray(stmt.cases)) {
323
+ for (const c of stmt.cases)
324
+ for (const s of c.body)
325
+ scanStmt(s);
326
+ }
327
+ if ("value" in stmt && stmt.value && typeof stmt.value === "object") {
328
+ scanExpr(stmt.value);
329
+ }
330
+ if ("callee" in stmt && typeof stmt.callee === "string") {
331
+ const parts = stmt.callee.split(/[\.\-\>]/);
332
+ for (const p of parts) {
333
+ if (/^[a-zA-Z_]\w*$/.test(p))
334
+ names.add(p);
335
+ }
336
+ }
337
+ if ("args" in stmt && Array.isArray(stmt.args)) {
338
+ for (const a of stmt.args)
339
+ scanExpr(a);
340
+ }
341
+ }
342
+ function scanExpr(expr) {
343
+ if (expr.kind === "identifier") {
344
+ names.add(expr.value);
345
+ }
346
+ if ("left" in expr) {
347
+ scanExpr(expr.left);
348
+ }
349
+ if ("right" in expr) {
350
+ scanExpr(expr.right);
351
+ }
352
+ if ("value" in expr && expr.value && typeof expr.value === "object") {
353
+ scanExpr(expr.value);
354
+ }
355
+ if ("elements" in expr && Array.isArray(expr.elements)) {
356
+ for (const e of expr.elements)
357
+ scanExpr(e);
358
+ }
359
+ if ("args" in expr && Array.isArray(expr.args)) {
360
+ for (const a of expr.args)
361
+ scanExpr(a);
362
+ }
363
+ if ("initializer" in expr && expr.initializer) {
364
+ scanExpr(expr.initializer);
365
+ }
366
+ if ("condition" in expr && typeof expr.condition === "object") {
367
+ scanExpr(expr.condition);
368
+ }
369
+ if ("whenTrue" in expr) {
370
+ scanExpr(expr.whenTrue);
371
+ }
372
+ if ("whenFalse" in expr) {
373
+ scanExpr(expr.whenFalse);
374
+ }
375
+ if ("inner" in expr) {
376
+ scanExpr(expr.inner);
377
+ }
378
+ if ("object" in expr && typeof expr.object === "object" && expr.kind !== "instanceof") {
379
+ scanExpr(expr.object);
380
+ }
381
+ }
382
+ for (const stmt of statements) {
383
+ scanStmt(stmt);
384
+ }
385
+ return names;
386
+ }
387
+ export function runTopLevelPreprocessing(ctx) {
388
+ const { program, strategy, symbolMap, isEntryFile, mappedFunctions } = ctx;
389
+ // Compile-time vs runtime separation
390
+ let compiletimeVarNames = new Set(program.topLevelStatements
391
+ .filter((stmt) => stmt.kind === "var_decl" && !statementRequiresRuntime(stmt))
392
+ .map((stmt) => stmt.name));
393
+ ctx.compiletimeVarNames = compiletimeVarNames;
394
+ const topLevelDeclarations = program.topLevelStatements.filter((item) => !statementRequiresRuntime(item));
395
+ const topLevelExecutables = program.topLevelStatements.filter((item) => statementRequiresRuntime(item));
396
+ // Reclassification pass: compile-time var_decls whose initializer references
397
+ // runtime variable names must be demoted to runtime so they stay inside main().
398
+ // This handles cases like `const arr = [runtimeVar1, runtimeVar2]` where the
399
+ // array literal itself looks compile-time (identifiers are not "runtime expressions")
400
+ // but it references variables that will only exist inside main().
401
+ //
402
+ // Additionally, a compile-time `const`/`let` that reads a top-level variable
403
+ // which is MUTATED at runtime (any `assign` target) must also be demoted.
404
+ // Otherwise the hoisted global captures the variable's startup value and never
405
+ // sees runtime mutations — e.g. `const reached = descended` freezes `reached`
406
+ // at `descended`'s initial value because both are emitted as file-scope globals
407
+ // initialized before main(), while the `descended = depth` assignments run
408
+ // inside main(). See SUPPORT_MATRIX §6.1.
409
+ {
410
+ // Collect every variable name that is the target of an assignment anywhere
411
+ // in the program (top-level statements + function/method bodies). Such
412
+ // names carry runtime-dependent values even if their declaration looked
413
+ // compile-time (e.g. `let descended = 0`).
414
+ const mutatedNames = new Set();
415
+ const scanStmtForAssigns = (stmt) => {
416
+ if (!stmt || typeof stmt !== 'object' || !stmt.kind)
417
+ return;
418
+ if (stmt.kind === "assign" && typeof stmt.target === "string") {
419
+ mutatedNames.add(stmt.target);
420
+ }
421
+ for (const key of Object.keys(stmt)) {
422
+ if (key === "kind" || key === "loc" || key === "range" || key === "sourceSpan")
423
+ continue;
424
+ const val = stmt[key];
425
+ if (Array.isArray(val)) {
426
+ for (const item of val) {
427
+ if (item && typeof item === 'object')
428
+ scanStmtForAssigns(item);
429
+ }
430
+ }
431
+ else if (val && typeof val === 'object') {
432
+ scanStmtForAssigns(val);
433
+ }
434
+ }
435
+ };
436
+ for (const stmt of program.topLevelStatements)
437
+ scanStmtForAssigns(stmt);
438
+ for (const fn of program.functions) {
439
+ for (const stmt of fn.statements)
440
+ scanStmtForAssigns(stmt);
441
+ }
442
+ for (const cls of program.classes) {
443
+ for (const method of cls.methods) {
444
+ for (const stmt of method.statements)
445
+ scanStmtForAssigns(stmt);
446
+ }
447
+ if (cls.constructor) {
448
+ for (const stmt of cls.constructor.statements)
449
+ scanStmtForAssigns(stmt);
450
+ }
451
+ }
452
+ const runtimeVarNames = new Set();
453
+ for (const stmt of topLevelExecutables) {
454
+ if (stmt.kind === "var_decl") {
455
+ runtimeVarNames.add(stmt.name);
456
+ }
457
+ }
458
+ const demoted = new Set();
459
+ let changed = true;
460
+ while (changed) {
461
+ changed = false;
462
+ for (const stmt of topLevelDeclarations) {
463
+ if (stmt.kind !== "var_decl" || !stmt.initializer)
464
+ continue;
465
+ if (demoted.has(stmt.name))
466
+ continue;
467
+ const referenced = collectExpressionIdentifiers(stmt.initializer);
468
+ for (const ref of referenced) {
469
+ // Demote if the reference is to a runtime-classified var OR to any
470
+ // mutated name (its value depends on runtime assignments).
471
+ if (runtimeVarNames.has(ref) || mutatedNames.has(ref)) {
472
+ demoted.add(stmt.name);
473
+ runtimeVarNames.add(stmt.name);
474
+ changed = true;
475
+ break;
476
+ }
477
+ }
478
+ }
479
+ }
480
+ if (demoted.size > 0) {
481
+ compiletimeVarNames = new Set([...compiletimeVarNames].filter((n) => !demoted.has(n)));
482
+ for (let i = topLevelDeclarations.length - 1; i >= 0; i--) {
483
+ const stmt = topLevelDeclarations[i];
484
+ if (stmt.kind === "var_decl" && demoted.has(stmt.name)) {
485
+ topLevelDeclarations.splice(i, 1);
486
+ topLevelExecutables.push(stmt);
487
+ }
488
+ }
489
+ topLevelExecutables.sort((a, b) => {
490
+ const aIdx = program.topLevelStatements.indexOf(a);
491
+ const bIdx = program.topLevelStatements.indexOf(b);
492
+ return aIdx - bIdx;
493
+ });
494
+ ctx.compiletimeVarNames = compiletimeVarNames;
495
+ }
496
+ }
497
+ const filteredTopLevelDeclarations = ctx.reservedNames.size > 0
498
+ ? topLevelDeclarations.filter((item) => {
499
+ if (item.kind === "var_decl") {
500
+ return !ctx.reservedNames.has(item.name);
501
+ }
502
+ return true;
503
+ })
504
+ : topLevelDeclarations;
505
+ const filteredTopLevelExecutables_presuppress = ctx.reservedNames.size > 0
506
+ ? topLevelExecutables.filter((item) => {
507
+ if (item.kind === "var_decl") {
508
+ return !ctx.reservedNames.has(item.name);
509
+ }
510
+ return true;
511
+ })
512
+ : topLevelExecutables;
513
+ const entrypointFunctionName = strategy.entrypointFunctionName();
514
+ const entrypointCallNames = new Set([entrypointFunctionName]);
515
+ for (const fn of program.functions) {
516
+ const mappedName = ctx.statementRenderer.mapFunctionName(fn.originalName);
517
+ if (mappedName === entrypointFunctionName) {
518
+ entrypointCallNames.add(fn.originalName);
519
+ entrypointCallNames.add(applySymbolMap(fn.originalName, symbolMap));
520
+ }
521
+ }
522
+ const filteredTopLevelExecutables = filteredTopLevelExecutables_presuppress.filter((statement) => {
523
+ if (statement.kind !== "call") {
524
+ return true;
525
+ }
526
+ const mappedCallee = applySymbolMap(statement.callee, symbolMap);
527
+ if (!entrypointCallNames.has(statement.callee) && !entrypointCallNames.has(mappedCallee)) {
528
+ return !ctx.asyncFunctionOriginalNames.has(statement.callee) && !ctx.asyncFunctionMappedNames.has(statement.callee);
529
+ }
530
+ return false;
531
+ });
532
+ ctx.filteredTopLevelExecutables = filteredTopLevelExecutables;
533
+ const emittedTopLevelStatements = isEntryFile
534
+ ? filteredTopLevelDeclarations
535
+ : [
536
+ ...filteredTopLevelDeclarations,
537
+ ...filteredTopLevelExecutables.filter((statement) => statement.kind === "var_decl"),
538
+ ];
539
+ ctx.filteredTopLevelDeclarations = filteredTopLevelDeclarations;
540
+ ctx.emittedTopLevelStatements = emittedTopLevelStatements;
541
+ // Collect pointer variable types
542
+ const allExecutableStatements = [...filteredTopLevelExecutables];
543
+ for (const fn of mappedFunctions) {
544
+ allExecutableStatements.push(...fn.statements);
545
+ }
546
+ const globalPointerVarTypes = collectPointerVarTypes(allExecutableStatements, ctx.classNameMap);
547
+ // Populate the existing ctx.globalPointerVarTypes map in place (rather than
548
+ // reassigning) so the ExpressionRenderer — constructed earlier in setup with
549
+ // the same Map reference — observes the resolved pointer types when it later
550
+ // decides `->` vs `.` for bare identifiers (e.g. ISR-captured globals).
551
+ ctx.globalPointerVarTypes.clear();
552
+ for (const [k, v] of globalPointerVarTypes)
553
+ ctx.globalPointerVarTypes.set(k, v);
554
+ // Promote timing variables to unsigned long
555
+ {
556
+ const timingVarNames = new Set();
557
+ const allStatementsForTiming = [...emittedTopLevelStatements];
558
+ for (const fn of mappedFunctions) {
559
+ allStatementsForTiming.push(...fn.statements);
560
+ }
561
+ for (let pass = 0; pass < 3; pass++) {
562
+ const prevSize = timingVarNames.size;
563
+ scanForTimingAssignments(allStatementsForTiming, timingVarNames);
564
+ if (timingVarNames.size === prevSize)
565
+ break;
566
+ }
567
+ promoteVarDecls(allStatementsForTiming, timingVarNames);
568
+ }
569
+ // Collect callback functions
570
+ const callbackFunctions = [];
571
+ const counter = { value: 0 };
572
+ collectCallbacks(filteredTopLevelExecutables, callbackFunctions, ctx.isrPrefix, counter);
573
+ for (const fn of mappedFunctions) {
574
+ collectCallbacks(fn.statements, callbackFunctions, ctx.isrPrefix, counter);
575
+ }
576
+ for (const cls of program.classes) {
577
+ if (cls.constructor) {
578
+ collectCallbacks(cls.constructor.statements, callbackFunctions, ctx.isrPrefix, counter);
579
+ }
580
+ for (const method of cls.methods) {
581
+ collectCallbacks(method.statements, callbackFunctions, ctx.isrPrefix, counter);
582
+ }
583
+ for (const getter of cls.getters) {
584
+ collectCallbacks(getter.statements, callbackFunctions, ctx.isrPrefix, counter);
585
+ }
586
+ for (const setter of cls.setters) {
587
+ collectCallbacks(setter.statements, callbackFunctions, ctx.isrPrefix, counter);
588
+ }
589
+ }
590
+ // Process registered callbacks from HAL resolver
591
+ for (const rc of (program.registeredCallbacks ?? [])) {
592
+ const callbackName = `${ctx.isrPrefix}_isr_${counter.value++}`;
593
+ const callbackIR = rc.callbackIR;
594
+ callbackFunctions.push({
595
+ name: callbackName,
596
+ params: callbackIR.params,
597
+ statements: callbackIR.statements ?? callbackIR.body ?? [],
598
+ debounceMs: callbackIR.debounceMs,
599
+ isInterruptHandler: callbackIR.isInterruptHandler,
600
+ });
601
+ replacePlaceholderInAllStatements(filteredTopLevelExecutables, rc.placeholderName, callbackName);
602
+ for (const fn of mappedFunctions) {
603
+ replacePlaceholderInAllStatements(fn.statements, rc.placeholderName, callbackName);
604
+ }
605
+ }
606
+ ctx.callbackFunctions = callbackFunctions;
607
+ // Promote function-referenced runtime var_decls to file scope.
608
+ // Runtime top-level vars are emitted inside setup()/main(), which free
609
+ // functions cannot access. Promoting them to file-scope globals and
610
+ // replacing the declaration with an assignment inside the entrypoint
611
+ // makes them visible to all functions while preserving init order.
612
+ const promotedVarDecls = new Map();
613
+ const globalVarNames = new Set();
614
+ for (const stmt of filteredTopLevelDeclarations) {
615
+ if (stmt.kind === "var_decl") {
616
+ globalVarNames.add(stmt.name);
617
+ }
618
+ }
619
+ // Collect identifiers referenced by ALL functions (ISR callbacks + free functions)
620
+ const allFuncIdentifiers = new Set();
621
+ for (const cb of callbackFunctions) {
622
+ for (const id of collectIdentifierNames(cb.statements)) {
623
+ allFuncIdentifiers.add(id);
624
+ }
625
+ }
626
+ for (const fn of mappedFunctions) {
627
+ for (const id of collectIdentifierNames(fn.statements)) {
628
+ allFuncIdentifiers.add(id);
629
+ }
630
+ }
631
+ if (allFuncIdentifiers.size > 0 && filteredTopLevelExecutables.length > 0) {
632
+ for (let i = 0; i < filteredTopLevelExecutables.length; i++) {
633
+ const stmt = filteredTopLevelExecutables[i];
634
+ if (stmt.kind === "var_decl" && allFuncIdentifiers.has(stmt.name)) {
635
+ if (globalVarNames.has(stmt.name)) {
636
+ continue;
637
+ }
638
+ const varType = strategy.normalizeCppType(stmt.cppType);
639
+ promotedVarDecls.set(stmt.name, { cppType: varType, index: i });
640
+ filteredTopLevelExecutables[i] = {
641
+ kind: "assign",
642
+ sourceSpan: stmt.sourceSpan,
643
+ leadingComments: stmt.leadingComments,
644
+ trailingComments: stmt.trailingComments,
645
+ target: stmt.name,
646
+ operator: "=",
647
+ value: stmt.initializer,
648
+ };
649
+ }
650
+ }
651
+ }
652
+ ctx.promotedVarDecls = promotedVarDecls;
653
+ // Remove local var_decls that shadow global variables and are referenced by ISRs
654
+ // Re-collect names of global variables (now including promoted ones)
655
+ const globalVarNames2 = new Set();
656
+ for (const stmt of filteredTopLevelDeclarations) {
657
+ if (stmt.kind === "var_decl") {
658
+ globalVarNames2.add(stmt.name);
659
+ }
660
+ }
661
+ for (const varName of promotedVarDecls.keys()) {
662
+ globalVarNames2.add(varName);
663
+ }
664
+ // Remove local var_decls that shadow globals and are ISR-referenced
665
+ if (callbackFunctions.length > 0) {
666
+ const isrIdentifiers = new Set();
667
+ for (const cb of callbackFunctions) {
668
+ for (const id of collectIdentifierNames(cb.statements)) {
669
+ isrIdentifiers.add(id);
670
+ }
671
+ }
672
+ for (const fn of mappedFunctions) {
673
+ fn.statements = removeShadowingVarDecls(fn.statements, globalVarNames2, isrIdentifiers);
674
+ }
675
+ }
676
+ // fixPointerFieldAccess was a post-hoc string rewriter that converted
677
+ // already-rendered `.` member access to `->` when the receiver resolved to a
678
+ // pointer. It has been REMOVED. The pointer/value decision is now made once,
679
+ // structurally, where the resolved C++ type of the receiver is known:
680
+ //
681
+ // - For `property-access` / `method-call` IR nodes, `expressionToIR` sets
682
+ // `isPointer` via `resolveExprCppType` + `parsedIsPointer`, and the IR
683
+ // also falls back to the module-scope `globalPointerVarTypes` registry
684
+ // (threaded into ExpressionRenderer / StatementRenderer) for receivers
685
+ // whose type wasn't visible at IR build time — notably ISR-captured
686
+ // globals (`const btn = new Button()` accessed inside a hoisted callback).
687
+ // - For assign/update targets and free `call` statements, the renderer
688
+ // arrows the leading receiver when it is a known global pointer.
689
+ //
690
+ // Why the rewriter had to go: it operated on rendered C++ text and keyed off
691
+ // *names*, not symbols. A name collision between a class value-field and a
692
+ // same-named pointer local (demo #23 Finding B: `this.heap` value field vs.
693
+ // a `heap` pointer local) let the `\b`/`(^|[^>.])` regex rewrite
694
+ // `this->heap.x` → `this->heap->x` (wrong: heap is a value), producing
695
+ // `base operand of '->' has non-pointer type 'std::vector<Job>'`. The demo
696
+ // history (#15–#23) is a series of these name-vs-symbol mismatches; each fix
697
+ // tightened one regex and exposed the next. Removing the rewriter (and its
698
+ // three duplicate copies) eliminates the whole class of bug.
699
+ //
700
+ // The field on EmitterContext remains as a permanent identity no-op because
701
+ // several render call sites still thread it as `calleeTransformer`; it no
702
+ // longer inspects or mutates its argument.
703
+ ctx.fixPointerFieldAccess = function fixPointerFieldAccess(callee) {
704
+ return callee;
705
+ };
706
+ }