@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,77 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Peripheral Instance Validation
|
|
3
|
+
//
|
|
4
|
+
// Validates that peripheral instances used in the program are available
|
|
5
|
+
// on the target board. Generates compile-time errors for invalid usage.
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
/**
|
|
8
|
+
* Get peripheral capacity from board constants.
|
|
9
|
+
*/
|
|
10
|
+
function getPeripheralCapacity(boardConstants) {
|
|
11
|
+
const defaultCapacity = {
|
|
12
|
+
i2c: 1,
|
|
13
|
+
spi: 1,
|
|
14
|
+
uart: 1,
|
|
15
|
+
};
|
|
16
|
+
if (!boardConstants) {
|
|
17
|
+
return defaultCapacity;
|
|
18
|
+
}
|
|
19
|
+
return {
|
|
20
|
+
i2c: boardConstants.get('peripherals.i2c.count') ?? 1,
|
|
21
|
+
spi: boardConstants.get('peripherals.spi.count') ?? 1,
|
|
22
|
+
uart: boardConstants.get('peripherals.uart.count') ?? 1,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Validate peripheral usage against board capacity.
|
|
27
|
+
* Returns an array of diagnostics for any invalid peripheral usage.
|
|
28
|
+
*/
|
|
29
|
+
function validatePeripheralUsage(usage, capacity, boardName = 'this board') {
|
|
30
|
+
const diagnostics = [];
|
|
31
|
+
// Validate I2C instances
|
|
32
|
+
for (const instance of usage.i2cInstancesUsed) {
|
|
33
|
+
if (instance >= capacity.i2c) {
|
|
34
|
+
const availableName = capacity.i2c === 1 ? 'I2C0' : `I2C0 through I2C${capacity.i2c - 1}`;
|
|
35
|
+
diagnostics.push({
|
|
36
|
+
severity: 'error',
|
|
37
|
+
message: `I2C${instance} is not available on ${boardName}. Available: ${availableName}`,
|
|
38
|
+
code: 'peripheral-not-available',
|
|
39
|
+
source: 'peripheral-validation',
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// Validate SPI instances
|
|
44
|
+
for (const instance of usage.spiInstancesUsed) {
|
|
45
|
+
if (instance >= capacity.spi) {
|
|
46
|
+
const availableName = capacity.spi === 1 ? 'SPI0' : `SPI0 through SPI${capacity.spi - 1}`;
|
|
47
|
+
diagnostics.push({
|
|
48
|
+
severity: 'error',
|
|
49
|
+
message: `SPI${instance} is not available on ${boardName}. Available: ${availableName}`,
|
|
50
|
+
code: 'peripheral-not-available',
|
|
51
|
+
source: 'peripheral-validation',
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
// Validate UART instances
|
|
56
|
+
for (const instance of usage.uartInstancesUsed) {
|
|
57
|
+
if (instance >= capacity.uart) {
|
|
58
|
+
const availableName = capacity.uart === 1 ? 'UART0 (Serial)' : `UART0 through UART${capacity.uart - 1}`;
|
|
59
|
+
diagnostics.push({
|
|
60
|
+
severity: 'error',
|
|
61
|
+
message: `UART${instance} is not available on ${boardName}. Available: ${availableName}`,
|
|
62
|
+
code: 'peripheral-not-available',
|
|
63
|
+
source: 'peripheral-validation',
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return diagnostics;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Validate peripheral usage and return diagnostics.
|
|
71
|
+
* This is the main entry point for peripheral validation.
|
|
72
|
+
*/
|
|
73
|
+
export function validatePeripherals(usage, boardConstants) {
|
|
74
|
+
const capacity = getPeripheralCapacity(boardConstants);
|
|
75
|
+
const boardName = boardConstants?.get('name') ?? 'this board';
|
|
76
|
+
return validatePeripheralUsage(usage, capacity, boardName);
|
|
77
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Diagnostic } from '../types.js';
|
|
2
|
+
import type { BoardConstants } from './board-resolver.js';
|
|
3
|
+
import type { PeripheralUsage } from './peripheral-usage.js';
|
|
4
|
+
export declare function validatePinAliasConflicts(usage: PeripheralUsage, boardConstants: BoardConstants | undefined): Diagnostic[];
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { findBoardPinByName } from './board-pin-utils.js';
|
|
2
|
+
export function validatePinAliasConflicts(usage, boardConstants) {
|
|
3
|
+
if (!boardConstants || usage.pinsUsed.size === 0) {
|
|
4
|
+
return [];
|
|
5
|
+
}
|
|
6
|
+
const usedNamesByCanonicalPin = new Map();
|
|
7
|
+
for (const usedPinName of usage.pinsUsed) {
|
|
8
|
+
const boardPin = findBoardPinByName(usedPinName, boardConstants);
|
|
9
|
+
if (!boardPin) {
|
|
10
|
+
continue;
|
|
11
|
+
}
|
|
12
|
+
const names = usedNamesByCanonicalPin.get(boardPin.name) ?? new Set();
|
|
13
|
+
names.add(usedPinName);
|
|
14
|
+
usedNamesByCanonicalPin.set(boardPin.name, names);
|
|
15
|
+
}
|
|
16
|
+
const boardName = boardConstants.get('name');
|
|
17
|
+
const boardLabel = typeof boardName === 'string' && boardName.length > 0
|
|
18
|
+
? ` on ${boardName}`
|
|
19
|
+
: '';
|
|
20
|
+
const diagnostics = [];
|
|
21
|
+
for (const [canonicalPinName, usedNames] of usedNamesByCanonicalPin) {
|
|
22
|
+
if (usedNames.size < 2) {
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
const orderedNames = [canonicalPinName, ...Array.from(usedNames).filter(name => name !== canonicalPinName).sort()];
|
|
26
|
+
diagnostics.push({
|
|
27
|
+
severity: 'warning',
|
|
28
|
+
code: 'pin-alias-conflict',
|
|
29
|
+
source: 'pin-alias-conflict',
|
|
30
|
+
message: `Pin '${canonicalPinName}' is referenced through multiple names${boardLabel}: ${orderedNames.join(', ')}. These names refer to the same physical pin. Pick one name to keep pin usage and diagnostics unambiguous.`,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
return diagnostics;
|
|
34
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ProgramIR } from '../api/index.js';
|
|
2
|
+
import type { Diagnostic } from '../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Validate that capability-specific methods are only called on pins that support them.
|
|
5
|
+
*/
|
|
6
|
+
export declare function validatePinCapabilities(program: ProgramIR): Diagnostic[];
|
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Pin Capability Validation
|
|
3
|
+
//
|
|
4
|
+
// Detects calls to capability-specific methods on pins that don't support them.
|
|
5
|
+
// E.g. D12.readAnalog() — D12 is a digital-only pin, use A0-A5 instead.
|
|
6
|
+
// A0.pwm() — A0 has no PWM, use D3/D5/D6/D9/D10/D11 instead.
|
|
7
|
+
// Produces diagnostics with actionable hints listing the correct pins.
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
/** Compile-time exhaustiveness check for switch statements on IR kinds. */
|
|
10
|
+
function assertNever(x) {
|
|
11
|
+
throw new Error(`Unhandled IR kind: ${JSON.stringify(x)}`);
|
|
12
|
+
}
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
// HAL operation → capability mapping
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
/** Maps a HAL operation string to the board-definition capability flag it requires. */
|
|
17
|
+
function operationToCapability(op) {
|
|
18
|
+
if (op === 'pwm.write' || op === 'pwm.get_frequency' || op === 'pwm.get_resolution' || op === 'tone.play') {
|
|
19
|
+
return 'pwm';
|
|
20
|
+
}
|
|
21
|
+
if (op === 'adc.read' || op === 'adc.read_voltage' || op === 'adc.get_resolution') {
|
|
22
|
+
return 'analogInput';
|
|
23
|
+
}
|
|
24
|
+
if (op === 'dac.write') {
|
|
25
|
+
return 'analogOutput';
|
|
26
|
+
}
|
|
27
|
+
if (op === 'interrupt.attach') {
|
|
28
|
+
return 'interrupt';
|
|
29
|
+
}
|
|
30
|
+
// GPIO and timing ops are always available — no capability check needed.
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
// ---------------------------------------------------------------------------
|
|
34
|
+
// Board constant lookups
|
|
35
|
+
// ---------------------------------------------------------------------------
|
|
36
|
+
/** Find the human-readable name for a pin number (e.g. 14 → "PC0" or "A0"). */
|
|
37
|
+
function getPinName(pinNumber, boardConstants) {
|
|
38
|
+
if (!boardConstants)
|
|
39
|
+
return `pin ${pinNumber}`;
|
|
40
|
+
const name = boardConstants.get(`pins.all.${pinNumber}.name`);
|
|
41
|
+
return name ? String(name) : `pin ${pinNumber}`;
|
|
42
|
+
}
|
|
43
|
+
/** Find all pins on this board that support a given capability. */
|
|
44
|
+
function findPinsWithCapability(capability, boardConstants) {
|
|
45
|
+
if (!boardConstants)
|
|
46
|
+
return [];
|
|
47
|
+
const result = [];
|
|
48
|
+
const funcTypeMap = {
|
|
49
|
+
pwm: 'pwm',
|
|
50
|
+
analogInput: 'adc',
|
|
51
|
+
analogOutput: 'dac',
|
|
52
|
+
interrupt: 'interrupt',
|
|
53
|
+
};
|
|
54
|
+
const funcType = funcTypeMap[capability];
|
|
55
|
+
for (let i = 0; i < 100; i++) {
|
|
56
|
+
const name = boardConstants.get(`pins.all.${i}.name`);
|
|
57
|
+
if (name === undefined)
|
|
58
|
+
continue;
|
|
59
|
+
// Check capabilities flag first
|
|
60
|
+
const capFlag = boardConstants.get(`pins.all.${i}.capabilities.${capability}`);
|
|
61
|
+
if (capFlag === true || capFlag === 'true') {
|
|
62
|
+
result.push(String(name));
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
// Fallback: check functions array
|
|
66
|
+
if (funcType) {
|
|
67
|
+
for (let j = 0; j < 10; j++) {
|
|
68
|
+
const type = boardConstants.get(`pins.all.${i}.functions.${j}.type`);
|
|
69
|
+
if (type === undefined)
|
|
70
|
+
break;
|
|
71
|
+
if (String(type) === funcType) {
|
|
72
|
+
result.push(String(name));
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return result;
|
|
79
|
+
}
|
|
80
|
+
// ---------------------------------------------------------------------------
|
|
81
|
+
// Capability check for a single HAL operation
|
|
82
|
+
// ---------------------------------------------------------------------------
|
|
83
|
+
function checkCapability(operation, sourceLine, sourceCol, boardConstants, diagnostics) {
|
|
84
|
+
// Only operations with a pin field are capability-checked.
|
|
85
|
+
const op = operation.operation;
|
|
86
|
+
if (!('pin' in operation))
|
|
87
|
+
return;
|
|
88
|
+
const capability = operationToCapability(op);
|
|
89
|
+
if (!capability)
|
|
90
|
+
return; // GPIO/timing — always available.
|
|
91
|
+
const pin = operation.pin;
|
|
92
|
+
if (typeof pin !== 'number' || pin < 0)
|
|
93
|
+
return;
|
|
94
|
+
// ADC channel reads (ADC.read(channel)) use channel numbers, not pin
|
|
95
|
+
// numbers — skip capability checking for adc ops where the "pin" is
|
|
96
|
+
// actually a channel index (0-7 range, below the first analog pin).
|
|
97
|
+
if (capability === 'analogInput' && op.startsWith('adc.') && pin < 14)
|
|
98
|
+
return;
|
|
99
|
+
// Check the pin's capability via the board definition.
|
|
100
|
+
// Try the capabilities flag first, then fall back to scanning the
|
|
101
|
+
// functions array (functions.N.type === capability prefix).
|
|
102
|
+
const capFlag = boardConstants?.get(`pins.all.${pin}.capabilities.${capability}`);
|
|
103
|
+
if (capFlag === true || capFlag === 'true')
|
|
104
|
+
return; // Capability confirmed.
|
|
105
|
+
// Fallback: scan the functions array for a matching type.
|
|
106
|
+
// PWM capability is indicated by functions[N].type === 'pwm',
|
|
107
|
+
// ADC by 'adc', interrupts by 'interrupt' (external), DAC by 'dac'.
|
|
108
|
+
const funcTypeMap = {
|
|
109
|
+
pwm: 'pwm',
|
|
110
|
+
analogInput: 'adc',
|
|
111
|
+
analogOutput: 'dac',
|
|
112
|
+
interrupt: 'interrupt',
|
|
113
|
+
};
|
|
114
|
+
const funcType = funcTypeMap[capability];
|
|
115
|
+
if (funcType) {
|
|
116
|
+
let hasCapabilityData = false;
|
|
117
|
+
for (let i = 0; i < 10; i++) {
|
|
118
|
+
const type = boardConstants?.get(`pins.all.${pin}.functions.${i}.type`);
|
|
119
|
+
if (type === undefined)
|
|
120
|
+
break;
|
|
121
|
+
hasCapabilityData = true;
|
|
122
|
+
if (String(type) === funcType)
|
|
123
|
+
return; // Capability confirmed via functions.
|
|
124
|
+
}
|
|
125
|
+
// If the pin has NO functions entries at all AND the capability we're
|
|
126
|
+
// checking is interrupt (which is stored in capabilities, not functions),
|
|
127
|
+
// we can't determine support — skip to avoid false positives.
|
|
128
|
+
if (!hasCapabilityData && capability === 'interrupt')
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
// Capability NOT supported — emit a diagnostic.
|
|
132
|
+
const pinName = getPinName(pin, boardConstants);
|
|
133
|
+
const validPins = findPinsWithCapability(capability, boardConstants);
|
|
134
|
+
const capLabel = capability === 'analogInput' ? 'analog input'
|
|
135
|
+
: capability === 'analogOutput' ? 'DAC output'
|
|
136
|
+
: capability === 'interrupt' ? 'external interrupts'
|
|
137
|
+
: capability.toUpperCase();
|
|
138
|
+
const hint = validPins.length > 0
|
|
139
|
+
? `Use one of: ${validPins.join(', ')}`
|
|
140
|
+
: `No pins on this board support ${capLabel}.`;
|
|
141
|
+
diagnostics.push({
|
|
142
|
+
severity: 'error',
|
|
143
|
+
code: 'pin-capability-mismatch',
|
|
144
|
+
message: `${pinName} does not support ${capLabel} on this board.`,
|
|
145
|
+
hint,
|
|
146
|
+
line: sourceLine,
|
|
147
|
+
column: sourceCol,
|
|
148
|
+
source: 'pin-capability-validation',
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
// ---------------------------------------------------------------------------
|
|
152
|
+
// IR tree scanner
|
|
153
|
+
// ---------------------------------------------------------------------------
|
|
154
|
+
function scanExpression(expr, boardConstants, parentLine, parentCol, diagnostics) {
|
|
155
|
+
if (!expr || typeof expr !== 'object')
|
|
156
|
+
return;
|
|
157
|
+
switch (expr.kind) {
|
|
158
|
+
case 'binary': {
|
|
159
|
+
scanExpression(expr.left, boardConstants, parentLine, parentCol, diagnostics);
|
|
160
|
+
scanExpression(expr.right, boardConstants, parentLine, parentCol, diagnostics);
|
|
161
|
+
break;
|
|
162
|
+
}
|
|
163
|
+
case 'ternary': {
|
|
164
|
+
scanExpression(expr.condition, boardConstants, parentLine, parentCol, diagnostics);
|
|
165
|
+
scanExpression(expr.whenTrue, boardConstants, parentLine, parentCol, diagnostics);
|
|
166
|
+
scanExpression(expr.whenFalse, boardConstants, parentLine, parentCol, diagnostics);
|
|
167
|
+
break;
|
|
168
|
+
}
|
|
169
|
+
case 'property-access': {
|
|
170
|
+
scanExpression(expr.object, boardConstants, parentLine, parentCol, diagnostics);
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
case 'unary': {
|
|
174
|
+
scanExpression(expr.operand, boardConstants, parentLine, parentCol, diagnostics);
|
|
175
|
+
break;
|
|
176
|
+
}
|
|
177
|
+
case 'paren': {
|
|
178
|
+
scanExpression(expr.inner, boardConstants, parentLine, parentCol, diagnostics);
|
|
179
|
+
break;
|
|
180
|
+
}
|
|
181
|
+
case 'array': {
|
|
182
|
+
for (const el of expr.elements) {
|
|
183
|
+
scanExpression(el, boardConstants, parentLine, parentCol, diagnostics);
|
|
184
|
+
}
|
|
185
|
+
break;
|
|
186
|
+
}
|
|
187
|
+
case 'object': {
|
|
188
|
+
for (const field of expr.fields) {
|
|
189
|
+
scanExpression(field.value, boardConstants, parentLine, parentCol, diagnostics);
|
|
190
|
+
}
|
|
191
|
+
break;
|
|
192
|
+
}
|
|
193
|
+
case 'callback': {
|
|
194
|
+
for (const s of expr.statements) {
|
|
195
|
+
scanStatement(s, boardConstants, diagnostics);
|
|
196
|
+
}
|
|
197
|
+
break;
|
|
198
|
+
}
|
|
199
|
+
case 'lambda': {
|
|
200
|
+
for (const s of expr.body) {
|
|
201
|
+
scanStatement(s, boardConstants, diagnostics);
|
|
202
|
+
}
|
|
203
|
+
break;
|
|
204
|
+
}
|
|
205
|
+
case 'method-call': {
|
|
206
|
+
for (const arg of expr.args) {
|
|
207
|
+
scanExpression(arg, boardConstants, parentLine, parentCol, diagnostics);
|
|
208
|
+
}
|
|
209
|
+
break;
|
|
210
|
+
}
|
|
211
|
+
case 'element-access': {
|
|
212
|
+
scanExpression(expr.object, boardConstants, parentLine, parentCol, diagnostics);
|
|
213
|
+
scanExpression(expr.index, boardConstants, parentLine, parentCol, diagnostics);
|
|
214
|
+
break;
|
|
215
|
+
}
|
|
216
|
+
case 'string_concat': {
|
|
217
|
+
for (const part of expr.parts) {
|
|
218
|
+
scanExpression(part, boardConstants, parentLine, parentCol, diagnostics);
|
|
219
|
+
}
|
|
220
|
+
break;
|
|
221
|
+
}
|
|
222
|
+
case 'template_string': {
|
|
223
|
+
scanExpression(expr.expression, boardConstants, parentLine, parentCol, diagnostics);
|
|
224
|
+
break;
|
|
225
|
+
}
|
|
226
|
+
case 'spread_array': {
|
|
227
|
+
scanExpression(expr.spreadExpr, boardConstants, parentLine, parentCol, diagnostics);
|
|
228
|
+
for (const el of expr.additionalElements) {
|
|
229
|
+
scanExpression(el, boardConstants, parentLine, parentCol, diagnostics);
|
|
230
|
+
}
|
|
231
|
+
break;
|
|
232
|
+
}
|
|
233
|
+
case 'instanceof': {
|
|
234
|
+
scanExpression(expr.object, boardConstants, parentLine, parentCol, diagnostics);
|
|
235
|
+
break;
|
|
236
|
+
}
|
|
237
|
+
case 'await': {
|
|
238
|
+
scanExpression(expr.value, boardConstants, parentLine, parentCol, diagnostics);
|
|
239
|
+
break;
|
|
240
|
+
}
|
|
241
|
+
case 'hal-expr': {
|
|
242
|
+
// Expression-form HAL operation (e.g. adc.read used as a value).
|
|
243
|
+
checkCapability(expr.operation, parentLine, parentCol, boardConstants, diagnostics);
|
|
244
|
+
break;
|
|
245
|
+
}
|
|
246
|
+
case 'number':
|
|
247
|
+
case 'string':
|
|
248
|
+
case 'boolean':
|
|
249
|
+
case 'identifier':
|
|
250
|
+
case 'raw':
|
|
251
|
+
case 'tuple-access':
|
|
252
|
+
break;
|
|
253
|
+
default:
|
|
254
|
+
assertNever(expr);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
function scanStatement(stmt, boardConstants, diagnostics) {
|
|
258
|
+
if (!stmt || typeof stmt !== 'object')
|
|
259
|
+
return;
|
|
260
|
+
const line = stmt.sourceSpan?.startLine;
|
|
261
|
+
const col = stmt.sourceSpan?.startColumn;
|
|
262
|
+
switch (stmt.kind) {
|
|
263
|
+
case 'var_decl': {
|
|
264
|
+
if (stmt.initializer)
|
|
265
|
+
scanExpression(stmt.initializer, boardConstants, line, col, diagnostics);
|
|
266
|
+
break;
|
|
267
|
+
}
|
|
268
|
+
case 'assign': {
|
|
269
|
+
if (stmt.value)
|
|
270
|
+
scanExpression(stmt.value, boardConstants, line, col, diagnostics);
|
|
271
|
+
break;
|
|
272
|
+
}
|
|
273
|
+
case 'if': {
|
|
274
|
+
if (stmt.condition)
|
|
275
|
+
scanExpression(stmt.condition, boardConstants, line, col, diagnostics);
|
|
276
|
+
for (const s of stmt.thenBranch)
|
|
277
|
+
scanStatement(s, boardConstants, diagnostics);
|
|
278
|
+
if (stmt.elseBranch)
|
|
279
|
+
for (const s of stmt.elseBranch)
|
|
280
|
+
scanStatement(s, boardConstants, diagnostics);
|
|
281
|
+
break;
|
|
282
|
+
}
|
|
283
|
+
case 'while':
|
|
284
|
+
case 'do_while': {
|
|
285
|
+
if (stmt.condition)
|
|
286
|
+
scanExpression(stmt.condition, boardConstants, line, col, diagnostics);
|
|
287
|
+
for (const s of stmt.body)
|
|
288
|
+
scanStatement(s, boardConstants, diagnostics);
|
|
289
|
+
break;
|
|
290
|
+
}
|
|
291
|
+
case 'for': {
|
|
292
|
+
if (stmt.condition)
|
|
293
|
+
scanExpression(stmt.condition, boardConstants, line, col, diagnostics);
|
|
294
|
+
if (stmt.initializer)
|
|
295
|
+
scanStatement(stmt.initializer, boardConstants, diagnostics);
|
|
296
|
+
if (stmt.increment)
|
|
297
|
+
scanStatement(stmt.increment, boardConstants, diagnostics);
|
|
298
|
+
for (const s of stmt.body)
|
|
299
|
+
scanStatement(s, boardConstants, diagnostics);
|
|
300
|
+
break;
|
|
301
|
+
}
|
|
302
|
+
case 'for_of':
|
|
303
|
+
case 'for_in': {
|
|
304
|
+
if (stmt.variable)
|
|
305
|
+
scanStatement(stmt.variable, boardConstants, diagnostics);
|
|
306
|
+
for (const s of stmt.body)
|
|
307
|
+
scanStatement(s, boardConstants, diagnostics);
|
|
308
|
+
break;
|
|
309
|
+
}
|
|
310
|
+
case 'return': {
|
|
311
|
+
if (stmt.value)
|
|
312
|
+
scanExpression(stmt.value, boardConstants, line, col, diagnostics);
|
|
313
|
+
break;
|
|
314
|
+
}
|
|
315
|
+
case 'call': {
|
|
316
|
+
for (const arg of stmt.args) {
|
|
317
|
+
scanExpression(arg, boardConstants, line, col, diagnostics);
|
|
318
|
+
}
|
|
319
|
+
break;
|
|
320
|
+
}
|
|
321
|
+
case 'hal-op': {
|
|
322
|
+
// Statement-form HAL operation — the primary capability check target.
|
|
323
|
+
checkCapability(stmt.operation, line, col, boardConstants, diagnostics);
|
|
324
|
+
break;
|
|
325
|
+
}
|
|
326
|
+
case 'switch': {
|
|
327
|
+
if (stmt.expression)
|
|
328
|
+
scanExpression(stmt.expression, boardConstants, line, col, diagnostics);
|
|
329
|
+
for (const c of stmt.cases) {
|
|
330
|
+
for (const s of c.body)
|
|
331
|
+
scanStatement(s, boardConstants, diagnostics);
|
|
332
|
+
}
|
|
333
|
+
break;
|
|
334
|
+
}
|
|
335
|
+
case 'block': {
|
|
336
|
+
for (const s of stmt.body)
|
|
337
|
+
scanStatement(s, boardConstants, diagnostics);
|
|
338
|
+
break;
|
|
339
|
+
}
|
|
340
|
+
case 'labeled': {
|
|
341
|
+
for (const s of stmt.body)
|
|
342
|
+
scanStatement(s, boardConstants, diagnostics);
|
|
343
|
+
break;
|
|
344
|
+
}
|
|
345
|
+
case 'try': {
|
|
346
|
+
for (const s of stmt.tryBlock)
|
|
347
|
+
scanStatement(s, boardConstants, diagnostics);
|
|
348
|
+
if (stmt.catchBlock)
|
|
349
|
+
for (const s of stmt.catchBlock)
|
|
350
|
+
scanStatement(s, boardConstants, diagnostics);
|
|
351
|
+
if (stmt.finallyBlock)
|
|
352
|
+
for (const s of stmt.finallyBlock)
|
|
353
|
+
scanStatement(s, boardConstants, diagnostics);
|
|
354
|
+
break;
|
|
355
|
+
}
|
|
356
|
+
case 'throw': {
|
|
357
|
+
if (stmt.value)
|
|
358
|
+
scanExpression(stmt.value, boardConstants, line, col, diagnostics);
|
|
359
|
+
break;
|
|
360
|
+
}
|
|
361
|
+
case 'update':
|
|
362
|
+
case 'break':
|
|
363
|
+
case 'continue':
|
|
364
|
+
case 'yield':
|
|
365
|
+
case 'super_call':
|
|
366
|
+
break;
|
|
367
|
+
default:
|
|
368
|
+
assertNever(stmt);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
// ---------------------------------------------------------------------------
|
|
372
|
+
// Public API
|
|
373
|
+
// ---------------------------------------------------------------------------
|
|
374
|
+
/**
|
|
375
|
+
* Validate that capability-specific methods are only called on pins that support them.
|
|
376
|
+
*/
|
|
377
|
+
export function validatePinCapabilities(program) {
|
|
378
|
+
const diagnostics = [];
|
|
379
|
+
const boardConstants = program.boardConstants;
|
|
380
|
+
if (program.topLevelStatements) {
|
|
381
|
+
for (const stmt of program.topLevelStatements) {
|
|
382
|
+
scanStatement(stmt, boardConstants, diagnostics);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
if (program.functions) {
|
|
386
|
+
for (const fn of program.functions) {
|
|
387
|
+
if (fn.statements) {
|
|
388
|
+
for (const stmt of fn.statements) {
|
|
389
|
+
scanStatement(stmt, boardConstants, diagnostics);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
if (program.classes) {
|
|
395
|
+
for (const cls of program.classes) {
|
|
396
|
+
if (cls.methods) {
|
|
397
|
+
for (const method of cls.methods) {
|
|
398
|
+
if (method.statements) {
|
|
399
|
+
for (const stmt of method.statements) {
|
|
400
|
+
scanStatement(stmt, boardConstants, diagnostics);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
if (cls.constructor?.statements) {
|
|
406
|
+
for (const stmt of cls.constructor.statements) {
|
|
407
|
+
scanStatement(stmt, boardConstants, diagnostics);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
return diagnostics;
|
|
413
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ProgramIR } from '../api/index.js';
|
|
2
|
+
import type { Diagnostic } from '../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Validate that GPIO I/O operations are preceded by mode configuration.
|
|
5
|
+
*
|
|
6
|
+
* - Read without prior mode → **warning** (undefined behavior on floating pin)
|
|
7
|
+
* - Write without prior mode → **info** (Arduino implicitly sets OUTPUT, but
|
|
8
|
+
* explicit configuration is recommended)
|
|
9
|
+
*/
|
|
10
|
+
export declare function validatePinModeConfig(program: ProgramIR): Diagnostic[];
|