wit-bindgen-cli 0.61.1

CLI tool to generate bindings for WIT documents and the component model.
//@ wasmtime-flags = '-Wcomponent-model-async'
//@ [lang]
//@ path = 'gen/interface/test/moonbit-local-async-primitives/operations/stub.mbt'

///|
suberror ExpectedPromiseFailure derive(Debug)

///|
priv struct LocalOnlyValue {
  marker : Int
}

///|
let previous_completed_task : Ref[@async-core.Task[Bool]?] = Ref(None)

///|
pub async fn exercise(background_group : @async-core.TaskGroup[Unit]) -> Bool {
  if previous_completed_task.val is Some(task) {
    task.cancel()
    previous_completed_task.val = None
  }

  let semaphore = @async-core.Semaphore(1, initial_value=1)
  guard semaphore.try_acquire() else { return false }
  guard !semaphore.try_acquire() else { return false }
  semaphore.release()
  semaphore.acquire()

  let mutex = @async-core.Mutex()
  guard mutex.try_acquire() else { return false }
  guard !mutex.try_acquire() else { return false }
  let (mutex_started, mutex_started_promise) = @async-core.Future::new()
  let mutex_waiter = background_group.spawn(
    async fn() -> Bool {
      guard mutex_started_promise.complete(()) else { return false }
      mutex.acquire()
      mutex.release()
      true
    },
    allow_failure=true,
  )
  mutex_started.get()
  mutex.release()
  guard mutex_waiter.wait() else { return false }

  let condition = @async-core.CondVar()
  let condition_ready = Ref(false)
  let (condition_started, condition_started_promise) = @async-core.Future::new()
  let condition_waiter = background_group.spawn(
    async fn() -> Bool {
      guard condition_started_promise.complete(()) else { return false }
      while !condition_ready.val {
        condition.wait()
      }
      true
    },
    allow_failure=true,
  )
  condition_started.get()
  condition_ready.val = true
  condition.signal()
  condition_waiter.cancel()
  guard condition_waiter.wait() else { return false }

  let cancellation_condition = @async-core.CondVar()
  let (condition_cancel_started, condition_cancel_started_promise) = @async-core.Future::new()
  let cancelled_condition_waiter = background_group.spawn(
    async fn() -> Unit {
      guard condition_cancel_started_promise.complete(()) else { panic() }
      cancellation_condition.wait()
    },
    allow_failure=true,
  )
  condition_cancel_started.get()
  cancelled_condition_waiter.cancel()
  let condition_wait_was_cancelled = try
    cancelled_condition_waiter.wait()
  catch {
    @async-core.Cancelled::Cancelled => true
    _ => false
  } noraise {
    _ => false
  }
  guard condition_wait_was_cancelled else { return false }

  let (condition_survivor_started, condition_survivor_started_promise) = @async-core.Future::new()
  let condition_survivor = background_group.spawn(
    async fn() -> Bool {
      guard condition_survivor_started_promise.complete(()) else {
        return false
      }
      cancellation_condition.wait()
      true
    },
    allow_failure=true,
  )
  condition_survivor_started.get()
  cancellation_condition.broadcast()
  guard condition_survivor.wait() else { return false }

  let (ready_future, ready_promise) = @async-core.Future::new()
  guard ready_promise.complete(41) else { return false }
  guard ready_future.get() == 41 else { return false }

  let (local_future, local_promise) = @async-core.Future::new()
  guard local_promise.complete({ marker: 47 }) else { return false }
  guard local_future.get().marker == 47 else { return false }

  let cleaned = Ref(0)
  let (discarded_future, discarded_promise) = @async-core.Future::new_with_cleanup(fn(
      value : Int,
    ) {
      cleaned.val = value
    },
  )
  guard discarded_promise.complete(42) else { return false }
  discarded_future.drop()
  discarded_future.drop()
  guard cleaned.val == 42 else { return false }

  let (dropped_future, dropped_promise) : (
    @async-core.Future[Int],
    @async-core.Promise[Int],
  ) = @async-core.Future::new()
  dropped_future.drop()
  guard !dropped_promise.complete(43) else { return false }

  let (failed_future, failed_promise) : (
    @async-core.Future[Int],
    @async-core.Promise[Int],
  ) = @async-core.Future::new()
  guard failed_promise.fail(ExpectedPromiseFailure) else { return false }
  let observed_failure = try failed_future.get() catch {
    ExpectedPromiseFailure::ExpectedPromiseFailure => true
    _ => false
  } noraise {
    _ => false
  }
  guard observed_failure else { return false }

  let (closed_future, closed_promise) : (
    @async-core.Future[Int],
    @async-core.Promise[Int],
  ) = @async-core.Future::new()
  guard closed_promise.close() else { return false }
  let observed_close = try closed_future.get() catch {
    @async-core.PromiseClosed::PromiseClosed => true
    _ => false
  } noraise {
    _ => false
  }
  guard observed_close else { return false }

  let (pending_future, pending_promise) = @async-core.Future::new()
  let (pending_started, pending_started_promise) = @async-core.Future::new()
  let pending_waiter = background_group.spawn(
    async fn() -> Int {
      guard pending_started_promise.complete(()) else { panic() }
      pending_future.get()
    },
    allow_failure=true,
  )
  pending_started.get()
  guard pending_promise.complete(44) else { return false }
  guard pending_waiter.wait() == 44 else { return false }

  let (cancelled_future, cancelled_promise) = @async-core.Future::new()
  let (cancel_started, cancel_started_promise) = @async-core.Future::new()
  let cancelled_waiter = background_group.spawn(
    async fn() -> Int {
      guard cancel_started_promise.complete(()) else { panic() }
      cancelled_future.get()
    },
    allow_failure=true,
  )
  cancel_started.get()
  cancelled_waiter.cancel()
  let observed_cancel = try cancelled_waiter.wait() catch {
    @async-core.Cancelled::Cancelled => true
    _ => false
  } noraise {
    _ => false
  }
  guard observed_cancel else { return false }
  guard !cancelled_promise.complete(45) else { return false }

  let (dropped_while_reading, dropped_while_reading_promise) = @async-core.Future::new()
  let (drop_read_started, drop_read_started_promise) = @async-core.Future::new()
  let dropped_reader = background_group.spawn(
    async fn() -> Bool {
      guard drop_read_started_promise.complete(()) else { panic() }
      dropped_while_reading.get() catch {
        @async-core.Cancelled::Cancelled => return true
        _ => return false
      }
      false
    },
    allow_failure=true,
  )
  drop_read_started.get()
  dropped_while_reading.drop()
  guard dropped_reader.wait() else { return false }
  guard !dropped_while_reading_promise.complete(()) else { return false }

  let completion_cleanup = Ref(0)
  let (completed_while_reading, completed_while_reading_promise) = @async-core.Future::new_with_cleanup(fn(
      value : Int,
    ) {
      completion_cleanup.val = value
    },
  )
  let (completed_read_started, completed_read_started_promise) = @async-core.Future::new()
  let completed_reader = background_group.spawn(
    async fn() -> Int {
      guard completed_read_started_promise.complete(()) else { panic() }
      completed_while_reading.get()
    },
    allow_failure=true,
  )
  completed_read_started.get()
  guard completed_while_reading_promise.complete(45) else { return false }
  completed_while_reading.drop()
  guard completed_reader.wait() == 45 else { return false }
  guard completion_cleanup.val == 0 else { return false }

  let (racing_future, racing_promise) = @async-core.Future::new()
  let (race_started, race_started_promise) = @async-core.Future::new()
  let racing_waiter = background_group.spawn(
    async fn() -> Int {
      guard race_started_promise.complete(()) else { panic() }
      racing_future.get()
    },
    allow_failure=true,
  )
  race_started.get()
  guard racing_promise.complete(46) else { return false }
  racing_waiter.cancel()
  guard racing_waiter.wait() == 46 else { return false }

  let fifo = @async-core.Semaphore(1, initial_value=0)
  let phase = Ref(0)
  let (first_started, first_started_promise) = @async-core.Future::new()
  let first = background_group.spawn(
    async fn() -> Bool {
      guard first_started_promise.complete(()) else { return false }
      fifo.acquire()
      guard phase.val == 0 else { return false }
      phase.val = 1
      fifo.release()
      true
    },
    allow_failure=true,
  )
  first_started.get()
  let (second_started, second_started_promise) = @async-core.Future::new()
  let second = background_group.spawn(
    async fn() -> Bool {
      guard second_started_promise.complete(()) else { return false }
      fifo.acquire()
      guard phase.val == 1 else { return false }
      phase.val = 2
      true
    },
    allow_failure=true,
  )
  second_started.get()
  fifo.release()
  guard first.wait() else { return false }
  guard second.wait() else { return false }
  guard phase.val == 2 else { return false }

  let cancellable = @async-core.Semaphore(1, initial_value=0)
  let (cancelled_acquire_started, cancelled_acquire_started_promise) = @async-core.Future::new()
  let cancelled_acquire = background_group.spawn(
    async fn() -> Bool {
      guard cancelled_acquire_started_promise.complete(()) else { return false }
      cancellable.acquire()
      false
    },
    allow_failure=true,
  )
  cancelled_acquire_started.get()
  cancelled_acquire.cancel()
  let acquire_was_cancelled = try cancelled_acquire.wait() catch {
    @async-core.Cancelled::Cancelled => true
    _ => false
  } noraise {
    _ => false
  }
  guard acquire_was_cancelled else { return false }

  let (survivor_started, survivor_started_promise) = @async-core.Future::new()
  let survivor = background_group.spawn(
    async fn() -> Bool {
      guard survivor_started_promise.complete(()) else { return false }
      cancellable.acquire()
      true
    },
    allow_failure=true,
  )
  survivor_started.get()
  cancellable.release()
  guard survivor.wait() else { return false }

  let assigned = @async-core.Semaphore(1, initial_value=0)
  let (assigned_started, assigned_started_promise) = @async-core.Future::new()
  let assigned_waiter = background_group.spawn(
    async fn() -> Bool {
      guard assigned_started_promise.complete(()) else { return false }
      assigned.acquire()
      true
    },
    allow_failure=true,
  )
  assigned_started.get()
  assigned.release()
  assigned_waiter.cancel()
  let result = assigned_waiter.wait()
  previous_completed_task.val = Some(assigned_waiter)
  result
}