@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.
- package/LICENSE +21 -0
- package/README.md +79 -0
- package/dist/api/board-types.d.ts +1 -0
- package/dist/api/board-types.js +4 -0
- package/dist/api/capabilities.d.ts +12 -0
- package/dist/api/capabilities.js +1 -0
- package/dist/api/config.d.ts +120 -0
- package/dist/api/config.js +7 -0
- package/dist/api/index.d.ts +5 -0
- package/dist/api/index.js +2 -0
- package/dist/api/schema/builder.d.ts +14 -0
- package/dist/api/schema/builder.js +15 -0
- package/dist/api/schema/index.d.ts +2 -0
- package/dist/api/schema/index.js +1 -0
- package/dist/api/schema/types.d.ts +257 -0
- package/dist/api/schema/types.js +4 -0
- package/dist/api/shared/async-runtime-static.d.ts +8 -0
- package/dist/api/shared/async-runtime-static.js +201 -0
- package/dist/api/shared/async-types.d.ts +42 -0
- package/dist/api/shared/async-types.js +8 -0
- package/dist/api/shared/board-resolver.d.ts +12 -0
- package/dist/api/shared/board-resolver.js +7 -0
- package/dist/api/shared/cpp-type-ir.d.ts +229 -0
- package/dist/api/shared/cpp-type-ir.js +672 -0
- package/dist/api/shared/display-adapter.d.ts +12 -0
- package/dist/api/shared/display-adapter.js +145 -0
- package/dist/api/shared/display-adapters/eink-mono.d.ts +2 -0
- package/dist/api/shared/display-adapters/eink-mono.js +53 -0
- package/dist/api/shared/display-adapters/sdl.d.ts +2 -0
- package/dist/api/shared/display-adapters/sdl.js +452 -0
- package/dist/api/shared/display-adapters/ssd1309.d.ts +2 -0
- package/dist/api/shared/display-adapters/ssd1309.js +136 -0
- package/dist/api/shared/display-adapters/st7796.d.ts +2 -0
- package/dist/api/shared/display-adapters/st7796.js +132 -0
- package/dist/api/shared/display-capabilities.d.ts +45 -0
- package/dist/api/shared/display-capabilities.js +54 -0
- package/dist/api/shared/display-op-ir.d.ts +62 -0
- package/dist/api/shared/display-op-ir.js +19 -0
- package/dist/api/shared/display-profile.d.ts +265 -0
- package/dist/api/shared/display-profile.js +338 -0
- package/dist/api/shared/graphics-strategy.d.ts +29 -0
- package/dist/api/shared/graphics-strategy.js +11 -0
- package/dist/api/shared/hal-op-ir.d.ts +393 -0
- package/dist/api/shared/hal-op-ir.js +18 -0
- package/dist/api/shared/index.d.ts +26 -0
- package/dist/api/shared/index.js +21 -0
- package/dist/api/shared/ir-core.d.ts +363 -0
- package/dist/api/shared/ir-core.js +8 -0
- package/dist/api/shared/ir-declarations.d.ts +201 -0
- package/dist/api/shared/ir-declarations.js +26 -0
- package/dist/api/shared/ir.d.ts +85 -0
- package/dist/api/shared/ir.js +13 -0
- package/dist/api/shared/platform-strategy.d.ts +402 -0
- package/dist/api/shared/platform-strategy.js +14 -0
- package/dist/api/shared/polyfill-helper-registry.d.ts +11 -0
- package/dist/api/shared/polyfill-helper-registry.js +86 -0
- package/dist/api/shared/polyfill-types.d.ts +33 -0
- package/dist/api/shared/polyfill-types.js +76 -0
- package/dist/api/shared/promise-runtime.d.ts +10 -0
- package/dist/api/shared/promise-runtime.js +244 -0
- package/dist/api/shared/snprintf-types.d.ts +29 -0
- package/dist/api/shared/snprintf-types.js +8 -0
- package/dist/api/shared/string-method-registry.d.ts +53 -0
- package/dist/api/shared/string-method-registry.js +168 -0
- package/dist/api/shared/toolchain-types.d.ts +63 -0
- package/dist/api/shared/toolchain-types.js +71 -0
- package/dist/api/shared/types.d.ts +50 -0
- package/dist/api/shared/types.js +6 -0
- package/dist/ast/parse.d.ts +2 -0
- package/dist/ast/parse.js +4 -0
- package/dist/cache.d.ts +26 -0
- package/dist/cache.js +95 -0
- package/dist/cli-utils.d.ts +37 -0
- package/dist/cli-utils.js +250 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +635 -0
- package/dist/config-loader.d.ts +78 -0
- package/dist/config-loader.js +508 -0
- package/dist/config-schema.d.ts +233 -0
- package/dist/config-schema.js +83 -0
- package/dist/create/board-checklist.d.ts +2 -0
- package/dist/create/board-checklist.js +52 -0
- package/dist/create/board-codegen.d.ts +9 -0
- package/dist/create/board-codegen.js +238 -0
- package/dist/create/board-generators.d.ts +12 -0
- package/dist/create/board-generators.js +652 -0
- package/dist/create/board-spec.d.ts +640 -0
- package/dist/create/board-spec.js +215 -0
- package/dist/create/eslint-rules-template.d.ts +2 -0
- package/dist/create/eslint-rules-template.js +672 -0
- package/dist/create/index.d.ts +11 -0
- package/dist/create/index.js +8 -0
- package/dist/create/init-scaffold.d.ts +27 -0
- package/dist/create/init-scaffold.js +150 -0
- package/dist/create/init-templates.d.ts +24 -0
- package/dist/create/init-templates.js +379 -0
- package/dist/create/init-wizard.d.ts +8 -0
- package/dist/create/init-wizard.js +168 -0
- package/dist/debug/breakpoint-loader.d.ts +24 -0
- package/dist/debug/breakpoint-loader.js +137 -0
- package/dist/debug/index.d.ts +3 -0
- package/dist/debug/index.js +7 -0
- package/dist/debug/preprocessor.d.ts +9 -0
- package/dist/debug/preprocessor.js +214 -0
- package/dist/debug/types.d.ts +32 -0
- package/dist/debug/types.js +6 -0
- package/dist/diagnostics/diagnostics-report.d.ts +51 -0
- package/dist/diagnostics/diagnostics-report.js +333 -0
- package/dist/diagnostics/json-schema.d.ts +138 -0
- package/dist/diagnostics/json-schema.js +27 -0
- package/dist/diagnostics/md-writer.d.ts +10 -0
- package/dist/diagnostics/md-writer.js +336 -0
- package/dist/diagnostics/mermaid-builder.d.ts +65 -0
- package/dist/diagnostics/mermaid-builder.js +681 -0
- package/dist/emit/cpp-emitter.d.ts +6 -0
- package/dist/emit/cpp-emitter.js +48 -0
- package/dist/emit/emitters/class-emitter.d.ts +2 -0
- package/dist/emit/emitters/class-emitter.js +523 -0
- package/dist/emit/emitters/emitter-context.d.ts +174 -0
- package/dist/emit/emitters/emitter-context.js +1 -0
- package/dist/emit/emitters/entrypoint-synthesizer.d.ts +2 -0
- package/dist/emit/emitters/entrypoint-synthesizer.js +175 -0
- package/dist/emit/emitters/function-emitter-impl.d.ts +19 -0
- package/dist/emit/emitters/function-emitter-impl.js +428 -0
- package/dist/emit/emitters/line-appender.d.ts +15 -0
- package/dist/emit/emitters/line-appender.js +344 -0
- package/dist/emit/emitters/namespace-emitter.d.ts +2 -0
- package/dist/emit/emitters/namespace-emitter.js +324 -0
- package/dist/emit/emitters/output-finalizer.d.ts +4 -0
- package/dist/emit/emitters/output-finalizer.js +267 -0
- package/dist/emit/emitters/setup.d.ts +3 -0
- package/dist/emit/emitters/setup.js +851 -0
- package/dist/emit/emitters/top-level-prep.d.ts +2 -0
- package/dist/emit/emitters/top-level-prep.js +706 -0
- package/dist/emit/emitters/type-decl-emitter.d.ts +2 -0
- package/dist/emit/emitters/type-decl-emitter.js +251 -0
- package/dist/emit/emitters/ui-emitter.d.ts +21 -0
- package/dist/emit/emitters/ui-emitter.js +564 -0
- package/dist/emit/enum-emitter.d.ts +1 -0
- package/dist/emit/enum-emitter.js +1 -0
- package/dist/emit/expression-renderer.d.ts +283 -0
- package/dist/emit/expression-renderer.js +1477 -0
- package/dist/emit/native-helpers-emitter.d.ts +11 -0
- package/dist/emit/native-helpers-emitter.js +34 -0
- package/dist/emit/route-hal-op.d.ts +5 -0
- package/dist/emit/route-hal-op.js +13 -0
- package/dist/emit/snprintf-helpers.d.ts +17 -0
- package/dist/emit/snprintf-helpers.js +462 -0
- package/dist/emit/statement-renderer.d.ts +189 -0
- package/dist/emit/statement-renderer.js +948 -0
- package/dist/emit/utils/async-state-machine.d.ts +42 -0
- package/dist/emit/utils/async-state-machine.js +343 -0
- package/dist/emit/utils/comment-helpers.d.ts +20 -0
- package/dist/emit/utils/comment-helpers.js +31 -0
- package/dist/emit/utils/cpp-helpers.d.ts +47 -0
- package/dist/emit/utils/cpp-helpers.js +85 -0
- package/dist/emit/utils/include-resolver.d.ts +58 -0
- package/dist/emit/utils/include-resolver.js +155 -0
- package/dist/emit/utils/index.d.ts +8 -0
- package/dist/emit/utils/index.js +12 -0
- package/dist/emit/utils/type-inference.d.ts +159 -0
- package/dist/emit/utils/type-inference.js +559 -0
- package/dist/eslint-check.d.ts +10 -0
- package/dist/eslint-check.js +102 -0
- package/dist/framework-package.d.ts +10 -0
- package/dist/framework-package.js +58 -0
- package/dist/framework-registry.d.ts +39 -0
- package/dist/framework-registry.js +30 -0
- package/dist/incremental-cache.d.ts +116 -0
- package/dist/incremental-cache.js +335 -0
- package/dist/ir/adc-range-validation.d.ts +11 -0
- package/dist/ir/adc-range-validation.js +250 -0
- package/dist/ir/ast-node-utils.d.ts +8 -0
- package/dist/ir/ast-node-utils.js +32 -0
- package/dist/ir/board-pin-utils.d.ts +13 -0
- package/dist/ir/board-pin-utils.js +65 -0
- package/dist/ir/board-resolver.d.ts +36 -0
- package/dist/ir/board-resolver.js +437 -0
- package/dist/ir/build-ir-state.d.ts +167 -0
- package/dist/ir/build-ir-state.js +306 -0
- package/dist/ir/build-ir.d.ts +2 -0
- package/dist/ir/build-ir.js +808 -0
- package/dist/ir/call-graph.d.ts +35 -0
- package/dist/ir/call-graph.js +194 -0
- package/dist/ir/compile-time-only.d.ts +2 -0
- package/dist/ir/compile-time-only.js +16 -0
- package/dist/ir/declaration-builders.d.ts +9 -0
- package/dist/ir/declaration-builders.js +608 -0
- package/dist/ir/entry-points.d.ts +30 -0
- package/dist/ir/entry-points.js +191 -0
- package/dist/ir/expression-to-ir.d.ts +5 -0
- package/dist/ir/expression-to-ir.js +2249 -0
- package/dist/ir/extract-property-chain.d.ts +10 -0
- package/dist/ir/extract-property-chain.js +30 -0
- package/dist/ir/feature-prescan.d.ts +3 -0
- package/dist/ir/feature-prescan.js +43 -0
- package/dist/ir/feature-registry.d.ts +30 -0
- package/dist/ir/feature-registry.js +816 -0
- package/dist/ir/filter.d.ts +7 -0
- package/dist/ir/filter.js +85 -0
- package/dist/ir/function-builder.d.ts +19 -0
- package/dist/ir/function-builder.js +670 -0
- package/dist/ir/hal/hal-emitter.d.ts +62 -0
- package/dist/ir/hal/hal-emitter.js +735 -0
- package/dist/ir/hal/hal-parser.d.ts +61 -0
- package/dist/ir/hal/hal-parser.js +473 -0
- package/dist/ir/hal/hal-plugins.d.ts +34 -0
- package/dist/ir/hal/hal-plugins.js +706 -0
- package/dist/ir/hal-resolver.d.ts +5 -0
- package/dist/ir/hal-resolver.js +5 -0
- package/dist/ir/heap-analysis.d.ts +8 -0
- package/dist/ir/heap-analysis.js +350 -0
- package/dist/ir/heap-array-validation.d.ts +24 -0
- package/dist/ir/heap-array-validation.js +29 -0
- package/dist/ir/identifier-collector.d.ts +18 -0
- package/dist/ir/identifier-collector.js +439 -0
- package/dist/ir/interrupt-analysis.d.ts +39 -0
- package/dist/ir/interrupt-analysis.js +467 -0
- package/dist/ir/memory-budget-validation.d.ts +10 -0
- package/dist/ir/memory-budget-validation.js +86 -0
- package/dist/ir/namespace-builder.d.ts +7 -0
- package/dist/ir/namespace-builder.js +152 -0
- package/dist/ir/ownership-analysis.d.ts +9 -0
- package/dist/ir/ownership-analysis.js +1207 -0
- package/dist/ir/peripheral-ownership.d.ts +3 -0
- package/dist/ir/peripheral-ownership.js +152 -0
- package/dist/ir/peripheral-symbols.d.ts +7 -0
- package/dist/ir/peripheral-symbols.js +57 -0
- package/dist/ir/peripheral-usage.d.ts +54 -0
- package/dist/ir/peripheral-usage.js +691 -0
- package/dist/ir/peripheral-validation.d.ts +8 -0
- package/dist/ir/peripheral-validation.js +77 -0
- package/dist/ir/pin-alias-conflict.d.ts +4 -0
- package/dist/ir/pin-alias-conflict.js +34 -0
- package/dist/ir/pin-capability-validation.d.ts +6 -0
- package/dist/ir/pin-capability-validation.js +413 -0
- package/dist/ir/pin-mode-validation.d.ts +10 -0
- package/dist/ir/pin-mode-validation.js +301 -0
- package/dist/ir/pin-safety.d.ts +11 -0
- package/dist/ir/pin-safety.js +58 -0
- package/dist/ir/program-analysis.d.ts +44 -0
- package/dist/ir/program-analysis.js +589 -0
- package/dist/ir/pulldown-validation.d.ts +7 -0
- package/dist/ir/pulldown-validation.js +49 -0
- package/dist/ir/pwm-timer-sharing.d.ts +4 -0
- package/dist/ir/pwm-timer-sharing.js +93 -0
- package/dist/ir/reachability.d.ts +68 -0
- package/dist/ir/reachability.js +224 -0
- package/dist/ir/register-decorators.d.ts +6 -0
- package/dist/ir/register-decorators.js +49 -0
- package/dist/ir/render-expr.d.ts +4 -0
- package/dist/ir/render-expr.js +127 -0
- package/dist/ir/resource-analysis.d.ts +19 -0
- package/dist/ir/resource-analysis.js +153 -0
- package/dist/ir/statement-to-ir.d.ts +23 -0
- package/dist/ir/statement-to-ir.js +349 -0
- package/dist/ir/symbol-table.d.ts +68 -0
- package/dist/ir/symbol-table.js +179 -0
- package/dist/ir/symbol-types.d.ts +56 -0
- package/dist/ir/symbol-types.js +107 -0
- package/dist/ir/timer0-pwm-timing-conflict.d.ts +4 -0
- package/dist/ir/timer0-pwm-timing-conflict.js +71 -0
- package/dist/ir/timing-validation.d.ts +7 -0
- package/dist/ir/timing-validation.js +95 -0
- package/dist/ir/transformers/array-methods.d.ts +8 -0
- package/dist/ir/transformers/array-methods.js +493 -0
- package/dist/ir/transformers/call-statement.d.ts +5 -0
- package/dist/ir/transformers/call-statement.js +758 -0
- package/dist/ir/transformers/callback-context-registry.d.ts +20 -0
- package/dist/ir/transformers/callback-context-registry.js +55 -0
- package/dist/ir/transformers/canvas-lowering.d.ts +42 -0
- package/dist/ir/transformers/canvas-lowering.js +249 -0
- package/dist/ir/transformers/control-flow.d.ts +8 -0
- package/dist/ir/transformers/control-flow.js +508 -0
- package/dist/ir/transformers/expressions.d.ts +7 -0
- package/dist/ir/transformers/expressions.js +406 -0
- package/dist/ir/transformers/hal-call-resolver.d.ts +29 -0
- package/dist/ir/transformers/hal-call-resolver.js +274 -0
- package/dist/ir/transformers/hal-emit-helpers.d.ts +14 -0
- package/dist/ir/transformers/hal-emit-helpers.js +63 -0
- package/dist/ir/transformers/namespace-methods.d.ts +20 -0
- package/dist/ir/transformers/namespace-methods.js +110 -0
- package/dist/ir/transformers/register-assignment.d.ts +5 -0
- package/dist/ir/transformers/register-assignment.js +56 -0
- package/dist/ir/transformers/ui-call-resolver.d.ts +149 -0
- package/dist/ir/transformers/ui-call-resolver.js +1136 -0
- package/dist/ir/transformers/ui-callback-lowering.d.ts +62 -0
- package/dist/ir/transformers/ui-callback-lowering.js +623 -0
- package/dist/ir/transformers/ui-mount.d.ts +20 -0
- package/dist/ir/transformers/ui-mount.js +35 -0
- package/dist/ir/transformers/ui-reactive.d.ts +68 -0
- package/dist/ir/transformers/ui-reactive.js +129 -0
- package/dist/ir/transformers/variables.d.ts +14 -0
- package/dist/ir/transformers/variables.js +1045 -0
- package/dist/ir/try-catch-validation.d.ts +26 -0
- package/dist/ir/try-catch-validation.js +128 -0
- package/dist/ir/type-resolution.d.ts +31 -0
- package/dist/ir/type-resolution.js +977 -0
- package/dist/ir/ui-element-auto-wire.d.ts +50 -0
- package/dist/ir/ui-element-auto-wire.js +218 -0
- package/dist/ir/unit-suspicion-validation.d.ts +12 -0
- package/dist/ir/unit-suspicion-validation.js +296 -0
- package/dist/ir/utils/walk-ir.d.ts +6 -0
- package/dist/ir/utils/walk-ir.js +162 -0
- package/dist/ir/validation-orchestrator.d.ts +4 -0
- package/dist/ir/validation-orchestrator.js +45 -0
- package/dist/libdef/base-class-resolver.d.ts +23 -0
- package/dist/libdef/base-class-resolver.js +50 -0
- package/dist/libdef/cpp-to-decl.d.ts +34 -0
- package/dist/libdef/cpp-to-decl.js +584 -0
- package/dist/libdef/header-parser.d.ts +53 -0
- package/dist/libdef/header-parser.js +269 -0
- package/dist/libdef/registry.d.ts +10 -0
- package/dist/libdef/registry.js +142 -0
- package/dist/mapping/peripheral-names.d.ts +23 -0
- package/dist/mapping/peripheral-names.js +63 -0
- package/dist/mapping/source-map.d.ts +46 -0
- package/dist/mapping/source-map.js +207 -0
- package/dist/orchestrator/dts-generator.d.ts +17 -0
- package/dist/orchestrator/dts-generator.js +83 -0
- package/dist/orchestrator/graph-builder.d.ts +18 -0
- package/dist/orchestrator/graph-builder.js +218 -0
- package/dist/orchestrator/semantic-facts-verifier.d.ts +38 -0
- package/dist/orchestrator/semantic-facts-verifier.js +121 -0
- package/dist/orchestrator/semantic-facts.d.ts +141 -0
- package/dist/orchestrator/semantic-facts.js +652 -0
- package/dist/orchestrator/type-checker.d.ts +39 -0
- package/dist/orchestrator/type-checker.js +760 -0
- package/dist/platform/async-runtime.d.ts +8 -0
- package/dist/platform/async-runtime.js +26 -0
- package/dist/platform/generic-strategy.d.ts +101 -0
- package/dist/platform/generic-strategy.js +289 -0
- package/dist/platform/index.d.ts +4 -0
- package/dist/platform/index.js +9 -0
- package/dist/platform/registry.d.ts +21 -0
- package/dist/platform/registry.js +42 -0
- package/dist/platform/toolchain.d.ts +4 -0
- package/dist/platform/toolchain.js +43 -0
- package/dist/preview/client.d.ts +1 -0
- package/dist/preview/client.js +137 -0
- package/dist/preview/server.d.ts +5 -0
- package/dist/preview/server.js +199 -0
- package/dist/profiler/index.d.ts +28 -0
- package/dist/profiler/index.js +28 -0
- package/dist/profiler/profiler.d.ts +95 -0
- package/dist/profiler/profiler.js +338 -0
- package/dist/profiler/types.d.ts +87 -0
- package/dist/profiler/types.js +12 -0
- package/dist/stores/display-profile-store.d.ts +16 -0
- package/dist/stores/display-profile-store.js +48 -0
- package/dist/stores/theme-store.d.ts +13 -0
- package/dist/stores/theme-store.js +30 -0
- package/dist/testing.d.ts +45 -0
- package/dist/testing.js +47 -0
- package/dist/transpile/resolution.d.ts +29 -0
- package/dist/transpile/resolution.js +282 -0
- package/dist/transpile.d.ts +3 -0
- package/dist/transpile.js +722 -0
- package/dist/types.d.ts +217 -0
- package/dist/types.js +1 -0
- package/dist/ui/ui-bridge.d.ts +4 -0
- package/dist/ui/ui-bridge.js +34 -0
- package/dist/ui-hook.d.ts +84 -0
- package/dist/ui-hook.js +45 -0
- package/dist/utils/cli.d.ts +3 -0
- package/dist/utils/cli.js +463 -0
- package/dist/utils/fs.d.ts +4 -0
- package/dist/utils/fs.js +23 -0
- package/dist/utils/logger.d.ts +2 -0
- package/dist/utils/logger.js +8 -0
- package/dist/utils/strings.d.ts +35 -0
- package/dist/utils/strings.js +142 -0
- package/dist/utils/ui.d.ts +66 -0
- package/dist/utils/ui.js +149 -0
- package/dist/watch.d.ts +35 -0
- package/dist/watch.js +111 -0
- package/package.json +127 -0
|
@@ -0,0 +1,439 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared utility for collecting identifiers from IR nodes.
|
|
3
|
+
* This consolidates duplicate logic that was previously in:
|
|
4
|
+
* - transpile.ts (collectExpressionIdentifiers, collectStatementIdentifiers)
|
|
5
|
+
* - call-graph.ts (collectExpressionIdentifiers, collectStatementIdentifiers)
|
|
6
|
+
* - build-ir.ts (similar traversal logic)
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Collect all identifiers from an expression IR node.
|
|
10
|
+
* Returns a Set of identifier names found.
|
|
11
|
+
*/
|
|
12
|
+
export function collectExpressionIdentifiers(expr) {
|
|
13
|
+
const identifiers = new Set();
|
|
14
|
+
// Safety check
|
|
15
|
+
if (!expr || typeof expr !== "object" || !expr.kind) {
|
|
16
|
+
return identifiers;
|
|
17
|
+
}
|
|
18
|
+
switch (expr.kind) {
|
|
19
|
+
case "identifier":
|
|
20
|
+
identifiers.add(expr.value);
|
|
21
|
+
break;
|
|
22
|
+
case "raw": {
|
|
23
|
+
// Extract identifiers from raw expressions
|
|
24
|
+
const matches = expr.value.match(/[A-Za-z_][A-Za-z0-9_]*/g);
|
|
25
|
+
if (matches) {
|
|
26
|
+
for (const match of matches) {
|
|
27
|
+
identifiers.add(match);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
break;
|
|
31
|
+
}
|
|
32
|
+
case "await":
|
|
33
|
+
for (const id of collectExpressionIdentifiers(expr.value)) {
|
|
34
|
+
identifiers.add(id);
|
|
35
|
+
}
|
|
36
|
+
break;
|
|
37
|
+
case "ternary":
|
|
38
|
+
for (const id of collectExpressionIdentifiers(expr.condition)) {
|
|
39
|
+
identifiers.add(id);
|
|
40
|
+
}
|
|
41
|
+
for (const id of collectExpressionIdentifiers(expr.whenTrue)) {
|
|
42
|
+
identifiers.add(id);
|
|
43
|
+
}
|
|
44
|
+
for (const id of collectExpressionIdentifiers(expr.whenFalse)) {
|
|
45
|
+
identifiers.add(id);
|
|
46
|
+
}
|
|
47
|
+
break;
|
|
48
|
+
case "array":
|
|
49
|
+
for (const element of expr.elements) {
|
|
50
|
+
for (const id of collectExpressionIdentifiers(element)) {
|
|
51
|
+
identifiers.add(id);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
break;
|
|
55
|
+
case "object":
|
|
56
|
+
for (const field of expr.fields) {
|
|
57
|
+
for (const id of collectExpressionIdentifiers(field.value)) {
|
|
58
|
+
identifiers.add(id);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
break;
|
|
62
|
+
case "instanceof":
|
|
63
|
+
for (const id of collectExpressionIdentifiers(expr.object)) {
|
|
64
|
+
identifiers.add(id);
|
|
65
|
+
}
|
|
66
|
+
identifiers.add(expr.className);
|
|
67
|
+
break;
|
|
68
|
+
case "spread_array":
|
|
69
|
+
for (const id of collectExpressionIdentifiers(expr.spreadExpr)) {
|
|
70
|
+
identifiers.add(id);
|
|
71
|
+
}
|
|
72
|
+
for (const element of expr.additionalElements) {
|
|
73
|
+
for (const id of collectExpressionIdentifiers(element)) {
|
|
74
|
+
identifiers.add(id);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
break;
|
|
78
|
+
case "binary":
|
|
79
|
+
for (const id of collectExpressionIdentifiers(expr.left)) {
|
|
80
|
+
identifiers.add(id);
|
|
81
|
+
}
|
|
82
|
+
for (const id of collectExpressionIdentifiers(expr.right)) {
|
|
83
|
+
identifiers.add(id);
|
|
84
|
+
}
|
|
85
|
+
break;
|
|
86
|
+
case "unary":
|
|
87
|
+
for (const id of collectExpressionIdentifiers(expr.operand)) {
|
|
88
|
+
identifiers.add(id);
|
|
89
|
+
}
|
|
90
|
+
break;
|
|
91
|
+
case "property-access":
|
|
92
|
+
for (const id of collectExpressionIdentifiers(expr.object)) {
|
|
93
|
+
identifiers.add(id);
|
|
94
|
+
}
|
|
95
|
+
break;
|
|
96
|
+
case "element-access":
|
|
97
|
+
for (const id of collectExpressionIdentifiers(expr.object)) {
|
|
98
|
+
identifiers.add(id);
|
|
99
|
+
}
|
|
100
|
+
for (const id of collectExpressionIdentifiers(expr.index)) {
|
|
101
|
+
identifiers.add(id);
|
|
102
|
+
}
|
|
103
|
+
break;
|
|
104
|
+
case "template_string":
|
|
105
|
+
for (const id of collectExpressionIdentifiers(expr.expression)) {
|
|
106
|
+
identifiers.add(id);
|
|
107
|
+
}
|
|
108
|
+
break;
|
|
109
|
+
case "string_concat":
|
|
110
|
+
for (const part of expr.parts) {
|
|
111
|
+
for (const id of collectExpressionIdentifiers(part)) {
|
|
112
|
+
identifiers.add(id);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
break;
|
|
116
|
+
case "callback":
|
|
117
|
+
// Callbacks have nested statements
|
|
118
|
+
for (const stmt of expr.statements) {
|
|
119
|
+
for (const id of collectStatementIdentifiers(stmt)) {
|
|
120
|
+
identifiers.add(id);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
break;
|
|
124
|
+
case "method-call": {
|
|
125
|
+
const calleeParts = expr.callee.split(/->|::|\./);
|
|
126
|
+
for (const part of calleeParts) {
|
|
127
|
+
if (part.length > 0) {
|
|
128
|
+
identifiers.add(part);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
for (const arg of expr.args) {
|
|
132
|
+
for (const id of collectExpressionIdentifiers(arg)) {
|
|
133
|
+
identifiers.add(id);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
// Parenthesized expression — recurse into the inner expression. The `paren`
|
|
139
|
+
// IR node exists to preserve explicit TS grouping (e.g. `(a + b) * c`), and
|
|
140
|
+
// any free-function call nested inside parens (such as `!fn(x)` inside an
|
|
141
|
+
// `(cond && !fn(x))` clause) MUST be visible to the call-graph/reachability
|
|
142
|
+
// pass, or the function is tree-shaken and g++ reports "not declared in
|
|
143
|
+
// this scope". Demo #22 Finding B — the root cause was the absence of this
|
|
144
|
+
// case, not a forward-declaration or return-type gap.
|
|
145
|
+
case "paren":
|
|
146
|
+
for (const id of collectExpressionIdentifiers(expr.inner)) {
|
|
147
|
+
identifiers.add(id);
|
|
148
|
+
}
|
|
149
|
+
break;
|
|
150
|
+
// Tuple element access `std::get<N>(object)` — the object may reference a
|
|
151
|
+
// reachable symbol.
|
|
152
|
+
case "tuple-access":
|
|
153
|
+
for (const id of collectExpressionIdentifiers(expr.object)) {
|
|
154
|
+
identifiers.add(id);
|
|
155
|
+
}
|
|
156
|
+
break;
|
|
157
|
+
// Arrow/lambda expression used as a value — walk its body for captured
|
|
158
|
+
// identifiers (the call graph must see free functions/vars a lambda uses).
|
|
159
|
+
case "lambda":
|
|
160
|
+
for (const param of expr.params) {
|
|
161
|
+
identifiers.add(param.name);
|
|
162
|
+
}
|
|
163
|
+
for (const stmt of expr.body) {
|
|
164
|
+
for (const id of collectStatementIdentifiers(stmt)) {
|
|
165
|
+
identifiers.add(id);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
break;
|
|
169
|
+
// HAL operation used as an expression — delegate to the HAL identifier
|
|
170
|
+
// collector (same logic as the hal-op statement case).
|
|
171
|
+
case "hal-expr":
|
|
172
|
+
for (const id of collectHALOpIdentifiers(expr.operation)) {
|
|
173
|
+
identifiers.add(id);
|
|
174
|
+
}
|
|
175
|
+
break;
|
|
176
|
+
// number, string, boolean have no identifiers
|
|
177
|
+
}
|
|
178
|
+
return identifiers;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Collect all identifiers from a statement IR node.
|
|
182
|
+
* Returns a Set of identifier names found.
|
|
183
|
+
*/
|
|
184
|
+
export function collectStatementIdentifiers(statement) {
|
|
185
|
+
const identifiers = new Set();
|
|
186
|
+
// Safety check
|
|
187
|
+
if (!statement || typeof statement !== "object" || !statement.kind) {
|
|
188
|
+
return identifiers;
|
|
189
|
+
}
|
|
190
|
+
switch (statement.kind) {
|
|
191
|
+
case "call":
|
|
192
|
+
// Extract function/method name from callee
|
|
193
|
+
const calleeParts = statement.callee.split(/->|::|[.(]/);
|
|
194
|
+
identifiers.add(calleeParts[0]);
|
|
195
|
+
// Add EVERY callee part, not just the first. A `call` statement's callee
|
|
196
|
+
// can be a lowered raw wrapper (`__RAW_STMT__out.push_back(glyphFor(op))`,
|
|
197
|
+
// produced by ir/transformers/call-statement.ts when an outer call wraps
|
|
198
|
+
// an inner free-function call). Only adding `calleeParts[0]` left the
|
|
199
|
+
// inner callee (`glyphFor`) invisible to the call graph, so a free
|
|
200
|
+
// function called only as a nested argument was tree-shaken and g++
|
|
201
|
+
// reported it "not declared in this scope". Demo #28 Finding C.
|
|
202
|
+
for (const part of calleeParts) {
|
|
203
|
+
if (part.length > 0) {
|
|
204
|
+
identifiers.add(part);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
// Also add the full callee (e.g. "Serial.begin") for polyfill detection
|
|
208
|
+
identifiers.add(statement.callee);
|
|
209
|
+
// Demo #31 Finding A — a `__RAW_STMT__` callee carries a fully-formed
|
|
210
|
+
// C++ expression in its raw text (e.g. `parts.push_back(ONES_TEENS[i])`
|
|
211
|
+
// or `__tc_pop(map[k])`), and the split on `/->|::|[.(]/` does NOT fully
|
|
212
|
+
// tokenize it: it stops splitting once it hits `]` or `)`, so an indexed
|
|
213
|
+
// identifier like `ONES_TEENS` survives glued to its suffix
|
|
214
|
+
// (`"ONES_TEENS[i])"`) and is never added. The result: a top-level
|
|
215
|
+
// variable referenced ONLY through `arr.push(globalArr[i])` from a class
|
|
216
|
+
// method is tree-shaken, then g++ reports it "not declared in this
|
|
217
|
+
// scope" from the inline method body. Same blind-spot family as demo
|
|
218
|
+
// #22 B / demo #28 C, but in a DIFFERENT shape: those missed a free
|
|
219
|
+
// FUNCTION buried in raw/paren text; this misses a free VARIABLE buried
|
|
220
|
+
// in raw text behind an index. Fix: when the callee is a raw wrapper,
|
|
221
|
+
// scan its raw text with the SAME identifier regex the `raw` expression
|
|
222
|
+
// case uses (`case "raw"` above), so EVERY identifier in the embedded
|
|
223
|
+
// expression is collected regardless of bracket/paren structure.
|
|
224
|
+
if (statement.callee.startsWith("__RAW_STMT__")) {
|
|
225
|
+
const matches = statement.callee.match(/[A-Za-z_][A-Za-z0-9_]*/g);
|
|
226
|
+
if (matches) {
|
|
227
|
+
for (const match of matches) {
|
|
228
|
+
identifiers.add(match);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
for (const arg of statement.args) {
|
|
233
|
+
// Special case: if this is an __EMIT__ call, scan string literals for identifiers
|
|
234
|
+
if (statement.callee === "__EMIT__" && arg.kind === "string") {
|
|
235
|
+
const matches = arg.value.match(/[A-Za-z_][A-Za-z0-9_]*/g);
|
|
236
|
+
if (matches) {
|
|
237
|
+
for (const match of matches) {
|
|
238
|
+
identifiers.add(match);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
for (const id of collectExpressionIdentifiers(arg)) {
|
|
243
|
+
identifiers.add(id);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
break;
|
|
247
|
+
case "var_decl":
|
|
248
|
+
identifiers.add(statement.name);
|
|
249
|
+
if (statement.initializer) {
|
|
250
|
+
for (const id of collectExpressionIdentifiers(statement.initializer)) {
|
|
251
|
+
identifiers.add(id);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
break;
|
|
255
|
+
case "assign":
|
|
256
|
+
identifiers.add(statement.target);
|
|
257
|
+
for (const id of collectExpressionIdentifiers(statement.value)) {
|
|
258
|
+
identifiers.add(id);
|
|
259
|
+
}
|
|
260
|
+
break;
|
|
261
|
+
case "update":
|
|
262
|
+
identifiers.add(statement.target);
|
|
263
|
+
break;
|
|
264
|
+
case "return":
|
|
265
|
+
if (statement.value) {
|
|
266
|
+
for (const id of collectExpressionIdentifiers(statement.value)) {
|
|
267
|
+
identifiers.add(id);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
break;
|
|
271
|
+
case "while":
|
|
272
|
+
case "do_while":
|
|
273
|
+
for (const id of collectExpressionIdentifiers(statement.condition)) {
|
|
274
|
+
identifiers.add(id);
|
|
275
|
+
}
|
|
276
|
+
for (const nested of statement.body) {
|
|
277
|
+
for (const id of collectStatementIdentifiers(nested)) {
|
|
278
|
+
identifiers.add(id);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
break;
|
|
282
|
+
case "if":
|
|
283
|
+
for (const id of collectExpressionIdentifiers(statement.condition)) {
|
|
284
|
+
identifiers.add(id);
|
|
285
|
+
}
|
|
286
|
+
for (const nested of statement.thenBranch) {
|
|
287
|
+
for (const id of collectStatementIdentifiers(nested)) {
|
|
288
|
+
identifiers.add(id);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
for (const nested of statement.elseBranch ?? []) {
|
|
292
|
+
for (const id of collectStatementIdentifiers(nested)) {
|
|
293
|
+
identifiers.add(id);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
break;
|
|
297
|
+
case "for":
|
|
298
|
+
if (statement.initializer) {
|
|
299
|
+
for (const id of collectStatementIdentifiers(statement.initializer)) {
|
|
300
|
+
identifiers.add(id);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
if (statement.condition) {
|
|
304
|
+
for (const id of collectExpressionIdentifiers(statement.condition)) {
|
|
305
|
+
identifiers.add(id);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
if (statement.increment) {
|
|
309
|
+
for (const id of collectStatementIdentifiers(statement.increment)) {
|
|
310
|
+
identifiers.add(id);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
for (const nested of statement.body) {
|
|
314
|
+
for (const id of collectStatementIdentifiers(nested)) {
|
|
315
|
+
identifiers.add(id);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
break;
|
|
319
|
+
case "for_of":
|
|
320
|
+
for (const id of collectStatementIdentifiers(statement.variable)) {
|
|
321
|
+
identifiers.add(id);
|
|
322
|
+
}
|
|
323
|
+
for (const id of collectExpressionIdentifiers(statement.iterable)) {
|
|
324
|
+
identifiers.add(id);
|
|
325
|
+
}
|
|
326
|
+
for (const nested of statement.body) {
|
|
327
|
+
for (const id of collectStatementIdentifiers(nested)) {
|
|
328
|
+
identifiers.add(id);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
break;
|
|
332
|
+
case "for_in":
|
|
333
|
+
for (const id of collectStatementIdentifiers(statement.variable)) {
|
|
334
|
+
identifiers.add(id);
|
|
335
|
+
}
|
|
336
|
+
for (const id of collectExpressionIdentifiers(statement.object)) {
|
|
337
|
+
identifiers.add(id);
|
|
338
|
+
}
|
|
339
|
+
for (const nested of statement.body) {
|
|
340
|
+
for (const id of collectStatementIdentifiers(nested)) {
|
|
341
|
+
identifiers.add(id);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
break;
|
|
345
|
+
case "switch":
|
|
346
|
+
for (const id of collectExpressionIdentifiers(statement.expression)) {
|
|
347
|
+
identifiers.add(id);
|
|
348
|
+
}
|
|
349
|
+
for (const caseClause of statement.cases) {
|
|
350
|
+
if (caseClause.value) {
|
|
351
|
+
for (const id of collectExpressionIdentifiers(caseClause.value)) {
|
|
352
|
+
identifiers.add(id);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
for (const nested of caseClause.body) {
|
|
356
|
+
for (const id of collectStatementIdentifiers(nested)) {
|
|
357
|
+
identifiers.add(id);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
break;
|
|
362
|
+
case "try":
|
|
363
|
+
if (statement.catchParam) {
|
|
364
|
+
identifiers.add(statement.catchParam);
|
|
365
|
+
}
|
|
366
|
+
for (const nested of statement.tryBlock) {
|
|
367
|
+
for (const id of collectStatementIdentifiers(nested)) {
|
|
368
|
+
identifiers.add(id);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
for (const nested of statement.catchBlock ?? []) {
|
|
372
|
+
for (const id of collectStatementIdentifiers(nested)) {
|
|
373
|
+
identifiers.add(id);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
if (statement.finallyBlock) {
|
|
377
|
+
for (const nested of statement.finallyBlock) {
|
|
378
|
+
for (const id of collectStatementIdentifiers(nested)) {
|
|
379
|
+
identifiers.add(id);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
break;
|
|
384
|
+
case "throw":
|
|
385
|
+
for (const id of collectExpressionIdentifiers(statement.value)) {
|
|
386
|
+
identifiers.add(id);
|
|
387
|
+
}
|
|
388
|
+
break;
|
|
389
|
+
case "labeled":
|
|
390
|
+
identifiers.add(statement.label);
|
|
391
|
+
for (const nested of statement.body) {
|
|
392
|
+
for (const id of collectStatementIdentifiers(nested)) {
|
|
393
|
+
identifiers.add(id);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
break;
|
|
397
|
+
case "block":
|
|
398
|
+
for (const nested of statement.body) {
|
|
399
|
+
for (const id of collectStatementIdentifiers(nested)) {
|
|
400
|
+
identifiers.add(id);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
break;
|
|
404
|
+
// break, continue have no identifiers
|
|
405
|
+
case "hal-op":
|
|
406
|
+
for (const id of collectHALOpIdentifiers(statement.operation)) {
|
|
407
|
+
identifiers.add(id);
|
|
408
|
+
}
|
|
409
|
+
break;
|
|
410
|
+
// break, continue have no identifiers
|
|
411
|
+
}
|
|
412
|
+
return identifiers;
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* Extract identifier names from a HAL operation's string fields.
|
|
416
|
+
* This ensures the call graph tracks function references embedded in
|
|
417
|
+
* semantic HAL ops (e.g. the handler name in interrupt.attach).
|
|
418
|
+
*/
|
|
419
|
+
function collectHALOpIdentifiers(op) {
|
|
420
|
+
const identifiers = new Set();
|
|
421
|
+
switch (op.operation) {
|
|
422
|
+
case "interrupt.attach":
|
|
423
|
+
// handler is a resolved C++ function name (e.g. "myIsr" or a placeholder)
|
|
424
|
+
identifiers.add(op.handler);
|
|
425
|
+
break;
|
|
426
|
+
case "raw": {
|
|
427
|
+
// Raw C++ code may reference user-defined identifiers
|
|
428
|
+
const matches = op.code.match(/[A-Za-z_][A-Za-z0-9_]*/g);
|
|
429
|
+
if (matches) {
|
|
430
|
+
for (const match of matches) {
|
|
431
|
+
identifiers.add(match);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
break;
|
|
435
|
+
}
|
|
436
|
+
// Other HAL ops have only numeric/literal fields — no identifier references
|
|
437
|
+
}
|
|
438
|
+
return identifiers;
|
|
439
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { ProgramIR } from '../api/index.js';
|
|
2
|
+
import type { PeripheralUsage } from './peripheral-usage.js';
|
|
3
|
+
import type { Diagnostic } from '../types.js';
|
|
4
|
+
export { walkNestedStatements as scanNestedStatements } from './utils/walk-ir.js';
|
|
5
|
+
/** ISR-unsafe operation entry. */
|
|
6
|
+
export interface IsrUnsafeOp {
|
|
7
|
+
reason: string;
|
|
8
|
+
severity: 'warning' | 'info';
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Track interrupt handlers attached to pins.
|
|
12
|
+
* Maps pin name to the number of handlers attached.
|
|
13
|
+
*/
|
|
14
|
+
export interface InterruptHandlerInfo {
|
|
15
|
+
pinName: string;
|
|
16
|
+
attachCount: number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Analyze a program for interrupt handler issues.
|
|
20
|
+
*
|
|
21
|
+
* @param program - The program IR to analyze
|
|
22
|
+
* @param usage - Peripheral usage information
|
|
23
|
+
* @param isrUnsafeOps - Platform-specific ISR-unsafe operations map (from strategy)
|
|
24
|
+
* @returns Array of diagnostics for interrupt-related issues
|
|
25
|
+
*/
|
|
26
|
+
export declare function analyzeInterruptSafety(program: ProgramIR, usage: PeripheralUsage, isrUnsafeOps?: Map<string, IsrUnsafeOp>): Diagnostic[];
|
|
27
|
+
/**
|
|
28
|
+
* Infer `volatile` for global variables shared between ISR callbacks and main
|
|
29
|
+
* code. Mutates the IR (sets isVolatile=true on qualifying var_decls) and
|
|
30
|
+
* emits an info diagnostic for each promotion. A variable qualifies when it is
|
|
31
|
+
* a global (top-level) that is assigned inside an isInterruptHandler callback
|
|
32
|
+
* AND read from non-ISR code (setup/loop/main/functions).
|
|
33
|
+
*/
|
|
34
|
+
export declare function inferVolatileForIsrSharedVars(program: ProgramIR, diagnostics: Diagnostic[]): void;
|
|
35
|
+
/**
|
|
36
|
+
* Detect functions called from both ISR callbacks and main-thread code.
|
|
37
|
+
* Emits a warning for each reentrancy-risk function.
|
|
38
|
+
*/
|
|
39
|
+
export declare function detectReentrancyRisk(program: ProgramIR, diagnostics: Diagnostic[]): void;
|