Programming Language

Nocter

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

index.nct

//! User-facing `std/process` API.
//!
//! exit is a standard-library API, not a compiler primitive. The target-specific
//! implementation calls the active target boundary.

use /mem.TryAllocator
use /io.{BlockingReader, BlockingWriter, Reader, Writer}
use /string.String
use /vec.Vec
see ./command_child_darwin.nct
see ./child_owner_darwin.nct
see ./child_darwin.nct
see ./closed_command_darwin.nct
see ./closed_io_blocking_darwin.nct
see ./configuration.nct
see ./darwin.nct
see ./command.nct
see ./command_darwin.nct
see ./launch_plan_darwin.nct
see ./launch_report_darwin.nct
see ./launch_report_tests_darwin.nct
see ./pipe_darwin.nct
see ./pipe_endpoint_darwin.nct
see ./pipe_readiness_darwin.nct
see ./pipe_readiness_tests_darwin.nct
see ./pipe_tests_darwin.nct
see ./subprocess_darwin.nct
see ./process_io.nct
see ./spawn_io_darwin.nct

/// An owning exact-path subprocess request.
pub struct Command

/// One standard-stream policy selected before a child is created.
pub enum Stdio {
    /// Preserves the corresponding descriptor inherited by the parent.
    inherit

    /// Connects the child stream to the target's null device.
    null

    /// Creates one directional pipe and returns its parent endpoint with the child.
    pipe
}

/// Independent input, output, and error policies for one spawn operation.
pub struct ProcessIo

/// Unique ownership of one live or not-yet-observed child process.
pub struct Child

/// The owning parent-side writer connected to one child's standard input.
pub struct ChildStdin

/// The owning parent-side reader connected to one child's standard output.
pub struct ChildStdout

/// The owning parent-side reader connected to one child's standard error.
pub struct ChildStderr

/// One observed terminal state of a reaped child process.
pub copy struct ExitStatus

/// Complete owned output from one closed child-process operation.
pub struct Output {
    /// The child's observed terminal state.
    pub status: ExitStatus

    /// Every byte captured from the child's standard output, in stream order.
    pub stdout: Vec<u8>

    /// Every byte captured from the child's standard error, in stream order.
    pub stderr: Vec<u8>
}

construct Command {
    /// Copies and validates one exact executable path.
    pub func new(path: &str): Self!
}

construct ProcessIo {
    /// Selects inherited descriptors for all three standard streams.
    pub noalloc func inherit(): Self

    /// Selects pipes for all three standard streams.
    pub noalloc func piped(): Self
}

instance ProcessIo {
    /// Replaces the child standard-input policy.
    pub noalloc method &+self.stdin(mode: Stdio): void

    /// Replaces the child standard-output policy.
    pub noalloc method &+self.stdout(mode: Stdio): void

    /// Replaces the child standard-error policy.
    pub noalloc method &+self.stderr(mode: Stdio): void
}

instance Command {
    /// Appends one exact argument after copying and validating it.
    pub method &+self.arg(value: &str): void!

    /// Sets the working directory used before executable replacement.
    pub method &+self.current_dir(path: &str): void!

    /// Sets one exact child environment value, replacing an equal name.
    pub method &+self.env(name: &str, value: &str): void!

    /// Removes one child environment name if inherited or explicitly set.
    pub method &+self.remove_env(name: &str): void!

    /// Removes every inherited and explicitly configured environment entry.
    pub method &+self.clear_env(): void

    /// Copies finite bytes that replace inherited standard input.
    pub method &+self.input(value: &[u8]): void

    /// Creates an owned child and configured pipe endpoints without blocking the executor.
    pub async method self.spawn(io: ProcessIo): Child!

    /// Creates an owned child and configured pipe endpoints while blocking the current thread.
    pub blocking method self.spawn_blocking(io: ProcessIo): Child!

    /// Launches the command and asynchronously observes its terminal status.
    pub async method self.status(): ExitStatus!

    /// Launches the command and synchronously observes its terminal status.
    pub blocking method self.status_blocking(): ExitStatus!

    /// Launches the command and asynchronously captures both complete output streams.
    pub async method self.output(): Output!

    /// Launches the command and synchronously captures both complete output streams.
    pub blocking method self.output_blocking(): Output!
}

instance Child {
    /// Transfers the configured standard-input endpoint exactly once.
    pub noalloc method &+self.take_stdin(): ChildStdin?

    /// Transfers the configured standard-output endpoint exactly once.
    pub noalloc method &+self.take_stdout(): ChildStdout?

    /// Transfers the configured standard-error endpoint exactly once.
    pub noalloc method &+self.take_stderr(): ChildStderr?

    /// Observes terminal state without waiting and retains the child for later operations.
    pub noalloc method &+self.try_wait(): ExitStatus?!

    /// Requests graceful termination while retaining the exact observation obligation.
    pub noalloc method &self.terminate(): void!

    /// Requests forced termination while retaining the exact observation obligation.
    pub noalloc method &self.kill(): void!

    /// Consumes and asynchronously observes this exact child's terminal state.
    pub async method self.wait(): ExitStatus!

    /// Consumes and synchronously observes this exact child's terminal state.
    pub blocking method self.wait_blocking(): ExitStatus!
}

instance ChildStdin {
    /// Closes the input endpoint without affecting child ownership.
    pub noalloc method &+self.close(): void
    impl Writer
    impl BlockingWriter
}

instance ChildStdout {
    /// Closes the output endpoint without affecting child ownership.
    pub noalloc method &+self.close(): void
    impl Reader
    impl BlockingReader
}

instance ChildStderr {
    /// Closes the error endpoint without affecting child ownership.
    pub noalloc method &+self.close(): void
    impl Reader
    impl BlockingReader
}

instance ExitStatus {
    /// Returns true exactly for ordinary exit code zero.
    pub noalloc method self.success(): bool

    /// Returns the ordinary exit code, or `none` for signal termination.
    pub noalloc method self.code(): i32?

    /// Returns the terminating signal, or `none` for ordinary exit.
    pub noalloc method self.signal(): i32?
}

/// One borrowed name/value pair from the process environment.
pub copy struct EnvironmentEntry {
    /// Borrowed environment-variable name retained by process storage.
    pub name: &str

    /// Borrowed environment-variable value retained by process storage.
    pub value: &str
}

/// Copies all process arguments into an owning Vec of process-lifetime views.
pub func args(): Vec<&str>!

/// Returns the number of process arguments, including the executable spelling.
pub noalloc func arg_count(): usize

/// Returns one process argument, `none` out of range, or a decoding failure.
pub noalloc func arg(index: usize): &str?!

/// Returns the number of environment entries.
pub noalloc func environment_count(): usize

/// Returns one environment entry, `none` out of range, or a decoding failure.
pub noalloc func environment(index: usize): EnvironmentEntry?!

/// Returns the value of one environment variable, `none` when absent, or a decoding failure.
pub noalloc func env(name: &str): &str?!

/// Returns the current working directory in current-context storage.
pub blocking func cwd(): String!

/// Returns the current working directory using recoverable storage from `allocator`.
pub blocking func try_cwd(allocator: &+TryAllocator): String!

/// Terminates the process with `code` and does not return.
pub notrap func exit(code: i32): never

/// Terminates the process immediately with an unsuccessful status.
pub notrap func abort(): never