/*---------------------------------------------------------------------------
  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.
---------------------------------------------------------------------------*/

module async/promisestd/async/promise

import async/internalasync/internal      // async-ioc
import async/asyncasync/async

// ----------------------------------------------------------------------------
// Promises 
// ----------------------------------------------------------------------------

// A _promise_ that carries a value of type `:a`. A promise is initially empty
// but can be `await`ed  asynchronously until it gets `resolve`d unblocking any
// `await` operations. After that a promise stays resolved and any `await` will
// return immediately. It is an error to try to resolve a promise more than once.
abstract struct promisestd/async/promise/promise: V -> V<aa: V>
  statestd/async/promise/promise/state: forall<a> (promise : promise<a>) -> ref<global,promise-state<a>> : refstd/core/types/ref: (H, V) -> V<globalstd/core/types/global: H,promise-statestd/async/promise/promise-state: V -> V<aa: V>>

type promise-statestd/async/promise/promise-state: V -> V<aa: V>
  Resolvedstd/async/promise/Resolved: forall<a> (value : a) -> promise-state<a>( value : aa: V )
  Awaitingstd/async/promise/Awaiting: forall<a> (listeners : list<(a) -> ioc ()>) -> promise-state<a>( listeners : liststd/core/types/list: V -> V<aa: V -> iocstd/core/ioc: E (std/core/types/unit: V)std/core/types/unit: V> )

// Create a new promise.
pub fun promisestd/async/promise/promise: forall<a> () -> async promise<a>()result: -> async promise<181> : asyncstd/async/async/async: E promisestd/async/promise/promise: V -> V<aa: V>
  async-ststd/async/async/async-st: (action : () -> (st<global>) promise<$137>) -> async promise<$137> { Promisestd/async/promise/Promise: forall<a> (state : ref<global,promise-state<a>>) -> promise<a>(refstd/core/types/ref: (value : promise-state<$137>) -> (st<global>) ref<global,promise-state<$137>>(Awaitingstd/async/promise/Awaiting: forall<a> (listeners : list<(a) -> ioc ()>) -> promise-state<a>([std/core/types/Nil: forall<a> list<a>]std/core/types/Nil: forall<a> list<a>))) }

