Programming Language

Nocter

A self-contained systems language built around simplicity, encapsulation, and foolproof design.

index.nct

//! Structured asynchronous computation composition.

use /time.Duration

see ./composition.nct
see ./group.nct

/// The completed branch of one two-computation race.
pub enum Race<T> {
    first(value: T)
    second(value: T)
}

/// The outcome of driving one computation within a relative timeout.
pub enum Timeout<T> {
    completed(value: T)
    elapsed
}

/// One runtime-sized, uniquely owned set of homogeneous child computations.
///
/// Adding transfers a lazy computation into the group. Awaiting `next` drives every retained
/// child fairly and removes exactly one completed computation. Destroying the group cancels every
/// child that remains.
pub struct TaskGroup<T>

construct TaskGroup<T> {
    /// Creates an empty group without allocating child storage.
    pub noalloc func empty(): Self
}

instance TaskGroup<T> {
    /// Transfers one lazy computation into this group.
    pub method &+self.add(computation: future T): void

    /// Returns the number of computations still owned by this group.
    pub noalloc method &self.len(): usize

    /// Reports whether this group owns no computations.
    pub noalloc method &self.is_empty(): bool

    /// Drives all retained computations and removes one completed output.
    ///
    /// Returns absence immediately when the group is empty. Cancelling this wait leaves every
    /// child in the group; destroying the group cancels them.
    pub async method &+self.next(): T?
}

/// Starts two owned computations, waits for both, and returns their outputs in argument order.
///
/// Destroying the returned computation before consumption cancels both children. Outcome layers
/// remain ordinary output values and are not propagated by `join`.
pub primitive func join<A, B>(
    first: future A,
    second: future B,
): future (A, B) from first | second

/// Starts two owned computations and returns the first output, cancelling the other computation.
///
/// When both computations can complete during the same drive step, `first` wins.
pub async func race<T>(first: future T, second: future T): Race<T>

/// Drives one owned computation until it completes or `timeout` elapses.
///
/// Completion wins when both outcomes become available during the same drive step.
pub async func with_timeout<T>(computation: future T, timeout: Duration): Timeout<T>