@typecad/framework-zephyr 1.0.0-alpha.12 → 1.0.0-alpha.13
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/dist/display/index.d.ts +1 -1
- package/dist/display/index.js +1 -1
- package/dist/display/profiles.d.ts +8 -0
- package/dist/display/profiles.js +19 -0
- package/dist/display/ui-adapter.d.ts +4 -0
- package/dist/display/ui-adapter.js +46 -0
- package/dist/dt-config/overlay.d.ts +8 -1
- package/dist/dt-config/overlay.js +19 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +5 -0
- package/dist/lowering/gpio.js +7 -3
- package/dist/strategy.d.ts +20 -0
- package/dist/strategy.js +242 -118
- package/dist/toolchain/debug-config.d.ts +43 -2
- package/dist/toolchain/debug-config.js +129 -17
- package/dist/toolchain/index.d.ts +13 -0
- package/dist/toolchain/index.js +65 -14
- package/dist/toolchain/scaffold.js +40 -20
- package/package.json +4 -4
- package/src/display/index.ts +1 -1
- package/src/display/profiles.ts +23 -0
- package/src/display/ui-adapter.ts +51 -0
- package/src/dt-config/overlay.ts +450 -423
- package/src/index.ts +6 -0
- package/src/lowering/gpio.ts +7 -3
- package/src/strategy.ts +271 -122
- package/src/toolchain/debug-config.ts +137 -14
- package/src/toolchain/index.ts +67 -15
- package/src/toolchain/scaffold.ts +39 -18
package/dist/display/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { DisplayHALOp } from '@typecad/cuttlefish/api/shared';
|
|
|
2
2
|
import { type ZephyrDisplayProfile } from './profiles.js';
|
|
3
3
|
export { zephyrUiDisplayAdapter, zephyrDisplayAdapterGenerator } from './ui-adapter.js';
|
|
4
4
|
export { zephyrTouchAdapter } from './touch-adapter.js';
|
|
5
|
-
export { ZEPHYR_DISPLAY_PROFILES, DEFAULT_ZEPHYR_DISPLAY_PROFILE } from './profiles.js';
|
|
5
|
+
export { ZEPHYR_DISPLAY_PROFILES, DEFAULT_ZEPHYR_DISPLAY_PROFILE, BUILT_IN_PROFILES } from './profiles.js';
|
|
6
6
|
export type { ZephyrDisplayProfile } from './profiles.js';
|
|
7
7
|
export interface DisplayState {
|
|
8
8
|
initialized: boolean;
|
package/dist/display/index.js
CHANGED
|
@@ -15,7 +15,7 @@ import { DEFAULT_ZEPHYR_DISPLAY_PROFILE } from './profiles.js';
|
|
|
15
15
|
// and consumers can reach them from the package barrel.
|
|
16
16
|
export { zephyrUiDisplayAdapter, zephyrDisplayAdapterGenerator } from './ui-adapter.js';
|
|
17
17
|
export { zephyrTouchAdapter } from './touch-adapter.js';
|
|
18
|
-
export { ZEPHYR_DISPLAY_PROFILES, DEFAULT_ZEPHYR_DISPLAY_PROFILE } from './profiles.js';
|
|
18
|
+
export { ZEPHYR_DISPLAY_PROFILES, DEFAULT_ZEPHYR_DISPLAY_PROFILE, BUILT_IN_PROFILES } from './profiles.js';
|
|
19
19
|
/** Fresh display state (used by the strategy per-build). */
|
|
20
20
|
export function newDisplayState() {
|
|
21
21
|
return { initialized: false, profile: DEFAULT_ZEPHYR_DISPLAY_PROFILE };
|
|
@@ -48,3 +48,11 @@ export declare function panelControllerFor(profile: Pick<ZephyrDisplayProfile, '
|
|
|
48
48
|
export declare const ZEPHYR_DISPLAY_PROFILES: Record<string, ZephyrDisplayProfile>;
|
|
49
49
|
/** The default profile used when resolveDisplayOp is probed without a display.init. */
|
|
50
50
|
export declare const DEFAULT_ZEPHYR_DISPLAY_PROFILE: ZephyrDisplayProfile;
|
|
51
|
+
/**
|
|
52
|
+
* The Zephyr profiles mapped to the shared DisplayProfile shape — the single
|
|
53
|
+
* mapping, so no consumer needs to know the DT-binding descriptor layout.
|
|
54
|
+
* The strategy's getProfileRegistry() and the preview's profile-registry
|
|
55
|
+
* loader both consume this (the same role `BUILT_IN_PROFILES` plays in
|
|
56
|
+
* framework-arduino's displays modules).
|
|
57
|
+
*/
|
|
58
|
+
export declare const BUILT_IN_PROFILES: Record<string, import('@typecad/cuttlefish/api/shared').DisplayProfile>;
|
package/dist/display/profiles.js
CHANGED
|
@@ -69,3 +69,22 @@ export const ZEPHYR_DISPLAY_PROFILES = {
|
|
|
69
69
|
};
|
|
70
70
|
/** The default profile used when resolveDisplayOp is probed without a display.init. */
|
|
71
71
|
export const DEFAULT_ZEPHYR_DISPLAY_PROFILE = ZEPHYR_DISPLAY_PROFILES['ili9341-zephyr'];
|
|
72
|
+
/**
|
|
73
|
+
* The Zephyr profiles mapped to the shared DisplayProfile shape — the single
|
|
74
|
+
* mapping, so no consumer needs to know the DT-binding descriptor layout.
|
|
75
|
+
* The strategy's getProfileRegistry() and the preview's profile-registry
|
|
76
|
+
* loader both consume this (the same role `BUILT_IN_PROFILES` plays in
|
|
77
|
+
* framework-arduino's displays modules).
|
|
78
|
+
*/
|
|
79
|
+
export const BUILT_IN_PROFILES = Object.fromEntries(Object.entries(ZEPHYR_DISPLAY_PROFILES).map(([name, p]) => [
|
|
80
|
+
name,
|
|
81
|
+
{
|
|
82
|
+
driver: p.driver,
|
|
83
|
+
width: p.width,
|
|
84
|
+
height: p.height,
|
|
85
|
+
nativeWidth: p.nativeWidth,
|
|
86
|
+
nativeHeight: p.nativeHeight,
|
|
87
|
+
colorFormat: p.colorFormat,
|
|
88
|
+
rotation: p.rotation ?? 1,
|
|
89
|
+
},
|
|
90
|
+
]));
|
|
@@ -10,6 +10,10 @@ export interface ZephyrDisplayReadbackOptions {
|
|
|
10
10
|
scanlineSync?: boolean;
|
|
11
11
|
/** MISO/SDO GPIO; readback is disabled when it is not explicitly wired. */
|
|
12
12
|
miso?: number;
|
|
13
|
+
/** Tearing-effect GPIO (panel TE output). When set, panel updates wait for
|
|
14
|
+
* the TE frame pulse instead of GET_SCANLINE readback — no MISO required.
|
|
15
|
+
* The overlay adds te-gpios to the display DT node from this. */
|
|
16
|
+
tearingEffectPin?: number;
|
|
13
17
|
}
|
|
14
18
|
export declare function zephyrUiDisplayAdapter(profile: ZephyrDisplayProfile, readback?: ZephyrDisplayReadbackOptions): DisplayAdapterCode;
|
|
15
19
|
/**
|
|
@@ -55,6 +55,9 @@ export function zephyrUiDisplayAdapter(profile, readback = {}) {
|
|
|
55
55
|
// react badly to GSCAN reads. Both an explicit opt-in and an explicit MISO
|
|
56
56
|
// pin are required before emitting an active synchronization path.
|
|
57
57
|
const scanlineSync = readback.scanlineSync === true && readback.miso !== undefined;
|
|
58
|
+
// TE (hardware tearing-effect) sync: strictly opt-in via a configured GPIO.
|
|
59
|
+
// Preferred over GET_SCANLINE when wired — no readback traffic, no MISO.
|
|
60
|
+
const tePin = typeof readback.tearingEffectPin === 'number' ? readback.tearingEffectPin : undefined;
|
|
58
61
|
const includes = [
|
|
59
62
|
`// --- Zephyr UI display adapter (${profile.driver}) ---`,
|
|
60
63
|
`// Native CuttlefishGFX path: do NOT #define CuttlefishCanvas16 so the`,
|
|
@@ -118,6 +121,22 @@ export function zephyrUiDisplayAdapter(profile, readback = {}) {
|
|
|
118
121
|
`// controller-specific validation are required; otherwise the display stays`,
|
|
119
122
|
`// on the existing retained/composited path with no extra SPI reads.`,
|
|
120
123
|
`static const bool __tc_pnl_scanline_sync = ${scanlineSync ? 'true' : 'false'};`,
|
|
124
|
+
`// Tearing-effect (TE) hardware sync: the panel pulses its TE line once`,
|
|
125
|
+
`// per frame. When te-gpios is present on the display DT node, panel`,
|
|
126
|
+
`// updates arm on the TE edge — tear-free writes with no MISO readback.`,
|
|
127
|
+
`#if DT_NODE_HAS_PROP(DT_NODELABEL(${dtLabel}), te_gpios)`,
|
|
128
|
+
`#define __TC_TE_SYNC 1`,
|
|
129
|
+
`static const struct gpio_dt_spec __tc_te =`,
|
|
130
|
+
` GPIO_DT_SPEC_GET(DT_NODELABEL(${dtLabel}), te_gpios);`,
|
|
131
|
+
`static struct gpio_callback __tc_te_cb;`,
|
|
132
|
+
`static volatile uint32_t __tc_te_count = 0;`,
|
|
133
|
+
`static void __tc_te_isr(const struct device* port, struct gpio_callback* cb, uint32_t pins) {`,
|
|
134
|
+
` (void)port; (void)cb; (void)pins;`,
|
|
135
|
+
` __tc_te_count++;`,
|
|
136
|
+
`}`,
|
|
137
|
+
`#else`,
|
|
138
|
+
`#define __TC_TE_SYNC 0`,
|
|
139
|
+
`#endif`,
|
|
121
140
|
`// Stashed address window from the last setAddrWindow call. The runtime`,
|
|
122
141
|
`// calls setAddrWindow + writePixels as a matched pair, so we stash the rect`,
|
|
123
142
|
`// here and consume it in writePixels.`,
|
|
@@ -134,6 +153,17 @@ export function zephyrUiDisplayAdapter(profile, readback = {}) {
|
|
|
134
153
|
// with DT_HAS_ALIAS (the safe primitive for an alias that may be absent —
|
|
135
154
|
// DT_NODE_HAS_STATUS(DT_ALIAS(...)) is version-dependent when the alias is
|
|
136
155
|
// missing and can fail the build).
|
|
156
|
+
// TE pin: input + rising-edge interrupt (the ST7796 TE pulse), then tell
|
|
157
|
+
// the controller to drive the line (TEON 0x35, mode 1 = vertical sync only).
|
|
158
|
+
const teInit = tePin !== undefined ? `#if __TC_TE_SYNC
|
|
159
|
+
if (device_is_ready(__tc_te.port)) {
|
|
160
|
+
gpio_pin_configure_dt(&__tc_te, GPIO_INPUT);
|
|
161
|
+
gpio_init_callback(&__tc_te_cb, __tc_te_isr, BIT(__tc_te.pin));
|
|
162
|
+
(void)gpio_add_callback(__tc_te.port, &__tc_te_cb);
|
|
163
|
+
(void)gpio_pin_interrupt_configure_dt(&__tc_te, GPIO_INT_EDGE_RISING);
|
|
164
|
+
__tc_pnl_cmd1(0x35, 0x01); // TEON: TE output = vsync pulse
|
|
165
|
+
}
|
|
166
|
+
#endif` : '';
|
|
137
167
|
const blInit = backlightAlias
|
|
138
168
|
? `#if DT_HAS_ALIAS(${backlightAlias})\n const struct gpio_dt_spec __bl = GPIO_DT_SPEC_GET(DT_ALIAS(${backlightAlias}), gpios);\n if (device_is_ready(__bl.port)) { gpio_pin_configure_dt(&__bl, GPIO_OUTPUT_ACTIVE); }\n#endif`
|
|
139
169
|
: '';
|
|
@@ -452,6 +482,19 @@ static uint16_t __tc_pnl_read_scanline(void) {
|
|
|
452
482
|
// have no safe post-rectangle interval, so they retain the normal single-burst
|
|
453
483
|
// behavior; the caller's framebuffer still prevents intermediate software frames.
|
|
454
484
|
static void __tc_pnl_wait_for_safe_rect(int16_t y, int16_t rh) {
|
|
485
|
+
#if __TC_TE_SYNC
|
|
486
|
+
// TE variant: arm on the next frame pulse, then start the burst — the write
|
|
487
|
+
// chases the scan beam from the top of the rect. Bounded so a stuck TE line
|
|
488
|
+
// can never hang the UI loop.
|
|
489
|
+
if (rh < 8 || y < 0) return;
|
|
490
|
+
uint32_t __was = __tc_te_count;
|
|
491
|
+
uint32_t __deadline = k_uptime_get_32() + 25U;
|
|
492
|
+
while (__tc_te_count == __was) {
|
|
493
|
+
if (static_cast<int32_t>(k_uptime_get_32() - __deadline) >= 0) break;
|
|
494
|
+
k_msleep(0);
|
|
495
|
+
}
|
|
496
|
+
return;
|
|
497
|
+
#endif
|
|
455
498
|
if (!__tc_pnl_scanline_sync || rh < 8 || y < 0) return;
|
|
456
499
|
int16_t __last = static_cast<int16_t>(y + rh - 1);
|
|
457
500
|
if (__last >= static_cast<int16_t>(${h} - 2)) return;
|
|
@@ -551,8 +594,10 @@ const CuttlefishPanelOps __tc_display_ops = {
|
|
|
551
594
|
CuttlefishGFX __tc_display(&__tc_display_ops, nullptr);
|
|
552
595
|
${initBlock}
|
|
553
596
|
// ── display_init (called from setup) ────────────────────────────────────
|
|
597
|
+
|
|
554
598
|
static inline void display_init() {
|
|
555
599
|
printk("TC_DISPLAY: device ready\\n");
|
|
600
|
+
${teInit}
|
|
556
601
|
${blInit}
|
|
557
602
|
gpio_pin_configure_dt(&__tc_pnl_cs, GPIO_OUTPUT);
|
|
558
603
|
gpio_pin_configure_dt(&__tc_pnl_dc, GPIO_OUTPUT);
|
|
@@ -699,5 +744,6 @@ export const zephyrDisplayAdapterGenerator = (display) => {
|
|
|
699
744
|
return zephyrUiDisplayAdapter(profile, {
|
|
700
745
|
scanlineSync: display.scanlineSync,
|
|
701
746
|
miso: display.spiPins?.miso,
|
|
747
|
+
tearingEffectPin: display.tearingEffectPin,
|
|
702
748
|
});
|
|
703
749
|
};
|
|
@@ -10,6 +10,9 @@ export interface DisplayWiring {
|
|
|
10
10
|
cs?: number;
|
|
11
11
|
dc?: number;
|
|
12
12
|
rst?: number;
|
|
13
|
+
/** Tearing-effect (TE) GPIO from display.tearingEffectPin — emitted as
|
|
14
|
+
* te-gpios on the display DT node. Opt-in; most boards don't wire TE. */
|
|
15
|
+
tearingEffectPin?: number;
|
|
13
16
|
spiFrequency?: number;
|
|
14
17
|
/** SPI bus pins. When present, the overlay remuxes the SPI controller's
|
|
15
18
|
* pinctrl to these pins (the board defaults rarely match a breakout's
|
|
@@ -49,4 +52,8 @@ export interface TouchWiring {
|
|
|
49
52
|
* panels need a few hundred 12-bit counts; default 400. */
|
|
50
53
|
minPressure?: number;
|
|
51
54
|
}
|
|
52
|
-
export
|
|
55
|
+
export interface OverlayDiagnostic {
|
|
56
|
+
severity: "warning" | "error";
|
|
57
|
+
message: string;
|
|
58
|
+
}
|
|
59
|
+
export declare function generateOverlay(chip: ZephyrChipDescriptor, usage: KconfigUsage, display: ZephyrDisplayProfile | undefined, wiring?: DisplayWiring, touch?: TouchWiring, diagnostics?: OverlayDiagnostic[]): string;
|
|
@@ -11,7 +11,18 @@
|
|
|
11
11
|
// library headers into .d.ts; Zephyr does it by enabling DT nodes + Kconfig.)
|
|
12
12
|
// ---------------------------------------------------------------------------
|
|
13
13
|
import { PANEL_CONTROLLER_DEFAULTS, panelControllerFor } from '../display/profiles.js';
|
|
14
|
-
export function generateOverlay(chip, usage, display, wiring, touch) {
|
|
14
|
+
export function generateOverlay(chip, usage, display, wiring, touch, diagnostics = []) {
|
|
15
|
+
// An I2C touch controller with no explicit bus pins: the overlay enables
|
|
16
|
+
// i2c0 and instantiates the node, but nothing remuxes the controller to
|
|
17
|
+
// the wired SDA/SCL (the board's default I2C pins rarely match a
|
|
18
|
+
// breakout). Every I2C read then fails and touch silently does nothing —
|
|
19
|
+
// surface it at build time instead of leaving it to a multimeter.
|
|
20
|
+
if (touch && touch.controller !== 'xpt2046' && (touch.sda === undefined || touch.scl === undefined)) {
|
|
21
|
+
diagnostics.push({
|
|
22
|
+
severity: "warning",
|
|
23
|
+
message: `touch: I2C controller '${touch.controller}' has no sda/scl pins in cuttlefish.config.ts — the overlay enables the bus without a pin assignment, so the controller may never answer. Add touch.sda and touch.scl (the board's default I2C pins are rarely the wired ones).`,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
15
26
|
const lines = [
|
|
16
27
|
'/* Auto-generated by @typecad/framework-zephyr from cuttlefish.config.ts. */',
|
|
17
28
|
'/* Enables peripherals the program uses. West merges this over the board DT. */',
|
|
@@ -177,6 +188,13 @@ function emitDisplayNode(lines, display, wiring, spiTouchCs) {
|
|
|
177
188
|
lines.push(` ${display.dtLabel}: display@0 {`);
|
|
178
189
|
lines.push(` compatible = "${compatible}";`);
|
|
179
190
|
lines.push(' reg = <0>;');
|
|
191
|
+
if (wiring?.tearingEffectPin !== undefined) {
|
|
192
|
+
const tePin = wiring.tearingEffectPin;
|
|
193
|
+
// Tearing-effect input on the display node: GPIO_DT_SPEC_GET(
|
|
194
|
+
// DT_NODELABEL(display0), te_gpios) in the adapter. Opt-in —
|
|
195
|
+
// most modules don't break the TE pad out.
|
|
196
|
+
lines.push(` te-gpios = <&${gpioController(tePin)} ${tePin} GPIO_ACTIVE_HIGH>;`);
|
|
197
|
+
}
|
|
180
198
|
lines.push(` mipi-max-frequency = <${freq}>;`);
|
|
181
199
|
lines.push(' mipi-mode = "MIPI_DBI_MODE_SPI_4WIRE";');
|
|
182
200
|
// Required by the lcd-controller binding (Zephyr 4.x): 0 = RGB565,
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { ZephyrStrategy as FrameworkStrategy } from './strategy.js';
|
|
2
2
|
export { ZephyrStrategy } from './strategy.js';
|
|
3
3
|
export { Toolchain } from './toolchain/index.js';
|
|
4
|
+
export { writeProjectDebugArtifacts } from './toolchain/debug-config.js';
|
|
4
5
|
export { runDoctor as doctor } from './doctor.js';
|
|
5
6
|
export { runLicensesPresenter as licenses } from './licenses.js';
|
|
6
7
|
export { chipForTarget, setActiveChip, getActiveChip, XIAO_BLE, } from './chips/index.js';
|
package/dist/index.js
CHANGED
|
@@ -8,6 +8,11 @@
|
|
|
8
8
|
export { ZephyrStrategy as FrameworkStrategy } from './strategy.js';
|
|
9
9
|
export { ZephyrStrategy } from './strategy.js';
|
|
10
10
|
export { Toolchain } from './toolchain/index.js';
|
|
11
|
+
// Create-time starter debug artifacts. The `cuttlefish create` flow reads this
|
|
12
|
+
// optional named export off the loaded framework module (same loader pattern
|
|
13
|
+
// as doctor/licenses) and calls it for freshly scaffolded projects, so F5 in
|
|
14
|
+
// VS Code works before the first build. No-ops for non-GDB targets.
|
|
15
|
+
export { writeProjectDebugArtifacts } from './toolchain/debug-config.js';
|
|
11
16
|
// `cuttlefish doctor` — verify the installed Zephyr is reachable + inside the
|
|
12
17
|
// declared compat range, and preview board-target normalization. Re-exported
|
|
13
18
|
// under the dispatcher-facing alias `doctor` so the loader picks it up as
|
package/dist/lowering/gpio.js
CHANGED
|
@@ -113,9 +113,13 @@ function lowerGpioRaw(op, chip) {
|
|
|
113
113
|
case 'gpio.read':
|
|
114
114
|
return { expression: `gpio_pin_get_raw(${controller}, ${pin})` };
|
|
115
115
|
case 'gpio.toggle':
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
116
|
+
// Native atomic toggle — never read-modify-write. gpio_pin_get_raw on
|
|
117
|
+
// a direction-only output reads the input latch, which is undefined on
|
|
118
|
+
// SoCs that don't latch it. Zephyr's toggle API has no _raw variant —
|
|
119
|
+
// gpio_pin_toggle is the driver-level atomic toggle, and for pins
|
|
120
|
+
// configured without GPIO_ACTIVE_LOW the logical level equals the
|
|
121
|
+
// physical one, so it matches the get_raw/set_raw used elsewhere.
|
|
122
|
+
return { code: `gpio_pin_toggle(${controller}, ${pin});` };
|
|
119
123
|
default:
|
|
120
124
|
throw new Error(`framework-zephyr does not yet support HAL op \`${op.operation}\`. ` +
|
|
121
125
|
`Open an issue or use rawCpp() to emit it manually.`);
|
package/dist/strategy.d.ts
CHANGED
|
@@ -32,6 +32,26 @@ export declare class ZephyrStrategy implements PlatformStrategy {
|
|
|
32
32
|
* nodes whose resolved `raw` code references it.
|
|
33
33
|
*/
|
|
34
34
|
private programUsesAsyncRuntime;
|
|
35
|
+
/** Pins referenced by gpio.* hal-ops in the program IR. lowerGpio routes a
|
|
36
|
+
* pin to its devicetree spec by pin NUMBER, so the structured hal-op pins
|
|
37
|
+
* are the authoritative signal for which __tc_dt_* specs are needed —
|
|
38
|
+
* regardless of when the final call text is rendered. */
|
|
39
|
+
private collectGpioPinUsage;
|
|
40
|
+
/** Run `re` (global) against every raw string in the IR — raw expression
|
|
41
|
+
* values plus raw hal-op codes — returning capture group 1 of each match
|
|
42
|
+
* (the full match when the regex has no group). This is how references the
|
|
43
|
+
* text scanners must see but that never appear as IR call nodes (e.g. a
|
|
44
|
+
* rawCpp() escape hatch naming `__tc_dt_sw0` directly) are discovered. */
|
|
45
|
+
private collectRawMatches;
|
|
46
|
+
/** Whether the wiring-compat GPIO read surface (__tc_gpio_read definition,
|
|
47
|
+
* __tc_gpio_dev dispatcher, and the wiring_compat polyfill's digitalRead /
|
|
48
|
+
* HIGH / LOW macros) must be emitted. Consumers: user digitalRead() calls
|
|
49
|
+
* (usesDigitalRead), the @typecad/safety voter (calls __tc_gpio_read
|
|
50
|
+
* directly via lowered raw text), and the UI runtime header's
|
|
51
|
+
* unconditional digitalRead() poll (entryHasUI — build-global, so every TU
|
|
52
|
+
* in a UI build carries the macros). With no analysis present (capability
|
|
53
|
+
* query), default to emitting — same convention as the uses() helper. */
|
|
54
|
+
private needsGpioReadShim;
|
|
35
55
|
shimLines(program?: ProgramIR, ctx?: PlatformContext): string[];
|
|
36
56
|
profileDiagnostics(program?: ProgramIR, ctx?: PlatformContext): Diagnostic[];
|
|
37
57
|
/**
|