@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,851 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { filterPolyfillHelpers, isStringEnum } from "../../api/shared/index.js";
|
|
3
|
+
import { analyzeProgram } from "../../ir/program-analysis.js";
|
|
4
|
+
import { collectStatementIdentifiers } from "../../ir/identifier-collector.js";
|
|
5
|
+
import { ensureDir } from "../../utils/fs.js";
|
|
6
|
+
import { resolveImport } from "../../libdef/registry.js";
|
|
7
|
+
import { emitPolyfillBoilerplate } from "../native-helpers-emitter.js";
|
|
8
|
+
import { resolveStrategy } from "../../platform/registry.js";
|
|
9
|
+
import { getLoadedFramework } from "../../framework-registry.js";
|
|
10
|
+
import { entryHasUI } from "../../ui-hook.js";
|
|
11
|
+
import { createEmissionScopeState, statementNeedsSnprintf, } from "../snprintf-helpers.js";
|
|
12
|
+
import { ExpressionRenderer } from "../expression-renderer.js";
|
|
13
|
+
import { StatementRenderer } from "../statement-renderer.js";
|
|
14
|
+
import { isCuttlefishSDKImport, normalizeInclude, applySymbolMap, generateAsyncTaskClass, resolveTranspiledModuleInclude, } from "../utils/index.js";
|
|
15
|
+
function resolveTemplateReturnType(returnType, typeParameters) {
|
|
16
|
+
if (!typeParameters || typeParameters.length === 0)
|
|
17
|
+
return returnType;
|
|
18
|
+
return returnType;
|
|
19
|
+
}
|
|
20
|
+
function filterShimBlock(lines, startMarker, endMarker) {
|
|
21
|
+
const startIdx = lines.findIndex(l => l.includes(startMarker));
|
|
22
|
+
if (startIdx === -1)
|
|
23
|
+
return lines;
|
|
24
|
+
const endIdx = lines.findIndex((l, i) => i >= startIdx && l.includes(endMarker));
|
|
25
|
+
if (endIdx === -1)
|
|
26
|
+
return lines;
|
|
27
|
+
const filtered = lines.slice();
|
|
28
|
+
filtered.splice(startIdx, endIdx - startIdx + 1);
|
|
29
|
+
while (filtered.length > 0 && filtered[startIdx] === '') {
|
|
30
|
+
filtered.splice(startIdx, 1);
|
|
31
|
+
}
|
|
32
|
+
return filtered;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Extract a `#ifndef MACRO ... #endif` include-guard block from a shim line
|
|
36
|
+
* list. Used to emit just the macro definition (e.g. CUTTLEFISH_UNDEFINED) in
|
|
37
|
+
* non-entry files of a split compilation, where the full helper shim belongs
|
|
38
|
+
* to the entry file but the macro token is still referenced here.
|
|
39
|
+
* Returns an empty array if no matching guard is found.
|
|
40
|
+
*/
|
|
41
|
+
function extractShimMacro(lines, macroName) {
|
|
42
|
+
const ifndefIdx = lines.findIndex(l => {
|
|
43
|
+
const trimmed = l.trim();
|
|
44
|
+
return trimmed.startsWith('#ifndef') && trimmed.endsWith(macroName);
|
|
45
|
+
});
|
|
46
|
+
if (ifndefIdx === -1)
|
|
47
|
+
return [];
|
|
48
|
+
// Find the matching #endif that closes this guard.
|
|
49
|
+
let depth = 1;
|
|
50
|
+
let endIdx = -1;
|
|
51
|
+
for (let i = ifndefIdx + 1; i < lines.length; i++) {
|
|
52
|
+
const trimmed = lines[i].trim();
|
|
53
|
+
if (trimmed.startsWith('#ifndef') || trimmed.startsWith('#ifdef'))
|
|
54
|
+
depth++;
|
|
55
|
+
else if (trimmed.startsWith('#endif')) {
|
|
56
|
+
depth--;
|
|
57
|
+
if (depth === 0) {
|
|
58
|
+
endIdx = i;
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (endIdx === -1)
|
|
64
|
+
return [];
|
|
65
|
+
return lines.slice(ifndefIdx, endIdx + 1);
|
|
66
|
+
}
|
|
67
|
+
export function buildEmitterContext(program, options) {
|
|
68
|
+
const largeEnumNames = new Set();
|
|
69
|
+
const enumNames = new Set();
|
|
70
|
+
const stringEnumNames = new Set();
|
|
71
|
+
for (const e of program.enums) {
|
|
72
|
+
enumNames.add(e.name);
|
|
73
|
+
if (isStringEnum(e)) {
|
|
74
|
+
stringEnumNames.add(e.name);
|
|
75
|
+
}
|
|
76
|
+
if (e.members.some(m => typeof m.value === "number" && (m.value > 32767 || m.value < -32768))) {
|
|
77
|
+
largeEnumNames.add(e.name);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
const namespaceNames = new Set();
|
|
81
|
+
for (const ns of program.namespaces) {
|
|
82
|
+
namespaceNames.add(ns.name);
|
|
83
|
+
for (const e of ns.enums) {
|
|
84
|
+
enumNames.add(e.name);
|
|
85
|
+
if (isStringEnum(e)) {
|
|
86
|
+
stringEnumNames.add(e.name);
|
|
87
|
+
}
|
|
88
|
+
if (e.members.some(m => typeof m.value === "number" && (m.value > 32767 || m.value < -32768))) {
|
|
89
|
+
largeEnumNames.add(e.name);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
if (options.crossModuleEnumNames) {
|
|
94
|
+
for (const name of options.crossModuleEnumNames) {
|
|
95
|
+
enumNames.add(name);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
if (options.crossModuleStringEnumNames) {
|
|
99
|
+
for (const name of options.crossModuleStringEnumNames) {
|
|
100
|
+
stringEnumNames.add(name);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
const strategy = options.strategy ?? resolveStrategy(options.target ?? "generic");
|
|
104
|
+
strategy.setLargeEnumNames?.(largeEnumNames);
|
|
105
|
+
const reservedNames = strategy.reservedNames();
|
|
106
|
+
ensureDir(options.outDir);
|
|
107
|
+
const classNameMap = (() => {
|
|
108
|
+
try {
|
|
109
|
+
const framework = getLoadedFramework();
|
|
110
|
+
if (framework.classNameMapBuilder) {
|
|
111
|
+
return framework.classNameMapBuilder(program.imports);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
// No loaded framework
|
|
116
|
+
}
|
|
117
|
+
return undefined;
|
|
118
|
+
})();
|
|
119
|
+
const programAnalysis = analyzeProgram(program, strategy);
|
|
120
|
+
if (options.platformContext) {
|
|
121
|
+
options.platformContext.analysis = programAnalysis;
|
|
122
|
+
if (!options.platformContext.architecture && program.boardConstants) {
|
|
123
|
+
options.platformContext.architecture = program.boardConstants.get("architecture");
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
const originalBaseName = path.basename(program.fileName).replace(/\.[^.]+$/, "");
|
|
127
|
+
const outDirBaseName = path.basename(path.resolve(options.outDir));
|
|
128
|
+
const baseName = options.npmPackage?.moduleKey
|
|
129
|
+
|| strategy.overrideBaseName(originalBaseName, outDirBaseName, options.isEntryFile ?? true, !!options.npmPackage);
|
|
130
|
+
const isNpmPackage = !!options.npmPackage;
|
|
131
|
+
const isEntryFile = options.isEntryFile !== false;
|
|
132
|
+
const isrPrefix = isEntryFile ? 'main' : originalBaseName;
|
|
133
|
+
const effectiveEmitMode = strategy.effectiveEmitMode(options.emitMode, isNpmPackage);
|
|
134
|
+
const includes = [];
|
|
135
|
+
const symbolMap = {};
|
|
136
|
+
let profileDiagnostics = [];
|
|
137
|
+
// Shared sink for emit-time diagnostics (HAL warnings, etc.). Passed by
|
|
138
|
+
// reference to the renderers and merged into the final diagnostics list by
|
|
139
|
+
// finalizeOutput.
|
|
140
|
+
const emitDiagnostics = [];
|
|
141
|
+
let shimLines = [];
|
|
142
|
+
const isEntryFileForPolyfills = isEntryFile;
|
|
143
|
+
const nativePolyfills = isEntryFileForPolyfills
|
|
144
|
+
? (strategy.generateNativePolyfills?.(program, options.platformContext) ?? [])
|
|
145
|
+
: (strategy.generateNativePolyfills?.(program, options.platformContext) ?? []);
|
|
146
|
+
let filteredNativePolyfills = filterPolyfillHelpers(nativePolyfills, programAnalysis.usedPolyfillHelpers);
|
|
147
|
+
if (!programAnalysis.hasThrowStatements) {
|
|
148
|
+
filteredNativePolyfills = filteredNativePolyfills.filter(p => p.id !== "cuttlefish_halt");
|
|
149
|
+
}
|
|
150
|
+
const usesTimers = programAnalysis.usedPolyfillHelpers.has('__tc_setInterval') ||
|
|
151
|
+
programAnalysis.usedPolyfillHelpers.has('__tc_setTimeout');
|
|
152
|
+
if (!usesTimers) {
|
|
153
|
+
filteredNativePolyfills = filteredNativePolyfills.filter(p => p.id !== "timer_methods");
|
|
154
|
+
}
|
|
155
|
+
const allPolyfills = filteredNativePolyfills;
|
|
156
|
+
const emittedPolyfills = allPolyfills.length > 0
|
|
157
|
+
? emitPolyfillBoilerplate(allPolyfills)
|
|
158
|
+
: undefined;
|
|
159
|
+
const hasAsyncRuntime = program.functions.some(fn => fn.isAsync);
|
|
160
|
+
const hasPromiseRuntime = nativePolyfills.some((p) => p.id === "async_runtime" && p.hasPromiseRuntime === true);
|
|
161
|
+
if (!isNpmPackage) {
|
|
162
|
+
includes.push(...strategy.forcedIncludes(program, options.platformContext));
|
|
163
|
+
Object.assign(symbolMap, strategy.symbolAliases(program, options.platformContext));
|
|
164
|
+
if (isEntryFile) {
|
|
165
|
+
shimLines = [...strategy.shimLines(program, options.platformContext)];
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
// Non-entry files in split compilation: always emit the full shim
|
|
169
|
+
// block. A class method body that uses `??` lowers to a
|
|
170
|
+
// cuttlefish_nullish(...) call, but the helper lives in the entry
|
|
171
|
+
// file's shim — which isn't visible from this header. We used to gate
|
|
172
|
+
// this on programAnalysis.usesNullish, but that flag is unreliable:
|
|
173
|
+
// the analysis runs before the expression renderer, which can
|
|
174
|
+
// introduce cuttlefish_nullish calls (e.g. for default-param
|
|
175
|
+
// destructuring, or `??` inside class methods on abstract bases)
|
|
176
|
+
// that the analysis pass didn't see, leaving the header referencing
|
|
177
|
+
// an undeclared helper. The shim is fully idempotent (#ifndef
|
|
178
|
+
// guards), so emitting it unconditionally is safe and cheap.
|
|
179
|
+
shimLines = [...strategy.shimLines(program, options.platformContext)];
|
|
180
|
+
}
|
|
181
|
+
if (!programAnalysis.usesStringConversion) {
|
|
182
|
+
shimLines = shimLines.filter(l => !l.includes('std::string String('));
|
|
183
|
+
}
|
|
184
|
+
if (!programAnalysis.usesDateNow) {
|
|
185
|
+
shimLines = shimLines.filter(l => !l.includes('namespace Date'));
|
|
186
|
+
}
|
|
187
|
+
// The UI runtime's per-frame tick uses millis() (injected by the emitter,
|
|
188
|
+
// not authored in user source), so keep the millis() shim when a UI is
|
|
189
|
+
// mounted even if the source-level analysis didn't flag usesMillis.
|
|
190
|
+
if (!programAnalysis.usesMillis && !entryHasUI()) {
|
|
191
|
+
shimLines = shimLines.filter(l => !l.includes('millis()'));
|
|
192
|
+
}
|
|
193
|
+
// Strip the nullish helper FUNCTIONS (not the CUTTLEFISH_UNDEFINED macro)
|
|
194
|
+
// when the file doesn't actually emit cuttlefish_nullish(...) calls. A
|
|
195
|
+
// file that only references `null`/`undefined` literals needs just the
|
|
196
|
+
// macro token, not the function definitions. The usesNullishHelper flag
|
|
197
|
+
// tracks files that lower `??` to cuttlefish_nullish(...) calls.
|
|
198
|
+
//
|
|
199
|
+
// Note: for split-file HEADERS, output-finalizer.ts separately injects
|
|
200
|
+
// the full shim when the header's emitted lines contain an actual
|
|
201
|
+
// cuttlefish_nullish( call (a more reliable post-emit check than the
|
|
202
|
+
// per-file pre-emit analysis flag). The logic here governs the .cpp
|
|
203
|
+
// source shim only.
|
|
204
|
+
if (!programAnalysis.usesNullishHelper) {
|
|
205
|
+
const filtered = [];
|
|
206
|
+
for (let i = 0; i < shimLines.length; i++) {
|
|
207
|
+
const l = shimLines[i];
|
|
208
|
+
if (l.includes('cuttlefish_is_nullish') || l.includes('cuttlefish_exists') || l.includes('cuttlefish_nullish'))
|
|
209
|
+
continue;
|
|
210
|
+
filtered.push(l);
|
|
211
|
+
}
|
|
212
|
+
shimLines = filtered;
|
|
213
|
+
}
|
|
214
|
+
if (!programAnalysis.usesNum) {
|
|
215
|
+
shimLines = filterShimBlock(shimLines, 'struct __tc_Num {', '} Num;');
|
|
216
|
+
}
|
|
217
|
+
if (!programAnalysis.usesTiming) {
|
|
218
|
+
shimLines = filterShimBlock(shimLines, 'struct __tc_Timing {', '} Timing;');
|
|
219
|
+
}
|
|
220
|
+
if (!programAnalysis.usesWDT) {
|
|
221
|
+
shimLines = filterShimBlock(shimLines, '#include <avr/wdt.h>', '} WDT;');
|
|
222
|
+
}
|
|
223
|
+
if (!programAnalysis.usesStrPtr) {
|
|
224
|
+
shimLines = filterShimBlock(shimLines, '#ifndef CUTTLEFISH_STR_BUF_SIZE', 'inline size_t (strlen)(const __tc_str_ptr& s) { return ::strlen(s.buf); }');
|
|
225
|
+
}
|
|
226
|
+
profileDiagnostics = [...strategy.profileDiagnostics(program, options.platformContext)];
|
|
227
|
+
}
|
|
228
|
+
for (const imported of program.imports) {
|
|
229
|
+
// Resolve the default import name (import X from "./mod.js") the same way as
|
|
230
|
+
// named imports — add it to the symbolMap so cross-module references
|
|
231
|
+
// resolve. Demo #12 Finding C — was skipped, so `encode` wasn't declared.
|
|
232
|
+
const defaultName = imported.defaultImportName;
|
|
233
|
+
if (isCuttlefishSDKImport(imported.moduleSpecifier, program.fileName)) {
|
|
234
|
+
for (const symbol of imported.namedImports) {
|
|
235
|
+
symbolMap[symbol] = symbol;
|
|
236
|
+
}
|
|
237
|
+
if (defaultName)
|
|
238
|
+
symbolMap[defaultName] = defaultName;
|
|
239
|
+
continue;
|
|
240
|
+
}
|
|
241
|
+
if (options.nativeModules && options.nativeModules.has(imported.moduleSpecifier)) {
|
|
242
|
+
for (const symbol of imported.namedImports) {
|
|
243
|
+
symbolMap[symbol] = symbol;
|
|
244
|
+
}
|
|
245
|
+
if (defaultName)
|
|
246
|
+
symbolMap[defaultName] = defaultName;
|
|
247
|
+
continue;
|
|
248
|
+
}
|
|
249
|
+
// .ui.html modules: their content is injected directly into the entry TU
|
|
250
|
+
// by emitUIRuntime (static tables + runtime header), so they need NO
|
|
251
|
+
// separate header include. Just register the imported symbols (e.g.
|
|
252
|
+
// `screen`) so cross-module references resolve.
|
|
253
|
+
if (imported.moduleSpecifier.endsWith(".ui.html")) {
|
|
254
|
+
for (const symbol of imported.namedImports) {
|
|
255
|
+
symbolMap[symbol] = symbol;
|
|
256
|
+
}
|
|
257
|
+
if (defaultName)
|
|
258
|
+
symbolMap[defaultName] = defaultName;
|
|
259
|
+
continue;
|
|
260
|
+
}
|
|
261
|
+
// Compile-time-only packages (@typecad/ui, @typecad/ui): their calls are
|
|
262
|
+
// intercepted at IR-build time; the package emits NO C++ module/header.
|
|
263
|
+
// Register the imported symbols so references resolve, but skip the
|
|
264
|
+
// #include generation (there is no Ui.h to include).
|
|
265
|
+
if (imported.moduleSpecifier === "@typecad/ui" || imported.moduleSpecifier === "@typecad/ui") {
|
|
266
|
+
for (const symbol of imported.namedImports) {
|
|
267
|
+
symbolMap[symbol] = symbol;
|
|
268
|
+
}
|
|
269
|
+
if (defaultName)
|
|
270
|
+
symbolMap[defaultName] = defaultName;
|
|
271
|
+
continue;
|
|
272
|
+
}
|
|
273
|
+
const transpiledInclude = resolveTranspiledModuleInclude(imported.moduleSpecifier, options.npmPackages, program.fileName);
|
|
274
|
+
if (transpiledInclude.isTranspiled) {
|
|
275
|
+
includes.push(transpiledInclude.include);
|
|
276
|
+
for (const symbol of imported.namedImports) {
|
|
277
|
+
symbolMap[symbol] = symbol;
|
|
278
|
+
}
|
|
279
|
+
if (defaultName)
|
|
280
|
+
symbolMap[defaultName] = defaultName;
|
|
281
|
+
}
|
|
282
|
+
else {
|
|
283
|
+
const resolved = resolveImport(imported, options.libdefs, options.target, options.platformContext, program.fileName);
|
|
284
|
+
includes.push(normalizeInclude(resolved.include));
|
|
285
|
+
Object.assign(symbolMap, resolved.symbolMap);
|
|
286
|
+
if (defaultName)
|
|
287
|
+
symbolMap[defaultName] = defaultName;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
const templateInterfaceNames = new Set();
|
|
291
|
+
const interfaceNamespaceMap = new Map();
|
|
292
|
+
const interfaceFieldTypes = new Map();
|
|
293
|
+
// Shared map populated as top-level const object literals are emitted
|
|
294
|
+
// (function-emitter-impl.ts) and read by the expression renderer to decide
|
|
295
|
+
// `.` vs `::` member access on those variables.
|
|
296
|
+
const knownTopLevelObjectTypes = new Map();
|
|
297
|
+
// Module-scope pointer variables, populated by runTopLevelPreprocessing
|
|
298
|
+
// (top-level-prep.ts) into THIS map (in place, by reference) so the
|
|
299
|
+
// ExpressionRenderer — constructed below with this same reference — can
|
|
300
|
+
// decide `->` vs `.` for bare identifiers that resolve to file-global
|
|
301
|
+
// pointers (e.g. ISR-captured `const btn = new Button()`). Replaces the
|
|
302
|
+
// file-wide text sweep formerly in output-finalizer.ts.
|
|
303
|
+
const globalPointerVarTypes = new Map();
|
|
304
|
+
for (const iface of program.interfaces) {
|
|
305
|
+
if (iface.parentScope) {
|
|
306
|
+
interfaceNamespaceMap.set(iface.name, iface.parentScope);
|
|
307
|
+
}
|
|
308
|
+
if (iface.fields.length > 0) {
|
|
309
|
+
const fieldTypes = new Map();
|
|
310
|
+
for (const field of iface.fields) {
|
|
311
|
+
fieldTypes.set(field.name, field.cppType);
|
|
312
|
+
}
|
|
313
|
+
interfaceFieldTypes.set(iface.name, fieldTypes);
|
|
314
|
+
for (const field of iface.fields) {
|
|
315
|
+
if (/^[A-Z]$/.test(field.cppType)) {
|
|
316
|
+
templateInterfaceNames.add(iface.name);
|
|
317
|
+
break;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
for (const classDef of program.classes) {
|
|
323
|
+
if (classDef.fields.length > 0 || classDef.extendsClass) {
|
|
324
|
+
const fieldTypes = new Map();
|
|
325
|
+
if (classDef.extendsClass) {
|
|
326
|
+
const parentFields = interfaceFieldTypes.get(classDef.extendsClass);
|
|
327
|
+
if (parentFields) {
|
|
328
|
+
for (const [fname, ftype] of parentFields) {
|
|
329
|
+
fieldTypes.set(fname, ftype);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
for (const field of classDef.fields) {
|
|
334
|
+
fieldTypes.set(field.name, field.cppType);
|
|
335
|
+
}
|
|
336
|
+
interfaceFieldTypes.set(classDef.name, fieldTypes);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
if (options.crossModuleClassFieldTypes) {
|
|
340
|
+
for (const [className, fieldTypes] of options.crossModuleClassFieldTypes) {
|
|
341
|
+
if (!interfaceFieldTypes.has(className)) {
|
|
342
|
+
interfaceFieldTypes.set(className, fieldTypes);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
// Build the set of all known class names (local + cross-module).
|
|
347
|
+
// Class instances are always created with `new`, which returns a pointer;
|
|
348
|
+
// function parameters that reference these types must also be pointers.
|
|
349
|
+
const classNames = new Set();
|
|
350
|
+
for (const cls of program.classes)
|
|
351
|
+
classNames.add(cls.name);
|
|
352
|
+
if (options.crossModuleClasses) {
|
|
353
|
+
for (const name of options.crossModuleClasses)
|
|
354
|
+
classNames.add(name);
|
|
355
|
+
}
|
|
356
|
+
// Map a function's original TS name to its emitted C++ name, applying the
|
|
357
|
+
// strategy's user-function renames. The entrypoint sentinel
|
|
358
|
+
// `__cuttlefish_entrypoint__` maps to the strategy's entrypoint name
|
|
359
|
+
// (`main` on native, `setup` on Arduino); every other name is routed through
|
|
360
|
+
// `strategy.mapFunctionName`, which is where a target renames a user
|
|
361
|
+
// function that would otherwise collide with a C++/framework reserved name
|
|
362
|
+
// — e.g. Arduino renames a user `function main()` to `cuttlefish_main`,
|
|
363
|
+
// because Arduino has no `main()` (the entrypoints are the auto-generated
|
|
364
|
+
// `setup()`/`loop()`), and a file-scope `static void main()` collides with
|
|
365
|
+
// C++'s required `int main()` signature. Call-site renames are applied
|
|
366
|
+
// uniformly in StatementRenderer.renderCall (the single call-rendering
|
|
367
|
+
// chokepoint), so every reference — definition, forward decl, and every call
|
|
368
|
+
// site including the top-level `main()` call spliced into `setup()` —
|
|
369
|
+
// follows the rename.
|
|
370
|
+
const mapEmittedFnName = (originalName) => originalName === "__cuttlefish_entrypoint__"
|
|
371
|
+
? strategy.entrypointFunctionName()
|
|
372
|
+
: strategy.mapFunctionName(originalName);
|
|
373
|
+
const mappedFunctions = program.functions.map((fn) => {
|
|
374
|
+
const fnName = mapEmittedFnName(fn.originalName);
|
|
375
|
+
return {
|
|
376
|
+
name: fnName,
|
|
377
|
+
returnType: resolveTemplateReturnType(strategy.mapReturnType(fnName, fn.returnType), fn.typeParameters),
|
|
378
|
+
sourceSpan: fn.sourceSpan,
|
|
379
|
+
leadingComments: fn.leadingComments,
|
|
380
|
+
trailingComments: fn.trailingComments,
|
|
381
|
+
parameters: fn.parameters,
|
|
382
|
+
isAsync: fn.isAsync,
|
|
383
|
+
typeParameters: fn.typeParameters,
|
|
384
|
+
typeParameterConstraints: fn.typeParameterConstraints,
|
|
385
|
+
isReadonlyReturnType: fn.isReadonlyReturnType,
|
|
386
|
+
isGenerator: fn.isGenerator,
|
|
387
|
+
isExported: fn.isExported,
|
|
388
|
+
statements: fn.statements.map((stmt) => {
|
|
389
|
+
if (stmt.kind === "call") {
|
|
390
|
+
return { ...stmt, callee: applySymbolMap(stmt.callee, symbolMap) };
|
|
391
|
+
}
|
|
392
|
+
return stmt;
|
|
393
|
+
}),
|
|
394
|
+
};
|
|
395
|
+
});
|
|
396
|
+
const knownFunctionReturnTypes = new Map(options.crossModuleFunctionReturnTypes);
|
|
397
|
+
for (const fn of mappedFunctions) {
|
|
398
|
+
knownFunctionReturnTypes.set(fn.name, fn.returnType);
|
|
399
|
+
}
|
|
400
|
+
for (const fn of program.functions) {
|
|
401
|
+
const fnName = fn.originalName === "__cuttlefish_entrypoint__" ? strategy.entrypointFunctionName() : fn.originalName;
|
|
402
|
+
knownFunctionReturnTypes.set(fn.originalName, strategy.mapReturnType(fnName, fn.returnType));
|
|
403
|
+
}
|
|
404
|
+
// Also register class method return types (keyed by bare method name) so
|
|
405
|
+
// downstream type inference — in particular snprintf format-specifier
|
|
406
|
+
// selection for `this->method()` / `obj->method()` operands in a string
|
|
407
|
+
// concat — can resolve a method's return type. Without this, a
|
|
408
|
+
// double-returning method like `cargoUsed()` defaults to `%d` in the
|
|
409
|
+
// emitted snprintf, which misaligns the format/arg list and corrupts
|
|
410
|
+
// output. The bare-name key is safe here because `inferExpressionCppType`
|
|
411
|
+
// looks up `expr.callee` which is the bare method name for member calls.
|
|
412
|
+
for (const cls of program.classes) {
|
|
413
|
+
for (const m of cls.methods) {
|
|
414
|
+
if (!knownFunctionReturnTypes.has(m.name)) {
|
|
415
|
+
knownFunctionReturnTypes.set(m.name, m.returnType);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
for (const g of cls.getters) {
|
|
419
|
+
if (!knownFunctionReturnTypes.has(g.name)) {
|
|
420
|
+
knownFunctionReturnTypes.set(g.name, g.returnType);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
const snprintfCounter = { value: 0 };
|
|
425
|
+
const topLevelScope = createEmissionScopeState();
|
|
426
|
+
if (options.crossModuleVariableTypes) {
|
|
427
|
+
for (const [name, cppType] of options.crossModuleVariableTypes) {
|
|
428
|
+
topLevelScope.knownVariableTypes.set(name, { cppType });
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
// Register namespace-scope const/let types in knownVariableTypes so the
|
|
432
|
+
// snprintf operand resolver (and other type-resolution consumers) see them
|
|
433
|
+
// — otherwise a namespace `const string` used in a concat fell through to
|
|
434
|
+
// the %d default (namespace stress test Finding 3b). Mirrors the cross-
|
|
435
|
+
// module registration above; walks nested namespaces recursively.
|
|
436
|
+
const registerNsConstants = (ns) => {
|
|
437
|
+
for (const c of ns.constants) {
|
|
438
|
+
topLevelScope.knownVariableTypes.set(c.name, { cppType: c.cppType });
|
|
439
|
+
}
|
|
440
|
+
for (const child of ns.children ?? [])
|
|
441
|
+
registerNsConstants(child);
|
|
442
|
+
};
|
|
443
|
+
for (const ns of program.namespaces)
|
|
444
|
+
registerNsConstants(ns);
|
|
445
|
+
const stringVarNames = new Set();
|
|
446
|
+
// Pre-populate known string variable names from the program IR so that
|
|
447
|
+
// string-concat / template rendering can detect string identifiers even when
|
|
448
|
+
// the dynamic knownVariableTypes map doesn't yet hold them at render time.
|
|
449
|
+
const isStringCppType = (t) => !!t && (t === "std::string" || t === "const char*");
|
|
450
|
+
const collectStringVars = (statements) => {
|
|
451
|
+
for (const stmt of statements) {
|
|
452
|
+
switch (stmt.kind) {
|
|
453
|
+
case "var_decl":
|
|
454
|
+
if (isStringCppType(stmt.cppType))
|
|
455
|
+
stringVarNames.add(stmt.name);
|
|
456
|
+
break;
|
|
457
|
+
case "if":
|
|
458
|
+
collectStringVars(stmt.thenBranch);
|
|
459
|
+
if (stmt.elseBranch)
|
|
460
|
+
collectStringVars(stmt.elseBranch);
|
|
461
|
+
break;
|
|
462
|
+
case "for":
|
|
463
|
+
if (stmt.initializer && stmt.initializer.kind === "var_decl" && isStringCppType(stmt.initializer.cppType)) {
|
|
464
|
+
stringVarNames.add(stmt.initializer.name);
|
|
465
|
+
}
|
|
466
|
+
collectStringVars(stmt.body);
|
|
467
|
+
break;
|
|
468
|
+
case "for_of":
|
|
469
|
+
case "for_in":
|
|
470
|
+
if (stmt.variable && stmt.variable.kind === "var_decl" && isStringCppType(stmt.variable.cppType)) {
|
|
471
|
+
stringVarNames.add(stmt.variable.name);
|
|
472
|
+
}
|
|
473
|
+
collectStringVars(stmt.body);
|
|
474
|
+
break;
|
|
475
|
+
case "while":
|
|
476
|
+
case "do_while":
|
|
477
|
+
case "block":
|
|
478
|
+
case "labeled":
|
|
479
|
+
collectStringVars(stmt.body);
|
|
480
|
+
break;
|
|
481
|
+
case "switch":
|
|
482
|
+
for (const c of stmt.cases)
|
|
483
|
+
collectStringVars(c.body);
|
|
484
|
+
break;
|
|
485
|
+
case "try":
|
|
486
|
+
collectStringVars(stmt.tryBlock);
|
|
487
|
+
if (stmt.catchBlock)
|
|
488
|
+
collectStringVars(stmt.catchBlock);
|
|
489
|
+
if (stmt.finallyBlock)
|
|
490
|
+
collectStringVars(stmt.finallyBlock);
|
|
491
|
+
break;
|
|
492
|
+
default:
|
|
493
|
+
break;
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
};
|
|
497
|
+
for (const stmt of program.topLevelStatements) {
|
|
498
|
+
if (stmt.kind === "var_decl" && isStringCppType(stmt.cppType))
|
|
499
|
+
stringVarNames.add(stmt.name);
|
|
500
|
+
}
|
|
501
|
+
for (const fn of program.functions) {
|
|
502
|
+
for (const param of fn.parameters) {
|
|
503
|
+
if (isStringCppType(param.cppType))
|
|
504
|
+
stringVarNames.add(param.name);
|
|
505
|
+
}
|
|
506
|
+
collectStringVars(fn.statements);
|
|
507
|
+
}
|
|
508
|
+
for (const cls of program.classes) {
|
|
509
|
+
for (const field of cls.fields) {
|
|
510
|
+
if (isStringCppType(field.cppType))
|
|
511
|
+
stringVarNames.add(field.name);
|
|
512
|
+
}
|
|
513
|
+
for (const method of cls.methods) {
|
|
514
|
+
for (const param of method.parameters) {
|
|
515
|
+
if (isStringCppType(param.cppType))
|
|
516
|
+
stringVarNames.add(param.name);
|
|
517
|
+
}
|
|
518
|
+
collectStringVars(method.statements);
|
|
519
|
+
}
|
|
520
|
+
if (cls.constructor) {
|
|
521
|
+
for (const param of cls.constructor.parameters) {
|
|
522
|
+
if (isStringCppType(param.cppType))
|
|
523
|
+
stringVarNames.add(param.name);
|
|
524
|
+
}
|
|
525
|
+
collectStringVars(cls.constructor.statements);
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
const varAccessorNames = new Map();
|
|
529
|
+
// Populate the variable → accessor map BEFORE constructing the renderers so
|
|
530
|
+
// every emit pass (free functions, class methods, top-level code) sees the
|
|
531
|
+
// full mapping. A getter read (`hero.alive`) must rewrite to `hero->getAlive()`
|
|
532
|
+
// regardless of whether `hero` is a local, a free-function parameter, a class
|
|
533
|
+
// method/ctor parameter, or a top-level binding. Previously only local
|
|
534
|
+
// var_decls were registered (in class-emitter), which ran too late for the
|
|
535
|
+
// free-function pass — leaving `hero->alive` unrewritten and failing g++.
|
|
536
|
+
// See SUPPORT_MATRIX §4.3 (demo #4 fix).
|
|
537
|
+
// `classAccessorNames` is built at the outer scope (not inside a nested
|
|
538
|
+
// block) so it can also be passed to the expression renderer as
|
|
539
|
+
// `typeAccessorNames` — the type-keyed fallback used when a getter access's
|
|
540
|
+
// receiver isn't a registered variable (e.g. a for-of loop variable, a
|
|
541
|
+
// function return, or a chained member access). See demo #6 fix C.
|
|
542
|
+
const classAccessorNames = new Map();
|
|
543
|
+
for (const classDef of program.classes) {
|
|
544
|
+
const accessors = new Map();
|
|
545
|
+
for (const g of classDef.getters) {
|
|
546
|
+
accessors.set(g.name, accessors.has(g.name) ? "both" : "getter");
|
|
547
|
+
}
|
|
548
|
+
for (const s of classDef.setters) {
|
|
549
|
+
accessors.set(s.name, accessors.has(s.name) ? "both" : "setter");
|
|
550
|
+
}
|
|
551
|
+
if (accessors.size > 0) {
|
|
552
|
+
classAccessorNames.set(classDef.name, accessors);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
// Merge cross-file (imported) class accessors so `obj.getter` and
|
|
556
|
+
// `Cls.staticGetter` accesses rewrite correctly when the class lives in
|
|
557
|
+
// another module (demo #14 Finding E).
|
|
558
|
+
if (options.crossModuleClassAccessors) {
|
|
559
|
+
for (const [className, accessors] of options.crossModuleClassAccessors) {
|
|
560
|
+
if (!classAccessorNames.has(className)) {
|
|
561
|
+
classAccessorNames.set(className, accessors);
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
const allVarDecls = [];
|
|
566
|
+
for (const stmt of program.topLevelStatements) {
|
|
567
|
+
if (stmt.kind === "var_decl")
|
|
568
|
+
allVarDecls.push(stmt);
|
|
569
|
+
}
|
|
570
|
+
for (const fn of mappedFunctions) {
|
|
571
|
+
for (const stmt of fn.statements) {
|
|
572
|
+
if (stmt.kind === "var_decl")
|
|
573
|
+
allVarDecls.push(stmt);
|
|
574
|
+
}
|
|
575
|
+
for (const param of fn.parameters) {
|
|
576
|
+
allVarDecls.push({ name: param.name, cppType: param.cppType });
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
for (const cls of program.classes) {
|
|
580
|
+
for (const method of cls.methods) {
|
|
581
|
+
for (const param of method.parameters) {
|
|
582
|
+
allVarDecls.push({ name: param.name, cppType: param.cppType });
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
if (cls.constructor) {
|
|
586
|
+
for (const param of cls.constructor.parameters) {
|
|
587
|
+
allVarDecls.push({ name: param.name, cppType: param.cppType });
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
for (const v of allVarDecls) {
|
|
592
|
+
const bareType = v.cppType.replace(/\*$/, "").replace(/^const\s+/, "");
|
|
593
|
+
const accessors = classAccessorNames.get(bareType);
|
|
594
|
+
if (accessors) {
|
|
595
|
+
varAccessorNames.set(v.name, accessors);
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
const exprRenderer = new ExpressionRenderer({
|
|
599
|
+
strategy,
|
|
600
|
+
boardConstants: program.boardConstants,
|
|
601
|
+
typeAccessorNames: classAccessorNames,
|
|
602
|
+
classNameMap,
|
|
603
|
+
enumNames,
|
|
604
|
+
stringEnumNames,
|
|
605
|
+
largeEnumNames,
|
|
606
|
+
knownFunctionReturnTypes,
|
|
607
|
+
knownVariableTypes: topLevelScope.knownVariableTypes,
|
|
608
|
+
globalPointerVarTypes,
|
|
609
|
+
namespaceNames,
|
|
610
|
+
snprintfCounter,
|
|
611
|
+
stringVarNames,
|
|
612
|
+
varAccessorNames,
|
|
613
|
+
interfaceFieldTypes,
|
|
614
|
+
crossModuleClassNames: classNames,
|
|
615
|
+
knownTopLevelObjectTypes,
|
|
616
|
+
diagnostics: emitDiagnostics,
|
|
617
|
+
});
|
|
618
|
+
const statementRenderer = new StatementRenderer({
|
|
619
|
+
strategy,
|
|
620
|
+
boardConstants: program.boardConstants,
|
|
621
|
+
classNameMap,
|
|
622
|
+
enumNames,
|
|
623
|
+
stringEnumNames,
|
|
624
|
+
largeEnumNames,
|
|
625
|
+
knownFunctionReturnTypes,
|
|
626
|
+
knownVariableTypes: topLevelScope.knownVariableTypes,
|
|
627
|
+
globalPointerVarTypes,
|
|
628
|
+
namespaceNames,
|
|
629
|
+
snprintfCounter,
|
|
630
|
+
stringVarNames,
|
|
631
|
+
varAccessorNames,
|
|
632
|
+
typeAccessorNames: classAccessorNames,
|
|
633
|
+
interfaceFieldTypes,
|
|
634
|
+
crossModuleClassNames: classNames,
|
|
635
|
+
diagnostics: emitDiagnostics,
|
|
636
|
+
});
|
|
637
|
+
const asyncFunctionOriginalNames = new Set(program.functions.filter((fn) => fn.isAsync).map((fn) => fn.originalName));
|
|
638
|
+
const mapFunctionNameLocal = (originalName) => statementRenderer.mapFunctionName(originalName);
|
|
639
|
+
const asyncFunctionMappedNames = new Set(program.functions.filter((fn) => fn.isAsync).map((fn) => mapFunctionNameLocal(fn.originalName)));
|
|
640
|
+
const asyncTaskClasses = [];
|
|
641
|
+
if (hasAsyncRuntime) {
|
|
642
|
+
for (const fn of program.functions) {
|
|
643
|
+
if (fn.isAsync) {
|
|
644
|
+
const task = generateAsyncTaskClass(fn.originalName, fn.statements, strategy, knownFunctionReturnTypes, (stmt, forHeader, strategy, pointerVarTypes, calleeTransformer, knownReturnTypes) => {
|
|
645
|
+
const contextRenderer = new StatementRenderer({
|
|
646
|
+
strategy,
|
|
647
|
+
boardConstants: program.boardConstants,
|
|
648
|
+
classNameMap,
|
|
649
|
+
enumNames,
|
|
650
|
+
stringEnumNames,
|
|
651
|
+
largeEnumNames,
|
|
652
|
+
knownFunctionReturnTypes: knownReturnTypes ?? knownFunctionReturnTypes,
|
|
653
|
+
knownVariableTypes: topLevelScope.knownVariableTypes,
|
|
654
|
+
globalPointerVarTypes,
|
|
655
|
+
namespaceNames,
|
|
656
|
+
snprintfCounter,
|
|
657
|
+
stringVarNames,
|
|
658
|
+
varAccessorNames,
|
|
659
|
+
typeAccessorNames: classAccessorNames,
|
|
660
|
+
pointerVarTypes,
|
|
661
|
+
diagnostics: emitDiagnostics,
|
|
662
|
+
});
|
|
663
|
+
// Use renderWithPrelude so snprintf buffer declarations (e.g.
|
|
664
|
+
// char __cuttlefish_str_N[...]; snprintf(...)) are emitted before
|
|
665
|
+
// the statement that references them. Without this, template-literal
|
|
666
|
+
// console.log inside async functions loses the buffer declaration.
|
|
667
|
+
const { prelude, statement } = contextRenderer.renderWithPrelude(stmt, forHeader, calleeTransformer);
|
|
668
|
+
if (prelude.length > 0) {
|
|
669
|
+
return prelude.join("\n") + "\n" + statement;
|
|
670
|
+
}
|
|
671
|
+
return statement;
|
|
672
|
+
});
|
|
673
|
+
asyncTaskClasses.push({ ...task, taskVarName: `${fn.originalName}Task` });
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
// Additional includes computed from analysis
|
|
678
|
+
if (strategy.needsIostream() && programAnalysis.hasConsoleCalls) {
|
|
679
|
+
includes.push("<iostream>");
|
|
680
|
+
}
|
|
681
|
+
const usesVectorTypes = programAnalysis.usesVectorTypes || programAnalysis.hasArrayInObjectLiteral;
|
|
682
|
+
if (programAnalysis.usesStdString && strategy.needsStdString()) {
|
|
683
|
+
includes.push("<string>");
|
|
684
|
+
}
|
|
685
|
+
if (strategy.needsStdVector() && programAnalysis.usesVectorTypes) {
|
|
686
|
+
includes.push("<vector>");
|
|
687
|
+
}
|
|
688
|
+
if (strategy.needsStdVector() && programAnalysis.hasArrayInObjectLiteral) {
|
|
689
|
+
includes.push("<vector>");
|
|
690
|
+
}
|
|
691
|
+
if (programAnalysis.usesStdFunction && strategy.needsStdFunction()) {
|
|
692
|
+
includes.push("<functional>");
|
|
693
|
+
}
|
|
694
|
+
if (programAnalysis.hasThrowStatements && strategy.needsStdExcept()) {
|
|
695
|
+
includes.push("<stdexcept>");
|
|
696
|
+
}
|
|
697
|
+
if (program.functions.some(fn => fn.typeParameterConstraints && fn.typeParameterConstraints.size > 0)) {
|
|
698
|
+
includes.push("<type_traits>");
|
|
699
|
+
}
|
|
700
|
+
if (programAnalysis.hasStdMathCalls) {
|
|
701
|
+
includes.push(strategy.mathHeader());
|
|
702
|
+
}
|
|
703
|
+
if (programAnalysis.usesStdMap) {
|
|
704
|
+
includes.push("<map>");
|
|
705
|
+
}
|
|
706
|
+
const needsSnprintf = strategy.useSnprintfForStrings() && (program.topLevelStatements.some((statement) => statementNeedsSnprintf(statement, strategy)) ||
|
|
707
|
+
program.functions.some((fn) => fn.statements.some((statement) => statementNeedsSnprintf(statement, strategy))) ||
|
|
708
|
+
program.classes.some((classDef) => (classDef.constructor?.statements.some((statement) => statementNeedsSnprintf(statement, strategy)) ?? false) ||
|
|
709
|
+
classDef.methods.some((method) => method.statements.some((statement) => statementNeedsSnprintf(statement, strategy)))));
|
|
710
|
+
if (needsSnprintf) {
|
|
711
|
+
includes.push("<stdio.h>");
|
|
712
|
+
includes.push("<stdlib.h>");
|
|
713
|
+
}
|
|
714
|
+
if (emittedPolyfills) {
|
|
715
|
+
includes.push(...emittedPolyfills.includes.map((include) => normalizeInclude(include)));
|
|
716
|
+
}
|
|
717
|
+
if (program.requiredIncludes) {
|
|
718
|
+
includes.push(...program.requiredIncludes);
|
|
719
|
+
}
|
|
720
|
+
// UI text bindings lower to snprintf bodies that need <stdio.h>. Pushed here
|
|
721
|
+
// (in buildEmitterContext) rather than in emitUIRuntime because emitPreamble
|
|
722
|
+
// runs before emitUIRuntime — a push there would never reach the output.
|
|
723
|
+
// Gated on entryHasUI so non-UI files don't pull in stdio unnecessarily.
|
|
724
|
+
if (entryHasUI() && !includes.includes("<stdio.h>")) {
|
|
725
|
+
includes.push("<stdio.h>");
|
|
726
|
+
}
|
|
727
|
+
// std::variant (from discriminated-union type aliases) needs <variant>.
|
|
728
|
+
// Scan type aliases AND function signatures (params/return types) — a union
|
|
729
|
+
// used only as a param/return may not survive tree-shaking as an alias, but
|
|
730
|
+
// the resolved `std::variant<...>` cppType still appears in signatures.
|
|
731
|
+
const variantInAliases = program.typeAliases.some((a) => (a.cppType ?? "").includes("std::variant"));
|
|
732
|
+
const variantInFunctions = program.functions.some((f) => (f.returnType ?? "").includes("std::variant")
|
|
733
|
+
|| f.parameters.some((p) => (p.cppType ?? "").includes("std::variant")));
|
|
734
|
+
if (variantInAliases || variantInFunctions) {
|
|
735
|
+
includes.push("<variant>");
|
|
736
|
+
}
|
|
737
|
+
// String enums lower to const char* and use strcmp() for === comparisons.
|
|
738
|
+
// Header name is platform-specific: <cstring> on hosted, <string.h> on AVR.
|
|
739
|
+
if (stringEnumNames.size > 0) {
|
|
740
|
+
includes.push(strategy.cstringHeader());
|
|
741
|
+
}
|
|
742
|
+
// Placeholder defaults for fields that are computed later by other phases
|
|
743
|
+
const noopFixPointer = (c) => c;
|
|
744
|
+
// Demo #18 Finding B: collect the names of non-exported free functions that
|
|
745
|
+
// are CALLED from at least one class method body (method/getter/setter/
|
|
746
|
+
// constructor). In split mode an inline class method body lives in the
|
|
747
|
+
// header, so such a function must be visible in the header too (a `static`
|
|
748
|
+
// forward decl in the .cpp is reached only after the header is processed).
|
|
749
|
+
// These functions are emitted non-static with a header prototype, like
|
|
750
|
+
// exported functions.
|
|
751
|
+
//
|
|
752
|
+
// Demo #30 Finding A: this previously had its OWN hand-rolled IR walk that
|
|
753
|
+
// only inspected structured `call`/`method-call` nodes. A free function
|
|
754
|
+
// reached through a `raw` IR wrapper — the lowering of
|
|
755
|
+
// `freeFn(x).trim()` / `__tc_trim(freeFn(x))` — was invisible to it, so the
|
|
756
|
+
// function was emitted `static` with no header prototype and g++ reported it
|
|
757
|
+
// "not declared in this scope" from the inline class-method body. This is
|
|
758
|
+
// the SAME blind spot demo #28 Finding C fixed in the tree-shaking walk
|
|
759
|
+
// (`identifier-collector.ts`): two parallel walks over the same IR diverged.
|
|
760
|
+
// The fix is to stop duplicating the walk and reuse the canonical collector
|
|
761
|
+
// — which already extracts identifiers from `raw` text, recurses through
|
|
762
|
+
// `paren`/`lambda`/`tuple-access`/`hal-expr`, and is the single place that
|
|
763
|
+
// knows every IR shape. Any free function reached through ANY lowering
|
|
764
|
+
// (raw wrapper, parenthesized call, lambda capture, HAL op) is now visible.
|
|
765
|
+
const freeFunctionNames = new Set();
|
|
766
|
+
for (const fn of program.functions) {
|
|
767
|
+
if (!fn.isExported)
|
|
768
|
+
freeFunctionNames.add(fn.originalName);
|
|
769
|
+
}
|
|
770
|
+
const freeFunctionsCalledFromClassMethods = new Set();
|
|
771
|
+
for (const cls of program.classes) {
|
|
772
|
+
const methodBodies = [];
|
|
773
|
+
for (const m of cls.methods)
|
|
774
|
+
for (const s of m.statements)
|
|
775
|
+
methodBodies.push(s);
|
|
776
|
+
for (const g of cls.getters)
|
|
777
|
+
for (const s of g.statements)
|
|
778
|
+
methodBodies.push(s);
|
|
779
|
+
for (const st of cls.setters)
|
|
780
|
+
for (const s of st.statements)
|
|
781
|
+
methodBodies.push(s);
|
|
782
|
+
if (cls.constructor)
|
|
783
|
+
for (const s of cls.constructor.statements)
|
|
784
|
+
methodBodies.push(s);
|
|
785
|
+
for (const stmt of methodBodies) {
|
|
786
|
+
for (const id of collectStatementIdentifiers(stmt)) {
|
|
787
|
+
if (freeFunctionNames.has(id))
|
|
788
|
+
freeFunctionsCalledFromClassMethods.add(id);
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
return {
|
|
793
|
+
program,
|
|
794
|
+
options,
|
|
795
|
+
strategy,
|
|
796
|
+
programAnalysis,
|
|
797
|
+
enumNames,
|
|
798
|
+
stringEnumNames,
|
|
799
|
+
largeEnumNames,
|
|
800
|
+
namespaceNames,
|
|
801
|
+
symbolMap,
|
|
802
|
+
includes,
|
|
803
|
+
shimLines,
|
|
804
|
+
baseName,
|
|
805
|
+
effectiveEmitMode,
|
|
806
|
+
isEntryFile,
|
|
807
|
+
isNpmPackage,
|
|
808
|
+
isrPrefix,
|
|
809
|
+
reservedNames,
|
|
810
|
+
knownFunctionReturnTypes,
|
|
811
|
+
mappedFunctions,
|
|
812
|
+
freeFunctionsCalledFromClassMethods,
|
|
813
|
+
topLevelScope,
|
|
814
|
+
snprintfCounter,
|
|
815
|
+
stringVarNames,
|
|
816
|
+
varAccessorNames,
|
|
817
|
+
exprRenderer,
|
|
818
|
+
statementRenderer,
|
|
819
|
+
classNameMap,
|
|
820
|
+
boardConstants: program.boardConstants,
|
|
821
|
+
restParamFunctions: program.restParamFunctions,
|
|
822
|
+
asyncTaskClasses,
|
|
823
|
+
asyncFunctionOriginalNames,
|
|
824
|
+
asyncFunctionMappedNames,
|
|
825
|
+
hasAsyncRuntime,
|
|
826
|
+
hasPromiseRuntime,
|
|
827
|
+
usesTimers,
|
|
828
|
+
emittedPolyfills,
|
|
829
|
+
sourceLines: [],
|
|
830
|
+
headerLines: ["#pragma once", ""],
|
|
831
|
+
sourceMapEntries: [],
|
|
832
|
+
headerMapEntries: [],
|
|
833
|
+
cArrayVarNames: new Set(),
|
|
834
|
+
fnCArrayVarNames: new Map(),
|
|
835
|
+
globalPointerVarTypes,
|
|
836
|
+
promotedVarDecls: new Map(),
|
|
837
|
+
callbackFunctions: [],
|
|
838
|
+
filteredTopLevelExecutables: [],
|
|
839
|
+
filteredTopLevelDeclarations: [],
|
|
840
|
+
emittedTopLevelStatements: [],
|
|
841
|
+
compiletimeVarNames: new Set(),
|
|
842
|
+
fixPointerFieldAccess: noopFixPointer,
|
|
843
|
+
knownTopLevelObjectTypes,
|
|
844
|
+
knownTopLevelObjectFields: new Map(),
|
|
845
|
+
profileDiagnostics,
|
|
846
|
+
emitDiagnostics,
|
|
847
|
+
templateInterfaceNames,
|
|
848
|
+
interfaceNamespaceMap,
|
|
849
|
+
interfaceFieldTypes,
|
|
850
|
+
};
|
|
851
|
+
}
|