@typecad/cuttlefish 1.0.0-alpha.13 → 1.0.0-alpha.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +82 -79
- package/assets/editor-extensions/typecad-debug/README.md +141 -0
- package/assets/editor-extensions/typecad-debug/out/extension.js +347 -0
- package/assets/editor-extensions/typecad-debug/out/extension.js.map +1 -0
- package/assets/editor-extensions/typecad-debug/package.json +76 -0
- package/assets/editor-extensions/typecad-ui/LICENSE +27 -0
- package/assets/editor-extensions/typecad-ui/README.md +52 -0
- package/assets/editor-extensions/typecad-ui/file-icon-dark.png +0 -0
- package/assets/editor-extensions/typecad-ui/file-icon-light.png +0 -0
- package/assets/editor-extensions/typecad-ui/icon.png +0 -0
- package/assets/editor-extensions/typecad-ui/language-configuration.json +43 -0
- package/assets/editor-extensions/typecad-ui/package.json +54 -0
- package/assets/editor-extensions/typecad-ui/snippets/typecad-ui.json +80 -0
- package/assets/editor-extensions/typecad-ui/syntaxes/markdown-ui.json +45 -0
- package/assets/editor-extensions/typecad-ui/syntaxes/typecad-ui.tmLanguage.json +1269 -0
- package/dist/api/config.d.ts +30 -27
- package/dist/api/schema/types.d.ts +20 -3
- package/dist/api/shared/async-runtime-static.d.ts +1 -1
- package/dist/api/shared/async-runtime-static.js +5 -5
- package/dist/api/shared/async-types.d.ts +3 -2
- package/dist/api/shared/board-catalog.d.ts +2 -0
- package/dist/api/shared/board-catalog.js +6 -0
- package/dist/api/shared/board-resolver.d.ts +4 -7
- package/dist/api/shared/board-resolver.js +2 -1
- package/dist/api/shared/coop-scheduler.d.ts +1 -1
- package/dist/api/shared/coop-scheduler.js +1 -1
- package/dist/api/shared/cpp-type-ir.d.ts +1 -1
- package/dist/api/shared/cpp-type-ir.js +1 -1
- package/dist/api/shared/display-profile.d.ts +1 -1
- package/dist/api/shared/display-profile.js +3 -5
- package/dist/api/shared/framework-manifest-registry.d.ts +1 -1
- package/dist/api/shared/framework-manifest-registry.js +0 -1
- package/dist/api/shared/framework-manifest.d.ts +65 -507
- package/dist/api/shared/framework-manifest.js +6 -11
- package/dist/api/shared/hal-op-ir.d.ts +294 -685
- package/dist/api/shared/hal-op-ir.js +31 -65
- package/dist/api/shared/index.d.ts +0 -4
- package/dist/api/shared/index.js +1 -7
- package/dist/api/shared/ir-core.d.ts +6 -0
- package/dist/api/shared/ir-declarations.d.ts +4 -0
- package/dist/api/shared/ir.d.ts +1 -3
- package/dist/api/shared/platform-strategy.d.ts +14 -37
- package/dist/api/shared/polyfill-helper-registry.js +0 -5
- package/dist/api/shared/polyfill-types.js +0 -27
- package/dist/api/shared/promise-runtime.js +3 -3
- package/dist/api/shared/spdx-licenses.d.ts +12 -10
- package/dist/api/shared/spdx-licenses.js +1 -1
- package/dist/api/shared/toolchain-types.d.ts +1 -1
- package/dist/api/shared/toolchain-types.js +3 -3
- package/dist/api/shared/types.d.ts +0 -3
- package/dist/api/shared/validate-framework-manifest.js +13 -33
- package/dist/board-catalog/dts-reader.d.ts +220 -0
- package/dist/board-catalog/dts-reader.js +1052 -0
- package/dist/board-catalog/index.d.ts +11 -0
- package/dist/board-catalog/index.js +12 -0
- package/dist/board-catalog/pinconfig.d.ts +48 -0
- package/dist/board-catalog/pinconfig.js +263 -0
- package/dist/board-catalog/sdk.d.ts +82 -0
- package/dist/board-catalog/sdk.js +180 -0
- package/dist/board-catalog/store.d.ts +196 -0
- package/dist/board-catalog/store.js +363 -0
- package/dist/board-catalog/types.d.ts +233 -0
- package/dist/board-catalog/types.js +7 -0
- package/dist/board-catalog/walker.d.ts +112 -0
- package/dist/board-catalog/walker.js +1101 -0
- package/dist/cli-utils.d.ts +2 -2
- package/dist/cli-utils.js +5 -5
- package/dist/cli.js +227 -244
- package/dist/config-loader.d.ts +14 -19
- package/dist/config-loader.js +242 -78
- package/dist/config-schema.d.ts +19 -227
- package/dist/config-schema.js +9 -8
- package/dist/contract/board-generator.d.ts +4 -4
- package/dist/contract/board-generator.js +16 -5
- package/dist/contract/contract-parser.d.ts +36 -127
- package/dist/contract/contract-parser.js +76 -0
- package/dist/contract/index.d.ts +1 -1
- package/dist/contract/index.js +70 -21
- package/dist/create/active-board-catalog.d.ts +9 -0
- package/dist/create/active-board-catalog.js +94 -0
- package/dist/create/board-catalog.generated.d.ts +96 -0
- package/dist/create/board-catalog.generated.js +128737 -0
- package/dist/create/board-search.d.ts +23 -0
- package/dist/create/board-search.js +88 -0
- package/dist/create/editor-integration.d.ts +32 -0
- package/dist/create/editor-integration.js +257 -0
- package/dist/create/eslint-rules-template.d.ts +2 -2
- package/dist/create/framework-catalog.d.ts +48 -8
- package/dist/create/framework-catalog.js +58 -44
- package/dist/create/index.d.ts +8 -13
- package/dist/create/index.js +5 -9
- package/dist/create/mcu-target.d.ts +39 -0
- package/dist/create/mcu-target.js +80 -0
- package/dist/create/pack-targets.d.ts +19 -0
- package/dist/create/pack-targets.js +56 -0
- package/dist/create/{init-scaffold.d.ts → scaffold.d.ts} +8 -11
- package/dist/create/{init-scaffold.js → scaffold.js} +28 -87
- package/dist/create/templates.d.ts +51 -0
- package/dist/create/{init-templates.js → templates.js} +135 -116
- package/dist/create/wizard.d.ts +19 -0
- package/dist/create/wizard.js +314 -0
- package/dist/debug/preprocessor.d.ts +5 -0
- package/dist/debug/preprocessor.js +31 -7
- package/dist/diagnostics/diagnostics-report.d.ts +1 -1
- package/dist/diagnostics/diagnostics-report.js +3 -11
- package/dist/diagnostics/json-schema.d.ts +1 -1
- package/dist/diagnostics/md-writer.js +2 -2
- package/dist/diagnostics/mermaid-builder.d.ts +1 -1
- package/dist/diagnostics/mermaid-builder.js +1 -1
- package/dist/emit/cpp-emitter.js +4 -1
- package/dist/emit/emitters/class-emitter.js +32 -4
- package/dist/emit/emitters/emitter-context.d.ts +11 -0
- package/dist/emit/emitters/entrypoint-synthesizer.js +1 -1
- package/dist/emit/emitters/function-emitter-impl.js +33 -17
- package/dist/emit/emitters/output-finalizer.d.ts +7 -0
- package/dist/emit/emitters/output-finalizer.js +31 -23
- package/dist/emit/emitters/setup.js +147 -63
- package/dist/emit/emitters/top-level-prep.js +1 -1
- package/dist/emit/emitters/type-decl-emitter.js +13 -8
- package/dist/emit/emitters/ui-emitter.js +1 -1
- package/dist/emit/expression-renderer.d.ts +3 -3
- package/dist/emit/expression-renderer.js +17 -7
- package/dist/emit/route-hal-op.js +17 -48
- package/dist/emit/snprintf-helpers.d.ts +1 -3
- package/dist/emit/snprintf-helpers.js +1 -39
- package/dist/emit/statement-renderer.d.ts +0 -4
- package/dist/emit/statement-renderer.js +54 -45
- package/dist/emit/utils/async-state-machine.d.ts +16 -9
- package/dist/emit/utils/async-state-machine.js +56 -54
- package/dist/emit/utils/comment-helpers.d.ts +0 -8
- package/dist/emit/utils/comment-helpers.js +1 -1
- package/dist/emit/utils/cpp-helpers.d.ts +2 -2
- package/dist/emit/utils/cpp-helpers.js +2 -2
- package/dist/emit/utils/hal-op-cpp-type.js +4 -6
- package/dist/emit/utils/index.d.ts +3 -3
- package/dist/emit/utils/index.js +3 -3
- package/dist/emit/utils/type-inference.d.ts +1 -29
- package/dist/emit/utils/type-inference.js +0 -75
- package/dist/framework-package.d.ts +3 -0
- package/dist/framework-package.js +23 -6
- package/dist/framework-registry.d.ts +5 -5
- package/dist/frameworks/native/graphics/terminal-preview.d.ts +5 -0
- package/dist/frameworks/native/graphics/terminal-preview.js +33 -0
- package/dist/frameworks/native/index.d.ts +3 -0
- package/dist/frameworks/native/index.js +15 -0
- package/dist/frameworks/native/native-compile.d.ts +17 -0
- package/dist/frameworks/native/native-compile.js +170 -0
- package/dist/frameworks/native/native-config.d.ts +41 -0
- package/dist/frameworks/native/native-config.js +7 -0
- package/dist/frameworks/native/strategy.d.ts +97 -0
- package/dist/frameworks/native/strategy.js +664 -0
- package/dist/ir/board-resolver.d.ts +18 -23
- package/dist/ir/board-resolver.js +43 -401
- package/dist/ir/build-ir-state.d.ts +3 -0
- package/dist/ir/build-ir-state.js +42 -0
- package/dist/ir/build-ir.d.ts +1 -1
- package/dist/ir/build-ir.js +64 -45
- package/dist/ir/declaration-builders.js +1 -0
- package/dist/ir/expression-to-ir.js +17 -10
- package/dist/ir/hal/hal-emitter.d.ts +0 -2
- package/dist/ir/hal/hal-emitter.js +92 -41
- package/dist/ir/hal/hal-parser.d.ts +5 -5
- package/dist/ir/hal/hal-parser.js +128 -36
- package/dist/ir/hal/hal-plugins.d.ts +0 -1
- package/dist/ir/hal/hal-plugins.js +425 -716
- package/dist/ir/heap-analysis.js +2 -41
- package/dist/ir/identifier-collector.js +32 -20
- package/dist/ir/network-validation.js +7 -11
- package/dist/ir/ownership-analysis.js +75 -13
- package/dist/ir/peripheral-usage.d.ts +8 -2
- package/dist/ir/peripheral-usage.js +78 -149
- package/dist/ir/peripheral-validation.js +23 -3
- package/dist/ir/pin-capability-validation.d.ts +12 -0
- package/dist/ir/pin-capability-validation.js +61 -97
- package/dist/ir/pin-mode-validation.js +5 -5
- package/dist/ir/program-analysis.d.ts +8 -15
- package/dist/ir/program-analysis.js +140 -323
- package/dist/ir/pulldown-validation.js +11 -4
- package/dist/ir/resource-analysis.js +15 -3
- package/dist/ir/statement-to-ir.js +0 -6
- package/dist/ir/timing-validation.js +1 -1
- package/dist/ir/transformers/array-methods.js +11 -5
- package/dist/ir/transformers/call-statement.js +20 -87
- package/dist/ir/transformers/callback-context-registry.d.ts +1 -1
- package/dist/ir/transformers/callback-context-registry.js +8 -16
- package/dist/ir/transformers/control-flow.js +0 -13
- package/dist/ir/transformers/expressions.js +10 -9
- package/dist/ir/transformers/hal-call-resolver.d.ts +2 -2
- package/dist/ir/transformers/hal-call-resolver.js +24 -10
- package/dist/ir/transformers/hal-emit-helpers.d.ts +2 -2
- package/dist/ir/transformers/hal-emit-helpers.js +2 -2
- package/dist/ir/transformers/namespace-methods.js +1 -1
- package/dist/ir/transformers/ui-callback-lowering.d.ts +0 -2
- package/dist/ir/transformers/ui-callback-lowering.js +0 -24
- package/dist/ir/transformers/variables.js +338 -42
- package/dist/ir/try-catch-validation.js +4 -3
- package/dist/ir/type-resolution.js +15 -4
- package/dist/ir/validation-orchestrator.js +0 -9
- package/dist/libdef/cpp-to-decl.d.ts +0 -9
- package/dist/libdef/cpp-to-decl.js +0 -72
- package/dist/libdef/registry.d.ts +0 -1
- package/dist/libdef/registry.js +1 -24
- package/dist/library/catalog.d.ts +35 -0
- package/dist/library/catalog.js +67 -0
- package/dist/library/cli.d.ts +2 -0
- package/dist/library/cli.js +168 -0
- package/dist/library/init.d.ts +25 -0
- package/dist/library/init.js +397 -0
- package/dist/library/install.d.ts +9 -0
- package/dist/library/install.js +80 -0
- package/dist/library/registry-search.d.ts +34 -0
- package/dist/library/registry-search.js +50 -0
- package/dist/library/validate.d.ts +17 -0
- package/dist/library/validate.js +175 -0
- package/dist/library-packages.d.ts +95 -0
- package/dist/library-packages.js +275 -0
- package/dist/mapping/peripheral-names.js +9 -4
- package/dist/mapping/source-map.d.ts +3 -4
- package/dist/mapping/source-map.js +12 -18
- package/dist/orchestrator/graph-builder.d.ts +3 -3
- package/dist/orchestrator/graph-builder.js +29 -12
- package/dist/orchestrator/type-checker.d.ts +3 -3
- package/dist/orchestrator/type-checker.js +3 -3
- package/dist/platform/async-runtime.js +1 -1
- package/dist/platform/coop-scheduler-runtime.js +2 -2
- package/dist/platform/generic-debug-codegen.d.ts +36 -0
- package/dist/platform/generic-debug-codegen.js +185 -0
- package/dist/platform/generic-strategy.d.ts +3 -4
- package/dist/platform/generic-strategy.js +5 -80
- package/dist/platform/index.js +1 -1
- package/dist/platform/registry.d.ts +2 -2
- package/dist/platform/registry.js +2 -2
- package/dist/preview/client.js +17 -3
- package/dist/safety/asil-decorators.d.ts +32 -0
- package/dist/safety/asil-decorators.js +32 -0
- package/dist/safety/authoring.d.ts +85 -0
- package/dist/safety/authoring.js +61 -0
- package/dist/safety/engine.d.ts +3 -0
- package/dist/safety/engine.js +83 -0
- package/dist/safety/hal/ops.d.ts +48 -0
- package/dist/safety/hal/ops.js +46 -0
- package/dist/safety/iso26262/analyze.d.ts +13 -0
- package/dist/safety/iso26262/analyze.js +29 -0
- package/dist/safety/iso26262/asil.d.ts +10 -0
- package/dist/safety/iso26262/asil.js +22 -0
- package/dist/safety/iso26262/collect.d.ts +14 -0
- package/dist/safety/iso26262/collect.js +137 -0
- package/dist/safety/iso26262/goto-checker.d.ts +10 -0
- package/dist/safety/iso26262/goto-checker.js +72 -0
- package/dist/safety/iso26262/heap-checker.d.ts +7 -0
- package/dist/safety/iso26262/heap-checker.js +57 -0
- package/dist/safety/iso26262/init-checker.d.ts +13 -0
- package/dist/safety/iso26262/init-checker.js +127 -0
- package/dist/safety/iso26262/loop-checker.d.ts +7 -0
- package/dist/safety/iso26262/loop-checker.js +86 -0
- package/dist/safety/iso26262/recursion-checker.d.ts +9 -0
- package/dist/safety/iso26262/recursion-checker.js +134 -0
- package/dist/safety/iso26262/sidecar-writer.d.ts +25 -0
- package/dist/safety/iso26262/sidecar-writer.js +13 -0
- package/dist/safety/passes/pinMode-intercept.d.ts +3 -0
- package/dist/safety/passes/pinMode-intercept.js +60 -0
- package/dist/safety/runtime/mode-table.d.ts +5 -0
- package/dist/safety/runtime/mode-table.js +55 -0
- package/dist/safety/runtime/polyfills.d.ts +6 -0
- package/dist/safety/runtime/polyfills.js +12 -0
- package/dist/safety/runtime/result-struct.d.ts +11 -0
- package/dist/safety/runtime/result-struct.js +98 -0
- package/dist/safety/runtime/safe-int.d.ts +33 -0
- package/dist/safety/runtime/safe-int.js +170 -0
- package/dist/safety/runtime/safe-traits.d.ts +4 -0
- package/dist/safety/runtime/safe-traits.js +95 -0
- package/dist/safety/runtime/safe-variable.d.ts +39 -0
- package/dist/safety/runtime/safe-variable.js +226 -0
- package/dist/safety/runtime/vote.d.ts +8 -0
- package/dist/safety/runtime/vote.js +92 -0
- package/dist/safety/runtime/write-verify.d.ts +8 -0
- package/dist/safety/runtime/write-verify.js +71 -0
- package/dist/safety/safe-int-types.d.ts +45 -0
- package/dist/safety/safe-int-types.js +25 -0
- package/dist/safety/safe-variable-types.d.ts +29 -0
- package/dist/safety/safe-variable-types.js +19 -0
- package/dist/safety/safety-bridge.d.ts +5 -6
- package/dist/safety/safety-bridge.js +15 -28
- package/dist/safety/sidecar-bridge.d.ts +1 -3
- package/dist/safety/sidecar-bridge.js +3 -20
- package/dist/safety/specifiers.d.ts +6 -0
- package/dist/safety/specifiers.js +14 -0
- package/dist/safety-hook.d.ts +8 -7
- package/dist/safety-hook.js +12 -13
- package/dist/testing.d.ts +5 -6
- package/dist/testing.js +5 -5
- package/dist/transpile/resolution.d.ts +1 -1
- package/dist/transpile/resolution.js +18 -9
- package/dist/transpile/test-pins.d.ts +18 -0
- package/dist/transpile/test-pins.js +142 -0
- package/dist/transpile.d.ts +1 -2
- package/dist/transpile.js +90 -29
- package/dist/types.d.ts +45 -26
- package/dist/ui-hook.d.ts +1 -1
- package/dist/utils/cli.d.ts +2 -2
- package/dist/utils/cli.js +160 -157
- package/dist/utils/fs.d.ts +3 -4
- package/dist/utils/fs.js +4 -5
- package/dist/utils/strings.d.ts +0 -1
- package/dist/utils/strings.js +0 -8
- package/dist/utils/ui.d.ts +5 -2
- package/dist/utils/ui.js +13 -3
- package/package.json +158 -149
- package/dist/add-preset.d.ts +0 -4
- package/dist/add-preset.js +0 -74
- package/dist/api/shared/async-symbol-detector.d.ts +0 -11
- package/dist/api/shared/async-symbol-detector.js +0 -140
- package/dist/api/shared/native-display-op-resolver.d.ts +0 -10
- package/dist/api/shared/native-display-op-resolver.js +0 -64
- package/dist/create/board-checklist.d.ts +0 -2
- package/dist/create/board-checklist.js +0 -52
- package/dist/create/board-codegen.d.ts +0 -9
- package/dist/create/board-codegen.js +0 -238
- package/dist/create/board-generators.d.ts +0 -12
- package/dist/create/board-generators.js +0 -651
- package/dist/create/board-spec.d.ts +0 -637
- package/dist/create/board-spec.js +0 -214
- package/dist/create/init-templates.d.ts +0 -28
- package/dist/create/init-wizard.d.ts +0 -8
- package/dist/create/init-wizard.js +0 -182
- package/dist/install/framework-catalog.d.ts +0 -53
- package/dist/install/framework-catalog.js +0 -107
- package/dist/install/handle-install.d.ts +0 -35
- package/dist/install/handle-install.js +0 -177
- package/dist/install/index.d.ts +0 -4
- package/dist/install/index.js +0 -3
- package/dist/ir/pin-state-tracking.d.ts +0 -58
- package/dist/ir/pin-state-tracking.js +0 -182
- package/dist/ir/pwm-timer-sharing.d.ts +0 -4
- package/dist/ir/pwm-timer-sharing.js +0 -94
- package/dist/ir/timer0-pwm-timing-conflict.d.ts +0 -4
- package/dist/ir/timer0-pwm-timing-conflict.js +0 -72
- package/dist/libdef/component-decls.d.ts +0 -2
- package/dist/libdef/component-decls.js +0 -6
- package/dist/libdef/component-discovery.d.ts +0 -43
- package/dist/libdef/component-discovery.js +0 -83
- package/dist/theme-tokens.d.ts +0 -22
- package/dist/theme-tokens.js +0 -172
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
// Checks that pins configured with inputPullDown() actually support
|
|
5
5
|
// hardware pulldown on the target board. Emits a compile-time error if not.
|
|
6
6
|
// ---------------------------------------------------------------------------
|
|
7
|
+
import { pinEntryIndexForNumber } from './pin-capability-validation.js';
|
|
7
8
|
/**
|
|
8
9
|
* Validate that pins used with inputPullDown() support pulldown on this board.
|
|
9
10
|
*/
|
|
@@ -13,9 +14,14 @@ export function validatePulldownSupport(usage, boardConstants, filePath) {
|
|
|
13
14
|
return diagnostics;
|
|
14
15
|
}
|
|
15
16
|
for (const pinNumber of usage.inputPulldownPins) {
|
|
16
|
-
// Check the pin's own pullDown capability from board definition
|
|
17
|
-
// undefined or false both mean pulldown is not supported on this pin
|
|
18
|
-
|
|
17
|
+
// Check the pin's own pullDown capability from board definition.
|
|
18
|
+
// undefined or false both mean pulldown is not supported on this pin.
|
|
19
|
+
// The entry is resolved by pin NUMBER — the pins.all array index diverges
|
|
20
|
+
// from the number on MCUs with unbonded pads (see pinEntryIndexForNumber).
|
|
21
|
+
const entryIdx = pinEntryIndexForNumber(pinNumber, boardConstants);
|
|
22
|
+
if (entryIdx < 0)
|
|
23
|
+
continue; // Unknown pin — the emitter's own resolution reports it.
|
|
24
|
+
const supportsPullDown = boardConstants?.get(`pins.all.${entryIdx}.capabilities.pullDown`);
|
|
19
25
|
if (supportsPullDown !== true) {
|
|
20
26
|
const pinName = getPinName(pinNumber, boardConstants);
|
|
21
27
|
const arch = boardConstants?.get('architecture');
|
|
@@ -39,7 +45,8 @@ function getPinName(pinNumber, boardConstants) {
|
|
|
39
45
|
return `A${pinNumber - 14}`;
|
|
40
46
|
return `D${pinNumber}`;
|
|
41
47
|
}
|
|
42
|
-
const
|
|
48
|
+
const entryIdx = pinEntryIndexForNumber(pinNumber, boardConstants);
|
|
49
|
+
const name = entryIdx >= 0 ? boardConstants.get(`pins.all.${entryIdx}.name`) : undefined;
|
|
43
50
|
if (typeof name === 'string')
|
|
44
51
|
return name;
|
|
45
52
|
// Fallback naming
|
|
@@ -125,10 +125,22 @@ function isPinUsedAsGpio(pinName, pinNumber, usage) {
|
|
|
125
125
|
return false;
|
|
126
126
|
}
|
|
127
127
|
function isPeripheralActive(type, instance, usage) {
|
|
128
|
+
// When the program's ops identify WHICH controller instances are used, only
|
|
129
|
+
// those instances claim pins. The old `usage.i2c || ...` disjunct claimed
|
|
130
|
+
// every instance's pins whenever the bus type appeared at all — on boards
|
|
131
|
+
// whose alternate-bus pin sets overlap another bus's (the blackpill's
|
|
132
|
+
// i2c-alt on PB3/PB4 shares pins with spi2), that manufactured phantom
|
|
133
|
+
// peripheral-peripheral conflicts. The bare-type fallback only applies when
|
|
134
|
+
// NO instance information was recorded (degenerate programs whose ops carry
|
|
135
|
+
// no instance), preserving the conservative claim where it's the only
|
|
136
|
+
// signal available.
|
|
128
137
|
switch (type) {
|
|
129
|
-
case 'i2c':
|
|
130
|
-
|
|
131
|
-
case '
|
|
138
|
+
case 'i2c':
|
|
139
|
+
return usage.i2cInstancesUsed.size > 0 ? usage.i2cInstancesUsed.has(instance) : usage.i2c;
|
|
140
|
+
case 'spi':
|
|
141
|
+
return usage.spiInstancesUsed.size > 0 ? usage.spiInstancesUsed.has(instance) : usage.spi;
|
|
142
|
+
case 'uart':
|
|
143
|
+
return usage.uartInstancesUsed.size > 0 ? usage.uartInstancesUsed.has(instance) : usage.uart;
|
|
132
144
|
default: return false;
|
|
133
145
|
}
|
|
134
146
|
}
|
|
@@ -3,7 +3,6 @@ import { isStringEnum } from "../api/shared/index.js";
|
|
|
3
3
|
import { extractNodeComments, makeDiagnostic, makeSourceSpan } from "./ast-node-utils.js";
|
|
4
4
|
import { isCompileTimeOnlyCallName, isCompileTimeOnlyClassName } from "./compile-time-only.js";
|
|
5
5
|
import { TYPED_ARRAY_ELEMENT_MAP, hoistedNestedEnums, hoistedNestedInterfaces, hoistedNestedTypeAliases, nestedFunctionAliases, nestedClassAliases, mutableArrayVars, arrayLiteralSizes, activeEnumNames, activeStringEnumNames, resetFunctionScopeState } from "./build-ir-state.js";
|
|
6
|
-
import { isPinFoldingEnabled, setPinFoldingEnabled, invalidatePinLevels } from "./pin-state-tracking.js";
|
|
7
6
|
import { getCurrentIrTypeScope, bindIrTypeScopeLocals } from "./symbol-types.js";
|
|
8
7
|
import { renderExprAsText } from "./render-expr.js";
|
|
9
8
|
import { expressionToIR } from "./expression-to-ir.js";
|
|
@@ -184,9 +183,6 @@ export function lowerStatementList(statements, fileName, sourceText, diagnostics
|
|
|
184
183
|
// top-level levels afterwards. "" and "<top-level>" are the top-level
|
|
185
184
|
// markers; everything else names a function/method/lambda body.
|
|
186
185
|
const isFunctionBodyCtx = functionNameForDiagnostics !== "" && functionNameForDiagnostics !== "<top-level>";
|
|
187
|
-
const prevPinFolding = isPinFoldingEnabled();
|
|
188
|
-
if (isFunctionBodyCtx)
|
|
189
|
-
setPinFoldingEnabled(false);
|
|
190
186
|
// Phase 1: Pre-scan for nested function declarations — register aliases only.
|
|
191
187
|
// This ensures sibling functions can reference each other.
|
|
192
188
|
for (const statement of statements) {
|
|
@@ -356,8 +352,6 @@ export function lowerStatementList(statements, fileName, sourceText, diagnostics
|
|
|
356
352
|
nestedClassAliases.delete(name);
|
|
357
353
|
}
|
|
358
354
|
if (isFunctionBodyCtx) {
|
|
359
|
-
setPinFoldingEnabled(prevPinFolding);
|
|
360
|
-
invalidatePinLevels();
|
|
361
355
|
}
|
|
362
356
|
return lowered;
|
|
363
357
|
}
|
|
@@ -87,7 +87,7 @@ export function validateBlockingDelayInLoop(program, strategy) {
|
|
|
87
87
|
? `Blocking delayMicroseconds() inside loop() is a busy-wait that wastes CPU cycles. ` +
|
|
88
88
|
`On RTOS targets (ESP-IDF), prefer timing.delay() (vTaskDelay) which yields the CPU to other tasks.`
|
|
89
89
|
: `Blocking delay() inside loop() freezes the async microtask queue and UI rendering ` +
|
|
90
|
-
`for the delay duration. This causes display tearing and makes the
|
|
90
|
+
`for the delay duration. This causes display tearing and makes the program unresponsive.`;
|
|
91
91
|
const hint = isRtos
|
|
92
92
|
? `Replace delayMicroseconds with delay() if the timing permits, or accept the brief busy-wait if sub-millisecond precision is required.`
|
|
93
93
|
: `Use the cooperative pattern instead: track elapsed time with millis() comparisons, ` +
|
|
@@ -229,9 +229,16 @@ export function tryLowerArrayAndStringMethods(expr, sourceText, diagnostics, poi
|
|
|
229
229
|
//
|
|
230
230
|
// Target gate: the __tc_* helpers are native/hosted-only (Arduino/embedded
|
|
231
231
|
// lower arrays to StaticArray, caught by the mutableArrayVars branch above,
|
|
232
|
-
// and have no __tc_* polyfills).
|
|
233
|
-
//
|
|
234
|
-
|
|
232
|
+
// and have no __tc_* polyfills). Two signals compose: the target has no
|
|
233
|
+
// repeatedly-called loop() (requiresLoopFunction() false — the historical
|
|
234
|
+
// proxy for "hosted"), AND it actually carries std::vector (getStdLibSupport
|
|
235
|
+
// ().hasVector). The second signal matters because a main()-entry RTOS
|
|
236
|
+
// target (Zephyr) also reports requiresLoopFunction()=false but lowers
|
|
237
|
+
// arrays to __tc_StaticArray — without the hasVector conjunct it would
|
|
238
|
+
// wrongly take the std::vector/.push_back path.
|
|
239
|
+
const strat = getContext().activeStrategy;
|
|
240
|
+
const isHostedTarget = !strat?.requiresLoopFunction()
|
|
241
|
+
&& (strat?.getStdLibSupport?.().hasVector ?? true);
|
|
235
242
|
if (isHostedTarget && ts.isPropertyAccessExpression(expr.expression)) {
|
|
236
243
|
const methodName = expr.expression.name.text;
|
|
237
244
|
// `push` lowers to native push_back (matches the old
|
|
@@ -403,8 +410,7 @@ function resolveReceiverCppType(receiverNode) {
|
|
|
403
410
|
*
|
|
404
411
|
* When the element type is integral and the arg is a numeric-enum value, wrap
|
|
405
412
|
* the rendered arg in `static_cast<int>(...)`. Demo #32 Finding A. Mirrors the
|
|
406
|
-
*
|
|
407
|
-
* in the emit layer.
|
|
413
|
+
* enum↔integral family fixed at the assign/var_decl sites in the emit layer.
|
|
408
414
|
*/
|
|
409
415
|
function renderPushArgForElement(argNode, receiverNode, sourceText, diagnostics, pointerVars) {
|
|
410
416
|
const rendered = renderExprAsText(expressionToIR(argNode, sourceText, diagnostics, pointerVars));
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import ts from "typescript";
|
|
2
|
-
import { requiredIncludes, mutableArrayVars, nestedClassAliases, hoistedNestedClasses, topLevelClassNames, topLevelClasses, activeEnumNames
|
|
2
|
+
import { requiredIncludes, mutableArrayVars, nestedClassAliases, hoistedNestedClasses, topLevelClassNames, topLevelClasses, activeEnumNames } from "../build-ir-state.js";
|
|
3
3
|
import { getCurrentIrTypeScope } from "../symbol-types.js";
|
|
4
|
-
import { extractNodeComments, makeSourceSpan } from "../ast-node-utils.js";
|
|
4
|
+
import { extractNodeComments, makeSourceSpan, makeDiagnostic } from "../ast-node-utils.js";
|
|
5
5
|
import { tryResolveHALMethod } from "./hal-call-resolver.js";
|
|
6
6
|
import { tryResolveUICall, isSignalName, resolveUIModuleImport, recordPressBinding, uiPressBindings, resolveNodeIndex, resolveNodeTag, watchPinSpecs, recordWatchPin, recordClickHandler, clickHandlers, pushUnknownElementDiagnostic } from "./ui-call-resolver.js";
|
|
7
7
|
import { hasSafetyHook, requireSafetyHook } from "../../safety-hook.js";
|
|
@@ -10,7 +10,6 @@ import { rewriteCanvasCall } from "./canvas-lowering.js";
|
|
|
10
10
|
import { callbackContextLabel, unsupportedStatementHint } from "./callback-context-registry.js";
|
|
11
11
|
import { tryLowerArrayAndStringMethods } from "./array-methods.js";
|
|
12
12
|
import { expressionToIR } from "../expression-to-ir.js";
|
|
13
|
-
import { lowerStatementList } from "../statement-to-ir.js";
|
|
14
13
|
import { escapeCppKeyword } from "../../utils/strings.js";
|
|
15
14
|
import { renderExprAsText, calleeToText } from "../render-expr.js";
|
|
16
15
|
import { parseCppType, renderCppType, parsedIsPointer, parsedIsMap, parsedIsSet } from "../../api/shared/cpp-type-ir.js";
|
|
@@ -163,14 +162,7 @@ function tryResolveSafetyCallStatement(call, fileName, sourceText) {
|
|
|
163
162
|
if (a.kind === ts.SyntaxKind.FalseKeyword)
|
|
164
163
|
return false;
|
|
165
164
|
if (ts.isIdentifier(a)) {
|
|
166
|
-
|
|
167
|
-
if (name === "INPUT")
|
|
168
|
-
return 0;
|
|
169
|
-
if (name === "OUTPUT")
|
|
170
|
-
return 1;
|
|
171
|
-
if (name === "INPUT_PULLUP")
|
|
172
|
-
return 2;
|
|
173
|
-
return name;
|
|
165
|
+
return a.text;
|
|
174
166
|
}
|
|
175
167
|
// Property access (e.g. r.value), arithmetic, or other expression:
|
|
176
168
|
// render to the C++ expression text so the op can emit it inline.
|
|
@@ -188,16 +180,23 @@ function tryResolveSafetyCallStatement(call, fileName, sourceText) {
|
|
|
188
180
|
}
|
|
189
181
|
export function callToStatement(statementNode, call, fileName, sourceText, diagnostics, pointerVars = new Map()) {
|
|
190
182
|
const comments = extractNodeComments(statementNode, sourceText);
|
|
191
|
-
// ──
|
|
192
|
-
// The
|
|
193
|
-
//
|
|
194
|
-
//
|
|
195
|
-
//
|
|
196
|
-
//
|
|
197
|
-
if (ts.
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
183
|
+
// ── console.* is not a supported API ────────────────────────────────────
|
|
184
|
+
// The TypeScript console carry-over (lowering to a platform print plus a
|
|
185
|
+
// config section routing it) is gone. Programs write to a serial console
|
|
186
|
+
// explicitly: USB0.writeLine(...) or UART0.writeLine(...). Sourced at IR
|
|
187
|
+
// build time so the diagnostic points at the user's statement and the
|
|
188
|
+
// real pipeline aborts before emit.
|
|
189
|
+
if (ts.isPropertyAccessExpression(call.expression) &&
|
|
190
|
+
ts.isIdentifier(call.expression.expression) &&
|
|
191
|
+
call.expression.expression.text === "console") {
|
|
192
|
+
diagnostics.push(makeDiagnostic(sourceText, call.getStart(), `console.${call.expression.name.text}() is not supported — write to a serial console instead: \`USB0.writeLine(...)\` (USB CDC) or \`UART0.writeLine(...)\` from the board module.`, "error", "console-unsupported"));
|
|
193
|
+
return {
|
|
194
|
+
kind: "block",
|
|
195
|
+
sourceSpan: makeSourceSpan(call, fileName, sourceText),
|
|
196
|
+
leadingComments: comments.leadingComments,
|
|
197
|
+
trailingComments: comments.trailingComments,
|
|
198
|
+
body: [],
|
|
199
|
+
};
|
|
201
200
|
}
|
|
202
201
|
// ── Ambient canvas ctx: rewrite ctx.method(...) while drawCanvas lowers ──
|
|
203
202
|
{
|
|
@@ -783,8 +782,6 @@ export function callToStatement(statementNode, call, fileName, sourceText, diagn
|
|
|
783
782
|
else {
|
|
784
783
|
calleeText = calleeToText(call.expression);
|
|
785
784
|
}
|
|
786
|
-
// Timer calls with arrow callbacks are intercepted before HAL (above);
|
|
787
|
-
// named-function callbacks fall through here unchanged.
|
|
788
785
|
return {
|
|
789
786
|
kind: "call",
|
|
790
787
|
sourceSpan: makeSourceSpan(call, fileName, sourceText),
|
|
@@ -794,70 +791,6 @@ export function callToStatement(statementNode, call, fileName, sourceText, diagn
|
|
|
794
791
|
args: call.arguments.map((arg) => expressionToIR(arg, sourceText, diagnostics, pointerVars)),
|
|
795
792
|
};
|
|
796
793
|
}
|
|
797
|
-
// ── setInterval/setTimeout arrow-callback hoisting ──────────────────────────
|
|
798
|
-
const TIMER_CALLEES = new Set(["setInterval", "setTimeout", "__tc_setInterval", "__tc_setTimeout"]);
|
|
799
|
-
let timerCallbackCounter = 0;
|
|
800
|
-
/**
|
|
801
|
-
* Hoist an inline arrow/function-expression callback argument of a
|
|
802
|
-
* setInterval/setTimeout call to a named free function, and return the
|
|
803
|
-
* rewritten call with the function name replacing the arrow.
|
|
804
|
-
*
|
|
805
|
-
* Returns null if arg[0] isn't an inline arrow/function (named-function
|
|
806
|
-
* callbacks pass through to the generic path unchanged).
|
|
807
|
-
*
|
|
808
|
-
* Called from the generic fallthrough at the end of callToStatement — NOT
|
|
809
|
-
* as an early return — because top-level timer calls reach the fallthrough
|
|
810
|
-
* path, not the early-interception points.
|
|
811
|
-
*/
|
|
812
|
-
function hoistTimerArrowArg(call, fileName, sourceText, diagnostics, pointerVars, comments) {
|
|
813
|
-
const callbackArg = call.arguments[0];
|
|
814
|
-
if (!callbackArg || !(ts.isArrowFunction(callbackArg) || ts.isFunctionExpression(callbackArg))) {
|
|
815
|
-
return null;
|
|
816
|
-
}
|
|
817
|
-
const fnName = `__tc_timer_cb_${timerCallbackCounter++}`;
|
|
818
|
-
const scope = getCurrentIrTypeScope();
|
|
819
|
-
const localVariableTypes = new Map();
|
|
820
|
-
if (scope) {
|
|
821
|
-
for (const [k, v] of scope.globals)
|
|
822
|
-
localVariableTypes.set(k, v);
|
|
823
|
-
}
|
|
824
|
-
const functionReturnTypes = new Map([...(getContext().activeFunctionReturnTypes ?? new Map())]);
|
|
825
|
-
const bodyStatements = lowerStatementList(ts.isBlock(callbackArg.body) ? callbackArg.body.statements : [], fileName, sourceText, diagnostics, functionReturnTypes, localVariableTypes, fnName, undefined, pointerVars);
|
|
826
|
-
if (!ts.isBlock(callbackArg.body)) {
|
|
827
|
-
const exprText = renderExprAsText(expressionToIR(callbackArg.body, sourceText, diagnostics));
|
|
828
|
-
bodyStatements.push({
|
|
829
|
-
kind: "call",
|
|
830
|
-
sourceSpan: makeSourceSpan(callbackArg.body, fileName, sourceText),
|
|
831
|
-
callee: "__EMIT__",
|
|
832
|
-
args: [{ kind: "string", value: exprText }],
|
|
833
|
-
});
|
|
834
|
-
}
|
|
835
|
-
hoistedNestedFunctions.push({
|
|
836
|
-
originalName: fnName,
|
|
837
|
-
isAsync: false,
|
|
838
|
-
returnType: "void",
|
|
839
|
-
sourceSpan: makeSourceSpan(callbackArg, fileName, sourceText),
|
|
840
|
-
leadingComments: [],
|
|
841
|
-
trailingComments: [],
|
|
842
|
-
parameters: [],
|
|
843
|
-
statements: bodyStatements,
|
|
844
|
-
});
|
|
845
|
-
// Apply the polyfill helper rename (setInterval → __tc_setInterval) so the
|
|
846
|
-
// emitted call matches the runtime helper the framework provides.
|
|
847
|
-
const rawCallee = ts.isIdentifier(call.expression) ? call.expression.text : calleeToText(call.expression);
|
|
848
|
-
const calleeText = rawCallee === "setInterval" ? "__tc_setInterval"
|
|
849
|
-
: rawCallee === "setTimeout" ? "__tc_setTimeout"
|
|
850
|
-
: rawCallee;
|
|
851
|
-
const remainingArgs = call.arguments.slice(1).map((arg) => expressionToIR(arg, sourceText, diagnostics, pointerVars));
|
|
852
|
-
return {
|
|
853
|
-
kind: "call",
|
|
854
|
-
sourceSpan: makeSourceSpan(call, fileName, sourceText),
|
|
855
|
-
leadingComments: comments.leadingComments,
|
|
856
|
-
trailingComments: comments.trailingComments,
|
|
857
|
-
callee: calleeText,
|
|
858
|
-
args: [{ kind: "identifier", value: fnName }, ...remainingArgs],
|
|
859
|
-
};
|
|
860
|
-
}
|
|
861
794
|
// ── Helper: lower a callback expression to C++ text ─────────────────────────
|
|
862
795
|
// (Moved to ui-callback-lowering.ts so onToggle and watchPin share one path,
|
|
863
796
|
// including console.* → platform transform which lived in neither copy.)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type CallbackContextId = "
|
|
1
|
+
export type CallbackContextId = "ui-event-callback" | "ui-draw-canvas";
|
|
2
2
|
export interface CallbackContextCapabilities {
|
|
3
3
|
id: CallbackContextId;
|
|
4
4
|
/** Human label used in diagnostic messages, e.g. "UI event callback". */
|
|
@@ -1,22 +1,14 @@
|
|
|
1
1
|
// ---------------------------------------------------------------------------
|
|
2
2
|
// Declarative capability registry for UI callback contexts.
|
|
3
3
|
//
|
|
4
|
-
// UI callback bodies (
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
// diagnostics.
|
|
4
|
+
// UI callback bodies (ui.bind/onClick/onToggle/watchPin, ui.drawCanvas)
|
|
5
|
+
// each lower through lowerCallbackStatements → lowerStatementList. This
|
|
6
|
+
// registry is the single declarative source of truth for diagnostics: each
|
|
7
|
+
// context lists what it lowers, and unsupportedStatementHint() renders that
|
|
8
|
+
// list into the hint text shown next to fatal "ui-callback-unsupported-
|
|
9
|
+
// statement" diagnostics.
|
|
11
10
|
// ---------------------------------------------------------------------------
|
|
12
11
|
export const CALLBACK_CONTEXTS = {
|
|
13
|
-
setInterval: {
|
|
14
|
-
id: "setInterval",
|
|
15
|
-
label: "setInterval callback",
|
|
16
|
-
statements: ["const/let", "if/else", "for", "while", "do/while", "break/continue", "nested blocks"],
|
|
17
|
-
expressions: ["the full statement-to-IR expression pipeline — the same one top-level code uses"],
|
|
18
|
-
escapeHatch: "setInterval callbacks already route through the main statement-to-IR pipeline, so a failure here reflects a general transpiler limitation rather than a callback-context restriction",
|
|
19
|
-
},
|
|
20
12
|
"ui-event-callback": {
|
|
21
13
|
id: "ui-event-callback",
|
|
22
14
|
label: "UI event callback",
|
|
@@ -27,7 +19,7 @@ export const CALLBACK_CONTEXTS = {
|
|
|
27
19
|
"console.* calls",
|
|
28
20
|
"any other expression via the standard expression pipeline (arithmetic, comparisons, ternaries, color literals, ...)",
|
|
29
21
|
],
|
|
30
|
-
escapeHatch: "move the logic to
|
|
22
|
+
escapeHatch: "move the logic to a Thread or a plain function",
|
|
31
23
|
},
|
|
32
24
|
"ui-draw-canvas": {
|
|
33
25
|
id: "ui-draw-canvas",
|
|
@@ -36,7 +28,7 @@ export const CALLBACK_CONTEXTS = {
|
|
|
36
28
|
expressions: [
|
|
37
29
|
"ctx.*() draw calls (drawPixel, fillRect, rect, fillRoundRect, roundRect, line, hline, vline, fillCircle, circle, rgbBitmap, text, fillScreen)",
|
|
38
30
|
],
|
|
39
|
-
escapeHatch: "move non-drawing side effects (calls not on ctx, e.g. signal writes or console output) to
|
|
31
|
+
escapeHatch: "move non-drawing side effects (calls not on ctx, e.g. signal writes or console output) to a Thread",
|
|
40
32
|
},
|
|
41
33
|
};
|
|
42
34
|
/** Human-readable name for a context, used in diagnostic messages. */
|
|
@@ -6,7 +6,6 @@ import { parseCppType, renderCppType, isPointer, parsedIsVector, parsedElementSt
|
|
|
6
6
|
import { expressionToIR } from "../expression-to-ir.js";
|
|
7
7
|
import { lowerStatementList, expressionStatementToIR } from "../statement-to-ir.js";
|
|
8
8
|
import { assignmentOperatorToString, updateLocalTypeFromAssignment, extractForInKeys } from "./variables.js";
|
|
9
|
-
import { snapshotPinLevels, restorePinLevels, mergePinLevels, invalidatePinLevels } from "../pin-state-tracking.js";
|
|
10
9
|
// Monotonic counter for synthetic for...of destructure loop variables.
|
|
11
10
|
let forOfDestructureCounter = 0;
|
|
12
11
|
/**
|
|
@@ -187,7 +186,6 @@ export function lowerControlFlowStatement(statement, fileName, sourceText, diagn
|
|
|
187
186
|
if (ts.isWhileStatement(statement)) {
|
|
188
187
|
// Loop conditions/bodies may evaluate any number of times, so tracked
|
|
189
188
|
// pin levels from before the loop are not valid inside it.
|
|
190
|
-
invalidatePinLevels();
|
|
191
189
|
const comments = extractNodeComments(statement, sourceText);
|
|
192
190
|
const bodyStatements = lowerStatementList(ts.isBlock(statement.statement) ? statement.statement.statements : [statement.statement], fileName, sourceText, diagnostics, functionReturnTypes, localVariableTypes, functionNameForDiagnostics, typeAliases, pointerVars);
|
|
193
191
|
return [{
|
|
@@ -205,19 +203,15 @@ export function lowerControlFlowStatement(statement, fileName, sourceText, diagn
|
|
|
205
203
|
// after the branches in this function but runs before them at runtime,
|
|
206
204
|
// so the pre-branch state is restored before the condition is evaluated
|
|
207
205
|
// and the merge is applied last.
|
|
208
|
-
const preBranchPinState = snapshotPinLevels();
|
|
209
206
|
const comments = extractNodeComments(statement, sourceText);
|
|
210
207
|
const thenStatements = lowerStatementList(ts.isBlock(statement.thenStatement) ? statement.thenStatement.statements : [statement.thenStatement], fileName, sourceText, diagnostics, functionReturnTypes, localVariableTypes, functionNameForDiagnostics, typeAliases, pointerVars);
|
|
211
|
-
const thenBranchPinState = snapshotPinLevels();
|
|
212
208
|
// Restore the pre-branch state before lowering the else branch and the
|
|
213
209
|
// condition — both run before the branches at runtime... the condition
|
|
214
210
|
// before them, the else on the path where the then branch never ran.
|
|
215
|
-
restorePinLevels(preBranchPinState);
|
|
216
211
|
let elseBranch;
|
|
217
212
|
if (statement.elseStatement) {
|
|
218
213
|
elseBranch = lowerStatementList(ts.isBlock(statement.elseStatement) ? statement.elseStatement.statements : [statement.elseStatement], fileName, sourceText, diagnostics, functionReturnTypes, localVariableTypes, functionNameForDiagnostics, typeAliases, pointerVars);
|
|
219
214
|
}
|
|
220
|
-
const elseBranchPinState = snapshotPinLevels();
|
|
221
215
|
// Evaluate the condition. If it's a bare identifier that resolves to a
|
|
222
216
|
// HAL alias (e.g. `if (bus2)` where bus2 = I2C0.take()), the alias is a
|
|
223
217
|
// compile-time non-null reference — constant-fold to `true` so the emit
|
|
@@ -229,10 +223,6 @@ export function lowerControlFlowStatement(statement, fileName, sourceText, diagn
|
|
|
229
223
|
else {
|
|
230
224
|
condition = expressionToIR(statement.expression, sourceText, diagnostics, pointerVars);
|
|
231
225
|
}
|
|
232
|
-
// Join the branch-end states into the live state. With no else branch,
|
|
233
|
-
// elseBranchPinState equals the pre-branch state, so pins written by the
|
|
234
|
-
// then branch invalidate unless the write agrees with the prior level.
|
|
235
|
-
mergePinLevels(thenBranchPinState, elseBranchPinState);
|
|
236
226
|
return [{
|
|
237
227
|
kind: "if",
|
|
238
228
|
sourceSpan: makeSourceSpan(statement, fileName, sourceText),
|
|
@@ -257,7 +247,6 @@ export function lowerControlFlowStatement(statement, fileName, sourceText, diagn
|
|
|
257
247
|
}
|
|
258
248
|
// Loop conditions/bodies may evaluate any number of times, so tracked
|
|
259
249
|
// pin levels from before the loop are not valid inside it.
|
|
260
|
-
invalidatePinLevels();
|
|
261
250
|
const condition = statement.condition
|
|
262
251
|
? expressionToIR(statement.condition, sourceText, diagnostics, pointerVars)
|
|
263
252
|
: undefined;
|
|
@@ -387,7 +376,6 @@ export function lowerControlFlowStatement(statement, fileName, sourceText, diagn
|
|
|
387
376
|
if (ts.isDoStatement(statement)) {
|
|
388
377
|
// Loop bodies may run more than once; pre-loop pin levels are not valid
|
|
389
378
|
// inside them.
|
|
390
|
-
invalidatePinLevels();
|
|
391
379
|
const comments = extractNodeComments(statement, sourceText);
|
|
392
380
|
const bodyStatements = lowerStatementList(ts.isBlock(statement.statement) ? statement.statement.statements : [statement.statement], fileName, sourceText, diagnostics, functionReturnTypes, localVariableTypes, functionNameForDiagnostics, typeAliases, pointerVars);
|
|
393
381
|
return [{
|
|
@@ -403,7 +391,6 @@ export function lowerControlFlowStatement(statement, fileName, sourceText, diagn
|
|
|
403
391
|
if (ts.isSwitchStatement(statement)) {
|
|
404
392
|
// Exactly one case runs at runtime, but all are lowered here; pin levels
|
|
405
393
|
// from case bodies must not leak past the switch.
|
|
406
|
-
invalidatePinLevels();
|
|
407
394
|
const comments = extractNodeComments(statement, sourceText);
|
|
408
395
|
const cases = [];
|
|
409
396
|
for (const clause of statement.caseBlock.clauses) {
|
|
@@ -11,6 +11,14 @@ export function expressionStatementToIR(statement, fileName, sourceText, diagnos
|
|
|
11
11
|
if (ts.isCallExpression(expr)) {
|
|
12
12
|
return callToStatement(statement, expr, fileName, sourceText, diagnostics, pointerVars);
|
|
13
13
|
}
|
|
14
|
+
// `void expr();` — the fire-and-forget idiom. Lower the inner call like a
|
|
15
|
+
// bare call statement (the raw (void)(...) form drops it entirely, which
|
|
16
|
+
// silently skipped the async-method kickoff: `void b.run();`). Free async
|
|
17
|
+
// function calls reaching here are still filtered at top level (their
|
|
18
|
+
// tasks auto-start), so the idiom keeps its meaning there.
|
|
19
|
+
if (ts.isVoidExpression(expr) && ts.isCallExpression(expr.expression)) {
|
|
20
|
+
return callToStatement(statement, expr.expression, fileName, sourceText, diagnostics, pointerVars);
|
|
21
|
+
}
|
|
14
22
|
if (ts.isAwaitExpression(expr) && ts.isCallExpression(expr.expression)) {
|
|
15
23
|
const callStmt = callToStatement(statement, expr.expression, fileName, sourceText, diagnostics, pointerVars);
|
|
16
24
|
if (callStmt && callStmt.kind === "call") {
|
|
@@ -420,17 +428,10 @@ export function expressionStatementToIR(statement, fileName, sourceText, diagnos
|
|
|
420
428
|
* timing.delay is included because `delay()` from @typecad/hal resolves to a
|
|
421
429
|
* hal-op, dropping the isAwaited flag the state machine keys on. */
|
|
422
430
|
const AWAITABLE_HAL_OPS = new Set([
|
|
423
|
-
"timing.
|
|
424
|
-
"wifi.
|
|
425
|
-
"wifi.wait_connected",
|
|
426
|
-
"wifi.wait_disconnected",
|
|
431
|
+
"timing.sleep",
|
|
432
|
+
"wifi.join",
|
|
427
433
|
"wifi.scan",
|
|
428
434
|
"http.send",
|
|
429
|
-
"ble.until_connected",
|
|
430
|
-
// Worker offload: `await worker.submit(...)` rewrites to submit + poll
|
|
431
|
-
// worker.done — mirrors `await http.send(...)`. The start op is worker.submit
|
|
432
|
-
// (emitted by the previous state segment); the poll predicate is worker.done.
|
|
433
|
-
"worker.submit",
|
|
434
435
|
]);
|
|
435
436
|
/**
|
|
436
437
|
* Rewrite an awaited hal-op statement (or a block whose LAST statement is
|
|
@@ -4,8 +4,8 @@ import { PointerTracker } from "../build-ir-state.js";
|
|
|
4
4
|
import { StatementIR, ExpressionIR, HALOpIR } from "../../api/index.js";
|
|
5
5
|
/**
|
|
6
6
|
* Resolve a HAL method call using the HAL resolver.
|
|
7
|
-
* Handles all HAL classes: Pin, I2CBus, SPIBus,
|
|
8
|
-
* plus device accessor patterns (
|
|
7
|
+
* Handles all HAL classes: Pin, I2CBus, SPIBus, UART, WDTClass,
|
|
8
|
+
* plus device accessor patterns (I2CTarget, SPITarget) and namespace methods (Pulse, Shift, Random).
|
|
9
9
|
*/
|
|
10
10
|
export declare function tryResolveHALMethod(call: ts.CallExpression, fileName: string, sourceText: string, diagnostics: Diagnostic[], pointerVars: PointerTracker): StatementIR | null;
|
|
11
11
|
/**
|
|
@@ -7,8 +7,8 @@ import { resolveNamespaceMethodCall } from "./namespace-methods.js";
|
|
|
7
7
|
import { makeSourceSpan } from "../ast-node-utils.js";
|
|
8
8
|
/**
|
|
9
9
|
* Resolve a HAL method call using the HAL resolver.
|
|
10
|
-
* Handles all HAL classes: Pin, I2CBus, SPIBus,
|
|
11
|
-
* plus device accessor patterns (
|
|
10
|
+
* Handles all HAL classes: Pin, I2CBus, SPIBus, UART, WDTClass,
|
|
11
|
+
* plus device accessor patterns (I2CTarget, SPITarget) and namespace methods (Pulse, Shift, Random).
|
|
12
12
|
*/
|
|
13
13
|
export function tryResolveHALMethod(call, fileName, sourceText, diagnostics, pointerVars) {
|
|
14
14
|
let method;
|
|
@@ -31,8 +31,8 @@ export function tryResolveHALMethod(call, fileName, sourceText, diagnostics, poi
|
|
|
31
31
|
if (instance) {
|
|
32
32
|
const result = processHALMethodBody(instance, method, argIRs);
|
|
33
33
|
if (result) {
|
|
34
|
-
// Collect emit lines and halOps from chained inner calls:
|
|
35
|
-
// The receiver of this call is itself a chained HAL call (
|
|
34
|
+
// Collect emit lines and halOps from chained inner calls: rgb.brightness(50).show()
|
|
35
|
+
// The receiver of this call is itself a chained HAL call (rgb.brightness(50)).
|
|
36
36
|
// We need to process that inner call to collect its emit lines too.
|
|
37
37
|
const chainedEmits = [];
|
|
38
38
|
const chainedHalOps = [];
|
|
@@ -101,7 +101,7 @@ export function tryResolveHALMethod(call, fileName, sourceText, diagnostics, poi
|
|
|
101
101
|
}
|
|
102
102
|
const receiver = ts.isPropertyAccessExpression(call.expression) ? call.expression.expression : null;
|
|
103
103
|
// Try device accessor pattern: <bus>.device(addr).method(args)
|
|
104
|
-
// This resolves
|
|
104
|
+
// This resolves I2CTarget and SPITarget device()-factory calls
|
|
105
105
|
if (receiver && ts.isCallExpression(receiver)) {
|
|
106
106
|
const deviceCall = receiver;
|
|
107
107
|
if (ts.isPropertyAccessExpression(deviceCall.expression) && deviceCall.expression.name.text === "device") {
|
|
@@ -112,12 +112,16 @@ export function tryResolveHALMethod(call, fileName, sourceText, diagnostics, poi
|
|
|
112
112
|
const deviceArgs = deviceCall.arguments;
|
|
113
113
|
if (deviceArgs && deviceArgs.length > 0) {
|
|
114
114
|
// Determine the device class based on bus class
|
|
115
|
-
const
|
|
115
|
+
const isSpiDevice = busInstance.className === "SPIBus";
|
|
116
|
+
const deviceClassName = isSpiDevice ? "SPITarget" : "I2CTarget";
|
|
116
117
|
// Build field values for the device: _bus from bus instance, _address/_cs from device() arg
|
|
117
118
|
const deviceFieldValues = new Map();
|
|
118
119
|
const busField = busInstance.fieldValues.get("_bus");
|
|
119
120
|
if (busField)
|
|
120
121
|
deviceFieldValues.set("_bus", busField);
|
|
122
|
+
deviceFieldValues.set("_hz", isSpiDevice ? "1000000" : "0");
|
|
123
|
+
if (isSpiDevice)
|
|
124
|
+
deviceFieldValues.set("_mode", "0");
|
|
121
125
|
const deviceArg = deviceArgs[0];
|
|
122
126
|
if (ts.isNumericLiteral(deviceArg)) {
|
|
123
127
|
const fieldName = busInstance.className === "SPIBus" ? "_cs" : "_address";
|
|
@@ -191,11 +195,15 @@ export function resolveHALCallForVarInit(call, sourceText, diagnostics, pointerV
|
|
|
191
195
|
if (busInstance) {
|
|
192
196
|
const deviceArgs = deviceCall.arguments;
|
|
193
197
|
if (deviceArgs && deviceArgs.length > 0) {
|
|
194
|
-
const
|
|
198
|
+
const isSpiDevice = busInstance.className === "SPIBus";
|
|
199
|
+
const deviceClassName = isSpiDevice ? "SPITarget" : "I2CTarget";
|
|
195
200
|
const deviceFieldValues = new Map();
|
|
196
201
|
const busField = busInstance.fieldValues.get("_bus");
|
|
197
202
|
if (busField)
|
|
198
203
|
deviceFieldValues.set("_bus", busField);
|
|
204
|
+
deviceFieldValues.set("_hz", isSpiDevice ? "1000000" : "0");
|
|
205
|
+
if (isSpiDevice)
|
|
206
|
+
deviceFieldValues.set("_mode", "0");
|
|
199
207
|
const deviceArg = deviceArgs[0];
|
|
200
208
|
if (ts.isNumericLiteral(deviceArg)) {
|
|
201
209
|
const fieldName = busInstance.className === "SPIBus" ? "_cs" : "_address";
|
|
@@ -239,10 +247,15 @@ export function tryResolveHALExpression(call, sourceText, diagnostics, pointerVa
|
|
|
239
247
|
if (result) {
|
|
240
248
|
// Prefer hal-expr for semantic HAL operations
|
|
241
249
|
if (result.halOps.length > 0) {
|
|
242
|
-
// Use the last halOp as the expression;
|
|
250
|
+
// Use the last halOp as the expression; PRECEDING ones are its
|
|
251
|
+
// prefixOps — a method body's leading side effects (bus transaction
|
|
252
|
+
// begin/write/end, a pin configure) that must still run. The renderer
|
|
253
|
+
// wraps them with the value in a statement-expression. (They were
|
|
254
|
+
// historically dropped here — the "dead keypress" bug class.)
|
|
243
255
|
const lastOp = result.halOps[result.halOps.length - 1];
|
|
256
|
+
const prefixOps = result.halOps.slice(0, -1);
|
|
244
257
|
return {
|
|
245
|
-
ir: { kind: "hal-expr", operation: lastOp },
|
|
258
|
+
ir: { kind: "hal-expr", operation: lastOp, ...(prefixOps.length > 0 ? { prefixOps } : {}) },
|
|
246
259
|
sideEffects: result.emitLines,
|
|
247
260
|
};
|
|
248
261
|
}
|
|
@@ -281,8 +294,9 @@ export function tryResolveHALExpression(call, sourceText, diagnostics, pointerVa
|
|
|
281
294
|
if (nsResult) {
|
|
282
295
|
if (nsResult.halOps.length > 0) {
|
|
283
296
|
const lastOp = nsResult.halOps[nsResult.halOps.length - 1];
|
|
297
|
+
const prefixOps = nsResult.halOps.slice(0, -1);
|
|
284
298
|
return {
|
|
285
|
-
ir: { kind: "hal-expr", operation: lastOp },
|
|
299
|
+
ir: { kind: "hal-expr", operation: lastOp, ...(prefixOps.length > 0 ? { prefixOps } : {}) },
|
|
286
300
|
sideEffects: nsResult.emitLines,
|
|
287
301
|
};
|
|
288
302
|
}
|
|
@@ -4,8 +4,8 @@ import { HALOpIR, StatementIR } from "../../api/index.js";
|
|
|
4
4
|
import { PointerTracker } from "../build-ir-state.js";
|
|
5
5
|
/**
|
|
6
6
|
* Recursively collect emit lines from chained HAL method calls.
|
|
7
|
-
* For an expression like
|
|
8
|
-
* the emit lines from the inner
|
|
7
|
+
* For an expression like rgb.brightness(50).show(), this collects
|
|
8
|
+
* the emit lines from the inner rgb.brightness(50) call.
|
|
9
9
|
*/
|
|
10
10
|
export declare function collectChainedHALEmits(expr: ts.Expression, sourceText: string, diagnostics: Diagnostic[], pointerVars: PointerTracker, emitLines: string[], halOps?: HALOpIR[]): void;
|
|
11
11
|
/** Convert emit lines to a StatementIR (single emit or block of emits). */
|
|
@@ -4,8 +4,8 @@ import { expressionToIR } from "../expression-to-ir.js";
|
|
|
4
4
|
import { resolveHALReceiver, processHALMethodBody } from "../hal-resolver.js";
|
|
5
5
|
/**
|
|
6
6
|
* Recursively collect emit lines from chained HAL method calls.
|
|
7
|
-
* For an expression like
|
|
8
|
-
* the emit lines from the inner
|
|
7
|
+
* For an expression like rgb.brightness(50).show(), this collects
|
|
8
|
+
* the emit lines from the inner rgb.brightness(50) call.
|
|
9
9
|
*/
|
|
10
10
|
export function collectChainedHALEmits(expr, sourceText, diagnostics, pointerVars, emitLines, halOps = []) {
|
|
11
11
|
// Chained call: led.tone(440).for(400) — the receiver is the inner call led.tone(440)
|
|
@@ -82,7 +82,7 @@ export function resolveNamespaceMethodCall(ns, method, argIRs) {
|
|
|
82
82
|
}
|
|
83
83
|
if (ns === "Random") {
|
|
84
84
|
// Random.* lowers to the random.* HAL op family, which frameworks lower to
|
|
85
|
-
// their platform PRNG (
|
|
85
|
+
// their platform PRNG (e.g. Zephyr's sys_rand).
|
|
86
86
|
// Previously these emitted bare `random()`/`randomSeed()` calls, which only
|
|
87
87
|
// resolve to symbols on Arduino-core frameworks — on ESP-IDF they were
|
|
88
88
|
// undefined and failed at C++ link time.
|
|
@@ -15,8 +15,6 @@ export declare function resolveColorsInStatements(statements: StatementIR[]): St
|
|
|
15
15
|
/** Recursively rename identifiers in a StatementIR tree (e.g. bindInput
|
|
16
16
|
* param → `text`, list tap param → `idx`). */
|
|
17
17
|
export declare function renameIdentifiersInStatements(statements: StatementIR[], from: string, to: string): StatementIR[];
|
|
18
|
-
export declare function noteConsoleInCallback(): void;
|
|
19
|
-
export declare function loweredConsoleInCallback(): boolean;
|
|
20
18
|
export declare function resetCallbackLoweringState(): void;
|
|
21
19
|
export declare function beginCanvasAmbient(ctxName: string, diagnostics: Diagnostic[], sourceText: string): void;
|
|
22
20
|
export declare function endCanvasAmbient(): void;
|