@typecad/cuttlefish 0.1.0-alpha.1 → 1.0.0-alpha.10
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/README.md +10 -10
- package/dist/api/board-types.d.ts +1 -1
- package/dist/api/config.d.ts +32 -0
- package/dist/api/index.d.ts +1 -1
- package/dist/api/schema/types.d.ts +15 -0
- package/dist/api/shared/async-runtime-static.d.ts +12 -1
- package/dist/api/shared/async-runtime-static.js +69 -24
- package/dist/api/shared/async-symbol-detector.d.ts +11 -0
- package/dist/api/shared/async-symbol-detector.js +140 -0
- package/dist/api/shared/async-types.d.ts +24 -0
- package/dist/api/shared/coop-scheduler.d.ts +60 -0
- package/dist/api/shared/coop-scheduler.js +149 -0
- package/dist/api/shared/display-adapter.d.ts +4 -3
- package/dist/api/shared/display-adapter.js +15 -118
- package/dist/api/shared/display-adapters/sdl.js +38 -31
- package/dist/api/shared/display-profile.d.ts +47 -25
- package/dist/api/shared/display-profile.js +31 -164
- package/dist/api/shared/framework-manifest-registry.d.ts +9 -0
- package/dist/api/shared/framework-manifest-registry.js +27 -0
- package/dist/api/shared/framework-manifest.d.ts +595 -0
- package/dist/api/shared/framework-manifest.js +193 -0
- package/dist/api/shared/glcdfont.d.ts +12 -0
- package/dist/api/shared/glcdfont.js +124 -0
- package/dist/api/shared/graphics-strategy.d.ts +37 -0
- package/dist/api/shared/hal-op-ir.d.ts +764 -1
- package/dist/api/shared/hal-op-ir.js +129 -1
- package/dist/api/shared/index.d.ts +20 -2
- package/dist/api/shared/index.js +25 -1
- package/dist/api/shared/ir-core.d.ts +4 -0
- package/dist/api/shared/ir-declarations.d.ts +6 -0
- package/dist/api/shared/native-display-op-resolver.d.ts +10 -0
- package/dist/api/shared/native-display-op-resolver.js +64 -0
- package/dist/api/shared/platform-strategy.d.ts +119 -2
- package/dist/api/shared/polyfill-helper-registry.js +18 -1
- package/dist/api/shared/promise-runtime.d.ts +1 -1
- package/dist/api/shared/promise-runtime.js +95 -13
- package/dist/api/shared/toolchain-types.d.ts +17 -0
- package/dist/api/shared/types.d.ts +8 -0
- package/dist/api/shared/validate-framework-manifest.d.ts +28 -0
- package/dist/api/shared/validate-framework-manifest.js +494 -0
- package/dist/api/shared/worker-runtime-polyfill.d.ts +22 -0
- package/dist/api/shared/worker-runtime-polyfill.js +34 -0
- package/dist/api/shared/worker-runtime.d.ts +69 -0
- package/dist/api/shared/worker-runtime.js +163 -0
- package/dist/cli-utils.d.ts +1 -0
- package/dist/cli-utils.js +3 -1
- package/dist/cli.js +260 -35
- package/dist/config-loader.d.ts +7 -2
- package/dist/config-loader.js +23 -3
- package/dist/config-schema.d.ts +112 -70
- package/dist/config-schema.js +14 -0
- package/dist/contract/board-generator.d.ts +17 -0
- package/dist/contract/board-generator.js +57 -0
- package/dist/contract/contract-parser.d.ts +217 -0
- package/dist/contract/contract-parser.js +224 -0
- package/dist/contract/index.d.ts +22 -0
- package/dist/contract/index.js +68 -0
- package/dist/create/board-codegen.js +4 -4
- package/dist/create/board-generators.js +4 -5
- package/dist/create/board-spec.d.ts +72 -75
- package/dist/create/board-spec.js +0 -1
- package/dist/create/framework-catalog.d.ts +64 -0
- package/dist/create/framework-catalog.js +136 -0
- package/dist/create/index.d.ts +5 -1
- package/dist/create/index.js +3 -1
- package/dist/create/init-scaffold.d.ts +12 -3
- package/dist/create/init-scaffold.js +49 -14
- package/dist/create/init-templates.d.ts +4 -0
- package/dist/create/init-templates.js +263 -17
- package/dist/create/init-wizard.js +41 -27
- package/dist/create/install-deps.d.ts +32 -0
- package/dist/create/install-deps.js +46 -0
- package/dist/debug/preprocessor.js +178 -39
- package/dist/debug/types.d.ts +23 -0
- package/dist/diagnostics/mermaid-builder.d.ts +1 -1
- package/dist/diagnostics/mermaid-builder.js +34 -24
- package/dist/emit/compliance/arxml-writer.d.ts +11 -0
- package/dist/emit/compliance/arxml-writer.js +34 -0
- package/dist/emit/compliance/compliance-context.d.ts +57 -0
- package/dist/emit/compliance/compliance-context.js +113 -0
- package/dist/emit/compliance/deviation-ledger.d.ts +27 -0
- package/dist/emit/compliance/deviation-ledger.js +47 -0
- package/dist/emit/compliance/deviation-writer.d.ts +30 -0
- package/dist/emit/compliance/deviation-writer.js +37 -0
- package/dist/emit/compliance/index.d.ts +7 -0
- package/dist/emit/compliance/index.js +6 -0
- package/dist/emit/compliance/rule-engine.d.ts +13 -0
- package/dist/emit/compliance/rule-engine.js +101 -0
- package/dist/emit/compliance/rules.d.ts +16 -0
- package/dist/emit/compliance/rules.js +191 -0
- package/dist/emit/compliance/types.d.ts +59 -0
- package/dist/emit/compliance/types.js +8 -0
- package/dist/emit/cpp-emitter.js +4 -3
- package/dist/emit/emitters/class-emitter.js +6 -1
- package/dist/emit/emitters/emitter-context.d.ts +28 -1
- package/dist/emit/emitters/function-emitter-impl.js +153 -53
- package/dist/emit/emitters/line-appender.js +19 -0
- package/dist/emit/emitters/line-marker.d.ts +38 -0
- package/dist/emit/emitters/line-marker.js +39 -0
- package/dist/emit/emitters/output-finalizer.d.ts +6 -0
- package/dist/emit/emitters/output-finalizer.js +101 -12
- package/dist/emit/emitters/setup.d.ts +17 -0
- package/dist/emit/emitters/setup.js +372 -30
- package/dist/emit/emitters/top-level-prep.js +8 -0
- package/dist/emit/emitters/type-decl-emitter.js +28 -3
- package/dist/emit/emitters/ui-emitter.js +33 -9
- package/dist/emit/expression-renderer.d.ts +1 -1
- package/dist/emit/expression-renderer.js +91 -6
- package/dist/emit/route-hal-op.js +18 -5
- package/dist/emit/snprintf-helpers.js +15 -4
- package/dist/emit/statement-renderer.d.ts +10 -0
- package/dist/emit/statement-renderer.js +34 -5
- package/dist/emit/utils/async-state-machine.js +221 -125
- package/dist/emit/utils/hal-op-cpp-type.d.ts +6 -0
- package/dist/emit/utils/hal-op-cpp-type.js +40 -0
- package/dist/framework-package.js +2 -0
- package/dist/framework-registry.d.ts +17 -0
- package/dist/install/framework-catalog.d.ts +53 -0
- package/dist/install/framework-catalog.js +107 -0
- package/dist/install/handle-install.d.ts +35 -0
- package/dist/install/handle-install.js +177 -0
- package/dist/install/index.d.ts +4 -0
- package/dist/install/index.js +3 -0
- package/dist/ir/adc-range-validation.js +40 -26
- package/dist/ir/build-ir-state.d.ts +1 -0
- package/dist/ir/build-ir-state.js +14 -0
- package/dist/ir/build-ir.js +9 -5
- package/dist/ir/call-graph.js +16 -0
- package/dist/ir/expression-to-ir.js +207 -6
- package/dist/ir/feature-registry.js +7 -25
- package/dist/ir/function-builder.js +22 -0
- package/dist/ir/hal/hal-emitter.d.ts +5 -2
- package/dist/ir/hal/hal-emitter.js +50 -18
- package/dist/ir/hal/hal-parser.d.ts +6 -0
- package/dist/ir/hal/hal-parser.js +81 -0
- package/dist/ir/hal/hal-plugins.js +733 -1
- package/dist/ir/identifier-collector.js +35 -0
- package/dist/ir/interrupt-analysis.d.ts +5 -1
- package/dist/ir/interrupt-analysis.js +16 -19
- package/dist/ir/memory-budget-validation.js +1 -0
- package/dist/ir/network-validation.d.ts +4 -0
- package/dist/ir/network-validation.js +184 -0
- package/dist/ir/ownership-analysis.js +39 -1
- package/dist/ir/peripheral-ownership.js +5 -0
- package/dist/ir/peripheral-validation.d.ts +1 -1
- package/dist/ir/peripheral-validation.js +6 -3
- package/dist/ir/pin-alias-conflict.d.ts +1 -1
- package/dist/ir/pin-alias-conflict.js +2 -1
- package/dist/ir/pin-capability-validation.js +71 -32
- package/dist/ir/pin-mode-validation.d.ts +2 -2
- package/dist/ir/pin-mode-validation.js +54 -18
- package/dist/ir/pin-safety.d.ts +1 -1
- package/dist/ir/pin-safety.js +2 -1
- package/dist/ir/program-analysis.d.ts +81 -0
- package/dist/ir/program-analysis.js +429 -0
- package/dist/ir/pulldown-validation.d.ts +1 -1
- package/dist/ir/pulldown-validation.js +2 -1
- package/dist/ir/pwm-timer-sharing.d.ts +1 -1
- package/dist/ir/pwm-timer-sharing.js +2 -1
- package/dist/ir/render-expr.js +11 -0
- package/dist/ir/resource-analysis.js +2 -0
- package/dist/ir/timer0-pwm-timing-conflict.d.ts +1 -1
- package/dist/ir/timer0-pwm-timing-conflict.js +2 -1
- package/dist/ir/timing-validation.d.ts +6 -1
- package/dist/ir/timing-validation.js +61 -13
- package/dist/ir/transformers/call-statement.js +105 -0
- package/dist/ir/transformers/expressions.js +62 -0
- package/dist/ir/transformers/hal-call-resolver.js +21 -0
- package/dist/ir/transformers/hal-emit-helpers.js +1 -1
- package/dist/ir/transformers/namespace-methods.js +17 -12
- package/dist/ir/transformers/ui-reactive.js +2 -2
- package/dist/ir/transformers/variables.js +137 -19
- package/dist/ir/try-catch-validation.js +2 -0
- package/dist/ir/type-resolution.js +20 -2
- package/dist/ir/ui-element-auto-wire.js +7 -5
- package/dist/ir/unit-suspicion-validation.js +9 -7
- package/dist/ir/utils/map-statements.d.ts +4 -0
- package/dist/ir/utils/map-statements.js +79 -0
- package/dist/ir/validation-orchestrator.js +15 -8
- package/dist/ir/worker-analysis.d.ts +10 -0
- package/dist/ir/worker-analysis.js +261 -0
- package/dist/libdef/c-to-decl.d.ts +27 -0
- package/dist/libdef/c-to-decl.js +397 -0
- package/dist/libdef/component-decls.d.ts +2 -0
- package/dist/libdef/component-decls.js +6 -0
- package/dist/libdef/component-discovery.d.ts +43 -0
- package/dist/libdef/component-discovery.js +83 -0
- package/dist/libdef/cpp-to-decl.d.ts +9 -0
- package/dist/libdef/cpp-to-decl.js +72 -0
- package/dist/libdef/registry.js +5 -2
- package/dist/lint-cache.d.ts +59 -0
- package/dist/lint-cache.js +257 -0
- package/dist/orchestrator/graph-builder.js +14 -9
- package/dist/orchestrator/type-checker.js +4 -2
- package/dist/platform/coop-scheduler-runtime.d.ts +19 -0
- package/dist/platform/coop-scheduler-runtime.js +41 -0
- package/dist/platform/generic-strategy.d.ts +15 -3
- package/dist/platform/generic-strategy.js +49 -4
- package/dist/safety/safety-bridge.d.ts +11 -0
- package/dist/safety/safety-bridge.js +48 -0
- package/dist/safety/sidecar-bridge.d.ts +5 -0
- package/dist/safety/sidecar-bridge.js +22 -0
- package/dist/safety-hook.d.ts +79 -0
- package/dist/safety-hook.js +35 -0
- package/dist/testing.d.ts +9 -2
- package/dist/testing.js +11 -2
- package/dist/transpile.d.ts +3 -0
- package/dist/transpile.js +202 -54
- package/dist/types.d.ts +22 -3
- package/dist/ui/ui-bridge.d.ts +12 -0
- package/dist/ui/ui-bridge.js +18 -0
- package/dist/ui-hook.d.ts +17 -3
- package/dist/utils/cli.js +122 -2
- package/dist/utils/fs.d.ts +13 -0
- package/dist/utils/fs.js +50 -0
- package/dist/utils/ui.js +3 -1
- package/package.json +147 -127
- package/dist/api/shared/display-adapters/eink-mono.d.ts +0 -2
- package/dist/api/shared/display-adapters/eink-mono.js +0 -53
- package/dist/api/shared/display-adapters/ssd1309.d.ts +0 -2
- package/dist/api/shared/display-adapters/ssd1309.js +0 -136
- package/dist/api/shared/display-adapters/st7796.d.ts +0 -2
- package/dist/api/shared/display-adapters/st7796.js +0 -132
- package/dist/ir/heap-array-validation.d.ts +0 -24
- package/dist/ir/heap-array-validation.js +0 -29
|
@@ -34,7 +34,7 @@ import { getRadioGroups } from "../../ir/ui-element-auto-wire.js";
|
|
|
34
34
|
// minPressure gate is skipped for them. Resistive controllers (XPT2046,
|
|
35
35
|
// STMPE610, Adafruit_TouchScreen) keep the gate.
|
|
36
36
|
// ---------------------------------------------------------------------------
|
|
37
|
-
const CAPACITIVE_TOUCH_LIBS = new Set(["FT6336U", "sdl"]);
|
|
37
|
+
const CAPACITIVE_TOUCH_LIBS = new Set(["FT6336U", "GT911", "CST816S", "sdl"]);
|
|
38
38
|
/** Generate the ui_poll_touch() body, or null for the no-touch path. */
|
|
39
39
|
export function generateTouchPollBody(input) {
|
|
40
40
|
const { library, minPressure, calibration, profile } = input;
|
|
@@ -141,9 +141,14 @@ export function emitUIRuntime(ctx) {
|
|
|
141
141
|
// display-adapter registry. Must precede the runtime header so the
|
|
142
142
|
// adapter functions (__tc_display, display_init, etc.) are available.
|
|
143
143
|
const profile = getDisplayProfile();
|
|
144
|
-
// 0. SPI-bus display drivers (ILI9341, ST7796, …) need the SPI
|
|
145
|
-
//
|
|
146
|
-
|
|
144
|
+
// 0. SPI-bus display drivers (ILI9341, ST7796, …) need the Arduino SPI
|
|
145
|
+
// library — but ONLY on the Adafruit path. Native adapters (AVR, ESP32)
|
|
146
|
+
// emit their own bus setup and would break on <SPI.h>. Host render targets
|
|
147
|
+
// (sdl, native-preview) have no SPI bus at all.
|
|
148
|
+
const nativeAdapter = ctx.strategy?.providesDisplayAdapter?.() ?? false;
|
|
149
|
+
const spiDriver = profile?.driver !== "sdl"
|
|
150
|
+
&& profile?.driver !== "native-preview"
|
|
151
|
+
&& !nativeAdapter;
|
|
147
152
|
if (spiDriver && !ctx.includes.includes("<SPI.h>")) {
|
|
148
153
|
ctx.includes.push("<SPI.h>");
|
|
149
154
|
}
|
|
@@ -151,7 +156,7 @@ export function emitUIRuntime(ctx) {
|
|
|
151
156
|
// buildEmitterContext (setup.ts), NOT here — emitPreamble runs before this
|
|
152
157
|
// function, so a push here would be too late to land in the output.
|
|
153
158
|
if (profile) {
|
|
154
|
-
const adapter = generateDisplayAdapter(profile);
|
|
159
|
+
const adapter = generateDisplayAdapter(profile, ctx.strategy);
|
|
155
160
|
// Prepend includes to the very front — Arduino's auto-prototyper scans
|
|
156
161
|
// the whole .ino and generates prototypes that reference GFXcanvas16
|
|
157
162
|
// etc. before any #include, so the GFX header must come first.
|
|
@@ -164,6 +169,23 @@ export function emitUIRuntime(ctx) {
|
|
|
164
169
|
ctx.sourceLines.push(is888
|
|
165
170
|
? "#define UI_COLOR_DEPTH 888\n#define UI_COLOR_T uint32_t\n#define UI_DIM_MASK 0x7F7F7Fu"
|
|
166
171
|
: "#define UI_COLOR_DEPTH 565\n#define UI_COLOR_T uint16_t\n#define UI_DIM_MASK 0x7BEFu");
|
|
172
|
+
// The native CuttlefishGFX/CuttlefishCanvas16 class slice is emitted ONLY
|
|
173
|
+
// for adapters that instantiate CuttlefishGFX by value (the planned
|
|
174
|
+
// framework-avr/framework-esp32 native panel drivers). Adapters that alias
|
|
175
|
+
// the token via macro — the Adafruit path (`#define CuttlefishCanvas16
|
|
176
|
+
// GFXcanvas16`) and the SDL path (`#define CuttlefishCanvas16 SdlGfxCanvas`)
|
|
177
|
+
// — own the canvas type; emitting the class slice alongside the macro makes
|
|
178
|
+
// `class CuttlefishCanvas16` macro-expand into a redefinition of Adafruit's
|
|
179
|
+
// GFXcanvas16. Detect the macro-alias path from the adapter's own includes
|
|
180
|
+
// and suppress the slice there. The previous gate reused
|
|
181
|
+
// providesDisplayAdapter(), which merely means "the strategy owns its
|
|
182
|
+
// adapters" (true for Arduino/Adafruit) and is unrelated to whether the
|
|
183
|
+
// native GFX class is wanted — it wrongly emitted the slice on every
|
|
184
|
+
// Arduino build, breaking compilation.
|
|
185
|
+
const macroAliasesCanvas16 = /^\s*#\s*define\s+CuttlefishCanvas16\b/m.test(adapter.includes);
|
|
186
|
+
if (!macroAliasesCanvas16) {
|
|
187
|
+
ctx.sourceLines.push(ui.emitCuttlefishGfx(true));
|
|
188
|
+
}
|
|
167
189
|
ctx.sourceLines.push(adapter.declaration);
|
|
168
190
|
ctx.sourceLines.push(adapter.functions);
|
|
169
191
|
}
|
|
@@ -173,7 +195,7 @@ export function emitUIRuntime(ctx) {
|
|
|
173
195
|
if (profile.touch) {
|
|
174
196
|
const t = profile.touch;
|
|
175
197
|
if (t.library) {
|
|
176
|
-
touchAdapter = generateTouchAdapter(t);
|
|
198
|
+
touchAdapter = generateTouchAdapter(t, ctx.strategy);
|
|
177
199
|
// Prepend includes to the front (Arduino auto-prototyper safety).
|
|
178
200
|
ctx.sourceLines.unshift(touchAdapter.includes[0]);
|
|
179
201
|
for (let i = 1; i < touchAdapter.includes.length; i++) {
|
|
@@ -252,13 +274,15 @@ export function emitUIRuntime(ctx) {
|
|
|
252
274
|
// header so its #ifndef guards adopt them. Source of truth:
|
|
253
275
|
// resolveScrollConfig(profile.scroll). Defaults derive from the declared
|
|
254
276
|
// touch hardware, so the demo (XPT2046) gets resistive+full with no config.
|
|
255
|
-
const scroll = resolveScrollConfig(profile
|
|
256
|
-
ctx.sourceLines.push(`#define UI_SCROLL_MAX_OVERSCROLL ${scroll.maxOverscroll}`, `#define UI_SCROLL_STIFFNESS_X10 ${Math.round(scroll.stiffness * 10)}`, `#define UI_SCROLL_EDGE_SNAP_PX ${scroll.edgeSnapPx}`, `#define UI_SCROLL_DRAG_SCALE_X10 ${Math.round(scroll.dragScale * 10)}`, `#define UI_SCROLL_INPUT_TIER_CAPACITIVE ${scroll.inputTier === "capacitive" ? 1 : 0}`, `#define UI_SCROLL_INPUT_TIER_RESISTIVE ${scroll.inputTier === "resistive" ? 1 : 0}`, `#define UI_SCROLL_INPUT_TIER_NONE ${scroll.inputTier === "none" ? 1 : 0}`, `#define UI_SCROLL_RENDER_TIER_FULL ${scroll.renderTier === "full" ? 1 : 0}`, `#define UI_SCROLL_RENDER_TIER_CONSTRAINED ${scroll.renderTier === "constrained" ? 1 : 0}`,
|
|
277
|
+
const scroll = resolveScrollConfig(profile);
|
|
278
|
+
ctx.sourceLines.push(`#define UI_SCROLL_MAX_OVERSCROLL ${scroll.maxOverscroll}`, `#define UI_SCROLL_STIFFNESS_X10 ${Math.round(scroll.stiffness * 10)}`, `#define UI_SCROLL_EDGE_SNAP_PX ${scroll.edgeSnapPx}`, `#define UI_SCROLL_DRAG_SCALE_X10 ${Math.round(scroll.dragScale * 10)}`, `#define UI_SCROLL_INPUT_TIER_CAPACITIVE ${scroll.inputTier === "capacitive" ? 1 : 0}`, `#define UI_SCROLL_INPUT_TIER_RESISTIVE ${scroll.inputTier === "resistive" ? 1 : 0}`, `#define UI_SCROLL_INPUT_TIER_NONE ${scroll.inputTier === "none" ? 1 : 0}`, `#define UI_SCROLL_RENDER_TIER_FULL ${scroll.renderTier === "full" ? 1 : 0}`, `#define UI_SCROLL_RENDER_TIER_CONSTRAINED ${scroll.renderTier === "constrained" ? 1 : 0}`, ...(scroll.debug ? [`#define UI_SCROLL_DEBUG 1`] : []));
|
|
257
279
|
// Forward-declare __ui_kb_set_onchange before the runtime header: the
|
|
258
280
|
// header's keyboard-open function calls it, but the definition is emitted
|
|
259
281
|
// later (section 8b). On native (single TU) this must precede the header.
|
|
260
282
|
ctx.sourceLines.push(`void __ui_kb_set_onchange();`);
|
|
261
|
-
ctx.sourceLines.push(emitRuntimeHeader(
|
|
283
|
+
ctx.sourceLines.push(emitRuntimeHeader({
|
|
284
|
+
nativeDisplayActive: ctx.strategy?.providesDisplayAdapter?.() ?? false,
|
|
285
|
+
}));
|
|
262
286
|
// 1.5. Touch poll function (uses the adapter pattern). Body is generated by
|
|
263
287
|
// generateTouchPollBody — extracted for unit-testability of the capacitive
|
|
264
288
|
// vs resistive branch (FT6336U/SDL skip the minPressure gate).
|
|
@@ -88,7 +88,7 @@ export declare class ExpressionRenderer {
|
|
|
88
88
|
private readonly stringEnumNames;
|
|
89
89
|
private readonly largeEnumNames;
|
|
90
90
|
private readonly knownFunctionReturnTypes?;
|
|
91
|
-
private
|
|
91
|
+
private knownVariableTypes?;
|
|
92
92
|
private readonly pointerVarTypes?;
|
|
93
93
|
private readonly globalPointerVarTypes?;
|
|
94
94
|
private readonly stringVarNames?;
|
|
@@ -10,6 +10,7 @@ import { accessorGetterName } from "./utils/cpp-helpers.js";
|
|
|
10
10
|
import { INTEGRAL_CPP_TYPE_RE } from "./utils/cpp-helpers.js";
|
|
11
11
|
import { renderPeripheralProperty } from "../mapping/peripheral-names.js";
|
|
12
12
|
import { parseCppType, renderCppType, bareType, parsedIsPointer, parsedIsVector, needsCStrForStringLike } from "../api/shared/cpp-type-ir.js";
|
|
13
|
+
import { cppTypeForHalOp } from "./utils/hal-op-cpp-type.js";
|
|
13
14
|
/**
|
|
14
15
|
* Renders ExpressionIR nodes to C++ code strings.
|
|
15
16
|
*/
|
|
@@ -79,6 +80,18 @@ export class ExpressionRenderer {
|
|
|
79
80
|
if (!expr || typeof expr !== 'object' || !expr.kind) {
|
|
80
81
|
return "/* invalid expression */";
|
|
81
82
|
}
|
|
83
|
+
// When a per-scope knownVariableTypes is passed (e.g. a function's child
|
|
84
|
+
// emission scope carrying its parameters), install it on the instance for
|
|
85
|
+
// the duration of this render so every recursive render() call and
|
|
86
|
+
// renderIdentifier() reads the merged scope (globals + params). Without
|
|
87
|
+
// this, recursive paths that don't forward knownVariableTypes (ternary
|
|
88
|
+
// branches, call args, array elements, …) would resolve identifiers
|
|
89
|
+
// against only the top-level scope, missing function parameters — which
|
|
90
|
+
// breaks reserved-name escaping for params like `min`/`max` on Arduino.
|
|
91
|
+
const prevKnownVariableTypes = this.knownVariableTypes;
|
|
92
|
+
if (knownVariableTypes) {
|
|
93
|
+
this.knownVariableTypes = knownVariableTypes;
|
|
94
|
+
}
|
|
82
95
|
let rendered;
|
|
83
96
|
switch (expr.kind) {
|
|
84
97
|
case "number": {
|
|
@@ -99,7 +112,7 @@ export class ExpressionRenderer {
|
|
|
99
112
|
rendered = expr.value ? "true" : "false";
|
|
100
113
|
break;
|
|
101
114
|
case "identifier":
|
|
102
|
-
rendered = this.renderIdentifier(expr.value);
|
|
115
|
+
rendered = this.renderIdentifier(expr.value, knownVariableTypes);
|
|
103
116
|
break;
|
|
104
117
|
case "raw":
|
|
105
118
|
rendered = this.renderRaw(expr.value, exprTransformer);
|
|
@@ -149,6 +162,18 @@ export class ExpressionRenderer {
|
|
|
149
162
|
case "method-call":
|
|
150
163
|
rendered = this.renderMethodCall(expr, exprTransformer);
|
|
151
164
|
break;
|
|
165
|
+
case "call": {
|
|
166
|
+
// Bare call expression: `Name(args)` with no receiver (e.g. a
|
|
167
|
+
// constructor call `SafeInt(x)` written inline, or a free function).
|
|
168
|
+
// Method-on-receiver calls lower as "method-call"; this arm is for the
|
|
169
|
+
// receiverless form. The callee is escaped against C++ reserved names;
|
|
170
|
+
// when a target type is in scope, renderValueForTarget (the caller)
|
|
171
|
+
// wraps this with template args (SafeInt(x) -> SafeInt<int32_t>(x)).
|
|
172
|
+
const callArgs = expr.args.map(a => this.render(a, exprTransformer)).join(", ");
|
|
173
|
+
const callCallee = escapeCppKeyword(exprTransformer ? exprTransformer(expr.callee) : expr.callee, this.strategy.reservedNames());
|
|
174
|
+
rendered = `${callCallee}(${callArgs})`;
|
|
175
|
+
break;
|
|
176
|
+
}
|
|
152
177
|
case "element-access":
|
|
153
178
|
rendered = this.renderElementAccess(expr, exprTransformer, knownVariableTypes);
|
|
154
179
|
break;
|
|
@@ -191,9 +216,10 @@ export class ExpressionRenderer {
|
|
|
191
216
|
`This is a transpiler bug; the renderer is missing a case for this kind.`);
|
|
192
217
|
}
|
|
193
218
|
}
|
|
219
|
+
this.knownVariableTypes = prevKnownVariableTypes;
|
|
194
220
|
return normalizeRawExpression(rendered, this.strategy, this.classNameMap);
|
|
195
221
|
}
|
|
196
|
-
renderIdentifier(value) {
|
|
222
|
+
renderIdentifier(value, scopeKnownVariableTypes) {
|
|
197
223
|
const nullVal = this.strategy.nullValue();
|
|
198
224
|
// expression-to-ir lowers the TS `null` literal to the identifier sentinel
|
|
199
225
|
// "nullptr" and `undefined` to "CUTTLEFISH_UNDEFINED". Both must route
|
|
@@ -209,7 +235,27 @@ export class ExpressionRenderer {
|
|
|
209
235
|
if (this.strategy.passthroughMacroNames().has(value)) {
|
|
210
236
|
return value;
|
|
211
237
|
}
|
|
212
|
-
|
|
238
|
+
// Platform-reserved names (e.g. Arduino `Serial`, or the `min`/`max` math
|
|
239
|
+
// macros) are globals/macros provided by the framework headers. Escaping
|
|
240
|
+
// them would break references to those globals — UNLESS the name is a
|
|
241
|
+
// user-declared variable/parameter that shadows and would collide. Check
|
|
242
|
+
// both the instance field (globals/locals seen so far) AND the per-scope
|
|
243
|
+
// map passed by the caller (function parameters, which live in the child
|
|
244
|
+
// emission scope and aren't on the instance field). Declaration sites
|
|
245
|
+
// already escape user vars (renderParameters → renderTypedName), so the
|
|
246
|
+
// body references must escape to match.
|
|
247
|
+
const reservedNames = this.strategy.reservedNames();
|
|
248
|
+
if (reservedNames.has(value)) {
|
|
249
|
+
const isUserVar = (this.knownVariableTypes !== undefined && this.knownVariableTypes.has(value)) ||
|
|
250
|
+
(scopeKnownVariableTypes !== undefined && scopeKnownVariableTypes.has(value)) ||
|
|
251
|
+
(this.pointerVarTypes !== undefined && this.pointerVarTypes.has(value)) ||
|
|
252
|
+
(this.globalPointerVarTypes !== undefined && this.globalPointerVarTypes.has(value)) ||
|
|
253
|
+
(this.stringVarNames !== undefined && this.stringVarNames.has(value));
|
|
254
|
+
if (!isUserVar) {
|
|
255
|
+
return value;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
return escapeCppKeyword(value, reservedNames);
|
|
213
259
|
}
|
|
214
260
|
renderRaw(value, exprTransformer) {
|
|
215
261
|
const effectiveClassNameMap = this.classNameMap;
|
|
@@ -403,6 +449,8 @@ export class ExpressionRenderer {
|
|
|
403
449
|
}
|
|
404
450
|
case "unary":
|
|
405
451
|
return expr.operator === "!" ? "bool" : this.inferExpressionCppType(expr.operand, knownVariableTypes);
|
|
452
|
+
case "hal-expr":
|
|
453
|
+
return cppTypeForHalOp(expr.operation.operation);
|
|
406
454
|
default:
|
|
407
455
|
return undefined;
|
|
408
456
|
}
|
|
@@ -714,10 +762,16 @@ export class ExpressionRenderer {
|
|
|
714
762
|
}
|
|
715
763
|
case "hal-expr": {
|
|
716
764
|
const rendered = this.render(expr, exprTransformer);
|
|
717
|
-
// HAL expressions that resolve to string-like outputs use %s
|
|
718
765
|
if (rendered.startsWith('"') || this.stringVarNames?.has(rendered)) {
|
|
719
766
|
return { format: "%s", arg: rendered, estimatedLength: 32 };
|
|
720
767
|
}
|
|
768
|
+
const cppType = cppTypeForHalOp(expr.operation.operation);
|
|
769
|
+
if (cppType && this.isStringLikeCppType(cppType)) {
|
|
770
|
+
return { format: "%s", arg: rendered, estimatedLength: 32 };
|
|
771
|
+
}
|
|
772
|
+
if (cppType === "bool") {
|
|
773
|
+
return { format: "%s", arg: `(${rendered} ? "true" : "false")`, estimatedLength: 5 };
|
|
774
|
+
}
|
|
721
775
|
return { format: "%d", arg: rendered, estimatedLength: 12 };
|
|
722
776
|
}
|
|
723
777
|
case "method-call":
|
|
@@ -878,10 +932,27 @@ export class ExpressionRenderer {
|
|
|
878
932
|
* (safer than a wrong cast).
|
|
879
933
|
*/
|
|
880
934
|
renderValueForTarget(expr, targetType, knownVariableTypes, exprTransformer) {
|
|
881
|
-
const rendered = this.render(expr, exprTransformer, knownVariableTypes);
|
|
882
935
|
if (!targetType)
|
|
883
|
-
return
|
|
936
|
+
return this.render(expr, exprTransformer, knownVariableTypes);
|
|
884
937
|
const normalizedTarget = targetType.trim();
|
|
938
|
+
// Inject template args for constructor calls on pre-C++17 toolchains
|
|
939
|
+
// (e.g. AVR without CTAD). SafeVariable(0) → SafeVariable<int32_t>(0).
|
|
940
|
+
// Handles both `method-call` (when the constructor appears as a standalone
|
|
941
|
+
// initializer) and `call` (when it appears on the RHS of an assignment,
|
|
942
|
+
// which lowers as `T x = {}; x = T(args);`). The callee must match the
|
|
943
|
+
// template name and the target must be a `Name<...>` instantiation, so a
|
|
944
|
+
// regular function call assigned to a non-templated type never matches.
|
|
945
|
+
const tmplMatch = normalizedTarget.match(/^([A-Za-z_]\w*)<(.+)>/);
|
|
946
|
+
const exprAny = expr;
|
|
947
|
+
const isCtorCall = tmplMatch != null
|
|
948
|
+
&& (exprAny.kind === "method-call" || exprAny.kind === "call")
|
|
949
|
+
&& exprAny.callee === tmplMatch[1]
|
|
950
|
+
&& exprAny.callee != null && !exprAny.callee.includes("<");
|
|
951
|
+
if (isCtorCall && exprAny.args) {
|
|
952
|
+
const argsText = exprAny.args.map(a => this.render(a, exprTransformer, knownVariableTypes)).join(", ");
|
|
953
|
+
return `${tmplMatch[1]}<${tmplMatch[2]}>(${argsText})`;
|
|
954
|
+
}
|
|
955
|
+
const rendered = this.render(expr, exprTransformer, knownVariableTypes);
|
|
885
956
|
// Never cast into string-like storage — enums that lower to const char*
|
|
886
957
|
// (string enums) already match, and a string target is never an enum boundary.
|
|
887
958
|
if (this.isStringLikeCppType(normalizedTarget))
|
|
@@ -1350,6 +1421,8 @@ export class ExpressionRenderer {
|
|
|
1350
1421
|
renderMethodCall(expr, exprTransformer) {
|
|
1351
1422
|
const argsText = expr.args.map(a => this.render(a, exprTransformer)).join(", ");
|
|
1352
1423
|
let callee = exprTransformer ? exprTransformer(expr.callee) : expr.callee;
|
|
1424
|
+
const rExpr = expr.receiverExpr;
|
|
1425
|
+
const mName = expr.methodName;
|
|
1353
1426
|
// Convert . to :: for static or namespace method calls if the IR flagged them.
|
|
1354
1427
|
if (expr.isStatic || expr.isNamespace) {
|
|
1355
1428
|
callee = callee.replace(/\./g, "::");
|
|
@@ -1380,6 +1453,18 @@ export class ExpressionRenderer {
|
|
|
1380
1453
|
return callee;
|
|
1381
1454
|
}
|
|
1382
1455
|
callee = this.escapeFinalMemberName(callee);
|
|
1456
|
+
// Structured-receiver path: when the method-call IR carries a receiverExpr
|
|
1457
|
+
// (the safe.read().ok().fail() chain builder sets this), render the receiver
|
|
1458
|
+
// via the full renderer so nested lambda args survive (the flat callee string
|
|
1459
|
+
// would have destroyed them as /* __lambda__ */ placeholders). The methodName
|
|
1460
|
+
// is escaped against reserved names (e.g. div -> div_).
|
|
1461
|
+
const receiverExpr = expr.receiverExpr;
|
|
1462
|
+
const methodName = expr.methodName;
|
|
1463
|
+
if (receiverExpr !== undefined && methodName !== undefined) {
|
|
1464
|
+
const receiverText = this.render(receiverExpr, exprTransformer);
|
|
1465
|
+
const escapedMethod = escapeCppKeyword(methodName, this.strategy.reservedNames());
|
|
1466
|
+
return `${receiverText}.${escapedMethod}(${argsText})`;
|
|
1467
|
+
}
|
|
1383
1468
|
return `${callee}(${argsText})`;
|
|
1384
1469
|
}
|
|
1385
1470
|
escapeFinalMemberName(callee) {
|
|
@@ -1,13 +1,26 @@
|
|
|
1
1
|
// ---------------------------------------------------------------------------
|
|
2
2
|
// Op routing — dispatch a HALOpIR to the right strategy resolver.
|
|
3
3
|
//
|
|
4
|
-
// display.* ops go to resolveDisplayOp (graphics-specific)
|
|
5
|
-
//
|
|
6
|
-
//
|
|
4
|
+
// display.* ops go to resolveDisplayOp (graphics-specific).
|
|
5
|
+
// safety.* ops go to the safety hook's resolveSafetyOp (when @typecad/safety
|
|
6
|
+
// is loaded) — NEVER to a per-target strategy, because the safety
|
|
7
|
+
// package is MCU-agnostic by construction.
|
|
8
|
+
// everything else goes to resolveHALOperation (the existing generic seam).
|
|
9
|
+
// Keeps the consumer sites (expression-renderer, statement-renderer,
|
|
10
|
+
// render-expr) DRY.
|
|
7
11
|
// ---------------------------------------------------------------------------
|
|
12
|
+
import { getSafetyHook } from "../safety-hook.js";
|
|
8
13
|
export function routeHALOp(op, strategy) {
|
|
9
|
-
if (typeof op.operation === "string"
|
|
10
|
-
|
|
14
|
+
if (typeof op.operation === "string") {
|
|
15
|
+
if (op.operation.startsWith("display.")) {
|
|
16
|
+
return strategy.resolveDisplayOp?.(op);
|
|
17
|
+
}
|
|
18
|
+
if (op.operation.startsWith("safety.")) {
|
|
19
|
+
// Safety ops are resolved by the @typecad/safety package via hook.
|
|
20
|
+
// Returns undefined if the package is not loaded (caller emits an
|
|
21
|
+
// unhandled-op warning).
|
|
22
|
+
return getSafetyHook()?.resolveSafetyOp?.(op);
|
|
23
|
+
}
|
|
11
24
|
}
|
|
12
25
|
return strategy.resolveHALOperation?.(op);
|
|
13
26
|
}
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
// Types are imported from @typecad/cuttlefish/api/shared.
|
|
9
9
|
// ---------------------------------------------------------------------------
|
|
10
10
|
import { escapeCppStringLiteral, escapeSnprintfFormatFragment } from "../utils/strings.js";
|
|
11
|
+
import { cppTypeForHalOp } from "./utils/hal-op-cpp-type.js";
|
|
11
12
|
import { parsedElementString, parsedIsStringLike } from "../api/shared/cpp-type-ir.js";
|
|
12
13
|
// ---------------------------------------------------------------------------
|
|
13
14
|
// Scope state management
|
|
@@ -235,11 +236,14 @@ export function inferSnprintfArg(expr, strategy, scopeState, renderExpression, p
|
|
|
235
236
|
return { format: "%d", arg: renderExpression(expr), estimatedLength: 12, preludeLines: [] };
|
|
236
237
|
}
|
|
237
238
|
}
|
|
238
|
-
const
|
|
239
|
-
|
|
240
|
-
|
|
239
|
+
const halIntFunctions = new Set([
|
|
240
|
+
...(strategy?.halCallNames?.() ?? new Set()),
|
|
241
|
+
// pulseIn/pulseInLong and the Wire_available/Serial_available forms
|
|
242
|
+
// are framework-specific suffix conventions; frameworks may add them
|
|
243
|
+
// to halCallNames. Kept as a fallback here until all frameworks do.
|
|
244
|
+
"pulseIn", "pulseInLong", "Wire_available", "Serial_available",
|
|
241
245
|
]);
|
|
242
|
-
if (
|
|
246
|
+
if (halIntFunctions.has(funcName)) {
|
|
243
247
|
return { format: "%d", arg: renderExpression(expr), estimatedLength: 12, preludeLines: [] };
|
|
244
248
|
}
|
|
245
249
|
}
|
|
@@ -369,6 +373,13 @@ export function inferSnprintfArg(expr, strategy, scopeState, renderExpression, p
|
|
|
369
373
|
if (rendered.startsWith('"') || stringVarNames?.has(rendered)) {
|
|
370
374
|
return { format: "%s", arg: rendered, estimatedLength: 32, preludeLines: [] };
|
|
371
375
|
}
|
|
376
|
+
const cppType = cppTypeForHalOp(expr.operation.operation);
|
|
377
|
+
if (cppType && strategy.isStringLikeType(cppType)) {
|
|
378
|
+
return { format: "%s", arg: rendered, estimatedLength: 32, preludeLines: [] };
|
|
379
|
+
}
|
|
380
|
+
if (cppType === "bool") {
|
|
381
|
+
return { format: "%s", arg: `(${rendered} ? "true" : "false")`, estimatedLength: 5, preludeLines: [] };
|
|
382
|
+
}
|
|
372
383
|
return { format: "%d", arg: rendered, estimatedLength: 12, preludeLines: [] };
|
|
373
384
|
}
|
|
374
385
|
default:
|
|
@@ -63,6 +63,14 @@ interface StatementRendererContext {
|
|
|
63
63
|
* list. Optional so ad-hoc/test constructions still work.
|
|
64
64
|
*/
|
|
65
65
|
diagnostics?: Diagnostic[];
|
|
66
|
+
/**
|
|
67
|
+
* Optional compliance context for A3-9-1 (fixed-width integer default).
|
|
68
|
+
* When provided and A3-9-1 is enforced, defaultNumericType() returns a
|
|
69
|
+
* fixed-width type instead of the legacy 'int'.
|
|
70
|
+
*/
|
|
71
|
+
compliance?: {
|
|
72
|
+
isBanned(ruleId: string): boolean;
|
|
73
|
+
};
|
|
66
74
|
}
|
|
67
75
|
/**
|
|
68
76
|
* Renders StatementIR nodes to C++ code strings.
|
|
@@ -83,6 +91,8 @@ export declare class StatementRenderer {
|
|
|
83
91
|
private readonly interfaceFieldTypes;
|
|
84
92
|
/** Shared emit-time diagnostics sink (see StatementRendererContext.diagnostics). */
|
|
85
93
|
private readonly _diagnostics;
|
|
94
|
+
/** Compliance context for A3-9-1 fixed-width integer default. */
|
|
95
|
+
private readonly _compliance?;
|
|
86
96
|
constructor(context: StatementRendererContext);
|
|
87
97
|
/**
|
|
88
98
|
* Gets the underlying expression renderer for direct use.
|
|
@@ -116,6 +116,7 @@ export class StatementRenderer {
|
|
|
116
116
|
this.namespaceNames = context.namespaceNames ?? new Set();
|
|
117
117
|
this.interfaceFieldTypes = context.interfaceFieldTypes ?? new Map();
|
|
118
118
|
this._diagnostics = context.diagnostics ?? [];
|
|
119
|
+
this._compliance = context.compliance;
|
|
119
120
|
// Create expression renderer with shared context
|
|
120
121
|
this.expressionRenderer = new ExpressionRenderer({
|
|
121
122
|
strategy: context.strategy,
|
|
@@ -324,7 +325,7 @@ export class StatementRenderer {
|
|
|
324
325
|
this.expressionRenderer.pushPrelude([
|
|
325
326
|
`const char* ${idxVar}_keys[] = { ${keysArr} };`,
|
|
326
327
|
]);
|
|
327
|
-
return `for (${this.strategy.defaultNumericType()} ${idxVar} = 0; ${idxVar} < ${statement.keys.length}; ${idxVar}++)`;
|
|
328
|
+
return `for (${this.strategy.defaultNumericType(this._compliance)} ${idxVar} = 0; ${idxVar} < ${statement.keys.length}; ${idxVar}++)`;
|
|
328
329
|
}
|
|
329
330
|
const varDecl = statement.variable;
|
|
330
331
|
if (varDecl.kind === "var_decl") {
|
|
@@ -485,6 +486,28 @@ export class StatementRenderer {
|
|
|
485
486
|
const rawStmt = statement.callee.slice('__RAW_STMT__'.length);
|
|
486
487
|
return forHeader ? rawStmt : `${rawStmt.endsWith(';') ? rawStmt : rawStmt + ';'}`;
|
|
487
488
|
}
|
|
489
|
+
// Handle expression statements whose IR must render at EMIT time (not the
|
|
490
|
+
// build-time renderExprAsText). The safe.read().ok().fail() chain uses this:
|
|
491
|
+
// its lambda args can only render via the emit-time renderLambda (which
|
|
492
|
+
// produces [&](){...}), so the structured chain IR is carried as args[0]
|
|
493
|
+
// and rendered here via the expression renderer.
|
|
494
|
+
if (statement.callee === '__EXPR_STMT__' && statement.args.length >= 1) {
|
|
495
|
+
const exprText = this.expressionRenderer.render(statement.args[0], undefined, knownVariableTypes);
|
|
496
|
+
return forHeader ? exprText : `${exprText};`;
|
|
497
|
+
}
|
|
498
|
+
// Awaited network markers (__WIFI_WAIT__/__HTTP_WAIT__) reaching the
|
|
499
|
+
// plain renderer means the await sits outside an async state machine
|
|
500
|
+
// (top-level await, or a position the state-machine splitter doesn't
|
|
501
|
+
// support). Fall back to the blocking form of the op they carry.
|
|
502
|
+
if ((statement.callee === "__WIFI_WAIT__" || statement.callee === "__HTTP_WAIT__" || statement.callee === "__BLE_WAIT__" || statement.callee === "__HAL_WAIT__")
|
|
503
|
+
&& statement.args[0]?.kind === "hal-expr") {
|
|
504
|
+
const resolved = routeHALOp(statement.args[0].operation, this.strategy);
|
|
505
|
+
const code = resolved?.code ?? (resolved?.expression ? `${resolved.expression};` : undefined);
|
|
506
|
+
if (code) {
|
|
507
|
+
return forHeader ? code.replace(/;$/, "") : code;
|
|
508
|
+
}
|
|
509
|
+
return `/* unhandled awaited hal-op: ${statement.args[0].operation.operation} */`;
|
|
510
|
+
}
|
|
488
511
|
// Handle emit() — compile-time C++ injection
|
|
489
512
|
if (statement.callee === "__EMIT__") {
|
|
490
513
|
const rawText = statement.args.map(arg => this.renderEmitArg(arg)).join("");
|
|
@@ -645,13 +668,13 @@ export class StatementRenderer {
|
|
|
645
668
|
// that don't support std::vector → emit as a plain C-style array.
|
|
646
669
|
// Mutable arrays (.push/.pop/.indexOf) are rewritten to StaticArray<int> in
|
|
647
670
|
// the IR builder (via mutableArrayVars) and never reach this branch.
|
|
648
|
-
const elementType = parsedElementString(rawType) ?? this.strategy.defaultNumericType();
|
|
671
|
+
const elementType = parsedElementString(rawType) ?? this.strategy.defaultNumericType(this._compliance);
|
|
649
672
|
return forHeader
|
|
650
673
|
? `${elementType} ${safeArrName}[] = { ${elements} }`
|
|
651
674
|
: `${elementType} ${safeArrName}[] = { ${elements} };`;
|
|
652
675
|
}
|
|
653
676
|
// Use "int" for "auto" element type since C arrays need explicit types
|
|
654
|
-
const arrayType = statement.initializer.elementType === "auto" ? this.strategy.defaultNumericType() : statement.initializer.elementType;
|
|
677
|
+
const arrayType = statement.initializer.elementType === "auto" ? this.strategy.defaultNumericType(this._compliance) : statement.initializer.elementType;
|
|
655
678
|
return forHeader
|
|
656
679
|
? `${arrayType} ${safeArrName}[] = { ${elements} }`
|
|
657
680
|
: `${arrayType} ${safeArrName}[] = { ${elements} };`;
|
|
@@ -726,7 +749,7 @@ export class StatementRenderer {
|
|
|
726
749
|
}
|
|
727
750
|
// Handle spread array initializers
|
|
728
751
|
if (statement.initializer.kind === "spread_array") {
|
|
729
|
-
let arrayType = statement.initializer.elementType === "auto" ? this.strategy.defaultNumericType() : statement.initializer.elementType;
|
|
752
|
+
let arrayType = statement.initializer.elementType === "auto" ? this.strategy.defaultNumericType(this._compliance) : statement.initializer.elementType;
|
|
730
753
|
const spreadName = this.expressionRenderer.render(statement.initializer.spreadExpr, calleeTransformer, knownVariableTypes);
|
|
731
754
|
if (statement.initializer.elementType === "auto" && knownVariableTypes && statement.initializer.spreadExpr.kind === "identifier") {
|
|
732
755
|
const srcInfo = knownVariableTypes.get(statement.initializer.spreadExpr.value);
|
|
@@ -879,11 +902,17 @@ export class StatementRenderer {
|
|
|
879
902
|
if (this.stringEnumNames.has(typeName)) {
|
|
880
903
|
return this.strategy.normalizeCppType("const char*");
|
|
881
904
|
}
|
|
905
|
+
// A3-9-1: under autosar, substitute the platform's default numeric type
|
|
906
|
+
// for the legacy "int" spelling. The IR layer hardcodes "int" for number
|
|
907
|
+
// literals, so we catch it here at the renderer boundary.
|
|
908
|
+
if (typeName === "int" && this._compliance?.isBanned("A3-9-1")) {
|
|
909
|
+
return this.strategy.defaultNumericType(this._compliance);
|
|
910
|
+
}
|
|
882
911
|
return this.strategy.normalizeCppType(typeName);
|
|
883
912
|
}
|
|
884
913
|
inferFieldType(value, parentName, fieldName) {
|
|
885
914
|
return inferObjectFieldType(value, this.pointerVarTypes, this.knownFunctionReturnTypes, undefined, undefined, undefined, // largeEnumNames - would need to pass through
|
|
886
|
-
parentName, fieldName, this.strategy.defaultNumericType(), (o, n) => this.strategy.resolvePinType?.(o, n));
|
|
915
|
+
parentName, fieldName, this.strategy.defaultNumericType(this._compliance), (o, n) => this.strategy.resolvePinType?.(o, n));
|
|
887
916
|
}
|
|
888
917
|
/**
|
|
889
918
|
* Transform console.log/error/warn calls based on target platform.
|