/*---------------------------------------------------------------------------
  Copyright 2026, Tim Whiting, Microsoft Research, Daan Leijen.

  This is free software; you can redistribute it and/or modify it under the
  terms of the Apache License, Version 2.0. A copy of the License can be
  found in the LICENSE file at the root of this distribution.
---------------------------------------------------------------------------*/

// Asynchronous interleavings.
//
// Various forms of interleaving for asynchronous operations.
module async/interleavestd/async/interleave

import std/time/durationstd/time/duration
import std/core/unsafestd/core/unsafe
import std/core/undivstd/core/undiv

import async/asyncasync/async
import async/channelasync/channel


/*
# Strands (interleave)

Multiple strands can be cooperatively executed, by running each in a custom
`async` handler. Instead of awaiting a result, the handler returns immediately
and the callback triggers an enqueue onto an internal channel.

Continuations are consumed from this channel until all strands have completed.

When one strand returns abnormally (e.g. exception), the entire async-scope is
canceled. This will cause any pending callbacks to be resolved with a Cancel
result.

# Interleave and cancelation

In order to control cancelation explicitly, `interleave-strands` creates a root
async-scope instead of a child async-scope to spawn operations in. No actions spawned
within this async-scope will be seen as children of the parent async-scope, preventing
automatic cancelation when a parent async-scope is canceled.

Instead, `interleave-strands` _observes_ when the parent async-scope is canceled, and
triggers cancelation on the child strands. Crucially this doesn't cancel the
interleaving bookkeeping itself, which ensures that:
 - `interleave-raw` always observes the final states of all strands, even if
   all of them are `Cancel`
 - We drive each strand to completion, including finalizers. If we simply
   abandoned the bookeeping, we'd potentially leave finalize actions sitting in
   an unconsumed channel instead of running them.
*/

// ----------------------------------------------------------------------------
// Interleaved strands of execution
// ----------------------------------------------------------------------------

// Execute `action` but if it is not finished within `secs` seconds duration
// `cancel` it (and return `Nothing`). Due to the generality of `cancel`, this `timeout`
// abstraction can reliably time out over any composition of asynchronous operations
// and is therefore quite expressive.
pub fun timeoutstd/async/interleave/timeout: forall<a,e> (secs : duration, action : () -> <async,ndet|e> a) -> <async,ndet|e> maybe<a>( secssecs: duration : durationstd/time/duration/duration: V, actionaction: () -> <async,ndet|$2564> $2563 : () -> <asyncstd/async/async/async: E,ndetstd/core/types/ndet: X|std/core/types/effect-extend: (X, E) -> Eee: E> aa: V )result: -> <async,ndet|2603> maybe<2602> : <asyncstd/async/async/async: E,ndetstd/core/types/ndet: X|std/core/types/effect-extend: (X, E) -> Eee: E> maybestd/core/types/maybe: V -> V<aa: V>
  firstofstd/async/interleave/two/firstof: (action1 : () -> <async,ndet|$2564> maybe<$2563>, action2 : () -> <async,ndet|$2564> maybe<$2563>) -> <async,ndet|$2564> maybe<$2563> { waitstd/async/async/duration/wait: (secs : ? duration) -> <async,ndet|$2564> ()(secssecs: duration); Nothingstd/core/types/Nothing: forall<a> maybe<a> } { Juststd/core/types/Just: forall<a> (value : a) -> maybe<a>(actionaction: () -> <async,ndet|$2564> $2563()) }

// Execute `a` and `b` interleaved. As soon as one of them finishes,
// `cancel` the other one and return the result of finished action.
pub fun two/firstofstd/async/interleave/two/firstof: forall<a,e> (action1 : () -> <async,ndet|e> a, action2 : () -> <async,ndet|e> a) -> <async,ndet|e> a( action1action1: () -> <async,ndet|$2525> $2524 : () -> <asyncstd/async/async/async: E,ndetstd/core/types/ndet: X|std/core/types/effect-extend: (X, E) -> Eee: E> aa: V, action2action2: () -> <async,ndet|$2525> $2524 : () -> <asyncstd/async/async/async: E,ndetstd/core/types/ndet: X|std/core/types/effect-extend: (X, E) -> Eee: E> aa: V)result: -> <async,ndet|2556> 2555 : <asyncstd/async/async/async: E,ndetstd/core/types/ndet: X|std/core/types/effect-extend: (X, E) -> Eee: E> aa: V
  list/firstof-anystd/async/interleave/list/firstof-any: (x : () -> <async,ndet|$2525> $2524, xs : list<() -> <async,ndet|$2525> $2524>) -> <async,ndet|$2525> $2524(action1action1: () -> <async,ndet|$2525> $2524,[std/core/types/Cons: forall<a> (head : a, tail : list<a>) -> list<a>action2action2: () -> <async,ndet|$2525> $2524]std/core/types/Nil: forall<a> list<a>)

// Interleave a list of actions `[x]++xs` and return the result of the first action
// that completes (and cancel all others).
// todo: we need a `:list1` type.
pub fun list/firstof-anystd/async/interleave/list/firstof-any: forall<a,e> (x : () -> <async,ndet|e> a, xs : list<() -> <async,ndet|e> a>) -> <async,ndet|e> a( xx: () -> <async,ndet|$2442> $2441 : () -> <asyncstd/async/async/async: E,ndetstd/core/types/ndet: X|std/core/types/effect-extend: (X, E) -> Eee: E> aa: V, xsxs: list<() -> <async,ndet|$2442> $2441> : liststd/core/types/list: V -> V<() -> <asyncstd/async/async/async: E,ndetstd/core/types/ndet: X|std/core/types/effect-extend: (X, E) -> Eee: E> aa: V>)result: -> <async,ndet|2517> 2516 : <asyncstd/async/async/async: E,ndetstd/core/types/ndet: X|std/core/types/effect-extend: (X, E) -> Eee: E> aa: V
  withwith: () -> <async,ndet,ndet|$2442> $2441 collapse-ndetstd/core/unsafe/collapse-ndet: (action : () -> <async,ndet,ndet|$2442> $2441) -> <async,ndet|$2442> $2441 // safe: <ndet,ndet,async|e> to <ndet,async|e>
  match Consstd/core/types/Cons: forall<a> (head : a, tail : list<a>) -> list<a>(xx: () -> <async,ndet|$2442> $2441,xsxs: list<() -> <async,ndet|$2442> $2441>).interleave-liststd/async/interleave/list/interleave-list: (xs : list<() -> <async,ndet|$2442> $2441>, needall : bool) -> <async,ndet,ndet|$2442> list<$2441>(Falsestd/core/types/False: bool)
    Consstd/core/types/Cons: forall<a> (head : a, tail : list<a>) -> list<a>(yy: $2441,_) -> yy: $2441
    Nilstd/core/types/Nil: forall<a> list<a>       -> impossiblestd/core/debug/impossible: (message : ? string, @implicit/kk-file-line : string) -> <async,ndet,ndet|$2442> $2441
