@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,608 @@
|
|
|
1
|
+
import ts from "typescript";
|
|
2
|
+
import { extractNodeComments, makeSourceSpan } from "./ast-node-utils.js";
|
|
3
|
+
import { typeNodeToCppType, extractOwnershipKindFromTypeNode } from "./type-resolution.js";
|
|
4
|
+
import { getBitsRange, getRegisterAddress } from "./register-decorators.js";
|
|
5
|
+
import { registerFieldMap, setActiveExtendsClass, discriminatedUnionVariantNames, requiredIncludes } from "./build-ir-state.js";
|
|
6
|
+
import { getCurrentIrTypeScope } from "./symbol-types.js";
|
|
7
|
+
import { expressionToIR } from "./expression-to-ir.js";
|
|
8
|
+
import { lowerStatementList } from "./statement-to-ir.js";
|
|
9
|
+
/**
|
|
10
|
+
* Format an `ExpressionWithTypeArguments` (a heritage-clause type) as a C++
|
|
11
|
+
* base-class specifier, resolving each type argument through `typeNodeToCppType`.
|
|
12
|
+
* `extends Registry<string, number>` → `Registry<std::string, double>`.
|
|
13
|
+
* Without this, `.expression.getText()` drops the type arguments and leaves
|
|
14
|
+
* the base as an unsubstituted template.
|
|
15
|
+
*/
|
|
16
|
+
function formatHeritageType(heritage, typeAliasNodes) {
|
|
17
|
+
const baseName = heritage.expression.getText();
|
|
18
|
+
if (!heritage.typeArguments || heritage.typeArguments.length === 0) {
|
|
19
|
+
return baseName;
|
|
20
|
+
}
|
|
21
|
+
const args = heritage.typeArguments.map(ta => typeNodeToCppType(ta, typeAliasNodes));
|
|
22
|
+
return `${baseName}<${args.join(", ")}>`;
|
|
23
|
+
}
|
|
24
|
+
export function classDeclarationToIR(node, fileName, sourceText, diagnostics, functionReturnTypes, typeAliasNodes, registerClasses, pointerVars = new Map(), scopePrefix) {
|
|
25
|
+
if (!node.name) {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
const className = node.name.text;
|
|
29
|
+
const regAddr = getRegisterAddress(node);
|
|
30
|
+
if (regAddr !== undefined) {
|
|
31
|
+
const classComments = extractNodeComments(node, sourceText);
|
|
32
|
+
const bitFields = [];
|
|
33
|
+
for (const member of node.members) {
|
|
34
|
+
if (ts.isPropertyDeclaration(member) && member.name && ts.isIdentifier(member.name)) {
|
|
35
|
+
const range = getBitsRange(member);
|
|
36
|
+
if (range) {
|
|
37
|
+
bitFields.push({
|
|
38
|
+
name: member.name.text,
|
|
39
|
+
hi: range.hi,
|
|
40
|
+
lo: range.lo,
|
|
41
|
+
width: range.hi - range.lo + 1,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
const regIR = {
|
|
47
|
+
name: className,
|
|
48
|
+
address: regAddr,
|
|
49
|
+
bitFields,
|
|
50
|
+
sourceSpan: makeSourceSpan(node, fileName, sourceText),
|
|
51
|
+
leadingComments: classComments.leadingComments,
|
|
52
|
+
trailingComments: classComments.trailingComments,
|
|
53
|
+
};
|
|
54
|
+
registerClasses.push(regIR);
|
|
55
|
+
const fieldMap = new Map();
|
|
56
|
+
for (const bf of bitFields) {
|
|
57
|
+
fieldMap.set(bf.name, { hi: bf.hi, lo: bf.lo, width: bf.width });
|
|
58
|
+
}
|
|
59
|
+
registerFieldMap.set(className, fieldMap);
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
const isAbstract = node.modifiers?.some(m => m.kind === ts.SyntaxKind.AbstractKeyword) ?? false;
|
|
63
|
+
// Render the extends-clause type, INCLUDING type arguments, so a subclass of
|
|
64
|
+
// a generic base (`extends Registry<string, number>`) lowers to
|
|
65
|
+
// `: public Registry<std::string, double>` rather than dropping the
|
|
66
|
+
// instantiation (which would leave the base as an unsubstituted template).
|
|
67
|
+
const extendsHeritage = node.heritageClauses
|
|
68
|
+
?.find((clause) => clause.token === ts.SyntaxKind.ExtendsKeyword)
|
|
69
|
+
?.types[0];
|
|
70
|
+
const extendsClass = extendsHeritage ? formatHeritageType(extendsHeritage, typeAliasNodes) : undefined;
|
|
71
|
+
const implementsInterfaces = node.heritageClauses
|
|
72
|
+
?.find((clause) => clause.token === ts.SyntaxKind.ImplementsKeyword)
|
|
73
|
+
?.types.map(t => t.expression?.getText())
|
|
74
|
+
.filter((name) => name !== undefined);
|
|
75
|
+
const classComments = extractNodeComments(node, sourceText);
|
|
76
|
+
const fields = [];
|
|
77
|
+
const methods = [];
|
|
78
|
+
const getters = [];
|
|
79
|
+
const setters = [];
|
|
80
|
+
let ctor;
|
|
81
|
+
const qualifiedName = scopePrefix ? `${scopePrefix}.${className}` : className;
|
|
82
|
+
const staticBlockStatements = [];
|
|
83
|
+
const preScannedFieldTypes = new Map();
|
|
84
|
+
for (const member of node.members) {
|
|
85
|
+
if (ts.isPropertyDeclaration(member) && member.name) {
|
|
86
|
+
const fName = ts.isIdentifier(member.name) ? member.name.text
|
|
87
|
+
: member.name.kind === ts.SyntaxKind.PrivateIdentifier ? `__priv_${member.name.text.substring(1)}` : null;
|
|
88
|
+
if (fName) {
|
|
89
|
+
const fType = typeNodeToCppType(member.type, typeAliasNodes);
|
|
90
|
+
preScannedFieldTypes.set(`this->${fName}`, fType);
|
|
91
|
+
getCurrentIrTypeScope()?.classFields.set(`this->${fName}`, fType);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
for (const member of node.members) {
|
|
96
|
+
if (ts.isClassStaticBlockDeclaration?.(member) || member.kind === ts.SyntaxKind.ClassStaticBlockDeclaration) {
|
|
97
|
+
const block = member;
|
|
98
|
+
if (block.body) {
|
|
99
|
+
const stmts = lowerStatementList(block.body.statements, fileName, sourceText, diagnostics, functionReturnTypes, new Map(), `${qualifiedName}.staticBlock`, typeAliasNodes, pointerVars);
|
|
100
|
+
staticBlockStatements.push(...stmts);
|
|
101
|
+
}
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
if (ts.isConstructorDeclaration(member)) {
|
|
105
|
+
const ctorParams = [];
|
|
106
|
+
const ctorLocalTypes = new Map();
|
|
107
|
+
const paramPropertyNames = [];
|
|
108
|
+
for (const param of member.parameters) {
|
|
109
|
+
if (ts.isIdentifier(param.name)) {
|
|
110
|
+
const paramType = typeNodeToCppType(param.type, typeAliasNodes);
|
|
111
|
+
ctorLocalTypes.set(param.name.text, paramType);
|
|
112
|
+
const paramOwnershipKind = extractOwnershipKindFromTypeNode(param.type, typeAliasNodes);
|
|
113
|
+
ctorParams.push({
|
|
114
|
+
name: param.name.text,
|
|
115
|
+
cppType: (paramType === "void" ? "auto" : paramType),
|
|
116
|
+
defaultValue: param.initializer
|
|
117
|
+
? expressionToIR(param.initializer, sourceText, diagnostics, pointerVars)
|
|
118
|
+
: undefined,
|
|
119
|
+
isRest: !!param.dotDotDotToken,
|
|
120
|
+
...(paramOwnershipKind ? { ownershipKind: paramOwnershipKind } : {}),
|
|
121
|
+
});
|
|
122
|
+
const hasVisibility = param.modifiers?.some(m => m.kind === ts.SyntaxKind.PublicKeyword ||
|
|
123
|
+
m.kind === ts.SyntaxKind.PrivateKeyword ||
|
|
124
|
+
m.kind === ts.SyntaxKind.ProtectedKeyword);
|
|
125
|
+
if (hasVisibility) {
|
|
126
|
+
const visibility = param.modifiers.some(m => m.kind === ts.SyntaxKind.PrivateKeyword)
|
|
127
|
+
? "private"
|
|
128
|
+
: param.modifiers.some(m => m.kind === ts.SyntaxKind.ProtectedKeyword)
|
|
129
|
+
? "protected"
|
|
130
|
+
: "public";
|
|
131
|
+
fields.push({
|
|
132
|
+
name: param.name.text,
|
|
133
|
+
cppType: (paramType === "void" ? "auto" : paramType),
|
|
134
|
+
visibility,
|
|
135
|
+
initializer: param.initializer
|
|
136
|
+
? expressionToIR(param.initializer, sourceText, diagnostics, pointerVars)
|
|
137
|
+
: undefined,
|
|
138
|
+
});
|
|
139
|
+
paramPropertyNames.push(param.name.text);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
const ctorBody = member.body
|
|
144
|
+
? lowerStatementList(member.body.statements, fileName, sourceText, diagnostics, functionReturnTypes, ctorLocalTypes, `${qualifiedName}.constructor`, typeAliasNodes, pointerVars)
|
|
145
|
+
: [];
|
|
146
|
+
const syntheticSpan = { filePath: fileName, startOffset: 0, endOffset: 0, startLine: 0, startColumn: 0, endLine: 0, endColumn: 0 };
|
|
147
|
+
const paramPropertyAssignments = paramPropertyNames.map(name => ({
|
|
148
|
+
kind: "assign",
|
|
149
|
+
sourceSpan: syntheticSpan,
|
|
150
|
+
target: `this->${name}`,
|
|
151
|
+
operator: "=",
|
|
152
|
+
value: { kind: "identifier", value: name },
|
|
153
|
+
}));
|
|
154
|
+
ctor = { parameters: ctorParams, statements: [...paramPropertyAssignments, ...ctorBody, ...staticBlockStatements] };
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
if (ts.isPropertyDeclaration(member) && member.name) {
|
|
158
|
+
if (member.modifiers?.some(m => m.kind === ts.SyntaxKind.AbstractKeyword)) {
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
let fieldName;
|
|
162
|
+
let fieldVisibility;
|
|
163
|
+
if (member.name.kind === ts.SyntaxKind.PrivateIdentifier) {
|
|
164
|
+
fieldName = `__priv_${member.name.text.substring(1)}`;
|
|
165
|
+
fieldVisibility = "private";
|
|
166
|
+
}
|
|
167
|
+
else if (ts.isIdentifier(member.name)) {
|
|
168
|
+
fieldName = member.name.text;
|
|
169
|
+
fieldVisibility = member.modifiers?.some(m => m.kind === ts.SyntaxKind.PrivateKeyword)
|
|
170
|
+
? "private"
|
|
171
|
+
: member.modifiers?.some(m => m.kind === ts.SyntaxKind.ProtectedKeyword)
|
|
172
|
+
? "protected"
|
|
173
|
+
: "public";
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
const fieldType = typeNodeToCppType(member.type, typeAliasNodes);
|
|
179
|
+
fields.push({
|
|
180
|
+
name: fieldName,
|
|
181
|
+
cppType: (fieldType === "void" ? "auto" : fieldType),
|
|
182
|
+
visibility: fieldVisibility,
|
|
183
|
+
initializer: member.initializer
|
|
184
|
+
? expressionToIR(member.initializer, sourceText, diagnostics, pointerVars)
|
|
185
|
+
: undefined,
|
|
186
|
+
isStatic: member.modifiers?.some(m => m.kind === ts.SyntaxKind.StaticKeyword) ?? false,
|
|
187
|
+
});
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
if (ts.isMethodDeclaration(member) && member.name) {
|
|
191
|
+
let methodName;
|
|
192
|
+
let methodVisibility;
|
|
193
|
+
if (member.name.kind === ts.SyntaxKind.PrivateIdentifier) {
|
|
194
|
+
methodName = `__priv_${member.name.text.substring(1)}`;
|
|
195
|
+
methodVisibility = "private";
|
|
196
|
+
}
|
|
197
|
+
else if (ts.isIdentifier(member.name)) {
|
|
198
|
+
methodName = member.name.text;
|
|
199
|
+
methodVisibility = member.modifiers?.some(m => m.kind === ts.SyntaxKind.PrivateKeyword)
|
|
200
|
+
? "private"
|
|
201
|
+
: member.modifiers?.some(m => m.kind === ts.SyntaxKind.ProtectedKeyword)
|
|
202
|
+
? "protected"
|
|
203
|
+
: "public";
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
const isStatic = member.modifiers?.some(m => m.kind === ts.SyntaxKind.StaticKeyword) ?? false;
|
|
209
|
+
const isMethodAbstract = member.modifiers?.some(m => m.kind === ts.SyntaxKind.AbstractKeyword) ?? false;
|
|
210
|
+
const isOverride = member.modifiers?.some(m => m.kind === ts.SyntaxKind.OverrideKeyword) ?? false;
|
|
211
|
+
if (extendsClass && !isStatic) {
|
|
212
|
+
setActiveExtendsClass(extendsClass);
|
|
213
|
+
}
|
|
214
|
+
// Resolve this method's declared return type and register it under the
|
|
215
|
+
// same qualified key used as functionNameForDiagnostics below, so that
|
|
216
|
+
// return statements inside the body get the enclosing return type
|
|
217
|
+
// annotated on the ReturnIR (used by the emitter to lower
|
|
218
|
+
// `return null`/`undefined` to `return {};` for struct returns — demo
|
|
219
|
+
// #14 Finding A). Top-level functions get this via buildFunctionReturnTypeMap;
|
|
220
|
+
// methods do not, so we add it here.
|
|
221
|
+
const methodQualifiedKey = `${qualifiedName}.${methodName}`;
|
|
222
|
+
const preMethodReturnType = typeNodeToCppType(member.type, typeAliasNodes);
|
|
223
|
+
if (preMethodReturnType && preMethodReturnType !== "void") {
|
|
224
|
+
functionReturnTypes.set(methodQualifiedKey, preMethodReturnType);
|
|
225
|
+
}
|
|
226
|
+
const methodParams = [];
|
|
227
|
+
const methodLocalTypes = new Map(preScannedFieldTypes);
|
|
228
|
+
for (const param of member.parameters) {
|
|
229
|
+
if (ts.isIdentifier(param.name)) {
|
|
230
|
+
const paramType = typeNodeToCppType(param.type, typeAliasNodes);
|
|
231
|
+
methodLocalTypes.set(param.name.text, paramType);
|
|
232
|
+
const paramOwnershipKind = extractOwnershipKindFromTypeNode(param.type, typeAliasNodes);
|
|
233
|
+
methodParams.push({
|
|
234
|
+
name: param.name.text,
|
|
235
|
+
cppType: (paramType === "void" ? "auto" : paramType),
|
|
236
|
+
defaultValue: param.initializer
|
|
237
|
+
? expressionToIR(param.initializer, sourceText, diagnostics, pointerVars)
|
|
238
|
+
: undefined,
|
|
239
|
+
isRest: !!param.dotDotDotToken,
|
|
240
|
+
...(paramOwnershipKind ? { ownershipKind: paramOwnershipKind } : {}),
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
const methodBody = member.body
|
|
245
|
+
? lowerStatementList(member.body.statements, fileName, sourceText, diagnostics, functionReturnTypes, methodLocalTypes, `${qualifiedName}.${methodName}`, typeAliasNodes, pointerVars)
|
|
246
|
+
: [];
|
|
247
|
+
const methodReturnType = typeNodeToCppType(member.type, typeAliasNodes);
|
|
248
|
+
setActiveExtendsClass(undefined);
|
|
249
|
+
methods.push({
|
|
250
|
+
name: methodName,
|
|
251
|
+
returnType: (member.type?.kind === ts.SyntaxKind.ThisType
|
|
252
|
+
? `${className}*`
|
|
253
|
+
: (methodReturnType === className ? `${className}*` : (methodReturnType === "void" ? "void" : methodReturnType))),
|
|
254
|
+
parameters: methodParams,
|
|
255
|
+
statements: methodBody,
|
|
256
|
+
visibility: methodVisibility,
|
|
257
|
+
isStatic,
|
|
258
|
+
isAbstract: isMethodAbstract,
|
|
259
|
+
isOverride,
|
|
260
|
+
...(member.typeParameters && member.typeParameters.length > 0
|
|
261
|
+
? { typeParameters: member.typeParameters.map(tp => tp.name.text) }
|
|
262
|
+
: {}),
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
if (ts.isGetAccessorDeclaration(member) && member.name && ts.isIdentifier(member.name)) {
|
|
266
|
+
const visibility = member.modifiers?.some(m => m.kind === ts.SyntaxKind.PrivateKeyword)
|
|
267
|
+
? "private"
|
|
268
|
+
: member.modifiers?.some(m => m.kind === ts.SyntaxKind.ProtectedKeyword)
|
|
269
|
+
? "protected"
|
|
270
|
+
: "public";
|
|
271
|
+
if (extendsClass) {
|
|
272
|
+
const isStatic = member.modifiers?.some(m => m.kind === ts.SyntaxKind.StaticKeyword) ?? false;
|
|
273
|
+
if (!isStatic)
|
|
274
|
+
setActiveExtendsClass(extendsClass);
|
|
275
|
+
}
|
|
276
|
+
const accessorLocalTypes = new Map();
|
|
277
|
+
const accessorBody = member.body
|
|
278
|
+
? lowerStatementList(member.body.statements, fileName, sourceText, diagnostics, functionReturnTypes, accessorLocalTypes, `${qualifiedName}.get:${member.name.text}`, typeAliasNodes, pointerVars)
|
|
279
|
+
: [];
|
|
280
|
+
setActiveExtendsClass(undefined);
|
|
281
|
+
getters.push({
|
|
282
|
+
name: member.name.text,
|
|
283
|
+
returnType: typeNodeToCppType(member.type, typeAliasNodes),
|
|
284
|
+
statements: accessorBody,
|
|
285
|
+
visibility,
|
|
286
|
+
isStatic: member.modifiers?.some(m => m.kind === ts.SyntaxKind.StaticKeyword) ?? false,
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
if (ts.isSetAccessorDeclaration(member) && member.name && ts.isIdentifier(member.name)) {
|
|
290
|
+
const visibility = member.modifiers?.some(m => m.kind === ts.SyntaxKind.PrivateKeyword)
|
|
291
|
+
? "private"
|
|
292
|
+
: member.modifiers?.some(m => m.kind === ts.SyntaxKind.ProtectedKeyword)
|
|
293
|
+
? "protected"
|
|
294
|
+
: "public";
|
|
295
|
+
const setParams = [];
|
|
296
|
+
const setterLocalTypes = new Map();
|
|
297
|
+
for (const param of member.parameters) {
|
|
298
|
+
if (ts.isIdentifier(param.name)) {
|
|
299
|
+
const paramType = typeNodeToCppType(param.type, typeAliasNodes);
|
|
300
|
+
setterLocalTypes.set(param.name.text, paramType);
|
|
301
|
+
setParams.push({
|
|
302
|
+
name: param.name.text,
|
|
303
|
+
cppType: (paramType === "void" ? "auto" : paramType),
|
|
304
|
+
isRest: !!param.dotDotDotToken,
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
if (extendsClass) {
|
|
309
|
+
const isStatic = member.modifiers?.some(m => m.kind === ts.SyntaxKind.StaticKeyword) ?? false;
|
|
310
|
+
if (!isStatic)
|
|
311
|
+
setActiveExtendsClass(extendsClass);
|
|
312
|
+
}
|
|
313
|
+
const accessorBody = member.body
|
|
314
|
+
? lowerStatementList(member.body.statements, fileName, sourceText, diagnostics, functionReturnTypes, setterLocalTypes, `${qualifiedName}.set:${member.name.text}`, typeAliasNodes, pointerVars)
|
|
315
|
+
: [];
|
|
316
|
+
setActiveExtendsClass(undefined);
|
|
317
|
+
setters.push({
|
|
318
|
+
name: member.name.text,
|
|
319
|
+
parameter: setParams[0] ?? { name: "value", cppType: "auto", isRest: false },
|
|
320
|
+
statements: accessorBody,
|
|
321
|
+
visibility,
|
|
322
|
+
isStatic: member.modifiers?.some(m => m.kind === ts.SyntaxKind.StaticKeyword) ?? false,
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
if (!ctor && staticBlockStatements.length > 0) {
|
|
327
|
+
ctor = { parameters: [], statements: [...staticBlockStatements] };
|
|
328
|
+
}
|
|
329
|
+
const classDecorators = node.decorators
|
|
330
|
+
? node.decorators
|
|
331
|
+
.map((d) => {
|
|
332
|
+
if (d.expression && ts.isIdentifier(d.expression))
|
|
333
|
+
return d.expression.text;
|
|
334
|
+
if (d.expression && ts.isCallExpression(d.expression) && ts.isIdentifier(d.expression.expression))
|
|
335
|
+
return d.expression.expression.text;
|
|
336
|
+
return undefined;
|
|
337
|
+
})
|
|
338
|
+
.filter((d) => d !== undefined)
|
|
339
|
+
: undefined;
|
|
340
|
+
const classTypeParams = node.typeParameters
|
|
341
|
+
? node.typeParameters.map(tp => tp.name.text)
|
|
342
|
+
: undefined;
|
|
343
|
+
return {
|
|
344
|
+
name: className,
|
|
345
|
+
extendsClass,
|
|
346
|
+
implementsInterfaces,
|
|
347
|
+
isAbstract,
|
|
348
|
+
sourceSpan: makeSourceSpan(node, fileName, sourceText),
|
|
349
|
+
leadingComments: classComments.leadingComments,
|
|
350
|
+
trailingComments: classComments.trailingComments,
|
|
351
|
+
fields,
|
|
352
|
+
methods,
|
|
353
|
+
constructor: ctor,
|
|
354
|
+
getters,
|
|
355
|
+
setters,
|
|
356
|
+
...(classTypeParams && classTypeParams.length > 0 ? { typeParameters: classTypeParams } : {}),
|
|
357
|
+
...(classDecorators && classDecorators.length > 0 ? { decorators: classDecorators } : {}),
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
function evaluateConstExpr(expr, memberMap, sourceText) {
|
|
361
|
+
if (ts.isNumericLiteral(expr)) {
|
|
362
|
+
return Number(expr.text);
|
|
363
|
+
}
|
|
364
|
+
if (ts.isPrefixUnaryExpression(expr)) {
|
|
365
|
+
const operand = evaluateConstExpr(expr.operand, memberMap, sourceText);
|
|
366
|
+
if (operand === undefined)
|
|
367
|
+
return undefined;
|
|
368
|
+
switch (expr.operator) {
|
|
369
|
+
case ts.SyntaxKind.MinusToken: return -operand;
|
|
370
|
+
case ts.SyntaxKind.PlusToken: return +operand;
|
|
371
|
+
case ts.SyntaxKind.TildeToken: return ~operand;
|
|
372
|
+
case ts.SyntaxKind.ExclamationToken: return operand ? 0 : 1;
|
|
373
|
+
default: return undefined;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
if (ts.isBinaryExpression(expr)) {
|
|
377
|
+
const left = evaluateConstExpr(expr.left, memberMap, sourceText);
|
|
378
|
+
const right = evaluateConstExpr(expr.right, memberMap, sourceText);
|
|
379
|
+
if (left === undefined || right === undefined)
|
|
380
|
+
return undefined;
|
|
381
|
+
switch (expr.operatorToken.kind) {
|
|
382
|
+
case ts.SyntaxKind.PlusToken: return left + right;
|
|
383
|
+
case ts.SyntaxKind.MinusToken: return left - right;
|
|
384
|
+
case ts.SyntaxKind.AsteriskToken: return left * right;
|
|
385
|
+
case ts.SyntaxKind.SlashToken: return Math.trunc(left / right);
|
|
386
|
+
case ts.SyntaxKind.PercentToken: return left % right;
|
|
387
|
+
case ts.SyntaxKind.BarToken: return left | right;
|
|
388
|
+
case ts.SyntaxKind.AmpersandToken: return left & right;
|
|
389
|
+
case ts.SyntaxKind.CaretToken: return left ^ right;
|
|
390
|
+
case ts.SyntaxKind.LessThanLessThanToken: return left << right;
|
|
391
|
+
case ts.SyntaxKind.GreaterThanGreaterThanToken: return left >> right;
|
|
392
|
+
case ts.SyntaxKind.BarBarToken: return left || right;
|
|
393
|
+
case ts.SyntaxKind.AmpersandAmpersandToken: return left && right;
|
|
394
|
+
default: return undefined;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
if (ts.isIdentifier(expr)) {
|
|
398
|
+
return memberMap.get(expr.text);
|
|
399
|
+
}
|
|
400
|
+
if (ts.isPropertyAccessExpression(expr)) {
|
|
401
|
+
if (ts.isIdentifier(expr.expression)) {
|
|
402
|
+
const enumPrefix = expr.expression.text;
|
|
403
|
+
const memberName = expr.name.text;
|
|
404
|
+
const qualifiedKey = `${enumPrefix}.${memberName}`;
|
|
405
|
+
return memberMap.get(qualifiedKey) ?? memberMap.get(memberName);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
if (ts.isParenthesizedExpression(expr)) {
|
|
409
|
+
return evaluateConstExpr(expr.expression, memberMap, sourceText);
|
|
410
|
+
}
|
|
411
|
+
return undefined;
|
|
412
|
+
}
|
|
413
|
+
export function enumDeclarationToIR(node, fileName, sourceText) {
|
|
414
|
+
if (!node.name) {
|
|
415
|
+
return undefined;
|
|
416
|
+
}
|
|
417
|
+
const enumName = node.name.text;
|
|
418
|
+
const enumComments = extractNodeComments(node, sourceText);
|
|
419
|
+
const isConst = node.modifiers?.some(m => m.kind === ts.SyntaxKind.ConstKeyword) ?? false;
|
|
420
|
+
const members = [];
|
|
421
|
+
const memberMap = new Map();
|
|
422
|
+
let nextValue = 0;
|
|
423
|
+
for (const member of node.members) {
|
|
424
|
+
if (ts.isIdentifier(member.name)) {
|
|
425
|
+
let value;
|
|
426
|
+
if (member.initializer) {
|
|
427
|
+
value = evaluateConstExpr(member.initializer, memberMap, sourceText);
|
|
428
|
+
if (value === undefined) {
|
|
429
|
+
if (ts.isNumericLiteral(member.initializer)) {
|
|
430
|
+
value = Number(member.initializer.text);
|
|
431
|
+
}
|
|
432
|
+
else if (ts.isPrefixUnaryExpression(member.initializer) &&
|
|
433
|
+
member.initializer.operator === ts.SyntaxKind.MinusToken &&
|
|
434
|
+
ts.isNumericLiteral(member.initializer.operand)) {
|
|
435
|
+
value = -Number(member.initializer.operand.text);
|
|
436
|
+
}
|
|
437
|
+
else if (ts.isStringLiteral(member.initializer)) {
|
|
438
|
+
value = member.initializer.text;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
if (value !== undefined && typeof value === "number") {
|
|
442
|
+
nextValue = value + 1;
|
|
443
|
+
}
|
|
444
|
+
else {
|
|
445
|
+
nextValue++;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
else {
|
|
449
|
+
value = nextValue;
|
|
450
|
+
nextValue++;
|
|
451
|
+
}
|
|
452
|
+
if (value !== undefined && typeof value === "number") {
|
|
453
|
+
memberMap.set(member.name.text, value);
|
|
454
|
+
memberMap.set(`${enumName}.${member.name.text}`, value);
|
|
455
|
+
}
|
|
456
|
+
members.push({
|
|
457
|
+
name: member.name.text,
|
|
458
|
+
value,
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
return {
|
|
463
|
+
name: node.name.text,
|
|
464
|
+
sourceSpan: makeSourceSpan(node, fileName, sourceText),
|
|
465
|
+
leadingComments: enumComments.leadingComments,
|
|
466
|
+
trailingComments: enumComments.trailingComments,
|
|
467
|
+
members,
|
|
468
|
+
isConst,
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
export function interfaceDeclarationToIR(node, fileName, sourceText, typeAliasNodes) {
|
|
472
|
+
if (!node.name) {
|
|
473
|
+
return undefined;
|
|
474
|
+
}
|
|
475
|
+
const interfaceComments = extractNodeComments(node, sourceText);
|
|
476
|
+
const interfaceName = node.name.text;
|
|
477
|
+
const extendsInterfaces = node.heritageClauses
|
|
478
|
+
?.find((clause) => clause.token === ts.SyntaxKind.ExtendsKeyword)
|
|
479
|
+
?.types.map(t => t.expression?.getText())
|
|
480
|
+
.filter((name) => name !== undefined);
|
|
481
|
+
const fields = [];
|
|
482
|
+
const methods = [];
|
|
483
|
+
let indexSignature;
|
|
484
|
+
for (const member of node.members) {
|
|
485
|
+
if (ts.isPropertySignature(member) && member.name && ts.isIdentifier(member.name)) {
|
|
486
|
+
const propName = member.name.text;
|
|
487
|
+
const isOptional = !!member.questionToken;
|
|
488
|
+
const propType = typeNodeToCppType(member.type, typeAliasNodes);
|
|
489
|
+
fields.push({
|
|
490
|
+
name: propName,
|
|
491
|
+
cppType: propType,
|
|
492
|
+
isOptional,
|
|
493
|
+
});
|
|
494
|
+
continue;
|
|
495
|
+
}
|
|
496
|
+
if (ts.isMethodSignature(member) && member.name && ts.isIdentifier(member.name)) {
|
|
497
|
+
const methodName = member.name.text;
|
|
498
|
+
const returnType = typeNodeToCppType(member.type, typeAliasNodes);
|
|
499
|
+
const params = [];
|
|
500
|
+
for (const param of member.parameters) {
|
|
501
|
+
if (ts.isIdentifier(param.name)) {
|
|
502
|
+
const paramType = typeNodeToCppType(param.type, typeAliasNodes);
|
|
503
|
+
params.push({
|
|
504
|
+
name: param.name.text,
|
|
505
|
+
cppType: (paramType === "void" ? "auto" : paramType),
|
|
506
|
+
isRest: !!param.dotDotDotToken,
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
methods.push({
|
|
511
|
+
name: methodName,
|
|
512
|
+
returnType,
|
|
513
|
+
parameters: params,
|
|
514
|
+
});
|
|
515
|
+
continue;
|
|
516
|
+
}
|
|
517
|
+
if (ts.isIndexSignatureDeclaration(member)) {
|
|
518
|
+
let keyType = "string";
|
|
519
|
+
if (member.parameters.length > 0 && ts.isIdentifier(member.parameters[0].name)) {
|
|
520
|
+
const paramType = member.parameters[0].type;
|
|
521
|
+
if (paramType && ts.isTypeNode(paramType)) {
|
|
522
|
+
keyType = typeNodeToCppType(paramType, typeAliasNodes);
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
const valueType = typeNodeToCppType(member.type, typeAliasNodes);
|
|
526
|
+
indexSignature = { keyType, valueType };
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
return {
|
|
530
|
+
name: interfaceName,
|
|
531
|
+
sourceSpan: makeSourceSpan(node, fileName, sourceText),
|
|
532
|
+
leadingComments: interfaceComments.leadingComments,
|
|
533
|
+
trailingComments: interfaceComments.trailingComments,
|
|
534
|
+
extendsInterfaces,
|
|
535
|
+
fields,
|
|
536
|
+
methods,
|
|
537
|
+
indexSignature,
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
export function typeAliasDeclarationToIR(node, fileName, sourceText, typeAliasNodes) {
|
|
541
|
+
const aliasComments = extractNodeComments(node, sourceText);
|
|
542
|
+
const aliasTypeParams = node.typeParameters
|
|
543
|
+
? node.typeParameters.map(tp => tp.name.text)
|
|
544
|
+
: undefined;
|
|
545
|
+
const resolved = node.type;
|
|
546
|
+
if (ts.isUnionTypeNode(resolved)) {
|
|
547
|
+
const variantStructs = extractDiscriminatedUnionVariants(resolved, typeAliasNodes, node.name.text);
|
|
548
|
+
if (variantStructs) {
|
|
549
|
+
const variantNames = variantStructs.map(v => v.name);
|
|
550
|
+
discriminatedUnionVariantNames.set(node.name.text, variantNames);
|
|
551
|
+
return {
|
|
552
|
+
name: node.name.text,
|
|
553
|
+
sourceSpan: makeSourceSpan(node, fileName, sourceText),
|
|
554
|
+
leadingComments: aliasComments.leadingComments,
|
|
555
|
+
trailingComments: aliasComments.trailingComments,
|
|
556
|
+
cppType: `std::variant<${variantNames.join(", ")}>`,
|
|
557
|
+
variantStructs,
|
|
558
|
+
...(aliasTypeParams && aliasTypeParams.length > 0 ? { typeParameters: aliasTypeParams } : {}),
|
|
559
|
+
};
|
|
560
|
+
// std::variant requires <variant>; register the include so the header
|
|
561
|
+
// compiles (demo #9 Finding A — was emitting `std::variant<...>` with
|
|
562
|
+
// no include, giving "'variant' is not a member of 'std'").
|
|
563
|
+
if (variantNames.length > 0) {
|
|
564
|
+
requiredIncludes.add("<variant>");
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
const cppType = typeNodeToCppType(node.type, typeAliasNodes);
|
|
569
|
+
let structFields;
|
|
570
|
+
if (ts.isTypeLiteralNode(resolved)) {
|
|
571
|
+
structFields = resolved.members
|
|
572
|
+
.filter(ts.isPropertySignature)
|
|
573
|
+
.filter(m => ts.isIdentifier(m.name))
|
|
574
|
+
.map(m => ({
|
|
575
|
+
name: m.name.text,
|
|
576
|
+
cppType: typeNodeToCppType(m.type, typeAliasNodes),
|
|
577
|
+
}));
|
|
578
|
+
}
|
|
579
|
+
return {
|
|
580
|
+
name: node.name.text,
|
|
581
|
+
sourceSpan: makeSourceSpan(node, fileName, sourceText),
|
|
582
|
+
leadingComments: aliasComments.leadingComments,
|
|
583
|
+
trailingComments: aliasComments.trailingComments,
|
|
584
|
+
cppType,
|
|
585
|
+
structFields,
|
|
586
|
+
...(aliasTypeParams && aliasTypeParams.length > 0 ? { typeParameters: aliasTypeParams } : {}),
|
|
587
|
+
};
|
|
588
|
+
}
|
|
589
|
+
function extractDiscriminatedUnionVariants(unionNode, typeAliasNodes, aliasName) {
|
|
590
|
+
const typeLiterals = unionNode.types.filter(ts.isTypeLiteralNode);
|
|
591
|
+
if (typeLiterals.length === 0 || typeLiterals.length !== unionNode.types.length) {
|
|
592
|
+
return null;
|
|
593
|
+
}
|
|
594
|
+
const variants = [];
|
|
595
|
+
for (let i = 0; i < typeLiterals.length; i++) {
|
|
596
|
+
const literal = typeLiterals[i];
|
|
597
|
+
const variantName = `_${aliasName}_Variant_${i}`;
|
|
598
|
+
const fields = literal.members
|
|
599
|
+
.filter(ts.isPropertySignature)
|
|
600
|
+
.filter(m => ts.isIdentifier(m.name))
|
|
601
|
+
.map(m => ({
|
|
602
|
+
name: m.name.text,
|
|
603
|
+
cppType: typeNodeToCppType(m.type, typeAliasNodes),
|
|
604
|
+
}));
|
|
605
|
+
variants.push({ name: variantName, fields });
|
|
606
|
+
}
|
|
607
|
+
return variants;
|
|
608
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { ProgramIR } from "../api/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Configuration for entry point detection
|
|
4
|
+
*/
|
|
5
|
+
export interface EntryPointConfig {
|
|
6
|
+
/** Default entry points when none are explicitly provided */
|
|
7
|
+
defaultEntryPoints: string[];
|
|
8
|
+
/** Additional custom entry points */
|
|
9
|
+
customEntryPoints: string[];
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Detect entry points for a program.
|
|
13
|
+
*
|
|
14
|
+
* @param program The IR program to analyze
|
|
15
|
+
* @param config Entry point configuration
|
|
16
|
+
* @param entryPointNames Explicit entry point names (overrides config defaults).
|
|
17
|
+
* Derived from the platform strategy's `entrypointFunctionName()`
|
|
18
|
+
* and `requiresLoopFunction()` at the call site.
|
|
19
|
+
*/
|
|
20
|
+
export declare function detectEntryPoints(program: ProgramIR, config?: Partial<EntryPointConfig>, entryPointNames?: string[]): Set<string>;
|
|
21
|
+
/**
|
|
22
|
+
* Detect symbols in a program that are imported by other files in the project.
|
|
23
|
+
* These become additional entry points for tree-shaking so they aren't
|
|
24
|
+
* eliminated as "unused" when they are only used externally.
|
|
25
|
+
*
|
|
26
|
+
* @param program The IR for one file
|
|
27
|
+
* @param importedByOtherFiles Symbol names that other files import from this one
|
|
28
|
+
* @returns Set of symbol names that should be treated as entry points
|
|
29
|
+
*/
|
|
30
|
+
export declare function detectExportedEntryPoints(program: ProgramIR, importedByOtherFiles: Set<string>): Set<string>;
|