@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,269 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Header parser for gen-decls.
|
|
3
|
+
*
|
|
4
|
+
* Parses C++ class declarations from .h files, capturing inheritance
|
|
5
|
+
* (`class X : public Y`) and stripping #if/#ifdef/#ifndef preprocessor
|
|
6
|
+
* blocks before parsing. See
|
|
7
|
+
* docs/superpowers/specs/2026-06-20-gen-decls-inheritance-design.md.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Normalizes C++ preprocessor directives so the class parser can see the
|
|
11
|
+
* declarations. Semantics:
|
|
12
|
+
*
|
|
13
|
+
* - Include guards (`#ifndef X` immediately followed by `#define X`, and
|
|
14
|
+
* `#pragma once`): directives dropped, all guarded content kept.
|
|
15
|
+
* - `#if` / `#ifdef` / `#ifndef` ... `#else` / `#elif` ... `#endif`: the
|
|
16
|
+
* FIRST branch's content is kept; `#else` / `#elif` branch content is
|
|
17
|
+
* dropped; all directives themselves are dropped. This preserves classes
|
|
18
|
+
* that real-world headers gate behind target conditionals (e.g.
|
|
19
|
+
* Adafruit_SPITFT wraps its whole class in `#if !defined(__AVR_ATtiny85__)`),
|
|
20
|
+
* at the cost of possibly emitting declarations from a branch that isn't
|
|
21
|
+
* active on the user's target. That's acceptable for .d.ts generation,
|
|
22
|
+
* where a slightly wider API surface beats no API surface.
|
|
23
|
+
*/
|
|
24
|
+
export function stripPreprocessorBlocks(content) {
|
|
25
|
+
const lines = content.split(/\r?\n/);
|
|
26
|
+
const out = [];
|
|
27
|
+
// Each entry tracks one open `#if/#ifdef/#ifndef`:
|
|
28
|
+
// - `active`: is the CURRENT branch being kept?
|
|
29
|
+
// - `satisfied`: has ANY branch at this level already been kept?
|
|
30
|
+
// A branch is active only if no prior branch was satisfied and all outer
|
|
31
|
+
// levels are active.
|
|
32
|
+
const branches = [];
|
|
33
|
+
// Macro names for open include guards; their content is always kept.
|
|
34
|
+
const guardMacros = [];
|
|
35
|
+
const keeping = () => branches.every(b => b.active);
|
|
36
|
+
for (let i = 0; i < lines.length; i++) {
|
|
37
|
+
const raw = lines[i];
|
|
38
|
+
const trimmed = raw.trim();
|
|
39
|
+
const isDirective = trimmed.startsWith("#");
|
|
40
|
+
const directiveBody = isDirective ? trimmed.slice(1).trim() : "";
|
|
41
|
+
// Include-guard #endif: closes a guard (outermost open guard).
|
|
42
|
+
if (/^endif\b/.test(directiveBody) && guardMacros.length > 0 && branches.length === 0) {
|
|
43
|
+
guardMacros.pop();
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
// Conditional directives (only meaningful when not inside a guard-only context).
|
|
47
|
+
if (/^(if|ifdef|ifndef)\b/.test(directiveBody)) {
|
|
48
|
+
// Is this an include-guard open (#ifndef X followed by #define X)?
|
|
49
|
+
if (/^ifndef\s+(\w+)/.test(directiveBody) && guardMacros.length === branches.length) {
|
|
50
|
+
const macro = /^ifndef\s+(\w+)/.exec(directiveBody)[1];
|
|
51
|
+
let nextNonBlank;
|
|
52
|
+
for (let j = i + 1; j < lines.length; j++) {
|
|
53
|
+
const t = lines[j].trim();
|
|
54
|
+
if (t.length > 0) {
|
|
55
|
+
nextNonBlank = t.startsWith("#") ? t.slice(1).trim() : t;
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (nextNonBlank && new RegExp(`^define\\s+${macro}(\\s|$)`).test(nextNonBlank)) {
|
|
60
|
+
guardMacros.push(macro);
|
|
61
|
+
continue; // drop the #ifndef
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
// Real conditional: first branch is active iff outer levels keep.
|
|
65
|
+
const active = keeping();
|
|
66
|
+
branches.push({ active, satisfied: active });
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
// #elif / #else: switch to a new branch. Active only if outer keeps AND
|
|
70
|
+
// no prior branch at this level was satisfied.
|
|
71
|
+
if (/^(elif|else)\b/.test(directiveBody)) {
|
|
72
|
+
if (branches.length === 0)
|
|
73
|
+
continue;
|
|
74
|
+
const outerKeeping = branches.slice(0, -1).every(b => b.active);
|
|
75
|
+
const top = branches[branches.length - 1];
|
|
76
|
+
top.active = outerKeeping && !top.satisfied;
|
|
77
|
+
if (top.active)
|
|
78
|
+
top.satisfied = true;
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
if (/^endif\b/.test(directiveBody)) {
|
|
82
|
+
if (branches.length > 0)
|
|
83
|
+
branches.pop();
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
// Guard's own #define — drop it.
|
|
87
|
+
if (guardMacros.length > branches.length && /^define\s/.test(directiveBody)) {
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
// `#pragma once` — drop the directive.
|
|
91
|
+
if (/^pragma\s+once\b/.test(directiveBody)) {
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
// Non-conditional content: keep if every open branch is keeping.
|
|
95
|
+
if (keeping()) {
|
|
96
|
+
out.push(raw);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return out.join("\n");
|
|
100
|
+
}
|
|
101
|
+
/** Maps C++ types to TypeScript types (mirrors cpp-to-decl's type mapper). */
|
|
102
|
+
function mapCppTypeToTs(cppType) {
|
|
103
|
+
const trimmed = cppType.trim();
|
|
104
|
+
const withoutConst = trimmed.replace(/^const\s+/, "");
|
|
105
|
+
const typeMap = {
|
|
106
|
+
"int": "number",
|
|
107
|
+
"unsigned int": "number",
|
|
108
|
+
"uint8_t": "number",
|
|
109
|
+
"uint16_t": "number",
|
|
110
|
+
"uint32_t": "number",
|
|
111
|
+
"int8_t": "number",
|
|
112
|
+
"int16_t": "number",
|
|
113
|
+
"int32_t": "number",
|
|
114
|
+
"float": "number",
|
|
115
|
+
"double": "number",
|
|
116
|
+
"bool": "boolean",
|
|
117
|
+
"void": "void",
|
|
118
|
+
"char": "string",
|
|
119
|
+
"char*": "string",
|
|
120
|
+
"const char*": "string",
|
|
121
|
+
"std::string": "string",
|
|
122
|
+
"String": "string",
|
|
123
|
+
};
|
|
124
|
+
if (typeMap[withoutConst])
|
|
125
|
+
return typeMap[withoutConst];
|
|
126
|
+
if (withoutConst.endsWith("*"))
|
|
127
|
+
return "number";
|
|
128
|
+
if (withoutConst.endsWith("&"))
|
|
129
|
+
return mapCppTypeToTs(withoutConst.slice(0, -1).trim());
|
|
130
|
+
return "any";
|
|
131
|
+
}
|
|
132
|
+
/** Extracts parameters from a C++ parameter list string. */
|
|
133
|
+
function parseParameters(paramString) {
|
|
134
|
+
if (!paramString.trim())
|
|
135
|
+
return [];
|
|
136
|
+
const params = [];
|
|
137
|
+
for (const part of paramString.split(",")) {
|
|
138
|
+
const trimmed = part.trim();
|
|
139
|
+
if (!trimmed)
|
|
140
|
+
continue;
|
|
141
|
+
const withoutDefault = trimmed.split("=")[0].trim();
|
|
142
|
+
const tokens = withoutDefault.split(/\s+/);
|
|
143
|
+
if (tokens.length >= 2) {
|
|
144
|
+
// C++ lets pointer/reference markers attach to either the type
|
|
145
|
+
// (`char* label`) or the name (`char *label`), and arrays appear as a
|
|
146
|
+
// trailing `[]` on the name. Peel leading `*`/`&` and trailing `[]`
|
|
147
|
+
// off the name token back onto the type, so the emitted name is a
|
|
148
|
+
// valid TS identifier and the type still routes through
|
|
149
|
+
// mapCppTypeToTs (which maps pointers/refs appropriately).
|
|
150
|
+
let name = tokens[tokens.length - 1];
|
|
151
|
+
const typeParts = tokens.slice(0, -1);
|
|
152
|
+
const prefix = [];
|
|
153
|
+
while (/^[*&]/.test(name)) {
|
|
154
|
+
prefix.push(name[0]);
|
|
155
|
+
name = name.slice(1);
|
|
156
|
+
}
|
|
157
|
+
// Trailing array marker on the name → treat as pointer for typing.
|
|
158
|
+
let arrayMarker = "";
|
|
159
|
+
if (/\[\]$/.test(name)) {
|
|
160
|
+
arrayMarker = "*";
|
|
161
|
+
name = name.replace(/\[\]$/, "");
|
|
162
|
+
}
|
|
163
|
+
if (prefix.length > 0 || arrayMarker) {
|
|
164
|
+
typeParts.push((prefix.join("") + arrayMarker) || "");
|
|
165
|
+
}
|
|
166
|
+
params.push({
|
|
167
|
+
name,
|
|
168
|
+
type: mapCppTypeToTs(typeParts.join(" ").trim()),
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
else if (tokens.length === 1) {
|
|
172
|
+
params.push({ type: mapCppTypeToTs(tokens[0]), name: "" });
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
return params;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Parses a header source string into ParsedClass[]. Strips #if blocks first,
|
|
179
|
+
* then finds `class Name [: access Base] { ... }` blocks and extracts public
|
|
180
|
+
* methods + constructors.
|
|
181
|
+
*/
|
|
182
|
+
export function parseHeader(content) {
|
|
183
|
+
const cleaned = stripPreprocessorBlocks(content);
|
|
184
|
+
const classes = [];
|
|
185
|
+
// class Name [: (public|protected|private) Base [, access Base2 ...]] {
|
|
186
|
+
// Group 1 = class name, group 2 = optional first base name. Additional
|
|
187
|
+
// bases after the first are consumed by `(?:\s*,\s*(?:public|protected|private)\s+\w+)*`
|
|
188
|
+
// but not captured (multiple inheritance beyond the first base is a
|
|
189
|
+
// documented limitation).
|
|
190
|
+
const classRegex = /\bclass\s+(\w+)\s*(?::\s*(?:public|protected|private)\s+(\w+)(?:\s*,\s*(?:public|protected|private)\s+\w+)*)?\s*\{/g;
|
|
191
|
+
let m;
|
|
192
|
+
while ((m = classRegex.exec(cleaned)) !== null) {
|
|
193
|
+
// Skip templated classes: a `template<...>` declaration immediately
|
|
194
|
+
// precedes the class keyword on the preceding non-empty content.
|
|
195
|
+
const preceding = cleaned.slice(0, m.index).replace(/\s+$/, "");
|
|
196
|
+
if (/template\s*<[^>]*>\s*$/.test(preceding)) {
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
const name = m[1];
|
|
200
|
+
const baseClass = m[2];
|
|
201
|
+
const bodyStart = m.index + m[0].length;
|
|
202
|
+
// Find matching closing brace.
|
|
203
|
+
let depth = 1;
|
|
204
|
+
let bodyEnd = bodyStart;
|
|
205
|
+
for (let i = bodyStart; i < cleaned.length && depth > 0; i++) {
|
|
206
|
+
if (cleaned[i] === "{")
|
|
207
|
+
depth++;
|
|
208
|
+
else if (cleaned[i] === "}")
|
|
209
|
+
depth--;
|
|
210
|
+
bodyEnd = i;
|
|
211
|
+
}
|
|
212
|
+
const body = cleaned.slice(bodyStart, bodyEnd);
|
|
213
|
+
const cls = {
|
|
214
|
+
name,
|
|
215
|
+
methods: [],
|
|
216
|
+
constructors: [],
|
|
217
|
+
baseClass,
|
|
218
|
+
source: "header",
|
|
219
|
+
};
|
|
220
|
+
// Split body by access specifiers.
|
|
221
|
+
const normalized = body.replace(/\s+/g, " ");
|
|
222
|
+
const segments = [];
|
|
223
|
+
let isPublic = false;
|
|
224
|
+
for (const p of normalized.split(/(public:|private:|protected:)/)) {
|
|
225
|
+
const t = p.trim();
|
|
226
|
+
if (t === "public:")
|
|
227
|
+
isPublic = true;
|
|
228
|
+
else if (t === "private:" || t === "protected:")
|
|
229
|
+
isPublic = false;
|
|
230
|
+
else if (t)
|
|
231
|
+
segments.push({ text: t, isPublic });
|
|
232
|
+
}
|
|
233
|
+
for (const seg of segments) {
|
|
234
|
+
// Methods with a return type: type name(params) [const] {|;
|
|
235
|
+
const methodRe = /(\w+(?:\s*[*&])?)\s+(\w+)\s*\(([^)]*)\)\s*(?:const\s*)?(?:\{|;)/g;
|
|
236
|
+
let mm;
|
|
237
|
+
while ((mm = methodRe.exec(seg.text)) !== null) {
|
|
238
|
+
const returnType = mm[1].trim();
|
|
239
|
+
const methName = mm[2].trim();
|
|
240
|
+
const params = mm[3];
|
|
241
|
+
if (methName === name) {
|
|
242
|
+
cls.constructors.push({ parameters: parseParameters(params) });
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
cls.methods.push({
|
|
246
|
+
name: methName,
|
|
247
|
+
returnType: mapCppTypeToTs(returnType),
|
|
248
|
+
parameters: parseParameters(params),
|
|
249
|
+
isPublic: seg.isPublic,
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
// Constructors without a return type: ClassName(params) {|;
|
|
254
|
+
// (the method regex above requires a leading type token, so bare
|
|
255
|
+
// constructors are missed without this pass).
|
|
256
|
+
const ctorRe = new RegExp(`\\b(${name})\\s*\\(([^)]*)\\)\\s*(?:\\{|;)`, "g");
|
|
257
|
+
let cm;
|
|
258
|
+
while ((cm = ctorRe.exec(seg.text)) !== null) {
|
|
259
|
+
const params = cm[2];
|
|
260
|
+
const already = cls.constructors.some(c => c.parameters.length === parseParameters(params).length);
|
|
261
|
+
if (!already) {
|
|
262
|
+
cls.constructors.push({ parameters: parseParameters(params) });
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
classes.push(cls);
|
|
267
|
+
}
|
|
268
|
+
return classes;
|
|
269
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { LibraryDefinition, PlatformContext, TargetProfile } from "../types.js";
|
|
2
|
+
import type { ImportIR } from "../api/index.js";
|
|
3
|
+
interface ResolvedImport {
|
|
4
|
+
include: string;
|
|
5
|
+
symbolMap: Record<string, string>;
|
|
6
|
+
}
|
|
7
|
+
export declare function loadLibraryDefinitions(definitionsDir: string): Map<string, LibraryDefinition>;
|
|
8
|
+
export declare function resolveImport(importNode: ImportIR, definitions: Map<string, LibraryDefinition>, target: TargetProfile, platformContext?: PlatformContext, importerFilePath?: string): ResolvedImport;
|
|
9
|
+
export declare function generateLibdefStubs(inputFile: string, imports: ImportIR[], outDir: string): string[];
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { listFiles, readText } from "../utils/fs.js";
|
|
4
|
+
import { toModuleKey, toPascalCase } from "../utils/strings.js";
|
|
5
|
+
import { getLoadedFramework, hasLoadedFramework } from "../framework-registry.js";
|
|
6
|
+
function toArchitectureFromFqbn(fqbn) {
|
|
7
|
+
if (!fqbn)
|
|
8
|
+
return undefined;
|
|
9
|
+
return fqbn.split(":")[1];
|
|
10
|
+
}
|
|
11
|
+
function getLibraryResolver() {
|
|
12
|
+
if (hasLoadedFramework()) {
|
|
13
|
+
const { libraryResolver } = getLoadedFramework();
|
|
14
|
+
if (libraryResolver)
|
|
15
|
+
return libraryResolver;
|
|
16
|
+
}
|
|
17
|
+
return {
|
|
18
|
+
isFrameworkLibraryImport: (_s) => false,
|
|
19
|
+
getFrameworkLibraryHeaderName: (_s) => undefined,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export function loadLibraryDefinitions(definitionsDir) {
|
|
23
|
+
const registry = new Map();
|
|
24
|
+
const files = listFiles(definitionsDir, ".libdef.json");
|
|
25
|
+
for (const filePath of files) {
|
|
26
|
+
let def;
|
|
27
|
+
try {
|
|
28
|
+
def = JSON.parse(readText(filePath));
|
|
29
|
+
}
|
|
30
|
+
catch (e) {
|
|
31
|
+
throw new Error(`Failed to parse library definition ${filePath}: ${e instanceof Error ? e.message : String(e)}`);
|
|
32
|
+
}
|
|
33
|
+
if (!def.module || !def.include) {
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
registry.set(toModuleKey(def.module), def);
|
|
37
|
+
}
|
|
38
|
+
return registry;
|
|
39
|
+
}
|
|
40
|
+
function fallbackInclude(moduleSpecifier) {
|
|
41
|
+
const resolver = getLibraryResolver();
|
|
42
|
+
if (resolver.isFrameworkLibraryImport(moduleSpecifier)) {
|
|
43
|
+
const actualHeader = resolver.getFrameworkLibraryHeaderName(moduleSpecifier);
|
|
44
|
+
if (actualHeader) {
|
|
45
|
+
return `<${actualHeader}>`;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
// Fallback to PascalCase conversion for other modules
|
|
49
|
+
const key = toModuleKey(moduleSpecifier);
|
|
50
|
+
const include = `${toPascalCase(key)}.h`;
|
|
51
|
+
return `<${include}>`;
|
|
52
|
+
}
|
|
53
|
+
function resolveLocalModuleHeader(moduleSpecifier, importerFilePath) {
|
|
54
|
+
if (!moduleSpecifier.startsWith(".")) {
|
|
55
|
+
return undefined;
|
|
56
|
+
}
|
|
57
|
+
const basePath = path.resolve(path.dirname(importerFilePath), moduleSpecifier);
|
|
58
|
+
const candidates = [
|
|
59
|
+
basePath,
|
|
60
|
+
`${basePath}.ts`,
|
|
61
|
+
`${basePath}.tsx`,
|
|
62
|
+
path.join(basePath, "index.ts"),
|
|
63
|
+
path.join(basePath, "index.tsx"),
|
|
64
|
+
];
|
|
65
|
+
for (const candidate of candidates) {
|
|
66
|
+
if (!fs.existsSync(candidate) || !fs.statSync(candidate).isFile()) {
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
const extension = path.extname(candidate).toLowerCase();
|
|
70
|
+
if (extension !== ".ts" && extension !== ".tsx") {
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
const headerBaseName = path.basename(candidate).replace(/\.[^.]+$/, "");
|
|
74
|
+
return `"${headerBaseName}.h"`;
|
|
75
|
+
}
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
function conditionMatches(condition, target, context) {
|
|
79
|
+
const architecture = context?.architecture ?? toArchitectureFromFqbn(context?.frameworkData?.fqbn);
|
|
80
|
+
const fqbn = context?.frameworkData?.fqbn;
|
|
81
|
+
if (condition.target && condition.target !== target) {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
if (condition.architecture && architecture !== condition.architecture.toLowerCase()) {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
if (condition.fqbnIncludes && !(fqbn ?? "").toLowerCase().includes(condition.fqbnIncludes.toLowerCase())) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
export function resolveImport(importNode, definitions, target, platformContext, importerFilePath) {
|
|
93
|
+
if (importerFilePath) {
|
|
94
|
+
const localInclude = resolveLocalModuleHeader(importNode.moduleSpecifier, importerFilePath);
|
|
95
|
+
if (localInclude) {
|
|
96
|
+
return {
|
|
97
|
+
include: localInclude,
|
|
98
|
+
symbolMap: Object.fromEntries(importNode.namedImports.map((symbol) => [symbol, symbol])),
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
const key = toModuleKey(importNode.moduleSpecifier);
|
|
103
|
+
const definition = definitions.get(key);
|
|
104
|
+
if (!definition) {
|
|
105
|
+
return {
|
|
106
|
+
include: fallbackInclude(importNode.moduleSpecifier),
|
|
107
|
+
symbolMap: Object.fromEntries(importNode.namedImports.map((symbol) => [symbol, symbol])),
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
const selectedVariant = definition.variants?.find((variant) => conditionMatches(variant.when, target, platformContext));
|
|
111
|
+
const include = selectedVariant?.include ?? definition.include;
|
|
112
|
+
const mappedSymbols = selectedVariant?.symbols ?? definition.symbols ?? {};
|
|
113
|
+
return {
|
|
114
|
+
include,
|
|
115
|
+
symbolMap: {
|
|
116
|
+
...Object.fromEntries(importNode.namedImports.map((symbol) => [symbol, symbol])),
|
|
117
|
+
...mappedSymbols,
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
export function generateLibdefStubs(inputFile, imports, outDir) {
|
|
122
|
+
const created = [];
|
|
123
|
+
if (!fs.existsSync(outDir)) {
|
|
124
|
+
fs.mkdirSync(outDir, { recursive: true });
|
|
125
|
+
}
|
|
126
|
+
for (const item of imports) {
|
|
127
|
+
const moduleKey = toModuleKey(item.moduleSpecifier);
|
|
128
|
+
const libdefPath = path.join(outDir, `${moduleKey}.libdef.json`);
|
|
129
|
+
if (!fs.existsSync(libdefPath)) {
|
|
130
|
+
const include = `<${toPascalCase(moduleKey)}.h>`;
|
|
131
|
+
const libdefContent = {
|
|
132
|
+
module: moduleKey,
|
|
133
|
+
include,
|
|
134
|
+
symbols: Object.fromEntries(item.namedImports.map((symbol) => [symbol, symbol])),
|
|
135
|
+
source: inputFile,
|
|
136
|
+
};
|
|
137
|
+
fs.writeFileSync(libdefPath, JSON.stringify(libdefContent, null, 2) + "\n", "utf8");
|
|
138
|
+
created.push(libdefPath);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return created;
|
|
142
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Peripheral name mapping utilities.
|
|
3
|
+
*
|
|
4
|
+
* Delegates peripheral identifier translation (e.g. I2C0 → Wire, SPI0 → SPI)
|
|
5
|
+
* to the platform strategy. Framework packages implement `mapPeripheralIdentifier()`
|
|
6
|
+
* to provide their target-specific naming conventions.
|
|
7
|
+
*/
|
|
8
|
+
import type { PlatformStrategy } from "../api/shared/index.js";
|
|
9
|
+
/**
|
|
10
|
+
* Maps a TypeCAD peripheral identifier to its platform-specific C++ name.
|
|
11
|
+
*
|
|
12
|
+
* Delegates to `strategy.mapPeripheralIdentifier()` when available.
|
|
13
|
+
* Returns `undefined` if the strategy does not recognize the name.
|
|
14
|
+
*/
|
|
15
|
+
export declare function mapPeripheralName(name: string, strategy?: PlatformStrategy): string | undefined;
|
|
16
|
+
/**
|
|
17
|
+
* Renders a peripheral property access chain to a C++ expression string.
|
|
18
|
+
*
|
|
19
|
+
* Handles TypeScript stub properties on peripheral objects that don't exist
|
|
20
|
+
* directly in C++. Returns `undefined` if the chain is not a recognized
|
|
21
|
+
* peripheral property.
|
|
22
|
+
*/
|
|
23
|
+
export declare function renderPeripheralProperty(chain: string[], strategy?: PlatformStrategy): string | undefined;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Peripheral name mapping utilities.
|
|
3
|
+
*
|
|
4
|
+
* Delegates peripheral identifier translation (e.g. I2C0 → Wire, SPI0 → SPI)
|
|
5
|
+
* to the platform strategy. Framework packages implement `mapPeripheralIdentifier()`
|
|
6
|
+
* to provide their target-specific naming conventions.
|
|
7
|
+
*/
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
// Peripheral name mapping
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
/**
|
|
12
|
+
* Maps a TypeCAD peripheral identifier to its platform-specific C++ name.
|
|
13
|
+
*
|
|
14
|
+
* Delegates to `strategy.mapPeripheralIdentifier()` when available.
|
|
15
|
+
* Returns `undefined` if the strategy does not recognize the name.
|
|
16
|
+
*/
|
|
17
|
+
export function mapPeripheralName(name, strategy) {
|
|
18
|
+
if (strategy?.mapPeripheralIdentifier) {
|
|
19
|
+
const mapped = strategy.mapPeripheralIdentifier(name);
|
|
20
|
+
if (mapped)
|
|
21
|
+
return mapped;
|
|
22
|
+
}
|
|
23
|
+
// Default fallbacks if strategy doesn't provide a mapping
|
|
24
|
+
const canonical = name.toUpperCase();
|
|
25
|
+
if (canonical === "UART0")
|
|
26
|
+
return "Serial";
|
|
27
|
+
if (canonical === "I2C0")
|
|
28
|
+
return "Wire";
|
|
29
|
+
if (canonical === "SPI0")
|
|
30
|
+
return "SPI";
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
// ---------------------------------------------------------------------------
|
|
34
|
+
// Peripheral property rendering
|
|
35
|
+
// ---------------------------------------------------------------------------
|
|
36
|
+
/**
|
|
37
|
+
* Renders a peripheral property access chain to a C++ expression string.
|
|
38
|
+
*
|
|
39
|
+
* Handles TypeScript stub properties on peripheral objects that don't exist
|
|
40
|
+
* directly in C++. Returns `undefined` if the chain is not a recognized
|
|
41
|
+
* peripheral property.
|
|
42
|
+
*/
|
|
43
|
+
export function renderPeripheralProperty(chain, strategy) {
|
|
44
|
+
if (chain.length !== 2)
|
|
45
|
+
return undefined;
|
|
46
|
+
const [peripheral, property] = chain;
|
|
47
|
+
const cppPeripheral = mapPeripheralName(peripheral, strategy);
|
|
48
|
+
if (!cppPeripheral)
|
|
49
|
+
return undefined;
|
|
50
|
+
if (property === "available") {
|
|
51
|
+
return `${cppPeripheral}.${property}`;
|
|
52
|
+
}
|
|
53
|
+
if (property === "isInitialized" || property === "isConnected") {
|
|
54
|
+
return "true";
|
|
55
|
+
}
|
|
56
|
+
if (property === "busNumber" || property === "uartNumber") {
|
|
57
|
+
return "0";
|
|
58
|
+
}
|
|
59
|
+
if (property === "speed") {
|
|
60
|
+
return "100000";
|
|
61
|
+
}
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { GeneratedSourceMap, MappedDiagnostic, SourceMapEntry } from "../types.js";
|
|
2
|
+
export declare function writeSourceMap(map: GeneratedSourceMap): string;
|
|
3
|
+
export declare function readSourceMap(mapPath: string): GeneratedSourceMap;
|
|
4
|
+
export declare function makeGeneratedMap(generatedFilePath: string, sourceFilePath: string, entries: SourceMapEntry[]): GeneratedSourceMap;
|
|
5
|
+
export declare function mapCppLocationToTs(map: GeneratedSourceMap, cppLine: number, cppColumn: number, message?: string, cppFilePath?: string): MappedDiagnostic;
|
|
6
|
+
export declare function resolveMapPath(mapFileOrGeneratedFile: string): string;
|
|
7
|
+
/**
|
|
8
|
+
* Resolve source map path for a flattened Arduino sketch
|
|
9
|
+
* When a sketch is flattened, the source map needs to account for merged files
|
|
10
|
+
*/
|
|
11
|
+
export declare function resolveSourceMapForSketch(sketchPath: string, originalSourceMapPath?: string): string | undefined;
|
|
12
|
+
/**
|
|
13
|
+
* Index of every per-file source map in a build directory, keyed by the
|
|
14
|
+
* normalized generated file path (the .cpp/.h each map covers).
|
|
15
|
+
*
|
|
16
|
+
* Native (g++) mode compiles every .cpp in the output dir, each with its
|
|
17
|
+
* own .thcppmap.json. An error can originate in any of them, so we need to
|
|
18
|
+
* resolve the correct map per error rather than relying on a single entry
|
|
19
|
+
* map.
|
|
20
|
+
*/
|
|
21
|
+
export type SourceMapIndex = Map<string, GeneratedSourceMap>;
|
|
22
|
+
/**
|
|
23
|
+
* Load every `*.thcppmap.json` in `buildDir` (non-recursive) into an index
|
|
24
|
+
* keyed by the normalized `generatedFilePath`. Returns an empty index if the
|
|
25
|
+
* directory is missing or contains no maps.
|
|
26
|
+
*/
|
|
27
|
+
export declare function buildSourceMapIndex(buildDir: string): SourceMapIndex;
|
|
28
|
+
/**
|
|
29
|
+
* Map a g++/compiler error back to its TypeScript source span.
|
|
30
|
+
*
|
|
31
|
+
* Selects the per-file source map whose `generatedFilePath` matches the
|
|
32
|
+
* error's `filePath`, then delegates to `mapCppLocationToTs`. If the exact
|
|
33
|
+
* generated file isn't keyed (e.g. the compiler reported a differently
|
|
34
|
+
* normalized path, or the error came from a header), falls back to a
|
|
35
|
+
* directory-wide search across every loaded map.
|
|
36
|
+
*
|
|
37
|
+
* Returns a `MappedDiagnostic` whose `mappedTsSpan` is `undefined` when no
|
|
38
|
+
* map could resolve the location (the caller should treat that as a raw
|
|
39
|
+
* C++ fallback).
|
|
40
|
+
*/
|
|
41
|
+
export declare function mapCppErrorToTs(index: SourceMapIndex, error: {
|
|
42
|
+
filePath: string;
|
|
43
|
+
line: number;
|
|
44
|
+
column: number;
|
|
45
|
+
message?: string;
|
|
46
|
+
}): MappedDiagnostic;
|