?kk-file-line=debug/file/kk-file-line(debug/file/kk-file,debug/file/kk-line)
("empty result list"literal: string
count= 17
) // Interleave two actions pub fun two/interleavedstd/async/interleave/two/interleaved: forall<a,b,e> (action1 : () -> <async|e> a, action2 : () -> <async|e> b) -> <async|e> (a, b)( action1action1: () -> <async|$3511> $3509 : () -> <asyncstd/async/async/async: E|ee: E> aa: V, action2action2: () -> <async|$3511> $3510 : () -> <asyncstd/async/async/async: E|ee: E> bb: V )result: -> <async|3754> (3752, 3753) : <asyncstd/async/async/async: E|ee: E> (std/core/types/tuple2: (V, V) -> Vaa: V,bb: V) fun actionLactionL: forall<a> () -> <async|$3511> either<$3509,a>()result: -> <async|$3511> either<$3509,3526> Leftstd/core/types/Left: forall<a,b> (left : a) -> either<a,b>(action1action1: () -> <async|$3511> $3509()) fun actionRactionR: forall<a> () -> <async|$3511> either<a,$3510>()result: -> <async|$3511> either<3542,$3510> Rightstd/core/types/Right: forall<a,b> (right : b) -> either<a,b>(action2action2: () -> <async|$3511> $3510()) match list/interleavedstd/async/interleave/list/interleaved: (xs : list<() -> <async|$3511> either<$3509,$3510>>) -> <async|$3511> list<either<$3509,$3510>>([std/core/types/Cons: forall<a> (head : a, tail : list<a>) -> list<a>actionLactionL: () -> <async|$3511> either<$3509,$3510>, actionRactionR: () -> <async|$3511> either<$3509,$3510>]std/core/types/Nil: forall<a> list<a>) [Leftstd/core/types/Cons: forall<a> (head : a, tail : list<a>) -> list<a>(ll: $3509),Rightstd/core/types/Cons: forall<a> (head : a, tail : list<a>) -> list<a>(rr: $3510)]std/core/types/Nil: forall<a> list<a> -> (std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b)ll: $3509,rr: $3510)std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b) otherother: list<either<$3509,$3510>> -> impossiblestd/core/debug/impossible: (message : ? string, @implicit/kk-file-line : string) -> <async|$3511> ($3509, $3510)
?kk-file-line=debug/file/kk-file-line(debug/file/kk-file,debug/file/kk-line)
("two/interleaved returned "literal: string
count= 25
++std/core/types/(++): (x : string, y : string) -> <async|$3511> string otherother: list<either<$3509,$3510>>.lengthstd/core/list/length: (xs : list<either<$3509,$3510>>) -> <async|$3511> int.showstd/core/int/show: (i : int) -> <async|$3511> string ++std/core/types/(++): (x : string, y : string) -> <async|$3511> string " values"literal: string
count= 7
) // Interleave a list of actions. If any raises an exception, cancels, or finalizes, // propagate that and cancel all others. pub fun list/interleavedstd/async/interleave/list/interleaved: forall<a,e> (xs : list<() -> <async|e> a>) -> <async|e> list<a>(xsxs: list<() -> <async|$2611> $2610> : liststd/core/types/list: V -> V<() -> <asyncstd/async/async/async: E|ee: E> aa: V> )result: -> <async|2642> list<2641> : <asyncstd/async/async/async: E|ee: E> liststd/core/types/list: V -> V<aa: V> withwith: () -> <async,ndet|$2611> list<$2610> pretend-no-ndetstd/core/unsafe/pretend-no-ndet: (action : () -> <async,ndet|$2611> list<$2610>) -> <async|$2611> list<$2610> // remove outer ndet: if all completed with a value, the final list of values is deterministic xsxs: list<() -> <async|$2611> $2610>.interleave-liststd/async/interleave/list/interleave-list: (xs : list<() -> <async|$2611> $2610>, needall : bool) -> <async,ndet|$2611> list<$2610>(Truestd/core/types/True: bool) // Interleave a list of actions fun list/interleave-liststd/async/interleave/list/interleave-list: forall<a,e> (xs : list<() -> <async|e> a>, needall : bool) -> <async,ndet|e> list<a>(xsxs: list<() -> <async|$2402> $2401> : liststd/core/types/list: V -> V<() -> <asyncstd/async/async/async: E|ee: E> aa: V>, needallneedall: bool : boolstd/core/types/bool: V )result: -> <async,ndet|2434> list<2433> : <asyncstd/async/async/async: E,ndetstd/core/types/ndet: X|std/core/types/effect-extend: (X, E) -> Eee: E> liststd/core/types/list: V -> V<aa: V> withwith: () -> <async,ndet,strands<(int, $2401)>|$2402> () strand-liststd/async/interleave/strand-list: (needall : bool, action : () -> <async,ndet,strands<(int, $2401)>|$2402> ()) -> <async,ndet|$2402> list<$2401>(needallneedall: bool) interleave-strand-liststd/async/interleave/interleave-strand-list: (xs : list<() -> <async|$2402> $2401>, needall : bool) -> <async,ndet,strands<(int, $2401)>|$2402> ()(xsxs: list<() -> <async|$2402> $2401>,needallneedall: bool) // Interleave ordered over a producer where the next producer result is interleaved with the current result. fun interleave-lockstepstd/async/interleave/interleave-lockstep: forall<a,e> (f : () -> <async|e> a, g : (a) -> <async|e> ()) -> <async,div,ndet|e> ()( ff: () -> <async|$3423> $3422 : () -> <asyncstd/async/async/async: E|ee: E> aa: V, gg: ($3422) -> <async|$3423> () : aa: V -> <asyncstd/async/async/async: E|ee: E> (std/core/types/unit: V)std/core/types/unit: V )result: -> <async,ndet,div|3462> () : <asyncstd/async/async/async: E,ndetstd/core/types/ndet: X,divstd/core/types/div: X|std/core/types/effect-extend: (X, E) -> Eee: E> (std/core/types/unit: V)std/core/types/unit: V withwith: () -> <async,div,ndet,strands<(int, ())>|$3423> () strand-actionsstd/async/interleave/strand-actions: (needall : bool, action : () -> <async,div,ndet,strands<(int, ())>|$3423> ()) -> <async,div,ndet|$3423> ()(Truestd/core/types/True: bool) interleave-strand-lockstepstd/async/interleave/interleave-strand-lockstep: (needall : bool, f : () -> <async|$3423> $3422, g : ($3422) -> <async|$3423> (), max-interleave : ? int) -> <async,div,ndet,strands<(int, ())>|$3423> ()(Truestd/core/types/True: bool,ff: () -> <async|$3423> $3422,gg: ($3422) -> <async|$3423> ()) // ------------------------------------------------------- // Strands // ------------------------------------------------------- // A strand result is either `Canceled` (by `discontinue`), // `Finalized` (by an exception etc) with a yield context (so we can reyield), // or a `Completed` result value. type strand-resultstd/async/interleave/strand-result: V -> V<aa: V> Canceledstd/async/interleave/Canceled: forall<a> strand-result<a> Finalizedstd/async/interleave/Finalized: forall<a> (yld : yield-context) -> strand-result<a>(yld : yield-contextstd/core/hnd/yield-context: V) // exception etc. Completedstd/async/interleave/Completed: forall<a> (result : a) -> strand-result<a>(result : aa: V) fun strand-result/showstd/async/interleave/strand-result/show: forall<a,e> (self : strand-result<a>) -> e string(selfself: strand-result<$3469> : strand-resultstd/async/interleave/strand-result: V -> V<aa: V> )result: -> 3502 string : ee: E stringstd/core/types/string: V match selfself: strand-result<$3469> Canceledstd/async/interleave/Canceled: forall<a> strand-result<a> -> "Canceled"literal: string
count= 8
Finalizedstd/async/interleave/Finalized: forall<a> (yld : yield-context) -> strand-result<a> -> "Finalized(...)"literal: string
count= 14
Completedstd/async/interleave/Completed: forall<a> (result : a) -> strand-result<a> -> "Completed(...)"literal: string
count= 14
// Continue from a strand result by either returning the // completed value or reyielding the finalized effect (or `discontinue`). fun strand-continuestd/async/interleave/strand-continue: forall<a> (res : strand-result<a>) -> async a( resres: strand-result<$480> : strand-resultstd/async/interleave/strand-result: V -> V<aa: V> )result: -> async 519 : asyncstd/async/async/async: E aa: V match resres: strand-result<$480> Completedstd/async/interleave/Completed: forall<a> (result : a) -> strand-result<a>(xx: $480) -> xx: $480 Finalizedstd/async/interleave/Finalized: forall<a> (yld : yield-context) -> strand-result<a>(yldyld: yield-context) -> unsafe-reyieldstd/core/hnd/unsafe-reyield: (yield-context) -> async $480(yldyld: yield-context) Canceledstd/async/interleave/Canceled: forall<a> strand-result<a> -> discontinuestd/async/async/discontinue: () -> async $480() // Merge a strand result. Used to collect all strand results. fun strand-mergestd/async/interleave/strand-merge: forall<a,b> (result : strand-result<a>, res : strand-result<b>, needall : bool, merge : (a, b) -> a, unit : a) -> strand-result<a>( resultresult: strand-result<$524> : strand-resultstd/async/interleave/strand-result: V -> V<aa: V>, resres: strand-result<$525> : strand-resultstd/async/interleave/strand-result: V -> V<bb: V>, needallneedall: bool : boolstd/core/types/bool: V, mergemerge: ($524, $525) -> $524 : (aa: V,bb: V) -> astd/core/types/total: E, unitunit: $524 : aa: V )result: -> total strand-result<642> : strand-resultstd/async/interleave/strand-result: V -> V<aa: V> match resres: strand-result<$525> Completedstd/async/interleave/Completed: forall<a> (result : a) -> strand-result<a>(xx: $525) -> match resultresult: strand-result<$524> Completedstd/async/interleave/Completed: forall<a> (result : a) -> strand-result<a>(yy: $524) -> Completedstd/async/interleave/Completed: forall<a> (result : a) -> strand-result<a>(mergemerge: ($524, $525) -> $524(yy: $524,xx: $525)) _ -> if !std/core/types/bool/(!): (b : bool) -> boolneedallneedall: bool then Completedstd/async/interleave/Completed: forall<a> (result : a) -> strand-result<a>(mergemerge: ($524, $525) -> $524(unitunit: $524,xx: $525)) else resultresult: strand-result<$524> Finalizedstd/async/interleave/Finalized: forall<a> (yld : yield-context) -> strand-result<a>(yldyld: yield-context) -> match resultresult: strand-result<$524> Completedstd/async/interleave/Completed: forall<a> (result : a) -> strand-result<a> | needallneedall: bool -> Finalizedstd/async/interleave/Finalized: forall<a> (yld : yield-context) -> strand-result<a>(yldyld: yield-context) Canceledstd/async/interleave/Canceled: forall<a> strand-result<a> -> Finalizedstd/async/interleave/Finalized: forall<a> (yld : yield-context) -> strand-result<a>(yldyld: yield-context) // prefer exceptions over canceled _ -> resultresult: strand-result<$524> Canceledstd/async/interleave/Canceled: forall<a> strand-result<a> -> match resultresult: strand-result<$524> Completedstd/async/interleave/Completed: forall<a> (result : a) -> strand-result<a> | needallneedall: bool -> Canceledstd/async/interleave/Canceled: forall<a> strand-result<a> _ -> resultresult: strand-result<$524> // Private effect to keep track of when a strand in an interleaving is done. // Preferred over using built-in state as this works well if there is an outer handler // over the state that resumes more than once -- redoing part of the interleaving. // See `test/algeff/async5.js` effectstd/async/interleave/strands: (V, E, V) -> V strandsstd/async/interleave/strands: (V, E, V) -> V<aa: V> // Are there still strands that need to be resumed? fun strands-are-active() : boolstd/core/types/bool: V // Start a strand and return its sequence number fun strand-init() : (std/core/types/unit: V)std/core/types/unit: V // Strand is done. fun strand-done(resultresult: strand-result<$1124> : strand-resultstd/async/interleave/strand-result: V -> V<aa: V>) : (std/core/types/unit: V)std/core/types/unit: V // Run asynchronous operations with unit results fun strand-actionsstd/async/interleave/strand-actions: forall<a,e> (needall : bool, action : () -> <async,strands<a>|e> ()) -> <async|e> ()( needallneedall: bool : boolstd/core/types/bool: V, actionaction: () -> <async,strands<$2649>|$2650> () : () -> <asyncstd/async/async/async: E,strandsstd/async/interleave/strands: (V, E, V) -> V<aa: V>|std/core/types/effect-extend: (X, E) -> Eee: E> (std/core/types/unit: V)std/core/types/unit: V )result: -> <async|3063> () : <asyncstd/async/async/async: E|ee: E> (std/core/types/unit: V)std/core/types/unit: V var resultresult: local-var<$2660,strand-result<()>> : strand-resultstd/async/interleave/strand-result: V -> V<(std/core/types/unit: V)std/core/types/unit: V> := Completedstd/async/interleave/Completed: forall<a> (result : a) -> strand-result<a>((std/core/types/Unit: ())std/core/types/Unit: ()) var outstandingoutstanding: local-var<$2660,int> := 0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
withwith: () -> <async,local<$2660>,local<_3023>,strands<$2649>|$2650> () handlerhandler: (() -> <async,local<$2660>,local<_3023>,strands<$2649>|$2650> ()) -> <async,local<$2660>,local<_3023>|$2650> ()<strandsstd/async/interleave/strands: (V, E, V) -> V> returnreturn: (_2698) -> <async,local<$2660>|_2722> ()(__w-l161-c12: _2698) -> resultresult: strand-result<()>
?hdiv=iev@2711
?hdiv=iev@2991
.strand-continuestd/async/interleave/strand-continue: (res : strand-result<()>) -> <async,local<$2660>|_2722> () fun strands-are-activestrands-are-active: () -> <async,local<$2660>,local<_3023>|$2650> bool() -> outstandingoutstanding: int
?hdiv=iev@2934
>std/core/int/(>): (x : int, y : int) -> <async,local<$2660>,local<_3023>|$2650> bool 0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
fun strand-initstrand-init: () -> <async,local<$2660>,local<_3023>|$2650> ()() -> outstandingoutstanding: local-var<$2660,int> :=std/core/types/local-set: (v : local-var<$2660,int>, assigned : int) -> <async,local<$2660>,local<_3023>|$2650> () outstandingoutstanding: int
?hdiv=iev@2900
+std/core/int/(+): (x : int, y : int) -> <async,local<$2660>,local<_3023>|$2650> int 1literal: int
dec = 1
hex8 = 0x01
bit8 = 0b00000001
fun strand-donestrand-done: (res : strand-result<$2649>) -> <async,local<$2660>,local<_3023>|$2650> ()(resres: strand-result<$2649>) // trace("strand done: " ++ res.show) resultresult: local-var<$2660,strand-result<()>> :=std/core/types/local-set: (v : local-var<$2660,strand-result<()>>, assigned : strand-result<()>) -> <async,local<$2660>,local<_3023>|$2650> () resultresult: strand-result<()>
?hdiv=iev@2816
.strand-mergestd/async/interleave/strand-merge: (result : strand-result<()>, res : strand-result<$2649>, needall : bool, merge : ((), $2649) -> (), unit : ()) -> <async,local<$2660>,local<_3023>|$2650> strand-result<()>(resres: strand-result<$2649>,needallneedall: bool,fnfn: ((), $2649) -> ()(_,_) (std/core/types/Unit: ())std/core/types/Unit: (),(std/core/types/Unit: ())std/core/types/Unit: ()) outstandingoutstanding: local-var<$2660,int> :=std/core/types/local-set: (v : local-var<$2660,int>, assigned : int) -> <async,local<$2660>,local<_3023>|$2650> () outstandingoutstanding: int
?hdiv=iev@2852
-std/core/int/(-): (x : int, y : int) -> <async,local<$2660>,local<_3023>|$2650> int 1literal: int
dec = 1
hex8 = 0x01
bit8 = 0b00000001
withwith: () -> <async,local<_3023>,strands<$2649>|$2650> () mask<local_1: H> actionaction: () -> <async,strands<$2649>|$2650> ()(
) // Run an indexed async operation and return the results (in the same order) fun strand-liststd/async/interleave/strand-list: forall<a,e> (needall : bool, action : () -> <async,strands<(int, a)>|e> ()) -> <async|e> list<a>( needallneedall: bool : boolstd/core/types/bool: V, actionaction: () -> <async,strands<(int, $1336)>|$1337> () : () -> <asyncstd/async/async/async: E,strandsstd/async/interleave/strands: (V, E, V) -> V<(std/core/types/tuple2: (V, V) -> Vintstd/core/types/int: V,aa: V)>|std/core/types/effect-extend: (X, E) -> Eee: E> (std/core/types/unit: V)std/core/types/unit: V )result: -> <async|1999> list<1998> : <asyncstd/async/async/async: E|ee: E> liststd/core/types/list: V -> V<aa: V> var resultresult: local-var<$1347,strand-result<list<(int, $1336)>>> : some<aa: V> strand-resultstd/async/interleave/strand-result: V -> V<liststd/core/types/list: V -> V<(std/core/types/tuple2: (V, V) -> Vintstd/core/types/int: V,aa: V)>> := Completedstd/async/interleave/Completed: forall<a> (result : a) -> strand-result<a>([std/core/types/Nil: forall<a> list<a>]std/core/types/Nil: forall<a> list<a>) var outstandingoutstanding: local-var<$1347,int> := 0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
withwith: () -> <async,local<$1347>,local<_1959>,strands<(int, $1336)>|$1337> () handlerhandler: (() -> <async,local<$1347>,local<_1959>,strands<(int, $1336)>|$1337> ()) -> <async,local<$1347>,local<_1959>|$1337> list<$1336><strandsstd/async/interleave/strands: (V, E, V) -> V> returnreturn: (_1387) -> <async,local<$1347>|_1449> list<$1336>(__w-l176-c12: _1387) resultresult: strand-result<list<(int, $1336)>>
?hdiv=iev@1438
?hdiv=iev@1844
.strand-continuestd/async/interleave/strand-continue: (res : strand-result<list<(int, $1336)>>) -> <async,local<$1347>|_1449> list<(int, $1336)>.mapstd/core/list/map: (xs : list<(int, $1336)>, f : ((int, $1336)) -> <async,local<$1347>|_1449> $1336) -> <async,local<$1347>|_1449> list<$1336>(sndstd/core/types/tuple2/snd: (tuple2 : (int, $1336)) -> <async,local<$1347>|_1449> $1336) fun strands-are-activestrands-are-active: () -> <async,local<$1347>,local<_1959>|$1337> bool() outstandingoutstanding: int
?hdiv=iev@1749
>std/core/int/(>): (x : int, y : int) -> <async,local<$1347>,local<_1959>|$1337> bool 0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
fun strand-initstrand-init: () -> <async,local<$1347>,local<_1959>|$1337> ()() outstandingoutstanding: local-var<$1347,int> :=std/core/types/local-set: (v : local-var<$1347,int>, assigned : int) -> <async,local<$1347>,local<_1959>|$1337> () outstandingoutstanding: int
?hdiv=iev@1715
+std/core/int/(+): (x : int, y : int) -> <async,local<$1347>,local<_1959>|$1337> int 1literal: int
dec = 1
hex8 = 0x01
bit8 = 0b00000001
fun strand-donestrand-done: (res : strand-result<(int, $1336)>) -> <async,local<$1347>,local<_1959>|$1337> ()(resres: strand-result<(int, $1336)>) // trace("strand done: " ++ res.show) resultresult: local-var<$1347,strand-result<list<(int, $1336)>>> :=std/core/types/local-set: (v : local-var<$1347,strand-result<list<(int, $1336)>>>, assigned : strand-result<list<(int, $1336)>>) -> <async,local<$1347>,local<_1959>|$1337> () resultresult: strand-result<list<(int, $1336)>>
?hdiv=iev@1626
.strand-mergestd/async/interleave/strand-merge: (result : strand-result<list<(int, $1336)>>, res : strand-result<(int, $1336)>, needall : bool, merge : (list<(int, $1336)>, (int, $1336)) -> list<(int, $1336)>, unit : list<(int, $1336)>) -> <async,local<$1347>,local<_1959>|$1337> strand-result<list<(int, $1336)>>(resres: strand-result<(int, $1336)>,needallneedall: bool,ordered-insertstd/async/interleave/ordered-insert: (xs : list<(int, $1336)>, y : (int, $1336)) -> list<(int, $1336)>,[std/core/types/Nil: forall<a> list<a>]std/core/types/Nil: forall<a> list<a>) outstandingoutstanding: local-var<$1347,int> :=std/core/types/local-set: (v : local-var<$1347,int>, assigned : int) -> <async,local<$1347>,local<_1959>|$1337> () outstandingoutstanding: int
?hdiv=iev@1667
-std/core/int/(-): (x : int, y : int) -> <async,local<$1347>,local<_1959>|$1337> int 1literal: int
dec = 1
hex8 = 0x01
bit8 = 0b00000001
withwith: () -> <async,local<_1959>,strands<(int, $1336)>|$1337> () mask<local_1: H> actionaction: () -> <async,strands<(int, $1336)>|$1337> ()(
) // Insert in order tail fun ordered-insertstd/async/interleave/ordered-insert: forall<a> (xs : list<(int, a)>, y : (int, a)) -> list<(int, a)>( xsxs: list<(int, $1182)> : liststd/core/types/list: V -> V<(std/core/types/tuple2: (V, V) -> Vintstd/core/types/int: V,aa: V)>, yy: (int, $1182) : (std/core/types/tuple2: (V, V) -> Vintstd/core/types/int: V,aa: V) )result: -> total list<(int, 1331)> : liststd/core/types/list: V -> V<(std/core/types/tuple2: (V, V) -> Vintstd/core/types/int: V,aa: V)> match xsxs: list<(int, $1182)> Consstd/core/types/Cons: forall<a> (head : a, tail : list<a>) -> list<a>(xx: (int, $1182),xxxx: list<(int, $1182)>) | xx: (int, $1182).fststd/core/types/tuple2/fst: (tuple2 : (int, $1182)) -> int <std/core/int/(<): (x : int, y : int) -> bool yy: (int, $1182).fststd/core/types/tuple2/fst: (tuple2 : (int, $1182)) -> int -> Consstd/core/types/Cons: forall<a> (head : a, tail : list<a>) -> list<a>(xx: (int, $1182), ordered-insertstd/async/interleave/ordered-insert: (xs : list<(int, $1182)>, y : (int, $1182)) -> list<(int, $1182)>(xxxx: list<(int, $1182)>,yy: (int, $1182))) _ -> Consstd/core/types/Cons: forall<a> (head : a, tail : list<a>) -> list<a>(yy: (int, $1182),xsxs: list<(int, $1182)>) // ------------------------------------------------------- // Interleaving primitives // ------------------------------------------------------- // Interleave a fixed number of asychronous actions fun interleave-strand-liststd/async/interleave/interleave-strand-list: forall<a,e> (xs : list<() -> <async|e> a>, needall : bool) -> <async,ndet,strands<(int, a)>|e> ()(xsxs: list<() -> <async|$2337> $2336> : liststd/core/types/list: V -> V<() -> <asyncstd/async/async/async: E|ee: E> aa: V>, needallneedall: bool : boolstd/core/types/bool: V )result: -> <async,ndet,strands<(int, 2393)>|2394> () : <asyncstd/async/async/async: E,ndetstd/core/types/ndet: X,strandsstd/async/interleave/strands: (V, E, V) -> V<(std/core/types/tuple2: (V, V) -> Vintstd/core/types/int: V,aa: V)> |std/core/types/effect-extend: (X, E) -> Eee: E> (std/core/types/unit: V)std/core/types/unit: V // we issed a fixed number of interleave's and thus always terminate (for the outer `:div`) withwith: () -> <async,div,ndet,strands<(int, $2336)>|$2337> () pretend-no-divstd/core/undiv/pretend-no-div: (action : () -> <async,div,ndet,strands<(int, $2336)>|$2337> ()) -> <async,ndet,strands<(int, $2336)>|$2337> () interleave-strandsstd/async/interleave/interleave-strands: (needall : bool, setup : (ileave : (action : () -> <async|$2337> (int, $2336)) -> <async,div,ndet,strands<(int, $2336)>|$2337> ()) -> <async,div,ndet,strands<(int, $2336)>|$2337> ()) -> <async,div,ndet,strands<(int, $2336)>|$2337> ()(needallneedall: bool) fnfn: (interleave : (action : () -> <async|$2337> (int, $2336)) -> <async,div,ndet,strands<(int, $2336)>|$2337> ()) -> <async,div,ndet,strands<(int, $2336)>|$2337> ()(interleaveinterleave: (action : () -> <async|$2337> (int, $2336)) -> <async,div,ndet,strands<(int, $2336)>|$2337> ()) xsxs: list<() -> <async|$2337> $2336>.list/foreach-indexedstd/core/list/foreach-indexed: (xs : list<() -> <async|$2337> $2336>, action : (int, () -> <async|$2337> $2336) -> <async,div,ndet,strands<(int, $2336)>|$2337> ()) -> <async,div,ndet,strands<(int, $2336)>|$2337> () fnfn: (i : int, action : () -> <async|$2337> $2336) -> <async,div,ndet,strands<(int, $2336)>|$2337> ()(ii: int,actionaction: () -> <async|$2337> $2336) interleaveinterleave: (action : () -> <async|$2337> (int, $2336)) -> <async,div,ndet,strands<(int, $2336)>|$2337> () (std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b)ii: int,actionaction: () -> <async|$2337> $2336())std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b) // Interleave _dynamically_ over a producer channel `ch` with an asynchronous consumer function `f`. // Results are indexed but may be produced out of order. fun interleave-strand-channelstd/async/interleave/interleave-strand-channel: forall<a,b,e> (needall : bool, max-interleave : ? int, ch : channel<a>, f : (a) -> <async|e> b) -> <async,div,ndet,strands<(int, b)>|e> ()(needallneedall: bool : boolstd/core/types/bool: V, max-interleavemax-interleave: ? int : intstd/core/types/int: V = 1000literal: int
dec = 1000
hex16= 0x03E8
bit16= 0b0000001111101000
, chch: channel<$4250> : channelstd/async/channel/channel: V -> V<aa: V>, ff: ($4250) -> <async|$4252> $4251 : aa: V -> <asyncstd/async/async/async: E|ee: E> bb: V )result: -> <async,ndet,div,strands<(int, 4327)>|4328> () : <asyncstd/async/async/async: E,ndetstd/core/types/ndet: X,divstd/core/types/div: X,strandsstd/async/interleave/strands: (V, E, V) -> V<(std/core/types/tuple2: (V, V) -> Vintstd/core/types/int: V,bb: V)>|std/core/types/effect-extend: (X, E) -> Eee: E> (std/core/types/unit: V)std/core/types/unit: V withwith: () -> <async,div,ndet,ndet,strands<(int, $4251)>|$4252> () collapse-ndetstd/core/unsafe/collapse-ndet: (action : () -> <async,div,ndet,ndet,strands<(int, $4251)>|$4252> ()) -> <async,div,ndet,strands<(int, $4251)>|$4252> () interleave-strand-composestd/async/interleave/interleave-strand-compose: (needall : bool, f : () -> <async,ndet|$4252> $4250, g : ($4250) -> <async,ndet|$4252> $4251, max-interleave : ? int) -> <async,div,ndet,ndet,strands<(int, $4251)>|$4252> ()(needallneedall: bool, { chch: channel<$4250>.receivestd/async/channel/receive: (ch : channel<$4250>) -> <async,ndet|$4252> $4250() }, fnfn: (x : $4250) -> <async,ndet|$4252> $4251(xx: $4250) withwith: () -> <async|$4252> $4251 mask<ndetstd/core/types/ndet: X> in ff: ($4250) -> <async|$4252> $4251(xx: $4250), max-interleavemax-interleave: int
) // TODO: make an `interleave-strand-channels` (or compose) that receives from one channel but then // emits on another channel _in order_ while still being somewhat concurrent (up to some N) by starting // processing on other elements but such that they won't emit out of order. // Interleave _dynamically_ over an asynchronous producer function `f` with an asynchronous consumer function `g`. // Results are indexed but may be produced out of order. fun interleave-strand-composestd/async/interleave/interleave-strand-compose: forall<a,b,e> (needall : bool, f : () -> <async|e> a, g : (a) -> <async|e> b, max-interleave : ? int) -> <async,div,ndet,strands<(int, b)>|e> ()(needallneedall: bool : boolstd/core/types/bool: V, ff: () -> <async|$3802> $3800 : () -> <asyncstd/async/async/async: E|ee: E> aa: V, gg: ($3800) -> <async|$3802> $3801 : aa: V -> <asyncstd/async/async/async: E|ee: E> bb: V, max-interleavemax-interleave: ? int : intstd/core/types/int: V = 1000literal: int
dec = 1000
hex16= 0x03E8
bit16= 0b0000001111101000
)result: -> <async,ndet,div,strands<(int, 4239)>|4240> () : <asyncstd/async/async/async: E,ndetstd/core/types/ndet: X,divstd/core/types/div: X,strandsstd/async/interleave/strands: (V, E, V) -> V<(std/core/types/tuple2: (V, V) -> Vintstd/core/types/int: V,bb: V)>|std/core/types/effect-extend: (X, E) -> Eee: E> (std/core/types/unit: V)std/core/types/unit: V var interleave-countinterleave-count: local-var<$3816,int> := 0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
var indexindex: local-var<$3816,int> := 0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
interleave-strands-exstd/async/interleave/interleave-strands-ex: (needall : bool, setup : (interleave : (action : () -> <async,div,local<$3816>,ndet,strands<(int, $3801)>|$3802> (int, $3801)) -> <async,div,local<$3816>,ndet,strands<(int, $3801)>|$3802> ()) -> <async,div,local<$3816>,ndet,strands<(int, $3801)>|$3802> ()) -> <async,div,local<$3816>,ndet,strands<(int, $3801)>|$3802> ()(needallneedall: bool) fnfn: (interleave : (action : () -> <async,div,local<$3816>,ndet,strands<(int, $3801)>|$3802> (int, $3801)) -> <async,div,local<$3816>,ndet,strands<(int, $3801)>|$3802> ()) -> <async,div,local<$3816>,ndet,strands<(int, $3801)>|$3802> ()(interleaveinterleave: (action : () -> <async,div,local<$3816>,ndet,strands<(int, $3801)>|$3802> (int, $3801)) -> <async,div,local<$3816>,ndet,strands<(int, $3801)>|$3802> ()) interleaveinterleave: (action : () -> <async,div,local<$3816>,ndet,strands<(int, $3801)>|$3802> (int, $3801)) -> <async,div,local<$3816>,ndet,strands<(int, $3801)>|$3802> () fun looploop: forall<a> () -> <async,div,local<$3816>,ndet,strands<(int, $3801)>|$3802> a()result: -> <async-await,async-cancel,async-ioc,discontinue,div,local<$3816>,ndet,strands<(int, $3801)>|$3802> _3859 val ii: int = indexindex: int
?hdiv=iev@3863
indexindex: local-var<$3816,int> :=std/core/types/local-set: (v : local-var<$3816,int>, assigned : int) -> <async,div,local<$3816>,ndet,strands<(int, $3801)>|$3802> () ii: int +std/core/int/(+): (x : int, y : int) -> <async,div,local<$3816>,ndet,strands<(int, $3801)>|$3802> int 1literal: int
dec = 1
hex8 = 0x01
bit8 = 0b00000001
val xx: $3800 = withwith: () -> <async,local<$3816>|$3802> $3800 mask<strands_1: V,ndetstd/core/types/ndet: X,divstd/core/types/div: X> in ff: () -> <async|$3802> $3800() if interleave-countinterleave-count: int
?hdiv=iev@3944
<std/core/int/(<): (x : int, y : int) -> <async,div,local<$3816>,ndet,strands<(int, $3801)>|$3802> bool max-interleavemax-interleave: int then // interleave the call to g interleave-countinterleave-count: local-var<$3816,int> :=std/core/types/local-set: (v : local-var<$3816,int>, assigned : int) -> <async,div,local<$3816>,ndet,strands<(int, $3801)>|$3802> () interleave-countinterleave-count: int
?hdiv=iev@4010
+std/core/int/(+): (x : int, y : int) -> <async,div,local<$3816>,ndet,strands<(int, $3801)>|$3802> int 1literal: int
dec = 1
hex8 = 0x01
bit8 = 0b00000001
interleaveinterleave: (action : () -> <async,div,local<$3816>,ndet,strands<(int, $3801)>|$3802> (int, $3801)) -> <async,div,local<$3816>,ndet,strands<(int, $3801)>|$3802> () withwith: () -> <async,div,local<$3816>,ndet,strands<(int, $3801)>|$3802> (int, $3801) finallystd/core/hnd/finally: (fin : () -> <async,div,local<$3816>,ndet,strands<(int, $3801)>|$3802> (), action : () -> <async,div,local<$3816>,ndet,strands<(int, $3801)>|$3802> (int, $3801)) -> <async,div,local<$3816>,ndet,strands<(int, $3801)>|$3802> (int, $3801) interleave-countinterleave-count: local-var<$3816,int> :=std/core/types/local-set: (v : local-var<$3816,int>, assigned : int) -> <async,div,local<$3816>,ndet,strands<(int, $3801)>|$3802> () interleave-countinterleave-count: int
?hdiv=iev@4051
-std/core/int/(-): (x : int, y : int) -> <async,div,local<$3816>,ndet,strands<(int, $3801)>|$3802> int 1literal: int
dec = 1
hex8 = 0x01
bit8 = 0b00000001
withwith: () -> <async,local<$3816>|$3802> (int, $3801) mask<strands_1: V,ndetstd/core/types/ndet: X,divstd/core/types/div: X> in (std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b)ii: int,gg: ($3800) -> <async|$3802> $3801(xx: $3800))std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b) looploop: () -> <async,div,local<$3816>,ndet,strands<(int, $3801)>|$3802> _3859() else // stop interleaving if too many interleavings withwith: () -> <async,local<$3816>|$3802> (int, $3801) mask<strands_1: V,ndetstd/core/types/ndet: X,divstd/core/types/div: X> in (std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b)ii: int,gg: ($3800) -> <async|$3802> $3801(xx: $3800))std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b) looploop: () -> <async,div,local<$3816>,ndet,strands<(int, $3801)>|$3802> _3859(
) looploop: () -> <async,div,local<$3816>,ndet,strands<(int, $3801)>|$3802> (int, $3801)(
) // Interleave _dynamically_ over an asynchronous producer function `f` with an asynchronous consumer function `g`. // Results are indexed and produced in-order where the next `f` request is interleaved with `g` (on the current result) fun interleave-strand-lockstepstd/async/interleave/interleave-strand-lockstep: forall<a,b,e> (needall : bool, f : () -> <async|e> a, g : (a) -> <async|e> b, max-interleave : ? int) -> <async,div,ndet,strands<(int, b)>|e> ()(needallneedall: bool : boolstd/core/types/bool: V, ff: () -> <async|$3072> $3070 : () -> <asyncstd/async/async/async: E|ee: E> aa: V, gg: ($3070) -> <async|$3072> $3071 : aa: V -> <asyncstd/async/async/async: E|ee: E> bb: V, max-interleavemax-interleave: ? int : intstd/core/types/int: V = 1000literal: int
dec = 1000
hex16= 0x03E8
bit16= 0b0000001111101000
)result: -> <async,ndet,div,strands<(int, 3411)>|3412> () : <asyncstd/async/async/async: E,ndetstd/core/types/ndet: X,divstd/core/types/div: X,strandsstd/async/interleave/strands: (V, E, V) -> V<(std/core/types/tuple2: (V, V) -> Vintstd/core/types/int: V,bb: V)>|std/core/types/effect-extend: (X, E) -> Eee: E> (std/core/types/unit: V)std/core/types/unit: V var interleave-countinterleave-count: local-var<$3086,int> := 0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
var indexindex: local-var<$3086,int> := 0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
interleave-strands-exstd/async/interleave/interleave-strands-ex: (needall : bool, setup : (interleave : (action : () -> <async,div,local<$3086>,ndet,strands<(int, $3071)>|$3072> (int, $3071)) -> <async,div,local<$3086>,ndet,strands<(int, $3071)>|$3072> ()) -> <async,div,local<$3086>,ndet,strands<(int, $3071)>|$3072> ()) -> <async,div,local<$3086>,ndet,strands<(int, $3071)>|$3072> ()(needallneedall: bool) fnfn: (interleave : (action : () -> <async,div,local<$3086>,ndet,strands<(int, $3071)>|$3072> (int, $3071)) -> <async,div,local<$3086>,ndet,strands<(int, $3071)>|$3072> ()) -> <async,div,local<$3086>,ndet,strands<(int, $3071)>|$3072> ()(interleaveinterleave: (action : () -> <async,div,local<$3086>,ndet,strands<(int, $3071)>|$3072> (int, $3071)) -> <async,div,local<$3086>,ndet,strands<(int, $3071)>|$3072> ()) interleaveinterleave: (action : () -> <async,div,local<$3086>,ndet,strands<(int, $3071)>|$3072> (int, $3071)) -> <async,div,local<$3086>,ndet,strands<(int, $3071)>|$3072> () fun looploop: forall<a> (x : $3070) -> <async,div,local<$3086>,ndet,strands<(int, $3071)>|$3072> a(xx: $3070)result: -> <div,ndet,strands<(int, $3071)>,async-await,async-cancel,async-ioc,discontinue,local<$3086>|$3072> _3130 val ii: int = indexindex: int
?hdiv=iev@3134
indexindex: local-var<$3086,int> :=std/core/types/local-set: (v : local-var<$3086,int>, assigned : int) -> <async,div,local<$3086>,ndet,strands<(int, $3071)>|$3072> () ii: int +std/core/int/(+): (x : int, y : int) -> <async,div,local<$3086>,ndet,strands<(int, $3071)>|$3072> int 1literal: int
dec = 1
hex8 = 0x01
bit8 = 0b00000001
interleaveinterleave: (action : () -> <async,div,local<$3086>,ndet,strands<(int, $3071)>|$3072> (int, $3071)) -> <async,div,local<$3086>,ndet,strands<(int, $3071)>|$3072> () withwith: () -> <async,div,local<$3086>,ndet,strands<(int, $3071)>|$3072> (int, $3071) finallystd/core/hnd/finally: (fin : () -> <async,div,local<$3086>,ndet,strands<(int, $3071)>|$3072> (), action : () -> <async,div,local<$3086>,ndet,strands<(int, $3071)>|$3072> (int, $3071)) -> <async,div,local<$3086>,ndet,strands<(int, $3071)>|$3072> (int, $3071) interleave-countinterleave-count: local-var<$3086,int> :=std/core/types/local-set: (v : local-var<$3086,int>, assigned : int) -> <async,div,local<$3086>,ndet,strands<(int, $3071)>|$3072> () interleave-countinterleave-count: int
?hdiv=iev@3192
-std/core/int/(-): (x : int, y : int) -> <async,div,local<$3086>,ndet,strands<(int, $3071)>|$3072> int 1literal: int
dec = 1
hex8 = 0x01
bit8 = 0b00000001
withwith: () -> <async,local<$3086>|$3072> (int, $3071) mask<strands_1: V,ndetstd/core/types/ndet: X,divstd/core/types/div: X> in (std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b)ii: int,gg: ($3070) -> <async|$3072> $3071(xx: $3070))std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b) val yy: $3070 = withwith: () -> <async,local<$3086>|$3072> $3070 mask<strands_1: V,ndetstd/core/types/ndet: X,divstd/core/types/div: X> in ff: () -> <async|$3072> $3070() looploop: (x : $3070) -> <async,div,local<$3086>,ndet,strands<(int, $3071)>|$3072> _3130(yy: $3070
) val xx: $3070 = withwith: () -> <async,local<$3086>|$3072> $3070 mask<strands_1: V,ndetstd/core/types/ndet: X,divstd/core/types/div: X> in ff: () -> <async|$3072> $3070() looploop: (x : $3070) -> <async,div,local<$3086>,ndet,strands<(int, $3071)>|$3072> (int, $3071)(xx: $3070
) // ------------------------------------------------------- // Primitive interleave strands // ------------------------------------------------------- alias async-exstd/async/interleave/async-ex: V -> E<aa: V> = <std/core/types/total: Easyncstd/async/async/async: E,divstd/core/types/div: X,ndetstd/core/types/ndet: X,strandsstd/async/interleave/strands: (V, E, V) -> V<aa: V>> // Interleave strands but hide the internal effects from `action`. fun interleave-strandsstd/async/interleave/interleave-strands: forall<a,e> (needall : bool, setup : (ileave : (action : () -> <async|e> a) -> <async,div,ndet,strands<a>|e> ()) -> <async,div,ndet,strands<a>|e> ()) -> <async,div,ndet,strands<a>|e> ()( needallneedall: bool : boolstd/core/types/bool: V, setupsetup: (ileave : (action : () -> <async|$2270> $2269) -> <async,div,ndet,strands<$2269>|$2270> ()) -> <async,div,ndet,strands<$2269>|$2270> () : (ileave : (action : () -> <asyncstd/async/async/async: E|ee: E> aa: V ) -> <async-exstd/async/interleave/async-ex: V -> E<aa: V>|ee: E> (std/core/types/unit: V)std/core/types/unit: V) -> <async-exstd/async/interleave/async-ex: V -> E<aa: V>|ee: E> (std/core/types/unit: V)std/core/types/unit: V )result: -> <async-ex<2328>|2329> () : <async-exstd/async/interleave/async-ex: V -> E<aa: V>|ee: E> (std/core/types/unit: V)std/core/types/unit: V interleave-strands-exstd/async/interleave/interleave-strands-ex: (needall : bool, setup : (interleave : (action : () -> <async,div,ndet,strands<$2269>|$2270> $2269) -> <async,div,ndet,strands<$2269>|$2270> ()) -> <async,div,ndet,strands<$2269>|$2270> ()) -> <async,div,ndet,strands<$2269>|$2270> ()(needallneedall: bool) fnfn: (interleave : (action : () -> <async,div,ndet,strands<$2269>|$2270> $2269) -> <async,div,ndet,strands<$2269>|$2270> ()) -> <async,div,ndet,strands<$2269>|$2270> ()(interleaveinterleave: (action : () -> <async,div,ndet,strands<$2269>|$2270> $2269) -> <async,div,ndet,strands<$2269>|$2270> ()) setupsetup: (ileave : (action : () -> <async|$2270> $2269) -> <async,div,ndet,strands<$2269>|$2270> ()) -> <async,div,ndet,strands<$2269>|$2270> () fnfn: (action : () -> <async|$2270> $2269) -> <async,div,ndet,strands<$2269>|$2270> ()(actionaction: () -> <async|$2270> $2269) interleaveinterleave: (action : () -> <async,div,ndet,strands<$2269>|$2270> $2269) -> <async,div,ndet,strands<$2269>|$2270> () withwith: () -> <async|$2270> $2269 mask<strands_1: V,ndetstd/core/types/ndet: X,divstd/core/types/div: X> in actionaction: () -> <async|$2270> $2269() // Call a `setup` function with an `interleave` function that will interleave a given `action` // by emitting any async resumption on a channel. We then receive these resumptions // on the channel and resume them as long as the strands are active. // This is more complex than using multi-shot resumptions directly, but now we can // implement interleaving using only single-shot resumptions (which we need for example when targeting native WASM stacks). fun interleave-strands-exstd/async/interleave/interleave-strands-ex: forall<a,e> (needall : bool, setup : (interleave : (action : () -> <async,div,ndet,strands<a>|e> a) -> <async,div,ndet,strands<a>|e> ()) -> <async,div,ndet,strands<a>|e> ()) -> <async,div,ndet,strands<a>|e> ()( needallneedall: bool : boolstd/core/types/bool: V, setupsetup: (interleave : (action : () -> <async,div,ndet,strands<$2185>|$2186> $2185) -> <async,div,ndet,strands<$2185>|$2186> ()) -> <async,div,ndet,strands<$2185>|$2186> () : (interleave : (action : () -> <async-exstd/async/interleave/async-ex: V -> E<aa: V>|ee: E> aa: V ) -> <async-exstd/async/interleave/async-ex: V -> E<aa: V>|ee: E> (std/core/types/unit: V)std/core/types/unit: V) -> <async-exstd/async/interleave/async-ex: V -> E<aa: V>|ee: E> (std/core/types/unit: V)std/core/types/unit: V )result: -> <async-ex<2261>|2262> () : <async-exstd/async/interleave/async-ex: V -> E<aa: V>|ee: E> (std/core/types/unit: V)std/core/types/unit: V val chch: channel<() -> <async,div,ndet,strands<$2185>|$2186> ()> : channelstd/async/channel/channel: V -> V<() -> <asyncstd/async/async/async: E|__w-l281-c33: E> (std/core/types/unit: V)std/core/types/unit: V> = channelstd/async/channel/channel: () -> <async,div,ndet,strands<$2185>|$2186> channel<() -> <async,div,ndet,strands<$2185>|$2186> ()>() // channel of resumptions val (std/core/types/Unit: ())std/core/types/Unit: () = withwith: () -> <async,div,ndet,strands<$2185>|$2186> () cancelation-scopestd/async/async/cancelation-scope: (action : () -> <async,div,ndet,strands<$2185>|$2186> ()) -> <async,div,ndet,strands<$2185>|$2186> () // limit cancelation to our interleaving setupsetup: (interleave : (action : () -> <async,div,ndet,strands<$2185>|$2186> $2185) -> <async,div,ndet,strands<$2185>|$2186> ()) -> <async,div,ndet,strands<$2185>|$2186> () fnfn: (action : () -> <async,div,ndet,strands<$2185>|$2186> $2185) -> <async,div,ndet,strands<$2185>|$2186> ()(actionaction: () -> <async,div,ndet,strands<$2185>|$2186> $2185) // setup interleaved operations interleave-strandstd/async/interleave/interleave-strand: (needall : bool, ch : channel<() -> <async,div,ndet,strands<$2185>|$2186> ()>, action : () -> <async,div,ndet,strands<$2185>|$2186> $2185) -> <async,div,ndet,strands<$2185>|$2186> ()(needallneedall: bool,chch: channel<() -> <async,div,ndet,strands<$2185>|$2186> ()>,actionaction: () -> <async,div,ndet,strands<$2185>|$2186> $2185) // interleave on our channel whilestd/core/while: (predicate : () -> <async,div,ndet,strands<$2185>|$2186> bool, action : () -> <async,div,ndet,strands<$2185>|$2186> ()) -> <async,div,ndet,strands<$2185>|$2186> (){ strands-are-activestd/async/interleave/strands-are-active: () -> <async,div,ndet,strands<$2185>|$2186> bool() } chch: channel<() -> <async,div,ndet,strands<$2185>|$2186> ()>.receivestd/async/channel/receive: (ch : channel<() -> <async,div,ndet,strands<$2185>|$2186> ()>) -> <async,div,ndet,strands<$2185>|$2186> (() -> <async,div,ndet,strands<$2185>|$2186> ())().() // receive and resume (note: this receive must be outside the cancelation scope) // Interleave an action such that all async operations are captured and emit a resumption on the given channel. fun interleave-strandstd/async/interleave/interleave-strand: forall<a,e> (needall : bool, ch : channel<() -> <async,strands<a>|e> ()>, action : () -> <async,strands<a>|e> a) -> <async,strands<a>|e> ()(needallneedall: bool : boolstd/core/types/bool: V, chch: channel<() -> <async,strands<$2006>|$2007> ()> : channelstd/async/channel/channel: V -> V<() -> <asyncstd/async/async/async: E,strandsstd/async/interleave/strands: (V, E, V) -> V<aa: V>|std/core/types/effect-extend: (X, E) -> Eee: E> (std/core/types/unit: V)std/core/types/unit: V>, actionaction: () -> <async,strands<$2006>|$2007> $2006 : () -> <asyncstd/async/async/async: E,strandsstd/async/interleave/strands: (V, E, V) -> V<aa: V>|std/core/types/effect-extend: (X, E) -> Eee: E> aa: V )result: -> <async,strands<2177>|2178> () : <asyncstd/async/async/async: E,strandsstd/async/interleave/strands: (V, E, V) -> V<aa: V>|std/core/types/effect-extend: (X, E) -> Eee: E> (std/core/types/unit: V)std/core/types/unit: V strand-initstd/async/interleave/strand-init: () -> <async,strands<$2006>|$2007> ()() // always initialize to keep outstanding count if is-canceledstd/async/async/is-canceled: () -> <async,strands<$2006>|$2007> bool() then strand-donestd/async/interleave/strand-done: (result : strand-result<$2006>) -> <async,strands<$2006>|$2007> ()(Canceledstd/async/interleave/Canceled: forall<a> strand-result<a>) // don't start any new interleavings once the scope is canceled else withwith: () -> <async,strands<$2006>|$2007> () emit-on-awaitstd/async/channel/emit-on-await: (ch : channel<() -> <async,strands<$2006>|$2007> ()>, action : () -> <async,strands<$2006>|$2007> ()) -> <async,strands<$2006>|$2007> ()(chch: channel<() -> <async,strands<$2006>|$2007> ()>) // redirect async calls to emit resumptions on the channel (and return () instead of waiting) val resres: either<yield-context,maybe<$2006>> = withwith: () -> <async,strands<$2006>|$2007> maybe<$2006> unsafe-unfinalizestd/core/hnd/unsafe-unfinalize: (action : () -> <async,strands<$2006>|$2007> maybe<$2006>) -> <async,strands<$2006>|$2007> either<yield-context,maybe<$2006>> // catches any final ctl (exceptions) withwith: () -> <async,strands<$2006>|$2007> $2006 unsafe-uncancelstd/async/async/unsafe-uncancel: (action : () -> <async,strands<$2006>|$2007> $2006) -> <async,strands<$2006>|$2007> maybe<$2006> // catches any discontinue() (so we can prefer exceptions over cancelations) actionaction: () -> <async,strands<$2006>|$2007> $2006() match resres: either<yield-context,maybe<$2006>> Rightstd/core/types/Right: forall<a,b> (right : b) -> either<a,b>(Juststd/core/types/Just: forall<a> (value : a) -> maybe<a>(xx: $2006)) -> { strand-donestd/async/interleave/strand-done: (result : strand-result<$2006>) -> <async,strands<$2006>|$2007> ()(Completedstd/async/interleave/Completed: forall<a> (result : a) -> strand-result<a>(xx: $2006)); if !std/core/types/bool/(!): (b : bool) -> <async,strands<$2006>|$2007> boolneedallneedall: bool then cancel-outstandingstd/async/async/cancel-outstanding: () -> <async,strands<$2006>|$2007> ()()std/core/types/Unit: () } Rightstd/core/types/Right: forall<a,b> (right : b) -> either<a,b>(Nothingstd/core/types/Nothing: forall<a> maybe<a>) -> { strand-donestd/async/interleave/strand-done: (result : strand-result<$2006>) -> <async,strands<$2006>|$2007> ()(Canceledstd/async/interleave/Canceled: forall<a> strand-result<a>) } Leftstd/core/types/Left: forall<a,b> (left : a) -> either<a,b>(yldyld: yield-context) -> { strand-donestd/async/interleave/strand-done: (result : strand-result<$2006>) -> <async,strands<$2006>|$2007> ()(Finalizedstd/async/interleave/Finalized: forall<a> (yld : yield-context) -> strand-result<a>(yldyld: yield-context)); if needallneedall: bool then cancel-outstandingstd/async/async/cancel-outstanding: () -> <async,strands<$2006>|$2007> ()()std/core/types/Unit: () }