@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,274 @@
|
|
|
1
|
+
import ts from "typescript";
|
|
2
|
+
import { resolveHALReceiver, processHALMethodBody } from "../hal-resolver.js";
|
|
3
|
+
import { expressionToIR } from "../expression-to-ir.js";
|
|
4
|
+
import { renderExprAsText } from "../render-expr.js";
|
|
5
|
+
import { collectChainedHALEmits, emitLinesToIR, halOpsToIR } from "./hal-emit-helpers.js";
|
|
6
|
+
import { resolveNamespaceMethodCall } from "./namespace-methods.js";
|
|
7
|
+
import { makeSourceSpan } from "../ast-node-utils.js";
|
|
8
|
+
/**
|
|
9
|
+
* Resolve a HAL method call using the HAL resolver.
|
|
10
|
+
* Handles all HAL classes: Pin, I2CBus, SPIBus, SerialPort, EEPROMClass, WDTClass,
|
|
11
|
+
* plus device accessor patterns (I2CDevice, SPIDevice) and namespace methods (Pulse, Shift, Random).
|
|
12
|
+
*/
|
|
13
|
+
export function tryResolveHALMethod(call, fileName, sourceText, diagnostics, pointerVars) {
|
|
14
|
+
let method;
|
|
15
|
+
let instance = null;
|
|
16
|
+
if (ts.isPropertyAccessExpression(call.expression)) {
|
|
17
|
+
method = call.expression.name.text;
|
|
18
|
+
const receiver = call.expression.expression;
|
|
19
|
+
instance = resolveHALReceiver(receiver);
|
|
20
|
+
}
|
|
21
|
+
else if (ts.isIdentifier(call.expression)) {
|
|
22
|
+
method = call.expression.text;
|
|
23
|
+
// Global functions are treated as methods on a pseudo-instance with no class
|
|
24
|
+
instance = { className: "", fieldValues: new Map() };
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
const argIRs = call.arguments.map(a => expressionToIR(a, sourceText, diagnostics, pointerVars));
|
|
30
|
+
// Try HAL class method resolution via resolver
|
|
31
|
+
if (instance) {
|
|
32
|
+
const result = processHALMethodBody(instance, method, argIRs);
|
|
33
|
+
if (result) {
|
|
34
|
+
// Collect emit lines and halOps from chained inner calls: led.tone(440).for(400)
|
|
35
|
+
// The receiver of this call is itself a chained HAL call (led.tone(440)).
|
|
36
|
+
// We need to process that inner call to collect its emit lines too.
|
|
37
|
+
const chainedEmits = [];
|
|
38
|
+
const chainedHalOps = [];
|
|
39
|
+
if (ts.isPropertyAccessExpression(call.expression)) {
|
|
40
|
+
const innerReceiver = call.expression.expression;
|
|
41
|
+
collectChainedHALEmits(innerReceiver, sourceText, diagnostics, pointerVars, chainedEmits, chainedHalOps);
|
|
42
|
+
}
|
|
43
|
+
// Prefer hal-op IR over raw emit lines, but preserve emit lines if both are generated
|
|
44
|
+
const allHalOps = [...chainedHalOps, ...result.halOps];
|
|
45
|
+
const allEmits = [...chainedEmits, ...result.emitLines];
|
|
46
|
+
if (allHalOps.length > 0 && allEmits.length > 0) {
|
|
47
|
+
const emitIR = emitLinesToIR(allEmits, call, fileName, sourceText);
|
|
48
|
+
const halOpIR = halOpsToIR(allHalOps, call, fileName, sourceText);
|
|
49
|
+
const body = [];
|
|
50
|
+
if (emitIR) {
|
|
51
|
+
if (emitIR.kind === "block")
|
|
52
|
+
body.push(...emitIR.body);
|
|
53
|
+
else
|
|
54
|
+
body.push(emitIR);
|
|
55
|
+
}
|
|
56
|
+
if (halOpIR) {
|
|
57
|
+
if (halOpIR.kind === "block")
|
|
58
|
+
body.push(...halOpIR.body);
|
|
59
|
+
else
|
|
60
|
+
body.push(halOpIR);
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
kind: "block",
|
|
64
|
+
body,
|
|
65
|
+
sourceSpan: makeSourceSpan(call, fileName, sourceText)
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
if (allHalOps.length > 0)
|
|
69
|
+
return halOpsToIR(allHalOps, call, fileName, sourceText);
|
|
70
|
+
if (allEmits.length > 0)
|
|
71
|
+
return emitLinesToIR(allEmits, call, fileName, sourceText);
|
|
72
|
+
// take()/release() are compile-time ownership markers — no runtime C++ on
|
|
73
|
+
// Arduino. Keep a call IR node so peripheral-ownership validation can see
|
|
74
|
+
// the bus name; emission is suppressed in StatementRenderer.renderCall.
|
|
75
|
+
if ((method === "take" || method === "release") && ts.isPropertyAccessExpression(call.expression)) {
|
|
76
|
+
const callReceiver = call.expression.expression;
|
|
77
|
+
const busInstance = resolveHALReceiver(callReceiver);
|
|
78
|
+
const busName = busInstance?.canonicalBusName
|
|
79
|
+
?? (ts.isIdentifier(callReceiver)
|
|
80
|
+
? callReceiver.text
|
|
81
|
+
: renderExprAsText(expressionToIR(callReceiver, sourceText, diagnostics, pointerVars)) ?? "unknown");
|
|
82
|
+
return {
|
|
83
|
+
kind: "call",
|
|
84
|
+
callee: `${busName}.${method}`,
|
|
85
|
+
args: argIRs,
|
|
86
|
+
sourceSpan: makeSourceSpan(call, fileName, sourceText),
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
if (result.returnValue === "this" && ts.isPropertyAccessExpression(call.expression)) {
|
|
90
|
+
const objText = renderExprAsText(expressionToIR(call.expression.expression, sourceText, diagnostics, pointerVars));
|
|
91
|
+
return {
|
|
92
|
+
kind: "call",
|
|
93
|
+
callee: `${objText}.${method}`,
|
|
94
|
+
args: argIRs,
|
|
95
|
+
sourceSpan: makeSourceSpan(call, fileName, sourceText)
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
if (result.returnValue)
|
|
99
|
+
return emitLinesToIR([`${result.returnValue};`], call, fileName, sourceText);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
const receiver = ts.isPropertyAccessExpression(call.expression) ? call.expression.expression : null;
|
|
103
|
+
// Try device accessor pattern: <bus>.device(addr).method(args)
|
|
104
|
+
// This resolves I2CDevice and SPIDevice calls
|
|
105
|
+
if (receiver && ts.isCallExpression(receiver)) {
|
|
106
|
+
const deviceCall = receiver;
|
|
107
|
+
if (ts.isPropertyAccessExpression(deviceCall.expression) && deviceCall.expression.name.text === "device") {
|
|
108
|
+
const busReceiver = deviceCall.expression.expression;
|
|
109
|
+
const busInstance = resolveHALReceiver(busReceiver);
|
|
110
|
+
if (busInstance) {
|
|
111
|
+
// Resolve device() arguments to create a device instance
|
|
112
|
+
const deviceArgs = deviceCall.arguments;
|
|
113
|
+
if (deviceArgs && deviceArgs.length > 0) {
|
|
114
|
+
// Determine the device class based on bus class
|
|
115
|
+
const deviceClassName = busInstance.className === "SPIBus" ? "SPIDevice" : "I2CDevice";
|
|
116
|
+
// Build field values for the device: _bus from bus instance, _address/_cs from device() arg
|
|
117
|
+
const deviceFieldValues = new Map();
|
|
118
|
+
const busField = busInstance.fieldValues.get("_bus");
|
|
119
|
+
if (busField)
|
|
120
|
+
deviceFieldValues.set("_bus", busField);
|
|
121
|
+
const deviceArg = deviceArgs[0];
|
|
122
|
+
if (ts.isNumericLiteral(deviceArg)) {
|
|
123
|
+
const fieldName = busInstance.className === "SPIBus" ? "_cs" : "_address";
|
|
124
|
+
deviceFieldValues.set(fieldName, deviceArg.text);
|
|
125
|
+
}
|
|
126
|
+
else if (ts.isIdentifier(deviceArg)) {
|
|
127
|
+
// For SPI device, resolve the pin
|
|
128
|
+
const pinInstance = resolveHALReceiver(deviceArg);
|
|
129
|
+
if (pinInstance && pinInstance.fieldValues.has("_pin")) {
|
|
130
|
+
deviceFieldValues.set("_cs", pinInstance.fieldValues.get("_pin"));
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
const deviceInstance = { className: deviceClassName, fieldValues: deviceFieldValues };
|
|
134
|
+
const argIRs = call.arguments.map(a => expressionToIR(a, sourceText, diagnostics, pointerVars));
|
|
135
|
+
const result = processHALMethodBody(deviceInstance, method, argIRs);
|
|
136
|
+
if (result) {
|
|
137
|
+
if (result.halOps.length > 0)
|
|
138
|
+
return halOpsToIR(result.halOps, call, fileName, sourceText);
|
|
139
|
+
if (result.emitLines.length > 0)
|
|
140
|
+
return emitLinesToIR(result.emitLines, call, fileName, sourceText);
|
|
141
|
+
if (result.returnValue)
|
|
142
|
+
return emitLinesToIR([`${result.returnValue};`], call, fileName, sourceText);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
// ── Inline fallbacks for namespace methods the HAL resolver can't express ──
|
|
149
|
+
if (receiver && ts.isIdentifier(receiver)) {
|
|
150
|
+
const ns = receiver.text;
|
|
151
|
+
const nsResult = resolveNamespaceMethodCall(ns, method, argIRs);
|
|
152
|
+
if (nsResult) {
|
|
153
|
+
if (nsResult.halOps.length > 0)
|
|
154
|
+
return halOpsToIR(nsResult.halOps, call, fileName, sourceText);
|
|
155
|
+
if (nsResult.returnValue)
|
|
156
|
+
return emitLinesToIR([`${nsResult.returnValue};`], call, fileName, sourceText);
|
|
157
|
+
if (nsResult.emitLines.length > 0)
|
|
158
|
+
return emitLinesToIR(nsResult.emitLines, call, fileName, sourceText);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Resolve a HAL call for use in variable initializers and expression contexts.
|
|
165
|
+
* Returns emitLines and returnValue via the HAL resolver.
|
|
166
|
+
*/
|
|
167
|
+
export function resolveHALCallForVarInit(call, sourceText, diagnostics, pointerVars) {
|
|
168
|
+
if (!ts.isPropertyAccessExpression(call.expression))
|
|
169
|
+
return null;
|
|
170
|
+
const method = call.expression.name.text;
|
|
171
|
+
const receiver = call.expression.expression;
|
|
172
|
+
const argIRs = call.arguments.map(a => expressionToIR(a, sourceText, diagnostics, pointerVars));
|
|
173
|
+
const instance = resolveHALReceiver(receiver);
|
|
174
|
+
if (instance) {
|
|
175
|
+
const result = processHALMethodBody(instance, method, argIRs);
|
|
176
|
+
if (result) {
|
|
177
|
+
// Variable-initializer context is effectively expression context: the
|
|
178
|
+
// returnValue is substituted into `T name = <returnValue>;`. A leading
|
|
179
|
+
// `return ` (baked into HAL rawCpp for statement context) would leak as
|
|
180
|
+
// `T name = return Preferences.getString(...);`. Strip it. Demo #33.
|
|
181
|
+
const returnValue = result.returnValue ? result.returnValue.replace(/^\s*return\s+/, "") : result.returnValue;
|
|
182
|
+
return { emitLines: result.emitLines, halOps: result.halOps, returnValue, returnClassName: result.returnClassName };
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
// Try device accessor pattern
|
|
186
|
+
if (ts.isCallExpression(receiver)) {
|
|
187
|
+
const deviceCall = receiver;
|
|
188
|
+
if (ts.isPropertyAccessExpression(deviceCall.expression) && deviceCall.expression.name.text === "device") {
|
|
189
|
+
const busReceiver = deviceCall.expression.expression;
|
|
190
|
+
const busInstance = resolveHALReceiver(busReceiver);
|
|
191
|
+
if (busInstance) {
|
|
192
|
+
const deviceArgs = deviceCall.arguments;
|
|
193
|
+
if (deviceArgs && deviceArgs.length > 0) {
|
|
194
|
+
const deviceClassName = busInstance.className === "SPIBus" ? "SPIDevice" : "I2CDevice";
|
|
195
|
+
const deviceFieldValues = new Map();
|
|
196
|
+
const busField = busInstance.fieldValues.get("_bus");
|
|
197
|
+
if (busField)
|
|
198
|
+
deviceFieldValues.set("_bus", busField);
|
|
199
|
+
const deviceArg = deviceArgs[0];
|
|
200
|
+
if (ts.isNumericLiteral(deviceArg)) {
|
|
201
|
+
const fieldName = busInstance.className === "SPIBus" ? "_cs" : "_address";
|
|
202
|
+
deviceFieldValues.set(fieldName, deviceArg.text);
|
|
203
|
+
}
|
|
204
|
+
else if (ts.isIdentifier(deviceArg)) {
|
|
205
|
+
const pinInstance = resolveHALReceiver(deviceArg);
|
|
206
|
+
if (pinInstance && pinInstance.fieldValues.has("_pin")) {
|
|
207
|
+
deviceFieldValues.set("_cs", pinInstance.fieldValues.get("_pin"));
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
const deviceInstance = { className: deviceClassName, fieldValues: deviceFieldValues };
|
|
211
|
+
const result = processHALMethodBody(deviceInstance, method, argIRs);
|
|
212
|
+
if (result)
|
|
213
|
+
return { emitLines: result.emitLines, halOps: result.halOps, returnValue: result.returnValue };
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
// Namespace method fallbacks (Pulse, Shift, Random) — used in variable initializer context
|
|
219
|
+
if (ts.isIdentifier(receiver)) {
|
|
220
|
+
const ns = receiver.text;
|
|
221
|
+
return resolveNamespaceMethodCall(ns, method, argIRs);
|
|
222
|
+
}
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Try to resolve a HAL expression call for use inside expression contexts.
|
|
227
|
+
* Returns a raw string ExpressionIR if resolved, or null if not a HAL call.
|
|
228
|
+
* Side effects (emitLines) are accumulated and returned separately.
|
|
229
|
+
*/
|
|
230
|
+
export function tryResolveHALExpression(call, sourceText, diagnostics, pointerVars) {
|
|
231
|
+
if (!ts.isPropertyAccessExpression(call.expression))
|
|
232
|
+
return null;
|
|
233
|
+
const method = call.expression.name.text;
|
|
234
|
+
const receiver = call.expression.expression;
|
|
235
|
+
const argIRs = call.arguments.map(a => expressionToIR(a, sourceText, diagnostics, pointerVars));
|
|
236
|
+
const instance = resolveHALReceiver(receiver);
|
|
237
|
+
if (instance) {
|
|
238
|
+
const result = processHALMethodBody(instance, method, argIRs);
|
|
239
|
+
if (result) {
|
|
240
|
+
// Prefer hal-expr for semantic HAL operations
|
|
241
|
+
if (result.halOps.length > 0) {
|
|
242
|
+
// Use the last halOp as the expression; preceding ones are side effects
|
|
243
|
+
const lastOp = result.halOps[result.halOps.length - 1];
|
|
244
|
+
return {
|
|
245
|
+
ir: { kind: "hal-expr", operation: lastOp },
|
|
246
|
+
sideEffects: result.emitLines,
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
if (result.returnValue === "this") {
|
|
250
|
+
// Return structured method call for analysis
|
|
251
|
+
const objText = renderExprAsText(expressionToIR(receiver, sourceText, diagnostics, pointerVars));
|
|
252
|
+
return {
|
|
253
|
+
ir: { kind: "method-call", callee: `${objText}.${method}`, args: argIRs },
|
|
254
|
+
sideEffects: result.emitLines
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
if (result.returnValue) {
|
|
258
|
+
// Expression context: a leading `return ` (baked into many HAL
|
|
259
|
+
// rawCpp definitions for statement context) is invalid inside an
|
|
260
|
+
// expression and would leak as e.g.
|
|
261
|
+
// `strcmp(return Preferences.getString(...), ...)` (avr-g++: "expected
|
|
262
|
+
// primary-expression before 'return'"). Strip it here so the value is
|
|
263
|
+
// usable as a sub-expression. Statement context keeps the `return`
|
|
264
|
+
// via tryResolveHALMethod. Demo #33 Finding B.
|
|
265
|
+
const exprValue = result.returnValue.replace(/^\s*return\s+/, "");
|
|
266
|
+
return { ir: { kind: "raw", value: exprValue }, sideEffects: result.emitLines };
|
|
267
|
+
}
|
|
268
|
+
if (result.emitLines.length > 0) {
|
|
269
|
+
return { ir: { kind: "raw", value: "0" }, sideEffects: result.emitLines };
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
return null;
|
|
274
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import ts from "typescript";
|
|
2
|
+
import { Diagnostic } from "../../types.js";
|
|
3
|
+
import { HALOpIR, StatementIR } from "../../api/index.js";
|
|
4
|
+
import { PointerTracker } from "../build-ir-state.js";
|
|
5
|
+
/**
|
|
6
|
+
* Recursively collect emit lines from chained HAL method calls.
|
|
7
|
+
* For an expression like led.tone(440).for(400), this collects
|
|
8
|
+
* the emit lines from the inner led.tone(440) call.
|
|
9
|
+
*/
|
|
10
|
+
export declare function collectChainedHALEmits(expr: ts.Expression, sourceText: string, diagnostics: Diagnostic[], pointerVars: PointerTracker, emitLines: string[], halOps?: HALOpIR[]): void;
|
|
11
|
+
/** Convert emit lines to a StatementIR (single emit or block of emits). */
|
|
12
|
+
export declare function emitLinesToIR(lines: string[], node: ts.Node, fileName: string, sourceText: string): StatementIR | null;
|
|
13
|
+
/** Convert HALOpIR array to hal-op StatementIR nodes. */
|
|
14
|
+
export declare function halOpsToIR(ops: HALOpIR[], node: ts.Node, fileName: string, sourceText: string): StatementIR | null;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import ts from "typescript";
|
|
2
|
+
import { makeSourceSpan } from "../ast-node-utils.js";
|
|
3
|
+
import { expressionToIR } from "../expression-to-ir.js";
|
|
4
|
+
import { resolveHALReceiver, processHALMethodBody } from "../hal-resolver.js";
|
|
5
|
+
/**
|
|
6
|
+
* Recursively collect emit lines from chained HAL method calls.
|
|
7
|
+
* For an expression like led.tone(440).for(400), this collects
|
|
8
|
+
* the emit lines from the inner led.tone(440) call.
|
|
9
|
+
*/
|
|
10
|
+
export function collectChainedHALEmits(expr, sourceText, diagnostics, pointerVars, emitLines, halOps = []) {
|
|
11
|
+
// Chained call: led.tone(440).for(400) — the receiver is the inner call led.tone(440)
|
|
12
|
+
if (ts.isCallExpression(expr) && ts.isPropertyAccessExpression(expr.expression)) {
|
|
13
|
+
const method = expr.expression.name.text;
|
|
14
|
+
const innerReceiver = expr.expression.expression;
|
|
15
|
+
const instance = resolveHALReceiver(innerReceiver);
|
|
16
|
+
if (instance) {
|
|
17
|
+
const argIRs = expr.arguments.map(a => expressionToIR(a, sourceText, diagnostics, pointerVars));
|
|
18
|
+
const result = processHALMethodBody(instance, method, argIRs);
|
|
19
|
+
if (result) {
|
|
20
|
+
if (result.emitLines.length > 0) {
|
|
21
|
+
// Prepend inner emits so they appear before outer emits
|
|
22
|
+
emitLines.unshift(...result.emitLines);
|
|
23
|
+
}
|
|
24
|
+
if (result.halOps.length > 0) {
|
|
25
|
+
halOps.unshift(...result.halOps);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
// Continue recursion to collect deeper chain levels
|
|
30
|
+
if (ts.isCallExpression(innerReceiver) && ts.isPropertyAccessExpression(innerReceiver)) {
|
|
31
|
+
collectChainedHALEmits(innerReceiver, sourceText, diagnostics, pointerVars, emitLines, halOps);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/** Convert emit lines to a StatementIR (single emit or block of emits). */
|
|
36
|
+
export function emitLinesToIR(lines, node, fileName, sourceText) {
|
|
37
|
+
if (lines.length === 0)
|
|
38
|
+
return null;
|
|
39
|
+
const emitStmts = lines.map(line => ({
|
|
40
|
+
kind: "call",
|
|
41
|
+
sourceSpan: makeSourceSpan(node, fileName, sourceText),
|
|
42
|
+
callee: "__EMIT__",
|
|
43
|
+
args: [{ kind: "string", value: line }],
|
|
44
|
+
}));
|
|
45
|
+
return emitStmts.length === 1
|
|
46
|
+
? emitStmts[0]
|
|
47
|
+
: { kind: "block", body: emitStmts, sourceSpan: makeSourceSpan(node, fileName, sourceText) };
|
|
48
|
+
}
|
|
49
|
+
/** Convert HALOpIR array to hal-op StatementIR nodes. */
|
|
50
|
+
export function halOpsToIR(ops, node, fileName, sourceText) {
|
|
51
|
+
if (ops.length === 0)
|
|
52
|
+
return null;
|
|
53
|
+
const span = makeSourceSpan(node, fileName, sourceText);
|
|
54
|
+
const halStmts = ops.map(op => ({
|
|
55
|
+
kind: "hal-op",
|
|
56
|
+
sourceSpan: span,
|
|
57
|
+
operation: op,
|
|
58
|
+
returns_value: false,
|
|
59
|
+
}));
|
|
60
|
+
return halStmts.length === 1
|
|
61
|
+
? halStmts[0]
|
|
62
|
+
: { kind: "block", body: halStmts, sourceSpan: span };
|
|
63
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ExpressionIR, HALOpIR } from "../../api/index.js";
|
|
2
|
+
export type NamespaceMethodResult = {
|
|
3
|
+
emitLines: string[];
|
|
4
|
+
halOps: HALOpIR[];
|
|
5
|
+
returnValue?: string;
|
|
6
|
+
} | null;
|
|
7
|
+
/**
|
|
8
|
+
* Resolve a Pulse, Shift, or Random namespace method call to its C++ equivalent.
|
|
9
|
+
*
|
|
10
|
+
* These methods are handled as inline fallbacks because they don't map to
|
|
11
|
+
* HAL class instances — they are free-standing Arduino API functions accessed
|
|
12
|
+
* through TypeCAD namespace objects.
|
|
13
|
+
*
|
|
14
|
+
* @param ns - The namespace identifier text ("Pulse", "Shift", "Random")
|
|
15
|
+
* @param method - The method name (e.g. "in", "out", "seed", "number")
|
|
16
|
+
* @param argIRs - Pre-built ExpressionIR for each call argument
|
|
17
|
+
* @returns A result object compatible with both statement and expression contexts,
|
|
18
|
+
* or null if the ns/method combination is not recognized.
|
|
19
|
+
*/
|
|
20
|
+
export declare function resolveNamespaceMethodCall(ns: string, method: string, argIRs: ExpressionIR[]): NamespaceMethodResult;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { renderExprAsText } from "../render-expr.js";
|
|
2
|
+
import { halInstances } from "../hal-resolver.js";
|
|
3
|
+
/**
|
|
4
|
+
* Resolve a Pulse, Shift, or Random namespace method call to its C++ equivalent.
|
|
5
|
+
*
|
|
6
|
+
* These methods are handled as inline fallbacks because they don't map to
|
|
7
|
+
* HAL class instances — they are free-standing Arduino API functions accessed
|
|
8
|
+
* through TypeCAD namespace objects.
|
|
9
|
+
*
|
|
10
|
+
* @param ns - The namespace identifier text ("Pulse", "Shift", "Random")
|
|
11
|
+
* @param method - The method name (e.g. "in", "out", "seed", "number")
|
|
12
|
+
* @param argIRs - Pre-built ExpressionIR for each call argument
|
|
13
|
+
* @returns A result object compatible with both statement and expression contexts,
|
|
14
|
+
* or null if the ns/method combination is not recognized.
|
|
15
|
+
*/
|
|
16
|
+
export function resolveNamespaceMethodCall(ns, method, argIRs) {
|
|
17
|
+
const argText = (idx) => {
|
|
18
|
+
const a = argIRs[idx];
|
|
19
|
+
if (!a)
|
|
20
|
+
return "";
|
|
21
|
+
return renderExprAsText(a);
|
|
22
|
+
};
|
|
23
|
+
const resolvePinArg = (idx) => {
|
|
24
|
+
const text = argText(idx);
|
|
25
|
+
const inst = halInstances.get(text);
|
|
26
|
+
if (inst && inst.fieldValues.has("_pin"))
|
|
27
|
+
return inst.fieldValues.get("_pin");
|
|
28
|
+
return text;
|
|
29
|
+
};
|
|
30
|
+
const resolveBoolArg = (idx) => {
|
|
31
|
+
const text = argText(idx);
|
|
32
|
+
if (text === "true")
|
|
33
|
+
return "HIGH";
|
|
34
|
+
if (text === "false")
|
|
35
|
+
return "LOW";
|
|
36
|
+
return text;
|
|
37
|
+
};
|
|
38
|
+
if (ns === "Pulse") {
|
|
39
|
+
// Legacy free-function style: Pulse.in(pin, level)
|
|
40
|
+
if (method === "in") {
|
|
41
|
+
const pin = resolvePinArg(0);
|
|
42
|
+
const level = resolveBoolArg(1);
|
|
43
|
+
const timeout = argText(2);
|
|
44
|
+
const call = timeout
|
|
45
|
+
? `pulseIn(${pin}, ${level}, ${timeout})`
|
|
46
|
+
: `pulseIn(${pin}, ${level})`;
|
|
47
|
+
return { emitLines: [], halOps: [], returnValue: call };
|
|
48
|
+
}
|
|
49
|
+
// Current fluent API: Pulse.on(pin) returns a PulseMeasurement builder.
|
|
50
|
+
// The builder methods (.high(), .low(), .timeout()) are chained, so we
|
|
51
|
+
// can't resolve them here — but the static Pulse.long() can be handled.
|
|
52
|
+
if (method === "long" || method === "long_") {
|
|
53
|
+
const pin = resolvePinArg(0);
|
|
54
|
+
const level = resolveBoolArg(1);
|
|
55
|
+
const timeout = argText(2);
|
|
56
|
+
const call = timeout
|
|
57
|
+
? `pulseInLong(${pin}, ${level}, ${timeout})`
|
|
58
|
+
: `pulseInLong(${pin}, ${level})`;
|
|
59
|
+
return { emitLines: [], halOps: [], returnValue: call };
|
|
60
|
+
}
|
|
61
|
+
// Pulse.long(pin, value) static method (current API)
|
|
62
|
+
if (method === "long") {
|
|
63
|
+
const pin = resolvePinArg(0);
|
|
64
|
+
const value = argText(1);
|
|
65
|
+
return { emitLines: [], halOps: [], returnValue: `pulseInLong(${pin}, ${value})` };
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (ns === "Shift") {
|
|
69
|
+
if (method === "in") {
|
|
70
|
+
return {
|
|
71
|
+
emitLines: [],
|
|
72
|
+
halOps: [],
|
|
73
|
+
returnValue: `shiftIn(${resolvePinArg(0)}, ${resolvePinArg(1)}, ${argText(2)})`,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
if (method === "out") {
|
|
77
|
+
return {
|
|
78
|
+
emitLines: [`shiftOut(${resolvePinArg(0)}, ${resolvePinArg(1)}, ${argText(2)}, ${argText(3)});`],
|
|
79
|
+
halOps: [],
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (ns === "Random") {
|
|
84
|
+
if (method === "seed") {
|
|
85
|
+
return { emitLines: [`randomSeed(${argText(0)});`], halOps: [] };
|
|
86
|
+
}
|
|
87
|
+
if (method === "number") {
|
|
88
|
+
const min = argText(0);
|
|
89
|
+
const max = argText(1);
|
|
90
|
+
return {
|
|
91
|
+
emitLines: [],
|
|
92
|
+
halOps: [],
|
|
93
|
+
returnValue: max ? `random(${min}, ${max})` : `random(${min})`,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
// Current class API: Random.upTo(max) → random(max)
|
|
97
|
+
if (method === "upTo") {
|
|
98
|
+
return { emitLines: [], halOps: [], returnValue: `random(${argText(0)})` };
|
|
99
|
+
}
|
|
100
|
+
// Random.between(min, max) → random(min, max)
|
|
101
|
+
if (method === "between") {
|
|
102
|
+
return { emitLines: [], halOps: [], returnValue: `random(${argText(0)}, ${argText(1)})` };
|
|
103
|
+
}
|
|
104
|
+
// Random.int() → random(2147483647)
|
|
105
|
+
if (method === "int") {
|
|
106
|
+
return { emitLines: [], halOps: [], returnValue: `random(2147483647)` };
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import ts from "typescript";
|
|
2
|
+
import { Diagnostic } from "../../types.js";
|
|
3
|
+
import { StatementIR, ExpressionIR } from "../../api/index.js";
|
|
4
|
+
export declare function tryLowerRegisterWrite(statement: ts.ExpressionStatement, expr: ts.BinaryExpression, fileName: string, sourceText: string, diagnostics: Diagnostic[]): StatementIR | null;
|
|
5
|
+
export declare function tryLowerRegisterRead(expr: ts.PropertyAccessExpression, sourceText: string, diagnostics: Diagnostic[]): ExpressionIR | null;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import ts from "typescript";
|
|
2
|
+
import { extractNodeComments, makeSourceSpan } from "../ast-node-utils.js";
|
|
3
|
+
import { registerFieldMap } from "../build-ir-state.js";
|
|
4
|
+
import { expressionToIR } from "../expression-to-ir.js";
|
|
5
|
+
import { renderExprAsText } from "../render-expr.js";
|
|
6
|
+
export function tryLowerRegisterWrite(statement, expr, fileName, sourceText, diagnostics) {
|
|
7
|
+
if (ts.isPropertyAccessExpression(expr.left) && expr.operatorToken.kind === ts.SyntaxKind.EqualsToken) {
|
|
8
|
+
const objExpr = expr.left.expression;
|
|
9
|
+
const fieldName = expr.left.name.text;
|
|
10
|
+
if (ts.isIdentifier(objExpr)) {
|
|
11
|
+
const regName = objExpr.text;
|
|
12
|
+
const fieldMap = registerFieldMap.get(regName);
|
|
13
|
+
if (fieldMap) {
|
|
14
|
+
const field = fieldMap.get(fieldName);
|
|
15
|
+
if (field) {
|
|
16
|
+
const fieldMask = ((1 << field.width) - 1) >>> 0;
|
|
17
|
+
const fieldMaskUL = fieldMask + 'UL';
|
|
18
|
+
const shiftMask = (fieldMask << field.lo) >>> 0;
|
|
19
|
+
const shiftMaskUL = shiftMask + 'UL';
|
|
20
|
+
const valueIR = expressionToIR(expr.right, sourceText, diagnostics);
|
|
21
|
+
const valueText = renderExprAsText(valueIR);
|
|
22
|
+
const comments = extractNodeComments(statement, sourceText);
|
|
23
|
+
return {
|
|
24
|
+
kind: "assign",
|
|
25
|
+
sourceSpan: makeSourceSpan(statement, fileName, sourceText),
|
|
26
|
+
leadingComments: comments.leadingComments,
|
|
27
|
+
trailingComments: comments.trailingComments,
|
|
28
|
+
target: `*${regName}`,
|
|
29
|
+
operator: "=",
|
|
30
|
+
value: { kind: "raw", value: `(*${regName} & ~${shiftMaskUL}) | ((${valueText} & ${fieldMaskUL}) << ${field.lo})` },
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
export function tryLowerRegisterRead(expr, sourceText, diagnostics) {
|
|
39
|
+
if (ts.isIdentifier(expr.expression)) {
|
|
40
|
+
const regName = expr.expression.text;
|
|
41
|
+
const fieldName = expr.name.text;
|
|
42
|
+
const fieldMap = registerFieldMap.get(regName);
|
|
43
|
+
if (fieldMap) {
|
|
44
|
+
const field = fieldMap.get(fieldName);
|
|
45
|
+
if (field) {
|
|
46
|
+
const mask = ((1 << field.width) - 1) >>> 0;
|
|
47
|
+
const maskUL = mask + 'UL';
|
|
48
|
+
if (field.lo === 0 && field.width === 1) {
|
|
49
|
+
return { kind: "raw", value: `(*${regName} >> ${field.lo}) & 1UL` };
|
|
50
|
+
}
|
|
51
|
+
return { kind: "raw", value: `(*${regName} >> ${field.lo}) & ${maskUL}` };
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return null;
|
|
56
|
+
}
|