Context
WASM P3 (WASI 0.3) introduces stream<T>, future<T>, and async component exports. Meld currently handles P2 components (synchronous only). RFC #46 establishes that Meld lowers component model constructs to core modules at build time, with the runtime providing host intrinsics.
For P3, Meld's job expands: lower async constructs to RFC #46 host intrinsic calls.
Problem
P3 async constructs can't be resolved at build time because they represent temporal relationships (data flowing over time). But they CAN be lowered to host intrinsic calls at build time, just like Meld already lowers canonical ABI lift/lower.
Proposal
1. Lower stream<T> to host intrinsics
P3 component-level:
export process: func(input: stream<command>) -> stream<telemetry>;
Meld-lowered core module:
;; Import stream operations from host
(import "pulseengine:async" "stream_new" (func $stream_new (result i64)))
(import "pulseengine:async" "stream_read" (func $stream_read (param i32 i32 i32 i32) (result i32)))
(import "pulseengine:async" "stream_write" (func $stream_write (param i32 i32 i32 i32) (result i32)))
(import "pulseengine:async" "stream_close_readable" (func $close_r (param i32)))
(import "pulseengine:async" "stream_close_writable" (func $close_w (param i32)))
2. Lower async exports to callback trampolines
P3 callback lifting mode (preferred for embedded):
- Component exports a callback function
- Host calls callback when async event occurs
- No persistent stack per in-flight async call
- Perfect for cFS-style "process one message at a time" pattern
Meld generates:
;; Callback trampoline: called by host when stream has data
(func $__callback_trampoline (param $event_type i32) (param $payload i32)
;; Dispatch based on event type
;; EVENT_STREAM_READ=2 → call component's message handler
;; EVENT_SUBTASK=1 → call component's subtask completion handler
)
(export "__callback" (func $__callback_trampoline))
3. Generate stream adapter code for cross-component streams
When two fused components share a stream<T>:
- Same memory (single-memory mode): Direct ring buffer access, zero-copy
- Different memories (multi-memory mode): Adapter copies elements across memory boundaries via
stream_read → stream_write chain
4. Static validation at build time
Meld can verify at build time:
- Stream type compatibility (source
stream<T> matches sink stream<T>)
- Backpressure configuration (bounded channels have capacity set)
- No circular stream dependencies (would deadlock)
- Resource lifetime correctness across async boundaries
P3 Callback vs Stackful
Meld needs to support both P3 async lifting modes:
Callback mode (preferred for embedded/Gale):
- Component provides
(callback ...) canonical option
- Meld generates callback dispatch trampoline
- One shared stack per component
- Lower memory overhead
Stackful mode (for languages with native async/await):
- Component uses
task.wait/task.yield to suspend
- Meld generates calls to
thread_new/thread_switch_to intrinsics
- Each in-flight async call needs its own stack
- Higher memory overhead but more natural for Rust async, Go, Java
Connects to
- kiln#226 (cFS Software Bus as host routing — streams ARE the SB)
- kiln P3 runtime issue (host intrinsic implementations)
- Gale typed ring buffer extension
Priority
High — P3 support is the next major feature for the Component Model ecosystem.
References
Context
WASM P3 (WASI 0.3) introduces
stream<T>,future<T>, and async component exports. Meld currently handles P2 components (synchronous only). RFC #46 establishes that Meld lowers component model constructs to core modules at build time, with the runtime providing host intrinsics.For P3, Meld's job expands: lower async constructs to RFC #46 host intrinsic calls.
Problem
P3 async constructs can't be resolved at build time because they represent temporal relationships (data flowing over time). But they CAN be lowered to host intrinsic calls at build time, just like Meld already lowers canonical ABI lift/lower.
Proposal
1. Lower
stream<T>to host intrinsicsP3 component-level:
Meld-lowered core module:
2. Lower async exports to callback trampolines
P3 callback lifting mode (preferred for embedded):
Meld generates:
3. Generate stream adapter code for cross-component streams
When two fused components share a
stream<T>:stream_read→stream_writechain4. Static validation at build time
Meld can verify at build time:
stream<T>matches sinkstream<T>)P3 Callback vs Stackful
Meld needs to support both P3 async lifting modes:
Callback mode (preferred for embedded/Gale):
(callback ...)canonical optionStackful mode (for languages with native async/await):
task.wait/task.yieldto suspendthread_new/thread_switch_tointrinsicsConnects to
Priority
High — P3 support is the next major feature for the Component Model ecosystem.
References
docs/architecture/rfc46-toolchain-architecture.md