@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,808 @@
|
|
|
1
|
+
import ts from "typescript";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { parseSource } from "../ast/parse.js";
|
|
5
|
+
import { isStringEnum } from "../api/shared/index.js";
|
|
6
|
+
import { makeDiagnostic } from "./ast-node-utils.js";
|
|
7
|
+
import { buildFunctionReturnTypeMap } from "./type-resolution.js";
|
|
8
|
+
import { resolveBoardConstants, tryResolveBoardDefFile } from "./board-resolver.js";
|
|
9
|
+
import { analyzePeripheralUsage, createEmptyPeripheralUsage } from "./peripheral-usage.js";
|
|
10
|
+
import { runProgramValidations } from "./validation-orchestrator.js";
|
|
11
|
+
import { registerFieldMap, hoistedNestedFunctions, hoistedNestedClasses, hoistedNestedEnums, hoistedNestedInterfaces, hoistedNestedTypeAliases, activeNamespaceNames, activeEnumNames, activeStringEnumNames, peripheralAliasMap, pinAliasMap, mcuPinReverseMap, topLevelClassNames, topLevelInterfaceNames, classTypeNames, topLevelClasses, requiredIncludes, resetBuildState, getCurrentBoardConstants, setCurrentBoardConstants, contextStorage, CompilationContext, registeredCallbacks, getContext, discriminatedUnionVariantNames, restParamFunctions, topLevelAliasReceivers } from "./build-ir-state.js";
|
|
12
|
+
import { collectPointerVars, expressionStatementToIR, lowerStatement, variableStatementToIR, prescanArrayUsage, lowerStatementList } from "./statement-to-ir.js";
|
|
13
|
+
import { registerUIModuleImport, registerElementValue } from "./transformers/ui-call-resolver.js";
|
|
14
|
+
import { requireUIHook } from "../ui-hook.js";
|
|
15
|
+
import { autoWireElements, registerScreenId } from "./ui-element-auto-wire.js";
|
|
16
|
+
import { loadHALModules, halInstances, resetHALResolver } from "./hal-resolver.js";
|
|
17
|
+
import { prescanUnsupportedFeatures } from "./feature-prescan.js";
|
|
18
|
+
import { classDeclarationToIR, enumDeclarationToIR, interfaceDeclarationToIR, typeAliasDeclarationToIR } from "./declaration-builders.js";
|
|
19
|
+
import { namespaceToIR } from "./namespace-builder.js";
|
|
20
|
+
import { functionDeclarationToIR, variableAsFunctionToIR } from "./function-builder.js";
|
|
21
|
+
function normalizeEntrypointSyntax(sourceText) {
|
|
22
|
+
return sourceText.replace(/\bfunction\s+void\s*\(/g, "function __cuttlefish_entrypoint__(");
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Synthesize forwarding constructors for subclasses that declare none.
|
|
26
|
+
*
|
|
27
|
+
* C++ does not inherit constructors. A TS subclass `class B extends A {}` with
|
|
28
|
+
* no explicit `constructor` previously lowered to a C++ class with NO
|
|
29
|
+
* constructor at all, so `new B(args)` failed (`no matching function for call`)
|
|
30
|
+
* and base parameter-property initialization was skipped. For each such
|
|
31
|
+
* subclass we synthesize a constructor that mirrors the base's parameter
|
|
32
|
+
* signature and forwards every argument via a synthesized `super_call`. If the
|
|
33
|
+
* base is default-constructible (no constructor), we synthesize an empty
|
|
34
|
+
* constructor so `new B()` still works.
|
|
35
|
+
*
|
|
36
|
+
* Bases may live in another file; they are resolved from the local `classes`
|
|
37
|
+
* list first, then from `topLevelClasses` (which carries prebuilt/cross-file
|
|
38
|
+
* ClassIR). Demo #14 Finding B.
|
|
39
|
+
*/
|
|
40
|
+
function synthesizeSubclassConstructors(classes) {
|
|
41
|
+
for (const cls of classes) {
|
|
42
|
+
if (cls.constructor || !cls.extendsClass)
|
|
43
|
+
continue;
|
|
44
|
+
// The extendsClass text may carry template args (e.g. "Generic<std::string>");
|
|
45
|
+
// the base class name is the identifier before any '<'.
|
|
46
|
+
const baseName = cls.extendsClass.split("<")[0].trim();
|
|
47
|
+
const base = classes.find((c) => c.name === baseName) ??
|
|
48
|
+
topLevelClasses.get(baseName);
|
|
49
|
+
if (!base)
|
|
50
|
+
continue;
|
|
51
|
+
if (base.constructor && base.constructor.parameters.length > 0) {
|
|
52
|
+
// Mirror the base parameter list, forwarding each as a super_call arg.
|
|
53
|
+
const fwdParams = base.constructor.parameters.map((p) => ({
|
|
54
|
+
name: p.name,
|
|
55
|
+
cppType: p.cppType,
|
|
56
|
+
defaultValue: p.defaultValue,
|
|
57
|
+
isRest: p.isRest,
|
|
58
|
+
...(p.ownershipKind ? { ownershipKind: p.ownershipKind } : {}),
|
|
59
|
+
}));
|
|
60
|
+
const superArgs = base.constructor.parameters.map((p) => ({
|
|
61
|
+
kind: "identifier",
|
|
62
|
+
value: p.name,
|
|
63
|
+
}));
|
|
64
|
+
const syntheticSpan = {
|
|
65
|
+
filePath: cls.name,
|
|
66
|
+
startOffset: 0,
|
|
67
|
+
endOffset: 0,
|
|
68
|
+
startLine: 1,
|
|
69
|
+
startColumn: 1,
|
|
70
|
+
endLine: 1,
|
|
71
|
+
endColumn: 1,
|
|
72
|
+
};
|
|
73
|
+
cls.constructor = {
|
|
74
|
+
parameters: fwdParams,
|
|
75
|
+
statements: [
|
|
76
|
+
{
|
|
77
|
+
kind: "super_call",
|
|
78
|
+
sourceSpan: syntheticSpan,
|
|
79
|
+
args: superArgs,
|
|
80
|
+
},
|
|
81
|
+
],
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
// Base is default-constructible; synthesize an empty ctor so the
|
|
86
|
+
// emitter produces `B() { }` rather than nothing.
|
|
87
|
+
cls.constructor = { parameters: [], statements: [] };
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
function scanSourceForEnumNames(src) {
|
|
92
|
+
const names = new Set();
|
|
93
|
+
const re = /(?:export\s+)?enum\s+(\w+)\s*\{/g;
|
|
94
|
+
let m;
|
|
95
|
+
while ((m = re.exec(src)) !== null) {
|
|
96
|
+
names.add(m[1]);
|
|
97
|
+
}
|
|
98
|
+
return names;
|
|
99
|
+
}
|
|
100
|
+
function resolveRelativeImportPath(fromFile, moduleSpecifier) {
|
|
101
|
+
// .ui.html modules export no TS symbols (enums/functions) — skip them in the
|
|
102
|
+
// early cross-module pre-scan so they aren't parsed as TypeScript.
|
|
103
|
+
if (moduleSpecifier.endsWith(".ui.html"))
|
|
104
|
+
return undefined;
|
|
105
|
+
let normalized = moduleSpecifier;
|
|
106
|
+
if (normalized.endsWith(".js"))
|
|
107
|
+
normalized = normalized.slice(0, -3) + ".ts";
|
|
108
|
+
else if (normalized.endsWith(".mjs"))
|
|
109
|
+
normalized = normalized.slice(0, -5) + ".ts";
|
|
110
|
+
const basePath = path.resolve(path.dirname(fromFile), normalized);
|
|
111
|
+
const candidates = [
|
|
112
|
+
basePath,
|
|
113
|
+
`${basePath}.ts`,
|
|
114
|
+
`${basePath}.tsx`,
|
|
115
|
+
path.join(basePath, "index.ts"),
|
|
116
|
+
path.join(basePath, "index.tsx"),
|
|
117
|
+
];
|
|
118
|
+
for (const c of candidates) {
|
|
119
|
+
try {
|
|
120
|
+
if (fs.statSync(c).isFile())
|
|
121
|
+
return c;
|
|
122
|
+
}
|
|
123
|
+
catch { /* skip */ }
|
|
124
|
+
}
|
|
125
|
+
return undefined;
|
|
126
|
+
}
|
|
127
|
+
/** Resolve a relative `.ui.html` import to its absolute path (for UI registration). */
|
|
128
|
+
function resolveUIImportPath(fromFile, moduleSpecifier) {
|
|
129
|
+
if (!moduleSpecifier.startsWith(".") && !moduleSpecifier.startsWith(".."))
|
|
130
|
+
return undefined;
|
|
131
|
+
const basePath = path.resolve(path.dirname(fromFile), moduleSpecifier);
|
|
132
|
+
if (basePath.toLowerCase().endsWith(".ui.html") && requireUIHook().getUIModule(basePath)) {
|
|
133
|
+
return basePath;
|
|
134
|
+
}
|
|
135
|
+
try {
|
|
136
|
+
if (fs.statSync(basePath).isFile() && basePath.toLowerCase().endsWith(".ui.html")) {
|
|
137
|
+
return basePath;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
catch { /* skip */ }
|
|
141
|
+
return undefined;
|
|
142
|
+
}
|
|
143
|
+
export function buildProgramIR(fileName, sourceText, boardPackage, prebuiltClassMap) {
|
|
144
|
+
const parentStrategy = getContext().activeStrategy;
|
|
145
|
+
return contextStorage.run(new CompilationContext(), () => {
|
|
146
|
+
getContext().activeStrategy = parentStrategy;
|
|
147
|
+
loadHALModules(true); // Parse HAL source files (force reload to pick up changes)
|
|
148
|
+
const normalizedSourceText = normalizeEntrypointSyntax(sourceText);
|
|
149
|
+
const source = parseSource(fileName, normalizedSourceText);
|
|
150
|
+
const diagnostics = [];
|
|
151
|
+
// Expose the diagnostics sink on the context so deep IR-lowering helpers
|
|
152
|
+
// (renderExprAsText, HAL fallbacks) that don't receive diagnostics as a
|
|
153
|
+
// parameter can still report unsupported patterns. This is the same array
|
|
154
|
+
// returned in ProgramIR.diagnostics, so throwIfFatalDiagnostics in
|
|
155
|
+
// transpile.ts will abort the build on any error pushed here.
|
|
156
|
+
getContext().diagnostics = diagnostics;
|
|
157
|
+
// Only prescan user code — skip library sources from node_modules and
|
|
158
|
+
// internal packages (the HAL package ships src/ for transpile-time
|
|
159
|
+
// introspection, but its internal use of `any`, Promise, etc. is not
|
|
160
|
+
// user code and should not trigger TS2CPP diagnostics).
|
|
161
|
+
const normalizedFileName = fileName.replace(/\\/g, "/");
|
|
162
|
+
if (!normalizedFileName.includes("/node_modules/") && !normalizedFileName.includes("/packages/")) {
|
|
163
|
+
diagnostics.push(...prescanUnsupportedFeatures(source, normalizedSourceText));
|
|
164
|
+
}
|
|
165
|
+
const imports = [];
|
|
166
|
+
const reExports = [];
|
|
167
|
+
const topLevelStatements = [];
|
|
168
|
+
const functions = [];
|
|
169
|
+
const enums = [];
|
|
170
|
+
const classes = [];
|
|
171
|
+
const typeAliases = [];
|
|
172
|
+
const interfaces = [];
|
|
173
|
+
const namespaces = [];
|
|
174
|
+
const registerClasses = [];
|
|
175
|
+
const typeAliasNodes = new Map();
|
|
176
|
+
const boilerplates = new Set();
|
|
177
|
+
// Reset module-level state for this file
|
|
178
|
+
resetBuildState();
|
|
179
|
+
resetHALResolver();
|
|
180
|
+
registerFieldMap.clear();
|
|
181
|
+
// Phase 0: Pre-scan for top-level classes and register them so type inference can resolve them.
|
|
182
|
+
// Also register classes from other files in the transpile graph so that property accesses
|
|
183
|
+
// on imported class instances are correctly typed (e.g. player.weaponName → std::string).
|
|
184
|
+
if (prebuiltClassMap) {
|
|
185
|
+
for (const [name, classIR] of prebuiltClassMap) {
|
|
186
|
+
topLevelClassNames.add(name);
|
|
187
|
+
classTypeNames.add(name);
|
|
188
|
+
topLevelClasses.set(name, classIR);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
const localClassDeclarations = source.statements.filter(ts.isClassDeclaration);
|
|
192
|
+
for (const statement of localClassDeclarations) {
|
|
193
|
+
if (!statement.name)
|
|
194
|
+
continue;
|
|
195
|
+
topLevelClassNames.add(statement.name.text);
|
|
196
|
+
classTypeNames.add(statement.name.text);
|
|
197
|
+
}
|
|
198
|
+
// Phase 0b: Pre-scan for top-level interface names. Interfaces lower to C++
|
|
199
|
+
// structs (value types), so a variable of an interface type is a value —
|
|
200
|
+
// never null. Registering the names here (before any statement lowering)
|
|
201
|
+
// lets the null-comparison guard in expression-to-ir recognise such values
|
|
202
|
+
// as value types. Demo #18 Finding A.
|
|
203
|
+
for (const statement of source.statements) {
|
|
204
|
+
if (ts.isInterfaceDeclaration(statement) && statement.name) {
|
|
205
|
+
topLevelInterfaceNames.add(statement.name.text);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
for (const statement of localClassDeclarations) {
|
|
209
|
+
// We don't build full IR yet, just enough for type mapping. All local
|
|
210
|
+
// names are already registered so forward and mutually recursive fields
|
|
211
|
+
// use the same class-reference representation.
|
|
212
|
+
const classIR = classDeclarationToIR(statement, fileName, sourceText, [], new Map(), new Map(), [], new Map());
|
|
213
|
+
if (classIR) {
|
|
214
|
+
topLevelClasses.set(classIR.name, classIR);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
const functionReturnTypes = buildFunctionReturnTypeMap(source);
|
|
218
|
+
// Expose return types on the compilation context so UI callbacks / timers
|
|
219
|
+
// can resolve helper types without every call site threading the map.
|
|
220
|
+
getContext().activeFunctionReturnTypes.clear();
|
|
221
|
+
for (const [name, type] of functionReturnTypes) {
|
|
222
|
+
getContext().activeFunctionReturnTypes.set(name, type);
|
|
223
|
+
}
|
|
224
|
+
const topLevelVariableTypes = new Map();
|
|
225
|
+
let defaultExportName;
|
|
226
|
+
// Pre-scan cross-module imports for enum names and function return types
|
|
227
|
+
// so that inferExprCppType can resolve imported enum members and function calls.
|
|
228
|
+
const earlyCrossModuleImports = [];
|
|
229
|
+
for (const stmt of source.statements) {
|
|
230
|
+
if (ts.isImportDeclaration(stmt) && stmt.moduleSpecifier && ts.isStringLiteral(stmt.moduleSpecifier)) {
|
|
231
|
+
const namedImports = [];
|
|
232
|
+
if (stmt.importClause?.namedBindings && ts.isNamedImports(stmt.importClause.namedBindings)) {
|
|
233
|
+
namedImports.push(...stmt.importClause.namedBindings.elements.map((e) => e.name.text));
|
|
234
|
+
}
|
|
235
|
+
earlyCrossModuleImports.push({ moduleSpecifier: stmt.moduleSpecifier.text, namedImports });
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
for (const imp of earlyCrossModuleImports) {
|
|
239
|
+
if (!imp.moduleSpecifier.startsWith('./') && !imp.moduleSpecifier.startsWith('../'))
|
|
240
|
+
continue;
|
|
241
|
+
const resolvedPath = resolveRelativeImportPath(fileName, imp.moduleSpecifier);
|
|
242
|
+
if (!resolvedPath)
|
|
243
|
+
continue;
|
|
244
|
+
try {
|
|
245
|
+
const importedSource = fs.readFileSync(resolvedPath, "utf8");
|
|
246
|
+
const importedEnumNames = scanSourceForEnumNames(importedSource);
|
|
247
|
+
for (const name of imp.namedImports) {
|
|
248
|
+
if (importedEnumNames.has(name)) {
|
|
249
|
+
activeEnumNames.add(name);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
const importedParsed = parseSource(resolvedPath, importedSource);
|
|
253
|
+
const importedFnReturnTypes = buildFunctionReturnTypeMap(importedParsed);
|
|
254
|
+
for (const [fnName, returnType] of importedFnReturnTypes) {
|
|
255
|
+
if (imp.namedImports.includes(fnName) && returnType !== "auto") {
|
|
256
|
+
functionReturnTypes.set(fnName, returnType);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
catch {
|
|
261
|
+
// Non-fatal — file might not be readable or parseable
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
// Collect pointer variables at top level (for correct -> vs . usage)
|
|
265
|
+
// This also populates activeCArrayVars for typed array variables
|
|
266
|
+
const topLevelPointerVars = collectPointerVars(source.statements);
|
|
267
|
+
for (const statement of source.statements) {
|
|
268
|
+
if (ts.isTypeAliasDeclaration(statement)) {
|
|
269
|
+
typeAliasNodes.set(statement.name.text, statement.type);
|
|
270
|
+
if (ts.isUnionTypeNode(statement.type) && statement.type.types.every(ts.isTypeLiteralNode)) {
|
|
271
|
+
const variantNames = statement.type.types.map((_, i) => `_${statement.name.text}_Variant_${i}`);
|
|
272
|
+
discriminatedUnionVariantNames.set(statement.name.text, variantNames);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
// Pre-scan for mutable arrays (push/pop/indexOf) at top level
|
|
277
|
+
for (const statement of source.statements) {
|
|
278
|
+
prescanArrayUsage(statement);
|
|
279
|
+
}
|
|
280
|
+
// Resolve board-definition constants BEFORE IR building so the HAL resolver
|
|
281
|
+
// can access them via currentBoardConstants during method body processing.
|
|
282
|
+
// First pass: collect imports so we can find the board package.
|
|
283
|
+
const earlyImports = [];
|
|
284
|
+
for (const stmt of source.statements) {
|
|
285
|
+
if (ts.isImportDeclaration(stmt) && stmt.moduleSpecifier && ts.isStringLiteral(stmt.moduleSpecifier)) {
|
|
286
|
+
const moduleSpecifier = stmt.moduleSpecifier.text;
|
|
287
|
+
const namedImports = [];
|
|
288
|
+
if (stmt.importClause?.namedBindings && ts.isNamedImports(stmt.importClause.namedBindings)) {
|
|
289
|
+
namedImports.push(...stmt.importClause.namedBindings.elements.map((e) => e.name.text));
|
|
290
|
+
}
|
|
291
|
+
// The `ui` namespace from @typecad/ui is a compile-time construct: its
|
|
292
|
+
// calls (ui.mount/signal/bind) are intercepted by tryResolveUICall and
|
|
293
|
+
// lowered to IR, but `ui` itself must NOT be emitted as a C++ value
|
|
294
|
+
// (it would synthesize a bogus _ui_t struct). Drop it from the imports
|
|
295
|
+
// IR so the emit path never sees it as an imported value.
|
|
296
|
+
const isUiPackage = moduleSpecifier === '@typecad/ui' || moduleSpecifier === '@typecad/ui';
|
|
297
|
+
const filteredImports = isUiPackage
|
|
298
|
+
? namedImports.filter((n) => n !== 'ui')
|
|
299
|
+
: namedImports;
|
|
300
|
+
earlyImports.push({ moduleSpecifier, namedImports: filteredImports });
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
for (const imp of earlyImports) {
|
|
304
|
+
const boardFile = tryResolveBoardDefFile(fileName, imp.moduleSpecifier, boardPackage);
|
|
305
|
+
if (boardFile) {
|
|
306
|
+
try {
|
|
307
|
+
setCurrentBoardConstants(resolveBoardConstants(boardFile));
|
|
308
|
+
}
|
|
309
|
+
catch {
|
|
310
|
+
// Non-fatal
|
|
311
|
+
}
|
|
312
|
+
break;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
// If only the default board constants are loaded (4 keys from getDefaultBoardConstants),
|
|
316
|
+
// try the config's boardPackage directly. This covers the case where board()/boardResolve()
|
|
317
|
+
// is imported from @typecad/hal but no @typecad/board-* import is present in the user's code.
|
|
318
|
+
const currentBC = getCurrentBoardConstants();
|
|
319
|
+
if (currentBC && currentBC.size <= 4 && boardPackage) {
|
|
320
|
+
const boardFile = tryResolveBoardDefFile(fileName, boardPackage, boardPackage);
|
|
321
|
+
if (boardFile) {
|
|
322
|
+
try {
|
|
323
|
+
setCurrentBoardConstants(resolveBoardConstants(boardFile));
|
|
324
|
+
}
|
|
325
|
+
catch {
|
|
326
|
+
// Non-fatal
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
// Phase 0c-bis: register UI module imports (name → .ui.html path) so
|
|
331
|
+
// ui.mount(screen, ...) can resolve `screen` back to its source tree.
|
|
332
|
+
// Only .ui.html specifiers are registered; their named imports are the UI
|
|
333
|
+
// tree handles (e.g. `screen`).
|
|
334
|
+
for (const imp of earlyImports) {
|
|
335
|
+
if (!imp.moduleSpecifier.endsWith(".ui.html"))
|
|
336
|
+
continue;
|
|
337
|
+
const htmlPath = resolveUIImportPath(fileName, imp.moduleSpecifier);
|
|
338
|
+
if (!htmlPath)
|
|
339
|
+
continue;
|
|
340
|
+
for (const name of imp.namedImports) {
|
|
341
|
+
registerUIModuleImport(name, htmlPath);
|
|
342
|
+
// Register each element in the tree for .value access
|
|
343
|
+
const mod = requireUIHook().getUIModule(htmlPath);
|
|
344
|
+
if (mod) {
|
|
345
|
+
// Register screen IDs → indices for <a href="#screenId"> navigation.
|
|
346
|
+
for (let si = 0; si < mod.allStyledScreens.length; si++) {
|
|
347
|
+
const screenNode = mod.allStyledScreens[si];
|
|
348
|
+
if (screenNode.id)
|
|
349
|
+
registerScreenId(screenNode.id, si);
|
|
350
|
+
}
|
|
351
|
+
// Register each element in ALL screens for .value access + auto-wire.
|
|
352
|
+
const collectIds = (node) => {
|
|
353
|
+
if (node.id)
|
|
354
|
+
registerElementValue(name, node.id, htmlPath);
|
|
355
|
+
node.children?.forEach(collectIds);
|
|
356
|
+
};
|
|
357
|
+
if (mod.allStyledScreens.length > 0) {
|
|
358
|
+
let nextUiNodeIndex = 0;
|
|
359
|
+
for (const screen of mod.allStyledScreens) {
|
|
360
|
+
collectIds(screen);
|
|
361
|
+
nextUiNodeIndex = autoWireElements(name, screen, nextUiNodeIndex);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
else {
|
|
365
|
+
collectIds(mod.styled);
|
|
366
|
+
autoWireElements(name, mod.styled, 0);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
// Phase 0d: record top-level HAL alias declarations (varName → receiver text)
|
|
372
|
+
// in a cheap, resolution-free pass. `resolveHALReceiver` follows this map
|
|
373
|
+
// lazily so a function that references an alias (`led.high()`) resolves it
|
|
374
|
+
// even when declared before the `const led = LED.asOutput()` — making HAL
|
|
375
|
+
// resolution order-independent (demo #34 Finding C). Only mode-SETTER calls
|
|
376
|
+
// (which return the pin itself) are recorded; value-bearing reads are
|
|
377
|
+
// excluded so their variables don't alias the pin (Finding B). The receiver
|
|
378
|
+
// is resolved at lookup time (after imports have registered `LED` etc.), not
|
|
379
|
+
// here, so import order doesn't matter.
|
|
380
|
+
const HAL_ALIASING_METHODS = new Set([
|
|
381
|
+
"asOutput", "asInput", "asInputPullUp", "asInputPullDown",
|
|
382
|
+
"output", "inputPullUp", "inputPullDown",
|
|
383
|
+
"device", // I2CBus.device(addr) / SPIBus.device(cs) → device instance
|
|
384
|
+
"tone", // OutputPin.tone(freq) → ToneChain
|
|
385
|
+
"begin", // I2CBus.begin() / SPIBus.begin() / SerialPort.begin() → same instance
|
|
386
|
+
"take", // Bus.take() → same instance (ownership is compile-time only)
|
|
387
|
+
]);
|
|
388
|
+
for (const node of source.statements) {
|
|
389
|
+
if (!ts.isVariableStatement(node))
|
|
390
|
+
continue;
|
|
391
|
+
for (const decl of node.declarationList.declarations) {
|
|
392
|
+
if (!decl.initializer || !ts.isIdentifier(decl.name))
|
|
393
|
+
continue;
|
|
394
|
+
const init = decl.initializer;
|
|
395
|
+
if (ts.isCallExpression(init) && ts.isPropertyAccessExpression(init.expression)
|
|
396
|
+
&& HAL_ALIASING_METHODS.has(init.expression.name.text)
|
|
397
|
+
&& ts.isIdentifier(init.expression.expression)) {
|
|
398
|
+
// Capture call arguments for factory methods like device(0x76) that
|
|
399
|
+
// need the arg to construct the derived instance (I2CDevice._address).
|
|
400
|
+
const argTexts = init.arguments.map(a => {
|
|
401
|
+
if (ts.isNumericLiteral(a))
|
|
402
|
+
return a.text;
|
|
403
|
+
if (ts.isStringLiteral(a))
|
|
404
|
+
return a.text;
|
|
405
|
+
if (ts.isIdentifier(a))
|
|
406
|
+
return a.text;
|
|
407
|
+
return a.getText();
|
|
408
|
+
});
|
|
409
|
+
topLevelAliasReceivers.set(decl.name.text, { receiver: init.expression.expression.text, method: init.expression.name.text, args: argTexts });
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
source.forEachChild((node) => {
|
|
414
|
+
if (ts.isImportDeclaration(node) && node.moduleSpecifier && ts.isStringLiteral(node.moduleSpecifier)) {
|
|
415
|
+
const moduleSpecifier = node.moduleSpecifier.text;
|
|
416
|
+
const namedImports = [];
|
|
417
|
+
let defaultImportName;
|
|
418
|
+
// Handle default import: import X from "./module.js"
|
|
419
|
+
if (node.importClause?.name && ts.isIdentifier(node.importClause.name)) {
|
|
420
|
+
defaultImportName = node.importClause.name.text;
|
|
421
|
+
}
|
|
422
|
+
// Handle named imports: import { a, b } from "./module.js"
|
|
423
|
+
if (node.importClause?.namedBindings && ts.isNamedImports(node.importClause.namedBindings)) {
|
|
424
|
+
namedImports.push(...node.importClause.namedBindings.elements.map((e) => e.name.text));
|
|
425
|
+
}
|
|
426
|
+
if (namedImports.length > 0 || defaultImportName) {
|
|
427
|
+
imports.push({
|
|
428
|
+
moduleSpecifier,
|
|
429
|
+
namedImports,
|
|
430
|
+
...(defaultImportName ? { defaultImportName } : {}),
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
// Register PascalCase imports from relative modules as potential class names
|
|
434
|
+
// so that static method calls (e.g., Button.start()) use the :: operator.
|
|
435
|
+
if (moduleSpecifier.startsWith('./') || moduleSpecifier.startsWith('../')) {
|
|
436
|
+
for (const name of namedImports) {
|
|
437
|
+
if (/^[A-Z]/.test(name)) {
|
|
438
|
+
topLevelClassNames.add(name);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
// Track HAL instances imported from board packages and framework stubs
|
|
443
|
+
// so the HAL resolver can resolve them to Arduino C++ names.
|
|
444
|
+
// The `@typecad/board` virtual import resolves to the board package, so it
|
|
445
|
+
// also registers pin aliases (LED, etc.). Case-insensitive on the scope.
|
|
446
|
+
const lowerSpecifier = moduleSpecifier.toLowerCase();
|
|
447
|
+
const isHALSource = lowerSpecifier.startsWith('@typecad/board-')
|
|
448
|
+
|| lowerSpecifier === '@typecad/framework-arduino/arduino'
|
|
449
|
+
|| lowerSpecifier === '@typecad/board';
|
|
450
|
+
// UI authoring namespace: `import { ui } from "@typecad/ui"`. The `ui`
|
|
451
|
+
// value is a compile-time construct (its calls are intercepted by
|
|
452
|
+
// tryResolveUICall); it must NOT be emitted as a C++ struct/value.
|
|
453
|
+
// Treat it like the HAL namespace imports (Pulse/Shift/Random): register
|
|
454
|
+
// as a namespace name and skip, so no struct is synthesized.
|
|
455
|
+
if (moduleSpecifier === '@typecad/ui' || moduleSpecifier === '@typecad/ui') {
|
|
456
|
+
for (const name of namedImports) {
|
|
457
|
+
if (name === 'ui') {
|
|
458
|
+
activeNamespaceNames.add(name);
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
if (isHALSource) {
|
|
463
|
+
const boardConstants = getCurrentBoardConstants();
|
|
464
|
+
const analogOffset = boardConstants.get("pins.analogOffset") ?? 14;
|
|
465
|
+
for (const name of namedImports) {
|
|
466
|
+
// Check if this name is a known pin alias (D0, A0, LED, etc.)
|
|
467
|
+
// Transitively resolve aliases: LED -> D13 -> "13"
|
|
468
|
+
let pinVal = pinAliasMap.get(name);
|
|
469
|
+
if (pinVal) {
|
|
470
|
+
// Resolve transitive aliases (e.g. LED -> D13 -> 13)
|
|
471
|
+
while (pinVal && pinAliasMap.has(pinVal) && !/^\d+$/.test(pinVal)) {
|
|
472
|
+
const nextVal = pinAliasMap.get(pinVal);
|
|
473
|
+
if (!nextVal || nextVal === pinVal)
|
|
474
|
+
break; // prevent infinite loop
|
|
475
|
+
pinVal = nextVal;
|
|
476
|
+
}
|
|
477
|
+
const fields = new Map([["_pin", pinVal]]);
|
|
478
|
+
const portName = mcuPinReverseMap.get(pinVal);
|
|
479
|
+
if (portName)
|
|
480
|
+
fields.set("_port", portName);
|
|
481
|
+
halInstances.set(name, { className: "Pin", fieldValues: fields });
|
|
482
|
+
continue;
|
|
483
|
+
}
|
|
484
|
+
// D-pins: D0-D53 → Pin instance with MCU port name (fallback)
|
|
485
|
+
const dMatch = name.match(/^D(\d+)$/);
|
|
486
|
+
if (dMatch) {
|
|
487
|
+
const fields = new Map([["_pin", dMatch[1]]]);
|
|
488
|
+
const portName = mcuPinReverseMap.get(dMatch[1]);
|
|
489
|
+
if (portName)
|
|
490
|
+
fields.set("_port", portName);
|
|
491
|
+
halInstances.set(name, { className: "Pin", fieldValues: fields });
|
|
492
|
+
continue;
|
|
493
|
+
}
|
|
494
|
+
// A-pins: A0-A19 → Pin instance with board-specific offset and MCU port name (fallback)
|
|
495
|
+
const aMatch = name.match(/^A(\d+)$/);
|
|
496
|
+
if (aMatch) {
|
|
497
|
+
const pinNum = String(analogOffset + parseInt(aMatch[1]));
|
|
498
|
+
const fields = new Map([["_pin", pinNum]]);
|
|
499
|
+
const portName = mcuPinReverseMap.get(pinNum);
|
|
500
|
+
if (portName)
|
|
501
|
+
fields.set("_port", portName);
|
|
502
|
+
halInstances.set(name, { className: "Pin", fieldValues: fields });
|
|
503
|
+
continue;
|
|
504
|
+
}
|
|
505
|
+
// I2C buses: I2C0, I2C1, ...
|
|
506
|
+
const i2cMatch = name.match(/^I2C(\d+)$/);
|
|
507
|
+
if (i2cMatch) {
|
|
508
|
+
const alias = peripheralAliasMap.get(name) ?? (i2cMatch[1] === '0' ? 'Wire' : `Wire${i2cMatch[1]}`);
|
|
509
|
+
halInstances.set(name, { className: "I2CBus", fieldValues: new Map([["_bus", alias]]) });
|
|
510
|
+
continue;
|
|
511
|
+
}
|
|
512
|
+
// SPI buses: SPI0, SPI1, ...
|
|
513
|
+
const spiMatch = name.match(/^SPI(\d+)$/);
|
|
514
|
+
if (spiMatch) {
|
|
515
|
+
const alias = peripheralAliasMap.get(name) ?? (spiMatch[1] === '0' ? 'SPI' : `SPI${spiMatch[1]}`);
|
|
516
|
+
halInstances.set(name, { className: "SPIBus", fieldValues: new Map([["_bus", alias]]) });
|
|
517
|
+
continue;
|
|
518
|
+
}
|
|
519
|
+
// UART: UART0, UART1, ...
|
|
520
|
+
const uartMatch = name.match(/^UART(\d+)$/);
|
|
521
|
+
if (uartMatch) {
|
|
522
|
+
const alias = peripheralAliasMap.get(name) ?? (uartMatch[1] === '0' ? 'Serial' : `Serial${uartMatch[1]}`);
|
|
523
|
+
halInstances.set(name, { className: "SerialPort", fieldValues: new Map([["_port", alias]]) });
|
|
524
|
+
continue;
|
|
525
|
+
}
|
|
526
|
+
// HAL namespace imports: Pulse, Shift, Random
|
|
527
|
+
if (name === 'Pulse' || name === 'Shift' || name === 'Random') {
|
|
528
|
+
activeNamespaceNames.add(name);
|
|
529
|
+
continue;
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
return;
|
|
534
|
+
}
|
|
535
|
+
// Handle re-exports: export * from "./module.js" or export { a, b } from "./module.js"
|
|
536
|
+
if (ts.isExportDeclaration(node) && node.moduleSpecifier && ts.isStringLiteral(node.moduleSpecifier)) {
|
|
537
|
+
const moduleSpecifier = node.moduleSpecifier.text;
|
|
538
|
+
const exportAll = !node.exportClause || !ts.isNamedExports(node.exportClause);
|
|
539
|
+
const namedExports = node.exportClause && ts.isNamedExports(node.exportClause)
|
|
540
|
+
? node.exportClause.elements.map((e) => e.name.text)
|
|
541
|
+
: undefined;
|
|
542
|
+
reExports.push({
|
|
543
|
+
moduleSpecifier,
|
|
544
|
+
exportAll,
|
|
545
|
+
namedExports,
|
|
546
|
+
});
|
|
547
|
+
return;
|
|
548
|
+
}
|
|
549
|
+
// Handle export default statements (ExportAssignment)
|
|
550
|
+
if (ts.isExportAssignment(node)) {
|
|
551
|
+
if (node.isExportEquals) {
|
|
552
|
+
// export = X — board config style, skip
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
// export default <identifier> — record the name for default import resolution
|
|
556
|
+
if (ts.isIdentifier(node.expression)) {
|
|
557
|
+
defaultExportName = node.expression.text;
|
|
558
|
+
}
|
|
559
|
+
else if (ts.isFunctionExpression(node.expression) && node.expression.name) {
|
|
560
|
+
// export default function name() { ... } — extract the function name.
|
|
561
|
+
defaultExportName = node.expression.name.text;
|
|
562
|
+
}
|
|
563
|
+
else if (ts.isFunctionExpression(node.expression)) {
|
|
564
|
+
// export default function() { ... } (anonymous) — synthesize a name.
|
|
565
|
+
defaultExportName = "__default_export__";
|
|
566
|
+
}
|
|
567
|
+
else if (ts.isClassExpression(node.expression) && node.expression.name) {
|
|
568
|
+
// export default class Name { ... } — extract the class name.
|
|
569
|
+
defaultExportName = node.expression.name.text;
|
|
570
|
+
}
|
|
571
|
+
else if (ts.isClassExpression(node.expression)) {
|
|
572
|
+
// export default class { ... } (anonymous) — synthesize a name.
|
|
573
|
+
defaultExportName = "__default_export__";
|
|
574
|
+
}
|
|
575
|
+
// For export default function/class, the declaration is already processed
|
|
576
|
+
// by the function/class handlers above — we just record the name.
|
|
577
|
+
return;
|
|
578
|
+
}
|
|
579
|
+
// Handle namespace declarations
|
|
580
|
+
if (ts.isModuleDeclaration(node)) {
|
|
581
|
+
const nsIR = namespaceToIR(node, fileName, sourceText, diagnostics, functionReturnTypes, typeAliasNodes, registerClasses, topLevelPointerVars);
|
|
582
|
+
if (nsIR) {
|
|
583
|
+
namespaces.push(nsIR);
|
|
584
|
+
activeNamespaceNames.add(nsIR.name);
|
|
585
|
+
}
|
|
586
|
+
return;
|
|
587
|
+
}
|
|
588
|
+
if (ts.isFunctionDeclaration(node)) {
|
|
589
|
+
const fnIR = functionDeclarationToIR(node, fileName, sourceText, diagnostics, functionReturnTypes, typeAliasNodes, boilerplates, topLevelPointerVars, lowerStatementList);
|
|
590
|
+
if (fnIR) {
|
|
591
|
+
functions.push(fnIR);
|
|
592
|
+
}
|
|
593
|
+
return;
|
|
594
|
+
}
|
|
595
|
+
if (ts.isVariableStatement(node)) {
|
|
596
|
+
// Check if all declarations are function expressions/arrow functions
|
|
597
|
+
const fnResults = variableAsFunctionToIR(node, fileName, sourceText, diagnostics, functionReturnTypes, typeAliasNodes, boilerplates, topLevelPointerVars, lowerStatementList);
|
|
598
|
+
if (fnResults) {
|
|
599
|
+
functions.push(...fnResults);
|
|
600
|
+
return;
|
|
601
|
+
}
|
|
602
|
+
topLevelStatements.push(...variableStatementToIR(node, fileName, sourceText, diagnostics, functionReturnTypes, topLevelVariableTypes, typeAliasNodes, topLevelPointerVars, "", lowerStatementList));
|
|
603
|
+
return;
|
|
604
|
+
}
|
|
605
|
+
if (ts.isExpressionStatement(node)) {
|
|
606
|
+
const lowered = expressionStatementToIR(node, fileName, sourceText, diagnostics, functionReturnTypes, topLevelVariableTypes, topLevelPointerVars);
|
|
607
|
+
if (lowered) {
|
|
608
|
+
topLevelStatements.push(lowered);
|
|
609
|
+
}
|
|
610
|
+
return;
|
|
611
|
+
}
|
|
612
|
+
if (ts.isClassDeclaration(node)) {
|
|
613
|
+
const classIR = classDeclarationToIR(node, fileName, sourceText, diagnostics, functionReturnTypes, typeAliasNodes, registerClasses, topLevelPointerVars);
|
|
614
|
+
if (classIR) {
|
|
615
|
+
classes.push(classIR);
|
|
616
|
+
topLevelClassNames.add(classIR.name);
|
|
617
|
+
classTypeNames.add(classIR.name);
|
|
618
|
+
topLevelClasses.set(classIR.name, classIR);
|
|
619
|
+
}
|
|
620
|
+
return;
|
|
621
|
+
}
|
|
622
|
+
// Handle enum declarations
|
|
623
|
+
if (ts.isEnumDeclaration(node)) {
|
|
624
|
+
const enumIR = enumDeclarationToIR(node, fileName, sourceText);
|
|
625
|
+
if (enumIR) {
|
|
626
|
+
enums.push(enumIR);
|
|
627
|
+
activeEnumNames.add(enumIR.name);
|
|
628
|
+
if (isStringEnum(enumIR)) {
|
|
629
|
+
activeStringEnumNames.add(enumIR.name);
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
return;
|
|
633
|
+
}
|
|
634
|
+
// Handle interface declarations
|
|
635
|
+
if (ts.isInterfaceDeclaration(node)) {
|
|
636
|
+
const ifaceIR = interfaceDeclarationToIR(node, fileName, sourceText, typeAliasNodes);
|
|
637
|
+
if (ifaceIR) {
|
|
638
|
+
interfaces.push(ifaceIR);
|
|
639
|
+
}
|
|
640
|
+
return;
|
|
641
|
+
}
|
|
642
|
+
// Handle type alias declarations
|
|
643
|
+
if (ts.isTypeAliasDeclaration(node)) {
|
|
644
|
+
const aliasIR = typeAliasDeclarationToIR(node, fileName, sourceText, typeAliasNodes);
|
|
645
|
+
if (aliasIR) {
|
|
646
|
+
typeAliases.push(aliasIR);
|
|
647
|
+
}
|
|
648
|
+
return;
|
|
649
|
+
}
|
|
650
|
+
if (node.kind === ts.SyntaxKind.EndOfFileToken) {
|
|
651
|
+
return;
|
|
652
|
+
}
|
|
653
|
+
// General fallthrough: lower any remaining statement types (while, for,
|
|
654
|
+
// if, switch, do-while, etc.) that appear at the top level directly.
|
|
655
|
+
{
|
|
656
|
+
const lowered = lowerStatement(node, fileName, sourceText, diagnostics, functionReturnTypes, topLevelVariableTypes, "<top-level>", typeAliasNodes, topLevelPointerVars);
|
|
657
|
+
if (lowered) {
|
|
658
|
+
topLevelStatements.push(...lowered);
|
|
659
|
+
return;
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
diagnostics.push(makeDiagnostic(normalizedSourceText, node.pos, "Top-level node currently unsupported and skipped.", "error", "TS2CPP_UNSUPPORTED_TOPLEVEL"));
|
|
663
|
+
});
|
|
664
|
+
// Collect any nested functions that were hoisted during IR building
|
|
665
|
+
functions.push(...hoistedNestedFunctions);
|
|
666
|
+
// Collect any nested classes that were hoisted during IR building
|
|
667
|
+
classes.push(...hoistedNestedClasses);
|
|
668
|
+
// Synthesize forwarding constructors for subclasses that don't declare one.
|
|
669
|
+
// A subclass `class B extends A {}` with no explicit constructor previously
|
|
670
|
+
// emitted NO constructor, so `new B(args)` failed (no matching ctor) and any
|
|
671
|
+
// base parameter-property initialization was lost. C++ has no implicit
|
|
672
|
+
// inherited constructor: we must synthesize one that mirrors the base's
|
|
673
|
+
// signature and forwards via a super_call. See demo #14 Finding B.
|
|
674
|
+
synthesizeSubclassConstructors(classes);
|
|
675
|
+
// Collect any nested enums that were hoisted during IR building
|
|
676
|
+
enums.push(...hoistedNestedEnums);
|
|
677
|
+
// Collect any local interface declarations that were hoisted during IR building
|
|
678
|
+
for (const iface of hoistedNestedInterfaces) {
|
|
679
|
+
if (!interfaces.some(i => i.name === iface.name)) {
|
|
680
|
+
interfaces.push(iface);
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
// Collect any local type alias declarations that were hoisted during IR building
|
|
684
|
+
for (const alias of hoistedNestedTypeAliases) {
|
|
685
|
+
if (!typeAliases.some(a => a.name === alias.name)) {
|
|
686
|
+
typeAliases.push(alias);
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
// Merge duplicate interface declarations (TS declaration merging)
|
|
690
|
+
{
|
|
691
|
+
const ifaceMap = new Map();
|
|
692
|
+
for (const iface of interfaces) {
|
|
693
|
+
const existing = ifaceMap.get(iface.name);
|
|
694
|
+
if (existing) {
|
|
695
|
+
existing.fields.push(...iface.fields);
|
|
696
|
+
existing.methods.push(...iface.methods);
|
|
697
|
+
}
|
|
698
|
+
else {
|
|
699
|
+
ifaceMap.set(iface.name, { ...iface, fields: [...iface.fields], methods: [...iface.methods] });
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
interfaces.length = 0;
|
|
703
|
+
interfaces.push(...ifaceMap.values());
|
|
704
|
+
}
|
|
705
|
+
// Record top-level interface names. Interfaces lower to C++ structs (value
|
|
706
|
+
// types), so a local/param of an interface type is a value — never null. The
|
|
707
|
+
// null-comparison guard in expression-to-ir consults this set to recognise
|
|
708
|
+
// such a value as a value type (topLevelClassNames holds only classes, which
|
|
709
|
+
// are always pointer/reference types). Demo #18 Finding A.
|
|
710
|
+
for (const iface of interfaces) {
|
|
711
|
+
topLevelInterfaceNames.add(iface.name);
|
|
712
|
+
}
|
|
713
|
+
// Merge duplicate namespace declarations
|
|
714
|
+
{
|
|
715
|
+
const nsMap = new Map();
|
|
716
|
+
for (const ns of namespaces) {
|
|
717
|
+
const existing = nsMap.get(ns.name);
|
|
718
|
+
if (existing) {
|
|
719
|
+
existing.enums.push(...ns.enums);
|
|
720
|
+
existing.classes.push(...ns.classes);
|
|
721
|
+
existing.functions.push(...ns.functions);
|
|
722
|
+
existing.constants.push(...ns.constants);
|
|
723
|
+
existing.interfaces.push(...ns.interfaces);
|
|
724
|
+
existing.typeAliases.push(...ns.typeAliases);
|
|
725
|
+
}
|
|
726
|
+
else {
|
|
727
|
+
nsMap.set(ns.name, {
|
|
728
|
+
...ns,
|
|
729
|
+
enums: [...ns.enums],
|
|
730
|
+
classes: [...ns.classes],
|
|
731
|
+
functions: [...ns.functions],
|
|
732
|
+
constants: [...ns.constants],
|
|
733
|
+
interfaces: [...ns.interfaces],
|
|
734
|
+
typeAliases: [...ns.typeAliases],
|
|
735
|
+
});
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
namespaces.length = 0;
|
|
739
|
+
namespaces.push(...nsMap.values());
|
|
740
|
+
}
|
|
741
|
+
// Populate top-level class names for :: static method rendering
|
|
742
|
+
for (const cls of classes) {
|
|
743
|
+
topLevelClassNames.add(cls.name);
|
|
744
|
+
classTypeNames.add(cls.name);
|
|
745
|
+
}
|
|
746
|
+
// Board constants were already resolved before IR building (for HAL resolver access).
|
|
747
|
+
// Reuse the module-level value for the ProgramIR output.
|
|
748
|
+
const boardConstants = getCurrentBoardConstants();
|
|
749
|
+
// Analyze peripheral usage for optimization
|
|
750
|
+
let peripheralUsage;
|
|
751
|
+
try {
|
|
752
|
+
const partialProgram = {
|
|
753
|
+
fileName,
|
|
754
|
+
imports,
|
|
755
|
+
reExports,
|
|
756
|
+
structs: [],
|
|
757
|
+
enums,
|
|
758
|
+
classes,
|
|
759
|
+
typeAliases,
|
|
760
|
+
registerClasses,
|
|
761
|
+
topLevelStatements,
|
|
762
|
+
functions,
|
|
763
|
+
boilerplates,
|
|
764
|
+
diagnostics,
|
|
765
|
+
boardConstants,
|
|
766
|
+
peripheralUsage: createEmptyPeripheralUsage(),
|
|
767
|
+
interfaces,
|
|
768
|
+
namespaces,
|
|
769
|
+
// Include registeredCallbacks so interrupt-safety analysis can see
|
|
770
|
+
// user ISR lambdas (onRising/onFalling/etc.) at validation time. The
|
|
771
|
+
// callbackIR on each entry carries isInterruptHandler=true (set in
|
|
772
|
+
// hal-emitter.ts); without this field the scanner's source (3) at
|
|
773
|
+
// interrupt-analysis.ts:212 never iterates, so ISR unsafe-op detection
|
|
774
|
+
// silently misses every user interrupt handler.
|
|
775
|
+
registeredCallbacks: [...registeredCallbacks],
|
|
776
|
+
};
|
|
777
|
+
peripheralUsage = analyzePeripheralUsage(partialProgram);
|
|
778
|
+
partialProgram.peripheralUsage = peripheralUsage;
|
|
779
|
+
diagnostics.push(...runProgramValidations(partialProgram));
|
|
780
|
+
}
|
|
781
|
+
catch (e) {
|
|
782
|
+
// If peripheral analysis fails, use empty usage
|
|
783
|
+
peripheralUsage = createEmptyPeripheralUsage();
|
|
784
|
+
}
|
|
785
|
+
return {
|
|
786
|
+
fileName,
|
|
787
|
+
imports,
|
|
788
|
+
reExports,
|
|
789
|
+
structs: [],
|
|
790
|
+
enums,
|
|
791
|
+
classes,
|
|
792
|
+
typeAliases,
|
|
793
|
+
registerClasses,
|
|
794
|
+
topLevelStatements,
|
|
795
|
+
functions,
|
|
796
|
+
boilerplates,
|
|
797
|
+
diagnostics,
|
|
798
|
+
boardConstants,
|
|
799
|
+
peripheralUsage,
|
|
800
|
+
requiredIncludes: new Set(requiredIncludes),
|
|
801
|
+
interfaces,
|
|
802
|
+
namespaces,
|
|
803
|
+
registeredCallbacks: [...registeredCallbacks],
|
|
804
|
+
restParamFunctions: new Map(restParamFunctions),
|
|
805
|
+
...(defaultExportName ? { defaultExportName } : {}),
|
|
806
|
+
};
|
|
807
|
+
});
|
|
808
|
+
}
|