// Await a promise; returns immediately if the promise was already resolved and otherwise
// waits asynchronously.
pub fun promise/awaitstd/async/promise/promise/await: forall<a> (p : promise<a>) -> async a( pp: promise<$254> : promisestd/async/promise/promise: V -> V<aa: V> )result: -> async 373 : asyncstd/async/async/async: E aa: V
  fun setupsetup: (cb : ($254) -> ioc ()) -> ioc ()(cbcb: ($254) -> ioc () : __w-l36-c18: V -> iocstd/core/ioc: E (std/core/types/unit: V)std/core/types/unit: V)result: -> ioc (): iocstd/core/ioc: E (std/core/types/unit: V)std/core/types/unit: V
    val rr: ref<global,promise-state<$254>> = pp: promise<$254>.statestd/async/promise/promise/state: (promise : promise<$254>) -> ioc ref<global,promise-state<$254>>
    match (!std/core/types/ref/(!): (ref : ref<global,promise-state<$254>>, @implicit/hdiv : hdiv<global,promise-state<$254>,<write<global>,alloc<global>,console,div,fsys,ndet,net,ui>>) -> ioc promise-state<$254>
?hdiv=iev@271
rr: ref<global,promise-state<$254>>) Awaitingstd/async/promise/Awaiting: forall<a> (listeners : list<(a) -> ioc ()>) -> promise-state<a>(listenerslisteners: list<($254) -> ioc ()>) -> rr: ref<global,promise-state<$254>> :=std/core/types/set: (ref : ref<global,promise-state<$254>>, assigned : promise-state<$254>) -> ioc () Awaitingstd/async/promise/Awaiting: forall<a> (listeners : list<(a) -> ioc ()>) -> promise-state<a>(Consstd/core/types/Cons: forall<a> (head : a, tail : list<a>) -> list<a>(cbcb: ($254) -> ioc (),listenerslisteners: list<($254) -> ioc ()>)) Resolvedstd/async/promise/Resolved: forall<a> (value : a) -> promise-state<a>(valuevalue: $254) -> cbcb: ($254) -> ioc ()(valuevalue: $254
) // resume right away; should not happen due to try-await match pp: promise<$254>.try-awaitstd/async/promise/try-await: (p : promise<$254>) -> async maybe<$254> Juststd/core/types/Just: forall<a> (value : a) -> maybe<a>(vv: $254) -> vv: $254 Nothingstd/core/types/Nothing: forall<a> maybe<a> -> await1-noexnstd/async/async/await1-noexn: (label : ? string, setup : (resume : ($254) -> ioc ()) -> ioc ()) -> async $254("promise/await"literal: string
count= 13
,setupsetup: (cb : ($254) -> ioc ()) -> ioc ()
) // Returns immediately if the promise was already resolved and otherwise return `Nothing`. pub fun try-awaitstd/async/promise/try-await: forall<a> (p : promise<a>) -> async maybe<a>( pp: promise<$186> : promisestd/async/promise/promise: V -> V<aa: V> )result: -> async maybe<249> : <std/core/types/total: Easyncstd/async/async/async: E> maybestd/core/types/maybe: V -> V<aa: V> async-iocstd/async/internal/async-ioc: (action : () -> ioc maybe<$186>) -> async maybe<$186> val rr: ref<global,promise-state<$186>> = pp: promise<$186>.statestd/async/promise/promise/state: (promise : promise<$186>) -> ioc ref<global,promise-state<$186>> match !std/core/types/ref/(!): (ref : ref<global,promise-state<$186>>, @implicit/hdiv : hdiv<global,promise-state<$186>,<alloc<global>,console,div,fsys,ndet,net,ui,write<global>>>) -> ioc promise-state<$186>
?hdiv=iev@210
rr: ref<global,promise-state<$186>> Resolvedstd/async/promise/Resolved: forall<a> (value : a) -> promise-state<a>(valuevalue: $186) -> Juststd/core/types/Just: forall<a> (value : a) -> maybe<a>(valuevalue: $186) _ -> Nothingstd/core/types/Nothing: forall<a> maybe<a>
// Resolve a promise to `value`. Raises an exception if the promise was already resolved. pub fun resolvestd/async/promise/resolve: forall<a> (p : promise<a>, value : a) -> <async,exn> ()( pp: promise<$497> : promisestd/async/promise/promise: V -> V<aa: V>, valuevalue: $497 : aa: V )result: -> <async,exn> () : <std/core/types/total: Easyncstd/async/async/async: E,exnstd/core/exn/exn: (E, V) -> V> (std/core/types/unit: V)std/core/types/unit: V if !std/core/types/bool/(!): (b : bool) -> <async,exn> booltry-resolvestd/async/promise/try-resolve: (p : promise<$497>, value : $497) -> <async,exn> bool(pp: promise<$497>, valuevalue: $497) then throwstd/core/exn/throw: (message : string, info : ? exception-info) -> <async,exn> ()("Promise was already resolved"literal: string
count= 28
)std/core/types/Unit: () // Resolve a promise to `value`. Returns False if the promise was already resolved. pub fun try-resolvestd/async/promise/try-resolve: forall<a> (p : promise<a>, value : a) -> async bool( pp: promise<$378> : promisestd/async/promise/promise: V -> V<aa: V>, valuevalue: $378 : aa: V )result: -> async bool : asyncstd/async/async/async: E boolstd/core/types/bool: V withwith: () -> ioc bool async-iocstd/async/internal/async-ioc: (action : () -> ioc bool) -> async bool val rr: ref<global,promise-state<$378>> = pp: promise<$378>.statestd/async/promise/promise/state: (promise : promise<$378>) -> ioc ref<global,promise-state<$378>> match !std/core/types/ref/(!): (ref : ref<global,promise-state<$378>>, @implicit/hdiv : hdiv<global,promise-state<$378>,<alloc<global>,console,div,fsys,ndet,net,ui,write<global>>>) -> ioc promise-state<$378>
?hdiv=iev@402
rr: ref<global,promise-state<$378>> Awaitingstd/async/promise/Awaiting: forall<a> (listeners : list<(a) -> ioc ()>) -> promise-state<a>(listenerslisteners: list<($378) -> ioc ()>) -> rr: ref<global,promise-state<$378>> :=std/core/types/set: (ref : ref<global,promise-state<$378>>, assigned : promise-state<$378>) -> ioc () Resolvedstd/async/promise/Resolved: forall<a> (value : a) -> promise-state<a>(valuevalue: $378) listenerslisteners: list<($378) -> ioc ()>.foreachstd/core/list/foreach: (xs : list<($378) -> ioc ()>, action : (($378) -> ioc ()) -> ioc ()) -> ioc () fnfn: (cbx : ($378) -> ioc ()) -> ioc ()(cbxcbx: ($378) -> ioc ()) // todo: through set-immediate? cbxcbx: ($378) -> ioc ()(valuevalue: $378) // set-immediate1( cbx, value ) Truestd/core/types/True: bool _ -> Falsestd/core/types/False: bool