@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,672 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// CppTypeIR — structured representation of a C++ type
|
|
3
|
+
//
|
|
4
|
+
// Replaces the stringly-typed `CppType = string` / `CppTypeHint` template-literal
|
|
5
|
+
// union. A C++ type is parsed once into this discriminated union and inspected by
|
|
6
|
+
// `kind` thereafter; the only place a type string is reconstructed is
|
|
7
|
+
// `renderCppType`. This eliminates the ~60+ ad-hoc `startsWith("std::vector<")` /
|
|
8
|
+
// `endsWith("*")` / `slice(len, -1)` sites scattered across `ir/` and `emit/`.
|
|
9
|
+
//
|
|
10
|
+
// ## Design notes
|
|
11
|
+
//
|
|
12
|
+
// - **Qualifiers are orthogonal wrappers.** `const`, `&`, and `*` are separate
|
|
13
|
+
// variants (`qualified` / `reference` / `pointer`) rather than baked into a
|
|
14
|
+
// string. This matches how they actually compose in `const std::vector<T>&`
|
|
15
|
+
// and lets consumers peel one layer at a time.
|
|
16
|
+
// - **Byte-identical round trip.** `renderCppType(parseCppType(s)) === s` for
|
|
17
|
+
// every type string the transpiler produces (verified by
|
|
18
|
+
// `tests/packages/cuttlefish/cpp-type-ir.test.ts`). The renderer must preserve
|
|
19
|
+
// the exact spelling the codebase already emits, including whitespace inside
|
|
20
|
+
// template argument lists (e.g. `std::variant<double, std::string>` keeps its
|
|
21
|
+
// ", " separator).
|
|
22
|
+
// - **Pseudo-types are first-class.** `__tc_StaticArray<T,N>`, `__tc_str_ptr`,
|
|
23
|
+
// `__tc_Generator<T>` all get explicit kinds so they can be matched without
|
|
24
|
+
// re-parsing. The transient value-level sentinel `__TYPED_ARRAY__:elem:size`
|
|
25
|
+
// is *not* a cppType (it lives in HAL return values) and is therefore not
|
|
26
|
+
// modeled here; the `T[N]` C-array it lowers to is modeled as `staticArray`.
|
|
27
|
+
// - **Class types are always pointers.** Per the producer's convention
|
|
28
|
+
// (type-resolution.ts:417-428) a TypeScript class reference is emitted as
|
|
29
|
+
// `ClassName*` so `new X()` never assigns to a value-typed `X`. The parser
|
|
30
|
+
// preserves this; it does not "unwrap" pointers.
|
|
31
|
+
//
|
|
32
|
+
// ## Out of scope
|
|
33
|
+
//
|
|
34
|
+
// `libdef/cpp-to-decl.ts` parses raw C++ *source text* (not IR `CppType`) along
|
|
35
|
+
// a separate pipeline; it is unaffected by and does not consume this module.
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
// Known spellings
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
const PRIMITIVE_NAMES = new Set([
|
|
41
|
+
"int", "long", "long long",
|
|
42
|
+
"unsigned int", "unsigned long", "unsigned long long",
|
|
43
|
+
"short", "unsigned short",
|
|
44
|
+
"float", "double", "long double",
|
|
45
|
+
"bool", "void",
|
|
46
|
+
"char", "signed char", "unsigned char",
|
|
47
|
+
"size_t", "ssize_t", "intptr_t", "uintptr_t", "ptrdiff_t",
|
|
48
|
+
"int8_t", "int16_t", "int32_t", "int64_t",
|
|
49
|
+
"uint8_t", "uint16_t", "uint32_t", "uint64_t",
|
|
50
|
+
]);
|
|
51
|
+
function isPrimitiveName(s) {
|
|
52
|
+
return PRIMITIVE_NAMES.has(s);
|
|
53
|
+
}
|
|
54
|
+
// ---------------------------------------------------------------------------
|
|
55
|
+
// splitTemplateArgs — the one correct nested-template-argument splitter
|
|
56
|
+
//
|
|
57
|
+
// Promoted from its private definition in type-resolution.ts. Splits a template
|
|
58
|
+
// argument list on top-level commas (depth-0), respecting nested `<>`. Returns
|
|
59
|
+
// the args with surrounding whitespace preserved (callers `.trim()` when they
|
|
60
|
+
// want canonical form). This is the only splitter in the codebase that handles
|
|
61
|
+
// `std::map<K, V>` and nested templates correctly — the half-dozen inline
|
|
62
|
+
// `slice(len, -1).split(",")` copies do not.
|
|
63
|
+
// ---------------------------------------------------------------------------
|
|
64
|
+
export function splitTemplateArgs(inner) {
|
|
65
|
+
const parts = [];
|
|
66
|
+
let depth = 0;
|
|
67
|
+
let start = 0;
|
|
68
|
+
for (let i = 0; i < inner.length; i++) {
|
|
69
|
+
const ch = inner[i];
|
|
70
|
+
if (ch === "<")
|
|
71
|
+
depth++;
|
|
72
|
+
else if (ch === ">")
|
|
73
|
+
depth--;
|
|
74
|
+
else if (ch === "," && depth === 0) {
|
|
75
|
+
parts.push(inner.slice(start, i));
|
|
76
|
+
start = i + 1;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
parts.push(inner.slice(start));
|
|
80
|
+
return parts;
|
|
81
|
+
}
|
|
82
|
+
// ---------------------------------------------------------------------------
|
|
83
|
+
// parseCppType — the single parser
|
|
84
|
+
//
|
|
85
|
+
// Peels `const` (prefix and suffix), `&`, `*`, smart pointers, and the
|
|
86
|
+
// `std::` / `__tc_` template wrappers from the outside in, then recurses into
|
|
87
|
+
// the template arguments.
|
|
88
|
+
//
|
|
89
|
+
// Returns `opaque` for any input it cannot classify, so unknown spellings
|
|
90
|
+
// survive a round trip rather than throwing.
|
|
91
|
+
// ---------------------------------------------------------------------------
|
|
92
|
+
export function parseCppType(s) {
|
|
93
|
+
const trimmed = s.trim();
|
|
94
|
+
if (trimmed === "") {
|
|
95
|
+
return { kind: "opaque", raw: s };
|
|
96
|
+
}
|
|
97
|
+
// Direct primitive hit.
|
|
98
|
+
if (isPrimitiveName(trimmed)) {
|
|
99
|
+
return { kind: "primitive", name: trimmed };
|
|
100
|
+
}
|
|
101
|
+
// Pointer suffix `T*` (greedy: collapse trailing `**`? — codebase only uses
|
|
102
|
+
// single indirection, but be conservative and peel one level).
|
|
103
|
+
if (trimmed.endsWith("*")) {
|
|
104
|
+
return { kind: "pointer", base: parseCppType(trimmed.slice(0, -1).trim()) };
|
|
105
|
+
}
|
|
106
|
+
// Reference suffix `T&`.
|
|
107
|
+
if (trimmed.endsWith("&")) {
|
|
108
|
+
const base = parseCppType(trimmed.slice(0, -1).trim());
|
|
109
|
+
return { kind: "reference", base, isConst: isConstQualified(base) };
|
|
110
|
+
}
|
|
111
|
+
// `const` prefix: `const T`. (Also matches `const T&` already peeled above.)
|
|
112
|
+
// We must be careful: `const char*` parses as `pointer(const char)`, not
|
|
113
|
+
// `qualified(const, pointer(char))`. So only peel `const ` when it is the
|
|
114
|
+
// outermost token AND the remainder is not itself a pointer/array.
|
|
115
|
+
{
|
|
116
|
+
const afterConst = peelConstPrefix(trimmed);
|
|
117
|
+
if (afterConst !== null) {
|
|
118
|
+
const inner = afterConst.trim();
|
|
119
|
+
// If peeling const leaves a pointer/reference, the const binds to the
|
|
120
|
+
// pointee (`const char*`), so don't peel — recurse into pointer branch.
|
|
121
|
+
if (!endsWithPointerOrRef(inner)) {
|
|
122
|
+
return { kind: "qualified", base: parseCppType(inner), isConst: true };
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// `const` suffix: `T const` (rare in this codebase, but legal C++).
|
|
127
|
+
{
|
|
128
|
+
const beforeSuffixConst = peelConstSuffix(trimmed);
|
|
129
|
+
if (beforeSuffixConst !== null) {
|
|
130
|
+
return { kind: "qualified", base: parseCppType(beforeSuffixConst.trim()), isConst: true };
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// Template form `Name<...>`: dispatch on the head name.
|
|
134
|
+
const templ = matchTemplate(trimmed);
|
|
135
|
+
if (templ) {
|
|
136
|
+
const { head, inner } = templ;
|
|
137
|
+
switch (head) {
|
|
138
|
+
case "std::vector":
|
|
139
|
+
return { kind: "vector", element: parseCppType(splitTemplateArgs(inner)[0].trim()) };
|
|
140
|
+
case "std::set":
|
|
141
|
+
case "std::unordered_set":
|
|
142
|
+
return { kind: "set", element: parseCppType(splitTemplateArgs(inner)[0].trim()) };
|
|
143
|
+
case "std::map":
|
|
144
|
+
case "std::unordered_map": {
|
|
145
|
+
const args = splitTemplateArgs(inner).map((a) => parseCppType(a.trim()));
|
|
146
|
+
return { kind: "map", key: args[0] ?? { kind: "opaque", raw: "" }, value: args[1] ?? { kind: "opaque", raw: "" } };
|
|
147
|
+
}
|
|
148
|
+
case "std::tuple":
|
|
149
|
+
return { kind: "tuple", elements: splitTemplateArgs(inner).map((a) => parseCppType(a.trim())) };
|
|
150
|
+
case "std::variant":
|
|
151
|
+
return { kind: "variant", members: splitTemplateArgs(inner).map((a) => parseCppType(a.trim())) };
|
|
152
|
+
case "std::function":
|
|
153
|
+
return parseStdFunction(inner);
|
|
154
|
+
case "std::shared_ptr":
|
|
155
|
+
case "std::unique_ptr":
|
|
156
|
+
return { kind: "smartPointer", wrapper: head, inner: parseCppType(splitTemplateArgs(inner)[0].trim()) };
|
|
157
|
+
case "__tc_StaticArray": {
|
|
158
|
+
const args = splitTemplateArgs(inner).map((a) => parseCppType(a.trim()));
|
|
159
|
+
const sizeNode = args[1];
|
|
160
|
+
const size = sizeNode && sizeNode.kind === "opaque" && /^\d+$/.test(sizeNode.raw.trim())
|
|
161
|
+
? Number(sizeNode.raw.trim())
|
|
162
|
+
: undefined;
|
|
163
|
+
return { kind: "staticArray", element: args[0] ?? { kind: "opaque", raw: "" }, size };
|
|
164
|
+
}
|
|
165
|
+
case "__tc_Generator":
|
|
166
|
+
return { kind: "generator", yieldType: parseCppType(splitTemplateArgs(inner)[0].trim()) };
|
|
167
|
+
default:
|
|
168
|
+
// Generic user template: `MyClass<T, U>` or `std::something_unmodeled<…>`.
|
|
169
|
+
return { kind: "named", name: head, args: splitTemplateArgs(inner).map((a) => parseCppType(a.trim())) };
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
// `__tc_str_ptr` — may carry no argument in current usage.
|
|
173
|
+
if (trimmed === "__tc_str_ptr") {
|
|
174
|
+
return { kind: "strPtr" };
|
|
175
|
+
}
|
|
176
|
+
// `__tc_str_ptr(inner)` form (value-level wrap; the inner is an expression,
|
|
177
|
+
// not a type, so we keep it opaque).
|
|
178
|
+
if (trimmed.startsWith("__tc_str_ptr(") && trimmed.endsWith(")")) {
|
|
179
|
+
return { kind: "strPtr" };
|
|
180
|
+
}
|
|
181
|
+
// `std::string` literal.
|
|
182
|
+
if (trimmed === "std::string") {
|
|
183
|
+
return { kind: "string" };
|
|
184
|
+
}
|
|
185
|
+
if (trimmed === "auto") {
|
|
186
|
+
return { kind: "auto" };
|
|
187
|
+
}
|
|
188
|
+
// `const char*` — common enough to model explicitly as pointer(primitive char)
|
|
189
|
+
// qualified const; but to keep round-tripping byte-identical, prefer letting
|
|
190
|
+
// the named-with-const-prefix path handle it. We land here for the bare
|
|
191
|
+
// `char` case via the named branch below.
|
|
192
|
+
// C-array forms `T[N]` / `T[]` (e.g. `uint8_t[16]`, `int[]`). These are
|
|
193
|
+
// emitted by HAL lowering (variables.ts) and parsed by element-access code.
|
|
194
|
+
{
|
|
195
|
+
const arr = matchCArray(trimmed);
|
|
196
|
+
if (arr) {
|
|
197
|
+
const { element, size } = arr;
|
|
198
|
+
// Use `staticArray` when a concrete size is present (matches the
|
|
199
|
+
// existing `T[N]` lowering), `cArray` when it's `T[]`.
|
|
200
|
+
return size !== undefined
|
|
201
|
+
? { kind: "staticArray", element: parseCppType(element), size }
|
|
202
|
+
: { kind: "cArray", element: parseCppType(element) };
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
// Otherwise: a bare named type (struct/class/enum/typedef/typename).
|
|
206
|
+
// Allow identifier-ish names including `::` scopes (e.g. `std::string`
|
|
207
|
+
// already handled above; `Foo::Bar` is a named type).
|
|
208
|
+
if (isValidTypeName(trimmed)) {
|
|
209
|
+
return { kind: "named", name: trimmed };
|
|
210
|
+
}
|
|
211
|
+
// Last resort: preserve verbatim.
|
|
212
|
+
return { kind: "opaque", raw: s };
|
|
213
|
+
}
|
|
214
|
+
function parseStdFunction(inner) {
|
|
215
|
+
// `inner` is `R(P, Q, ...)` where `R` itself may be a function type.
|
|
216
|
+
// Find the *last* top-level `(` so the head is the return type and the
|
|
217
|
+
// tail is the parameter list.
|
|
218
|
+
let depth = 0;
|
|
219
|
+
let parenIdx = -1;
|
|
220
|
+
for (let i = inner.length - 1; i >= 0; i--) {
|
|
221
|
+
const ch = inner[i];
|
|
222
|
+
if (ch === ")")
|
|
223
|
+
depth++;
|
|
224
|
+
else if (ch === "(") {
|
|
225
|
+
depth--;
|
|
226
|
+
if (depth === 0) {
|
|
227
|
+
parenIdx = i;
|
|
228
|
+
break;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
if (parenIdx < 0) {
|
|
233
|
+
return { kind: "function", returnType: parseCppType(inner.trim()), params: [] };
|
|
234
|
+
}
|
|
235
|
+
const returnTypeStr = inner.slice(0, parenIdx).trim();
|
|
236
|
+
const paramsStr = inner.slice(parenIdx + 1, inner.lastIndexOf(")")).trim();
|
|
237
|
+
const params = paramsStr === ""
|
|
238
|
+
? []
|
|
239
|
+
: splitFunctionParams(paramsStr).map((p) => parseCppType(p.trim()));
|
|
240
|
+
return { kind: "function", returnType: parseCppType(returnTypeStr), params };
|
|
241
|
+
}
|
|
242
|
+
/** Split a function parameter list on top-level commas, respecting `()` and `<>`. */
|
|
243
|
+
function splitFunctionParams(s) {
|
|
244
|
+
const parts = [];
|
|
245
|
+
let depth = 0;
|
|
246
|
+
let start = 0;
|
|
247
|
+
for (let i = 0; i < s.length; i++) {
|
|
248
|
+
const ch = s[i];
|
|
249
|
+
if (ch === "(" || ch === "<")
|
|
250
|
+
depth++;
|
|
251
|
+
else if (ch === ")" || ch === ">")
|
|
252
|
+
depth--;
|
|
253
|
+
else if (ch === "," && depth === 0) {
|
|
254
|
+
parts.push(s.slice(start, i));
|
|
255
|
+
start = i + 1;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
parts.push(s.slice(start));
|
|
259
|
+
return parts;
|
|
260
|
+
}
|
|
261
|
+
/** If `s` ends with `>` and has a top-level `<`, split into `head` and the
|
|
262
|
+
* raw inner string (whitespace preserved). Returns null otherwise. */
|
|
263
|
+
function matchTemplate(s) {
|
|
264
|
+
if (!s.endsWith(">"))
|
|
265
|
+
return null;
|
|
266
|
+
// Locate the *matching* opening `<` for the final `>`.
|
|
267
|
+
let depth = 0;
|
|
268
|
+
let openIdx = -1;
|
|
269
|
+
for (let i = s.length - 1; i >= 0; i--) {
|
|
270
|
+
const ch = s[i];
|
|
271
|
+
if (ch === ">")
|
|
272
|
+
depth++;
|
|
273
|
+
else if (ch === "<") {
|
|
274
|
+
depth--;
|
|
275
|
+
if (depth === 0) {
|
|
276
|
+
openIdx = i;
|
|
277
|
+
break;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
if (openIdx < 0)
|
|
282
|
+
return null;
|
|
283
|
+
const head = s.slice(0, openIdx);
|
|
284
|
+
// Reject `head` that itself looks like a pointer/array tail, e.g. `int*<…>`.
|
|
285
|
+
if (!isValidTypeName(head.trim()))
|
|
286
|
+
return null;
|
|
287
|
+
const inner = s.slice(openIdx + 1, s.length - 1);
|
|
288
|
+
return { head: head.trim(), inner };
|
|
289
|
+
}
|
|
290
|
+
function matchCArray(s) {
|
|
291
|
+
// `T[N]` or `T[]`. Use the *last* `[` to find the array suffix.
|
|
292
|
+
if (!s.endsWith("]"))
|
|
293
|
+
return null;
|
|
294
|
+
const openIdx = s.lastIndexOf("[");
|
|
295
|
+
if (openIdx < 0)
|
|
296
|
+
return null;
|
|
297
|
+
const element = s.slice(0, openIdx).trim();
|
|
298
|
+
const sizeStr = s.slice(openIdx + 1, s.length - 1).trim();
|
|
299
|
+
if (sizeStr === "")
|
|
300
|
+
return { element };
|
|
301
|
+
if (/^\d+$/.test(sizeStr))
|
|
302
|
+
return { element, size: Number(sizeStr) };
|
|
303
|
+
return null;
|
|
304
|
+
}
|
|
305
|
+
function peelConstPrefix(s) {
|
|
306
|
+
return s.startsWith("const ") ? s.slice("const ".length) : null;
|
|
307
|
+
}
|
|
308
|
+
function peelConstSuffix(s) {
|
|
309
|
+
return s.endsWith(" const") ? s.slice(0, -" const".length) : null;
|
|
310
|
+
}
|
|
311
|
+
function endsWithPointerOrRef(s) {
|
|
312
|
+
return s.endsWith("*") || s.endsWith("&");
|
|
313
|
+
}
|
|
314
|
+
function isConstQualified(ir) {
|
|
315
|
+
return ir.kind === "qualified" && ir.isConst;
|
|
316
|
+
}
|
|
317
|
+
function isValidTypeName(s) {
|
|
318
|
+
// Identifier-ish, possibly scoped with `::`. Used only to decide whether to
|
|
319
|
+
// accept a `head` or `bare` token as a type name.
|
|
320
|
+
return /^(?:[A-Za-z_][A-Za-z0-9_]*)(?:::[A-Za-z_][A-Za-z0-9_]*)*$/.test(s);
|
|
321
|
+
}
|
|
322
|
+
// ---------------------------------------------------------------------------
|
|
323
|
+
// renderCppType — the single renderer
|
|
324
|
+
//
|
|
325
|
+
// Must be byte-identical to the historical spelling for every type string the
|
|
326
|
+
// transpiler emits. In particular:
|
|
327
|
+
// - template args are joined with ", "
|
|
328
|
+
// - `vector`/`map`/`set`/`tuple`/`variant` use the `std::` prefix
|
|
329
|
+
// - `__tc_StaticArray<T, N>` joins element and size with ", "
|
|
330
|
+
// - pointers print as `${base}*` (no space); references as `${base}&`
|
|
331
|
+
// - qualified-const prints as `const ${base}` (prefix form, matching producer)
|
|
332
|
+
// ---------------------------------------------------------------------------
|
|
333
|
+
export function renderCppType(ir) {
|
|
334
|
+
switch (ir.kind) {
|
|
335
|
+
case "primitive": return ir.name;
|
|
336
|
+
case "auto": return "auto";
|
|
337
|
+
case "string": return "std::string";
|
|
338
|
+
case "strPtr": return "__tc_str_ptr";
|
|
339
|
+
case "opaque": return ir.raw;
|
|
340
|
+
case "named":
|
|
341
|
+
return ir.args && ir.args.length > 0
|
|
342
|
+
? `${ir.name}<${ir.args.map(renderCppType).join(", ")}>`
|
|
343
|
+
: ir.name;
|
|
344
|
+
case "pointer": return `${renderCppType(ir.base)}*`;
|
|
345
|
+
case "reference": return `${renderCppType(ir.base)}&`;
|
|
346
|
+
case "qualified": return ir.isConst ? `const ${renderCppType(ir.base)}` : renderCppType(ir.base);
|
|
347
|
+
case "vector": return `std::vector<${renderCppType(ir.element)}>`;
|
|
348
|
+
case "set": return `std::set<${renderCppType(ir.element)}>`;
|
|
349
|
+
case "map": return `std::map<${renderCppType(ir.key)}, ${renderCppType(ir.value)}>`;
|
|
350
|
+
case "tuple": return `std::tuple<${ir.elements.map(renderCppType).join(", ")}>`;
|
|
351
|
+
case "variant": return `std::variant<${ir.members.map(renderCppType).join(", ")}>`;
|
|
352
|
+
case "function": {
|
|
353
|
+
const params = ir.params.map(renderCppType).join(", ");
|
|
354
|
+
return `std::function<${renderCppType(ir.returnType)}(${params})>`;
|
|
355
|
+
}
|
|
356
|
+
case "staticArray":
|
|
357
|
+
return ir.size !== undefined
|
|
358
|
+
? `__tc_StaticArray<${renderCppType(ir.element)}, ${ir.size}>`
|
|
359
|
+
: `__tc_StaticArray<${renderCppType(ir.element)}>`;
|
|
360
|
+
case "cArray":
|
|
361
|
+
return ir.size !== undefined
|
|
362
|
+
? `${renderCppType(ir.element)}[${ir.size}]`
|
|
363
|
+
: `${renderCppType(ir.element)}[]`;
|
|
364
|
+
case "generator": return `__tc_Generator<${renderCppType(ir.yieldType)}>`;
|
|
365
|
+
case "smartPointer": return `${ir.wrapper}<${renderCppType(ir.inner)}>`;
|
|
366
|
+
default: {
|
|
367
|
+
// Exhaustiveness guard.
|
|
368
|
+
const _exhaustive = ir;
|
|
369
|
+
void _exhaustive;
|
|
370
|
+
return "";
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
// ---------------------------------------------------------------------------
|
|
375
|
+
// Predicate helpers — thin wrappers that replace inline string inspection.
|
|
376
|
+
//
|
|
377
|
+
// These cover the recurring idioms found across `ir/` and `emit/`:
|
|
378
|
+
// `endsWith("*")` → `isPointer`; `startsWith("std::vector<")` → `isVector`;
|
|
379
|
+
// `startsWith("std::map<") || startsWith("std::set<")` → `isAssociative`;
|
|
380
|
+
// etc.
|
|
381
|
+
// ---------------------------------------------------------------------------
|
|
382
|
+
/** True for `T*` (any depth of indirection). */
|
|
383
|
+
export function isPointer(ir) {
|
|
384
|
+
return ir.kind === "pointer";
|
|
385
|
+
}
|
|
386
|
+
/** True for `T&` (and `const T&`). */
|
|
387
|
+
export function isReference(ir) {
|
|
388
|
+
return ir.kind === "reference";
|
|
389
|
+
}
|
|
390
|
+
/** True for any container that supports element/index access:
|
|
391
|
+
* vector, set, map, staticArray, cArray. */
|
|
392
|
+
export function isContainer(ir) {
|
|
393
|
+
return ir.kind === "vector" || ir.kind === "set" || ir.kind === "map"
|
|
394
|
+
|| ir.kind === "staticArray" || ir.kind === "cArray";
|
|
395
|
+
}
|
|
396
|
+
export function isVector(ir) { return ir.kind === "vector"; }
|
|
397
|
+
export function isMap(ir) { return ir.kind === "map"; }
|
|
398
|
+
export function isSet(ir) { return ir.kind === "set"; }
|
|
399
|
+
export function isTuple(ir) { return ir.kind === "tuple"; }
|
|
400
|
+
export function isVariant(ir) { return ir.kind === "variant"; }
|
|
401
|
+
export function isStdFunction(ir) { return ir.kind === "function"; }
|
|
402
|
+
export function isStaticArray(ir) { return ir.kind === "staticArray"; }
|
|
403
|
+
export function isCArray(ir) { return ir.kind === "cArray"; }
|
|
404
|
+
/** True for `std::string` / `__tc_str_ptr` / `const char*`-ish string types.
|
|
405
|
+
* Does NOT consult platform strategy — callers that need platform-aware string
|
|
406
|
+
* detection (e.g. Arduino `String`) should still call `strategy.isStringLikeType`. */
|
|
407
|
+
export function isStringLike(ir) {
|
|
408
|
+
if (ir.kind === "string" || ir.kind === "strPtr")
|
|
409
|
+
return true;
|
|
410
|
+
if (ir.kind === "pointer") {
|
|
411
|
+
const pointee = ir.base.kind === "qualified" ? ir.base.base : ir.base;
|
|
412
|
+
return pointee.kind === "primitive"
|
|
413
|
+
&& (pointee.name === "char" || pointee.name === "signed char" || pointee.name === "unsigned char");
|
|
414
|
+
}
|
|
415
|
+
return false;
|
|
416
|
+
}
|
|
417
|
+
/** True for builtin scalars (`int`, `double`, …) and `std::string`/`bool`.
|
|
418
|
+
* Corresponds to the `isPrimitiveCppType` helpers in statement-renderer. */
|
|
419
|
+
export function isPrimitive(ir) {
|
|
420
|
+
if (ir.kind === "primitive")
|
|
421
|
+
return true;
|
|
422
|
+
if (ir.kind === "qualified")
|
|
423
|
+
return isPrimitive(ir.base);
|
|
424
|
+
return false;
|
|
425
|
+
}
|
|
426
|
+
/** Peel pointer/reference/const qualification and return the underlying type.
|
|
427
|
+
* `Foo*` → `Foo`, `const Bar&` → `Bar`, `std::vector<T>*` → `std::vector<T>`.
|
|
428
|
+
* Corresponds to the `replace(/\*$/, "").replace(/^const\s+/, "").trim()`
|
|
429
|
+
* idiom scattered through expression-renderer / setup. */
|
|
430
|
+
export function bareType(ir) {
|
|
431
|
+
let cur = ir;
|
|
432
|
+
while (true) {
|
|
433
|
+
if (cur.kind === "pointer" || cur.kind === "reference") {
|
|
434
|
+
cur = cur.base;
|
|
435
|
+
}
|
|
436
|
+
else if (cur.kind === "qualified") {
|
|
437
|
+
cur = cur.base;
|
|
438
|
+
}
|
|
439
|
+
else {
|
|
440
|
+
return cur;
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
/** Element type of a vector/set/staticArray/cArray, or the value type of a map.
|
|
445
|
+
* Returns undefined for non-containers. Replaces the duplicated
|
|
446
|
+
* `slice("std::vector<".length, -1).trim()` copies. */
|
|
447
|
+
export function elementOf(ir) {
|
|
448
|
+
switch (ir.kind) {
|
|
449
|
+
case "vector":
|
|
450
|
+
case "set":
|
|
451
|
+
case "staticArray":
|
|
452
|
+
case "cArray":
|
|
453
|
+
return ir.element;
|
|
454
|
+
case "map":
|
|
455
|
+
return ir.value;
|
|
456
|
+
default:
|
|
457
|
+
return undefined;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
export function formatKindOf(ir) {
|
|
461
|
+
// `char*` / `const char*` are C-strings (%s), not single chars (%c).
|
|
462
|
+
// Must be checked BEFORE the generic pointer branch.
|
|
463
|
+
if (isCharPointer(ir))
|
|
464
|
+
return "string";
|
|
465
|
+
// Any other pointer → %p-ish dispatch bucket. Checked before bareType()
|
|
466
|
+
// strips the pointer.
|
|
467
|
+
if (ir.kind === "pointer")
|
|
468
|
+
return "pointer";
|
|
469
|
+
const bare = bareType(ir);
|
|
470
|
+
if (bare.kind === "string" || bare.kind === "strPtr")
|
|
471
|
+
return "string";
|
|
472
|
+
if (bare.kind === "primitive") {
|
|
473
|
+
switch (bare.name) {
|
|
474
|
+
case "bool": return "bool";
|
|
475
|
+
case "char":
|
|
476
|
+
case "signed char":
|
|
477
|
+
case "unsigned char": return "char";
|
|
478
|
+
case "float":
|
|
479
|
+
case "double":
|
|
480
|
+
case "long double": return "float";
|
|
481
|
+
case "int":
|
|
482
|
+
case "short": return "int";
|
|
483
|
+
case "unsigned int":
|
|
484
|
+
case "unsigned short":
|
|
485
|
+
case "uint8_t":
|
|
486
|
+
case "uint16_t": return "uint";
|
|
487
|
+
case "long":
|
|
488
|
+
case "int32_t":
|
|
489
|
+
case "int64_t": return "long";
|
|
490
|
+
case "unsigned long":
|
|
491
|
+
case "unsigned long long":
|
|
492
|
+
case "long long":
|
|
493
|
+
case "uint32_t":
|
|
494
|
+
case "uint64_t":
|
|
495
|
+
case "size_t":
|
|
496
|
+
case "uintptr_t": return "ulong";
|
|
497
|
+
default: return "other";
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
return "other";
|
|
501
|
+
}
|
|
502
|
+
/** True for `char*`, `const char*`, `signed char*`, etc. — C-strings, not
|
|
503
|
+
* pointers-to-single-chars. Drives `%s` formatting in snprintf dispatch. */
|
|
504
|
+
function isCharPointer(ir) {
|
|
505
|
+
if (ir.kind !== "pointer")
|
|
506
|
+
return false;
|
|
507
|
+
const pointee = ir.base.kind === "qualified" ? ir.base.base : ir.base;
|
|
508
|
+
return pointee.kind === "primitive"
|
|
509
|
+
&& (pointee.name === "char" || pointee.name === "signed char" || pointee.name === "unsigned char");
|
|
510
|
+
}
|
|
511
|
+
// ---------------------------------------------------------------------------
|
|
512
|
+
// Builder helpers — replace inline `${x}*` / `std::vector<${x}>` construction.
|
|
513
|
+
// ---------------------------------------------------------------------------
|
|
514
|
+
export const CppTypeIR = {
|
|
515
|
+
primitive: (name) => ({ kind: "primitive", name }),
|
|
516
|
+
auto: () => ({ kind: "auto" }),
|
|
517
|
+
string: () => ({ kind: "string" }),
|
|
518
|
+
bool: () => ({ kind: "primitive", name: "bool" }),
|
|
519
|
+
void: () => ({ kind: "primitive", name: "void" }),
|
|
520
|
+
int: () => ({ kind: "primitive", name: "int" }),
|
|
521
|
+
double: () => ({ kind: "primitive", name: "double" }),
|
|
522
|
+
named: (name, args) => ({ kind: "named", name, args }),
|
|
523
|
+
pointer: (base) => ({ kind: "pointer", base }),
|
|
524
|
+
reference: (base, isConst = false) => ({ kind: "reference", base, isConst }),
|
|
525
|
+
const_: (base) => ({ kind: "qualified", base, isConst: true }),
|
|
526
|
+
vector: (element) => ({ kind: "vector", element }),
|
|
527
|
+
set: (element) => ({ kind: "set", element }),
|
|
528
|
+
map: (key, value) => ({ kind: "map", key, value }),
|
|
529
|
+
tuple: (elements) => ({ kind: "tuple", elements }),
|
|
530
|
+
variant: (members) => ({ kind: "variant", members }),
|
|
531
|
+
function: (returnType, params) => ({ kind: "function", returnType, params }),
|
|
532
|
+
staticArray: (element, size) => ({ kind: "staticArray", element, size }),
|
|
533
|
+
cArray: (element, size) => ({ kind: "cArray", element, size }),
|
|
534
|
+
generator: (yieldType) => ({ kind: "generator", yieldType }),
|
|
535
|
+
smartPointer: (wrapper, inner) => ({ kind: "smartPointer", wrapper, inner }),
|
|
536
|
+
strPtr: () => ({ kind: "strPtr" }),
|
|
537
|
+
opaque: (raw) => ({ kind: "opaque", raw }),
|
|
538
|
+
};
|
|
539
|
+
// ---------------------------------------------------------------------------
|
|
540
|
+
// Convenience: parse-then-inspect. Lets call sites that today do
|
|
541
|
+
// `cppType.endsWith("*")` become `parsedIsPointer(cppType)` while `CppType`
|
|
542
|
+
// is still a string during the staged migration.
|
|
543
|
+
// ---------------------------------------------------------------------------
|
|
544
|
+
export function parsedIsPointer(cppType) { return isPointer(parseCppType(cppType)); }
|
|
545
|
+
export function parsedIsStringLike(cppType) { return isStringLike(parseCppType(cppType)); }
|
|
546
|
+
export function parsedIsPrimitive(cppType) { return isPrimitive(parseCppType(cppType)); }
|
|
547
|
+
export function parsedIsContainer(cppType) { return isContainer(parseCppType(cppType)); }
|
|
548
|
+
export function parsedIsVector(cppType) { return isVector(parseCppType(cppType)); }
|
|
549
|
+
export function parsedIsMap(cppType) { return isMap(parseCppType(cppType)); }
|
|
550
|
+
export function parsedIsSet(cppType) { return isSet(parseCppType(cppType)); }
|
|
551
|
+
export function parsedIsTuple(cppType) { return isTuple(parseCppType(cppType)); }
|
|
552
|
+
export function parsedIsVariant(cppType) { return isVariant(parseCppType(cppType)); }
|
|
553
|
+
export function parsedIsStaticArray(cppType) { return isStaticArray(parseCppType(cppType)); }
|
|
554
|
+
/** True for `std::string` (and `std::string&`, `const std::string`, etc.). */
|
|
555
|
+
export function parsedIsStdString(cppType) {
|
|
556
|
+
const ir = parseCppType(cppType);
|
|
557
|
+
return bareType(ir).kind === "string";
|
|
558
|
+
}
|
|
559
|
+
export function parsedElementOf(cppType) { return elementOf(parseCppType(cppType)); }
|
|
560
|
+
/** Element/value type of a container, rendered back to a string. Replaces the
|
|
561
|
+
* `slice("std::vector<".length, -1).trim()` idiom at consumer sites. */
|
|
562
|
+
export function parsedElementString(cppType) {
|
|
563
|
+
const e = elementOf(parseCppType(cppType));
|
|
564
|
+
return e ? renderCppType(e) : undefined;
|
|
565
|
+
}
|
|
566
|
+
/** Bare (pointer/const/reference-stripped) type rendered as a string. Replaces
|
|
567
|
+
* `cppType.replace(/\*$/, "").replace(/^const\s+/, "").trim()` at consumer sites. */
|
|
568
|
+
export function parsedBareString(cppType) { return renderCppType(bareType(parseCppType(cppType))); }
|
|
569
|
+
export function parsedBareType(cppType) { return bareType(parseCppType(cppType)); }
|
|
570
|
+
/**
|
|
571
|
+
* Collect every user-named type referenced anywhere inside a C++ type string
|
|
572
|
+
* (including nested template args, pointer bases, vector elements, etc.).
|
|
573
|
+
* Replaces the historical "match all identifiers then filter primitives"
|
|
574
|
+
* idiom used for dependency tracking in call-graph analysis.
|
|
575
|
+
*
|
|
576
|
+
* Returns only `named`-kind names — primitives, `std::string`, `auto`, etc.
|
|
577
|
+
* are excluded because they are not user-defined types.
|
|
578
|
+
*/
|
|
579
|
+
export function collectNamedTypes(ir) {
|
|
580
|
+
const out = [];
|
|
581
|
+
const walk = (node) => {
|
|
582
|
+
switch (node.kind) {
|
|
583
|
+
case "named":
|
|
584
|
+
out.push(node.name);
|
|
585
|
+
if (node.args)
|
|
586
|
+
for (const a of node.args)
|
|
587
|
+
walk(a);
|
|
588
|
+
break;
|
|
589
|
+
case "pointer":
|
|
590
|
+
case "reference":
|
|
591
|
+
case "qualified":
|
|
592
|
+
walk(node.base);
|
|
593
|
+
break;
|
|
594
|
+
case "vector":
|
|
595
|
+
case "set":
|
|
596
|
+
case "staticArray":
|
|
597
|
+
case "cArray":
|
|
598
|
+
walk(node.element);
|
|
599
|
+
break;
|
|
600
|
+
case "generator":
|
|
601
|
+
walk(node.yieldType);
|
|
602
|
+
break;
|
|
603
|
+
case "smartPointer":
|
|
604
|
+
walk(node.inner);
|
|
605
|
+
break;
|
|
606
|
+
case "map":
|
|
607
|
+
walk(node.key);
|
|
608
|
+
walk(node.value);
|
|
609
|
+
break;
|
|
610
|
+
case "tuple":
|
|
611
|
+
for (const m of node.elements)
|
|
612
|
+
walk(m);
|
|
613
|
+
break;
|
|
614
|
+
case "variant":
|
|
615
|
+
for (const m of node.members)
|
|
616
|
+
walk(m);
|
|
617
|
+
break;
|
|
618
|
+
case "function":
|
|
619
|
+
walk(node.returnType);
|
|
620
|
+
for (const p of node.params)
|
|
621
|
+
walk(p);
|
|
622
|
+
break;
|
|
623
|
+
default:
|
|
624
|
+
// primitive, auto, string, strPtr, opaque — no named children.
|
|
625
|
+
break;
|
|
626
|
+
}
|
|
627
|
+
};
|
|
628
|
+
walk(ir);
|
|
629
|
+
return out;
|
|
630
|
+
}
|
|
631
|
+
/** String-in convenience for `collectNamedTypes(parseCppType(s))`. */
|
|
632
|
+
export function parsedCollectNamedTypes(cppType) {
|
|
633
|
+
return collectNamedTypes(parseCppType(cppType));
|
|
634
|
+
}
|
|
635
|
+
/** True if the type is a plain struct/class name with no template args, pointer,
|
|
636
|
+
* reference, array, or container wrapper — i.e. the kind of type that a
|
|
637
|
+
* `return null` should lower to `return {};` (value-init).
|
|
638
|
+
* Replaces the `!includes("<") && !endsWith("*") && !endsWith("]")` idiom. */
|
|
639
|
+
export function parsedIsPlainStructType(cppType) {
|
|
640
|
+
const ir = parseCppType(cppType);
|
|
641
|
+
const bare = bareType(ir);
|
|
642
|
+
if (bare.kind !== "named")
|
|
643
|
+
return false;
|
|
644
|
+
if (bare.args && bare.args.length > 0)
|
|
645
|
+
return false;
|
|
646
|
+
return true;
|
|
647
|
+
}
|
|
648
|
+
/**
|
|
649
|
+
* True for types that own a string buffer and therefore need `.c_str()` when
|
|
650
|
+
* passed to a C variadic (printf/snprintf): `std::string`, `__tc_str_ptr`,
|
|
651
|
+
* and platform string types like Arduino `String`. NOT true for `const char*`
|
|
652
|
+
* / `char*`, which are already C-strings.
|
|
653
|
+
*
|
|
654
|
+
* This is the structured replacement for the
|
|
655
|
+
* `normalized === "std::string" || normalized === "String" || normalized === "__tc_str_ptr"`
|
|
656
|
+
* idiom in the snprintf/expression renderers.
|
|
657
|
+
*/
|
|
658
|
+
export function needsCStrForStringLike(cppType) {
|
|
659
|
+
const ir = parseCppType(cppType);
|
|
660
|
+
// A top-level pointer (char*) is already a C-string — no .c_str() needed.
|
|
661
|
+
if (ir.kind === "pointer")
|
|
662
|
+
return false;
|
|
663
|
+
// Peel const/reference wrappers to reach the underlying category.
|
|
664
|
+
let node = ir;
|
|
665
|
+
while (node.kind === "qualified" || node.kind === "reference") {
|
|
666
|
+
node = node.base;
|
|
667
|
+
if (node.kind === "pointer")
|
|
668
|
+
return false;
|
|
669
|
+
}
|
|
670
|
+
return node.kind === "string" || node.kind === "strPtr"
|
|
671
|
+
|| (node.kind === "named" && node.name === "String");
|
|
672
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ResolvedDisplay } from "./display-profile.js";
|
|
2
|
+
export interface DisplayAdapterCode {
|
|
3
|
+
/** C++ #include lines (e.g. "#include <Adafruit_ILI9341.h>"). */
|
|
4
|
+
includes: string;
|
|
5
|
+
/** C++ display object declaration (e.g. "Adafruit_ILI9341 __tc_display = ..."). */
|
|
6
|
+
declaration: string;
|
|
7
|
+
/** C++ static inline adapter functions (display_init, display_fillScreen, etc.). */
|
|
8
|
+
functions: string;
|
|
9
|
+
}
|
|
10
|
+
export type DisplayAdapterGenerator = (display: ResolvedDisplay) => DisplayAdapterCode;
|
|
11
|
+
export declare function registerDisplayAdapter(driver: string, gen: DisplayAdapterGenerator): void;
|
|
12
|
+
export declare function generateDisplayAdapter(display: ResolvedDisplay): DisplayAdapterCode;
|