Add standard library reference manual with per-module API docs

Create docs/manual/stdlib/ with 12 topic pages covering all stdlib
modules (builtins, Option/Result, collections, iterators, math,
strings, ranges, async runtime, networking, time, synchronization).
Move scattered stdlib content from language manual pages into the
dedicated stdlib section, replacing with concise summaries and links.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-04 19:13:31 +02:00
parent 04edece055
commit d29afd5884
18 changed files with 1079 additions and 218 deletions

View File

@@ -4,10 +4,10 @@ This manual has been split into topic pages for easier navigation.
**[Go to the manual](manual/index.md)**
## Quick links
## Language
- [Basics](manual/basics.md) -- variables, comments, strings, primitive types
- [Type Declarations](manual/types.md) -- objects, tuples, ref objects, enums, standard library types
- [Type Declarations](manual/types.md) -- objects, tuples, ref objects, enums
- [Functions](manual/functions.md) -- functions, async, lambdas, closures, UFCS
- [Control Flow](manual/control-flow.md) -- if/else, while, for, pattern matching, blocks
- [Generics](manual/generics.md) -- parametric polymorphism, constraints, static parameters
@@ -19,5 +19,19 @@ This manual has been split into topic pages for easier navigation.
- [Compile-Time Features](manual/compile-time.md) -- `when`/`defined()`, CTFE, pragmas
- [Modules](manual/modules.md) -- import/export, visibility, module execution
- [C Interop](manual/c-interop.md) -- importc, exportc, C-compatible types, converters
## Standard Library
- **[Standard Library Reference](manual/stdlib/index.md)**
- [Built-in Functions](manual/stdlib/builtins.md) -- print, panic, clone, sizeof, etc.
- [Option and Result](manual/stdlib/types.md) -- Option[T], Result[T, E]
- [Collections](manual/stdlib/collections.md) -- array, seq, deque
- [Iterators](manual/stdlib/iterators.md) -- Generator, Iterator protocols
- [Math](manual/stdlib/math.md) | [Strings](manual/stdlib/strings.md) | [Ranges](manual/stdlib/ranges.md)
- [Async Runtime](manual/stdlib/async.md) | [Networking](manual/stdlib/net.md) | [Time](manual/stdlib/time.md)
- [Synchronization](manual/stdlib/sync.md) -- Event, LIFOQueue, FIFOQueue
## Reference
- [Grammar](grammar.md)
- [Bytecode](bytecode.md)

View File

@@ -185,66 +185,10 @@ Custom converter functions can be defined with the `converter` pragma
## Built-in functions
The standard library provides these built-in functions:
The standard library provides built-in functions for output (`print`, `panic`),
ownership (`borrow`, `clone`, `move`, `destroy`), type introspection (`sizeof`,
`typeof`, `needsDestroy`), collection queries (`len`, `low`, `high`), heap allocation
(`new`), raw memory (`alloc`, `create`, `realloc`, `dealloc`, `copyMem`, `cast`),
and iterator operations (`start`, `resume`, `next`).
| Function | Description |
|----------|-------------|
| `print(x)` | Print a value to stdout followed by a newline |
| `panic()` | Abort the program with a runtime panic |
| `panic(msg)` | Abort with a message |
| `borrow(x)` or `&x` | Create a non-owning borrow (`lent`) of `x` |
| `move(src, dst)` | Explicitly move `src` into `dst` |
| `clone(x)` | Create an independent copy of `x` |
| `cast[T](x)` | Reinterpret `x` as `T` for low-level raw-pointer or same-size scalar bitcasts. Requires `unsafe`. |
| `new(T)` | Heap-allocate a new value of type `T` |
| `low(T)` | Return the minimum value of a numeric type (`-inf` for floats) |
| `high(T)` | Return the maximum value of a numeric type (`inf` for floats) |
| `typeof(x)` | Return the compile-time type witness for the value `x` |
| `sizeof(T)` | Return the compile-time size in bytes of a sized type |
| `sizeof(x)` | Return the compile-time size in bytes of the type of `x` |
| `needsDestroy(T)` | Return whether values of type `T` carry owned cleanup work |
| `low(x)` | Return the first valid index of a string, array, or `seq` |
| `high(x)` | Return the last valid index of a string, array, or `seq` |
| `len(x)` | Return the length of a collection |
| `alloc(T, n)` | Allocate raw storage for `n` values of type `T` (uninitialized). Requires `unsafe`. |
| `create(T, n)` | Allocate zero-initialized raw storage for `n` values of type `T`. Requires `unsafe`. |
| `realloc(ptr, n)` | Resize a raw allocation to `n` elements. Requires `unsafe`. |
| `dealloc(ptr)` | Free a raw pointer allocation. Requires `unsafe`. |
| `copyMem(dst, src, n)` | Copy `n` bytes from `src` to `dst` (well-defined even for overlapping regions). Requires `unsafe`. |
| `addr(x)` | Take the raw address of a raw-pointer-backed value, returning `ptr T`. |
| `append(s, x)` | Append element `x` to `mut lent seq[T]` |
| `start(g)` | Start a generator, returning `GeneratorState[Y, R]` |
| `resume(g, v)` | Resume a generator with send value `v`, returning `GeneratorState[Y, R]` |
| `next(it)` | Advance an iterator or generator, returning `Option[Y]` |
For collections, valid indices are `low(x) .. high(x)` when the collection is not
empty. For strings, arrays, and `seq`s, `low(x)` is always `0` and `high(x)` is the
last valid index (`-1` for empty values).
`typeof(x)` returns a compile-time type witness, which can be passed to helpers like
`sizeof`. Both `sizeof(T)` and `sizeof(x)` are compile-time constants. They are useful
for raw allocation helpers and FFI-style layout checks:
```peon
type Pair = object {
left: int64;
right: int64;
}
print(sizeof(int64)); # 8
print(sizeof(array[3, int64])); # 24
print(sizeof(Pair)); # 16
let pair = Pair(left = 1, right = 2);
print(sizeof(pair)); # 16
```
String indexing uses the same bounds as `low(text)` and `high(text)`, but because
strings are immutable it returns an owned `char` value rather than a borrow:
```peon
let text = "abc";
let middle: char = text[1];
print(middle); # b
print(low(text)); # 0
print(high(text)); # 2
```
See [Standard Library -- Built-in Functions](stdlib/builtins.md) for the full reference.

View File

@@ -14,9 +14,12 @@ async fn parallelSum(a: string, b: string): int64 {
}
```
For the async runtime API (`runAsync`, `AsyncCompletion`, timing/cancellation helpers),
see [Standard Library -- Async Runtime](stdlib/async.md).
Current status:
- synchronous code enters async execution with `runAsync(...)`, which returns `AsyncCompletion[T]`
- synchronous code enters async execution with [`runAsync(...)`](stdlib/async.md#runasync), which returns [`AsyncCompletion[T]`](stdlib/types.md#asynccompletiont)
- `async fn` bodies may use `await`, and async roots run through the native C backend
- `spawn` starts child work inside a `nursery`, and `await` accepts either direct async calls or `SpawnHandle[Return]`
- async calls must be explicitly `await`ed or `spawn`ed

View File

@@ -10,8 +10,10 @@ in), Rust, C and many others.
## Table of contents
### Language
- [Basics](basics.md) -- variables, comments, strings, primitive types
- [Type Declarations](types.md) -- objects, tuples, ref objects, enums, standard library types
- [Type Declarations](types.md) -- objects, tuples, ref objects, enums
- [Functions](functions.md) -- functions, async, lambdas, closures, UFCS
- [Control Flow](control-flow.md) -- if/else, while, for, pattern matching, blocks
- [Generics](generics.md) -- parametric polymorphism, constraints, static parameters
@@ -23,6 +25,24 @@ in), Rust, C and many others.
- [Compile-Time Features](compile-time.md) -- `when`/`defined()`, CTFE, pragmas
- [Modules](modules.md) -- import/export, visibility, module execution
- [C Interop](c-interop.md) -- importc, exportc, C-compatible types, converters
### Standard Library
- **[Standard Library Reference](stdlib/index.md)** -- full API documentation
- [Built-in Functions](stdlib/builtins.md) -- print, panic, borrow, clone, sizeof, etc.
- [Option and Result](stdlib/types.md) -- Option[T], Result[T, E], AsyncCompletion[T]
- [Collections](stdlib/collections.md) -- array[N, T], seq[T], deque[T]
- [Iterators](stdlib/iterators.md) -- Generator, Iterator, Iterable protocols
- [Math](stdlib/math.md) -- constants and functions
- [Strings](stdlib/strings.md) -- concat, join, operators
- [Ranges](stdlib/ranges.md) -- InclusiveRange, ExclusiveRange, .., ..<
- [Async Runtime](stdlib/async.md) -- runAsync, sleep, cancellation, WaitQueue
- [Networking](stdlib/net.md) -- sockets, getAddrInfo, readSome/writeSome
- [Time](stdlib/time.md) -- cpuTime
- [Synchronization](stdlib/sync.md) -- Event, LIFOQueue, FIFOQueue
### Reference
- [Grammar](../grammar.md)
- [Bytecode](../bytecode.md)

View File

@@ -117,3 +117,7 @@ corresponding iterator type via `iter()`, `items()`, and `mitems()`.
Types can participate in `for` loops by implementing the direct iterator
protocol (`Iterator[T]`), or by implementing one of the collection adapter
protocols.
For `Generator[Y, S, R]`, `GeneratorState`, and the `start`/`resume`/`next`
advancement functions, see the
[Standard Library -- Iterators](stdlib/iterators.md) reference.

View File

@@ -0,0 +1,95 @@
# Async Runtime
[Back to Standard Library](index.md) | [Back to Manual](../index.md)
The async runtime provides the execution infrastructure for
[structured concurrency](../concurrency.md). Available through the implicit `import std`.
## Entry point
### `runAsync`
The sync-to-async bridge. Returns [`AsyncCompletion[T]`](types.md#asynccompletiont):
```peon
fn runAsync[T](value: T): AsyncCompletion[T]
fn runAsync[T](value: T, options: AsyncRuntimeOptions): AsyncCompletion[T]
```
`runAsync` is rejected inside `async fn` -- it is only for entering the async
world from synchronous code.
### `AsyncRuntimeOptions`
```peon
type AsyncRuntimeOptions = object with ImplicitCopy {
maxBlockingThreads: int64;
maxBlockingJobs: int64;
}
```
| Field | Description |
|-------|-------------|
| `maxBlockingThreads` | Maximum idle threads in the blocking call pool. |
| `maxBlockingJobs` | Maximum blocking jobs queued at once. |
## Clock
| Function | Description |
|----------|-------------|
| `clock()` | Return an `AsyncClock` for measuring async time. |
| `now(clock)` | Return the current time as `float` from an `AsyncClock`. |
## Timing and sleep
All timing functions are `async fn` and require an async context.
| Function | Description |
|----------|-------------|
| `sleep(seconds)` | Suspend the current task for `seconds`. |
| `sleepUntil(deadline)` | Suspend until the absolute `deadline`. |
| `checkpoint()` | Yield control to the scheduler. Every `await` should be a checkpoint. |
## Cancellation
These operate on [`nursery`](../concurrency.md#current-rules) capabilities:
| Function | Description |
|----------|-------------|
| `cancel(nursery)` | Cancel a nursery immediately. |
| `cancelAfter(nursery, seconds)` | Cancel the nursery after `seconds`. |
| `cancelAt(nursery, deadline)` | Cancel the nursery at an absolute `deadline`. |
| `clearDeadline(nursery)` | Remove the cancellation deadline. |
| `deadline(nursery)` | Return the current deadline as `Option[float]`. |
| `extendDeadline(nursery, seconds)` | Extend the deadline by `seconds`. |
## I/O waiting
| Function | Description |
|----------|-------------|
| `waitReadable(fd)` | `async fn` -- suspend until file descriptor `fd` is readable. |
| `waitWritable(fd)` | `async fn` -- suspend until file descriptor `fd` is writable. |
These are the building blocks for non-blocking I/O in the [networking](net.md) module.
## `WaitQueue`
A low-level task parking primitive used by [synchronization types](sync.md):
```peon
type WaitQueue = object { ... }
```
| Function | Description |
|----------|-------------|
| `WaitQueue()` | Construct an empty wait queue. |
| `init(q)` | Re-initialize a wait queue. |
| `wakeFirst(q)` | Wake the first parked task. Returns `true` if a task was woken. |
| `wakeLast(q)` | Wake the last parked task. Returns `true` if a task was woken. |
| `wakeAll(q)` | Wake all parked tasks. Returns the count woken. |
| `isEmpty(q)` | Return whether no tasks are parked. |
| `park(q)` | `async fn` -- suspend the current task in the queue. |
`WaitQueue` is imported from the C runtime and is not intended for direct use
in application code. Use [`Event`](sync.md#event) or the async
[queues](sync.md#async-queues) instead.

View File

@@ -0,0 +1,113 @@
# Built-in Functions
[Back to Standard Library](index.md) | [Back to Manual](../index.md)
These functions are available in every module through the implicit `import std`.
## Output and diagnostics
| Function | Description |
|----------|-------------|
| `print(x)` | Print a value to stdout followed by a newline. Accepts any [`Printable`](../interfaces.md#built-in-interfaces) type. |
| `panic()` | Abort the program with a runtime panic. |
| `panic(msg)` | Abort with a message. |
## Ownership and copying
| Function | Description |
|----------|-------------|
| `borrow(x)` or `&x` | Create a non-owning borrow (`lent T`) of `x`. See [Memory Model -- Borrows](../memory-model.md#borrows-and-lent). |
| `clone(x)` | Create an independent copy of `x`. Requires `T: Copy`. See [Interfaces -- Copy](../interfaces.md#built-in-interfaces). |
| `move(src, dst)` | Explicitly move `src` into `dst`. |
| `destroy(x)` | Explicitly destroy a value. See [Memory Model -- Lifecycle hooks](../memory-model.md#lifecycle-hooks). |
| `defaultClone()` | Default clone implementation (only valid inside a `clone=` hook). |
| `defaultMove()` | Default move implementation (only valid inside a `move=` hook). |
| `defaultDestroy()` | Default destroy implementation (only valid inside a `destroy=` hook). |
## Type introspection
| Function | Description |
|----------|-------------|
| `typeof(x)` | Return the compile-time type witness for the value `x`. |
| `sizeof(T)` | Return the compile-time size in bytes of a sized type. |
| `sizeof(x)` | Return the compile-time size in bytes of the type of `x`. |
| `needsDestroy(T)` | Return whether values of type `T` carry owned cleanup work. Used in generic [lifecycle hooks](../memory-model.md#lifecycle-hooks). |
Both `sizeof(T)` and `sizeof(x)` are compile-time constants:
```peon
type Pair = object {
left: int64;
right: int64;
}
print(sizeof(int64)); # 8
print(sizeof(array[3, int64])); # 24
print(sizeof(Pair)); # 16
let pair = Pair(left = 1, right = 2);
print(sizeof(pair)); # 16
```
## Collection queries
| Function | Description |
|----------|-------------|
| `len(x)` | Return the length of a string, [array](collections.md#static-arrays), [seq](collections.md#sequences), or [deque](collections.md#double-ended-queue). |
| `low(T)` | Return the minimum value of a numeric type (`-inf` for floats). |
| `high(T)` | Return the maximum value of a numeric type (`inf` for floats). |
| `low(x)` | Return the first valid index of a string, array, or `seq` (always `0`). |
| `high(x)` | Return the last valid index of a string, array, or `seq` (`-1` for empty values). |
For strings, arrays, and `seq`s, valid indices are `low(x)` through `high(x)`.
String indexing returns an owned `char` value (strings are immutable):
```peon
let text = "abc";
let middle: char = text[1];
print(middle); # b
print(low(text)); # 0
print(high(text)); # 2
```
## Heap allocation
| Function | Description |
|----------|-------------|
| `new(T)` | Heap-allocate a new value of type `T`, returning `ref T`. |
```peon
var cell = new(int64);
cell[] = 42;
print(cell[]); # 42
```
## Raw memory (unsafe)
These require [`unsafe { ... }`](../unsafe.md#unsafe-blocks):
| Function | Description |
|----------|-------------|
| `alloc(T, n)` | Allocate raw storage for `n` values of type `T` (uninitialized). Returns `ptr T`. |
| `create(T, n)` | Allocate zero-initialized raw storage for `n` values of type `T`. Returns `ptr T`. |
| `realloc(ptr, n)` | Resize a raw allocation to `n` elements. Returns `ptr T`. |
| `dealloc(ptr)` | Free a raw pointer allocation. |
| `copyMem(dst, src, n)` | Copy `n` bytes from `src` to `dst` (well-defined for overlapping regions). |
| `addr(x)` | Take the raw address of a raw-pointer-backed value, returning `ptr T`. |
| `cast[T](x)` | Reinterpret the bits of `x` as type `T`. Source and target must have the same size. |
See [Unsafe -- Raw pointers](../unsafe.md#raw-pointers) for usage examples.
## Sequence operations
| Function | Description |
|----------|-------------|
| `append(s, x)` | Append element `x` to `mut lent seq[T]`. See [Collections -- Sequences](collections.md#sequences). |
## Generator and iterator operations
| Function | Description |
|----------|-------------|
| `start(g)` | Start a [generator](iterators.md#generators), returning `GeneratorState[Y, R]`. |
| `resume(g, v)` | Resume a generator with send value `v`, returning `GeneratorState[Y, R]`. |
| `next(it)` | Advance an [iterator](iterators.md#iterator-interfaces) or generator, returning `Option[Y]`. |

View File

@@ -0,0 +1,172 @@
# Collections
[Back to Standard Library](index.md) | [Back to Manual](../index.md)
## Static arrays (`array[N, T]`)
The built-in `array[N, T]` type constructor creates fixed-size arrays:
```peon
type IntVec = array[3, int64];
var a = IntVec(1, 2, 3);
var b = [1, 2, 3, 4]; # Inferred as array[4, int64]
print(a[0]); # 1
a[0] = 9;
print(len(a)); # 3
```
Array access is bounds-checked at runtime when `boundChecks` is enabled
(see [Compile-Time Features -- Config symbols](../compile-time.md#config-symbols)).
Out-of-bounds access panics.
### Value semantics
Plain arrays are value types. Assignment moves the array:
```peon
var a = [1, 2, 3];
var b = a; # a is moved into b
# print(a[0]); # Error: a has been moved
print(b[0]); # 1
```
Use `clone` for an independent copy:
```peon
var a = [1, 2, 3];
var b = clone(a);
b[0] = 9;
print(a[0]); # 1 -- unchanged
```
### Ref arrays
Heap-allocated arrays can be mutably borrowed:
```peon
type RefVec = ref array[2, int64];
var a = RefVec(4, 5);
var b = mut borrow(a);
b[1] = 7;
print(a[1]); # 7 -- shared data
```
### API
| Function | Description |
|----------|-------------|
| `len(a)` | Return the array length (compile-time constant `N`). |
| `low(a)` | Return `0`. |
| `high(a)` | Return `N - 1`. |
| `items(a)` | Generator yielding `lent T` for each element. |
| `mitems(a)` | Generator yielding `mut lent T` for each element. |
| `indexOf(a, v)` | Return `Option[int64]` with the index of the first match. |
| `unsafe { get_unchecked(a, i) }` | Element access without bounds checking. |
## Sequences (`seq[T]`)
`seq[T]` is a growable dynamic array. Create one with the `@` prefix on an array
literal:
```peon
var ints = @[1, 2, 3];
ints.append(4);
print(len(ints)); # 4
print(ints[3][]); # 4
```
The `@` operator also converts a static array to a `seq`:
```peon
var arr = [1, 2, 3];
var s = @arr; # seq[int64]
```
### Indexing semantics
- `s[i]` returns a **borrow** (`lent T` or `mut lent T`), not an owned value.
- For scalars, use `s[i][]` (whole-deref) to get the owned value.
- `s[i] = newValue` assigns through a mutable borrow.
- Field access works through borrows: `boxes[0].value` is valid.
```peon
type Box = object { value: int64; }
var boxes = @[Box(value = 1), Box(value = 2)];
let first: mut lent Box = boxes[0];
first.value = 9;
var ints = @[1, 2, 3];
ints[1] = 7;
print(ints[1][]); # 7
```
### API
| Function | Description |
|----------|-------------|
| `newSeq[T]()` | Create an empty sequence. |
| `newSeqOfCap[T](n)` | Create an empty sequence with pre-allocated capacity. |
| `append(s, x)` | Append element `x` to the end. |
| `pop(s, i)` | Remove element at index `i`, shift tail left, return the removed value. |
| `pop(s)` | Remove and return the last element. Panics if empty. |
| `delete(s, i)` | Remove element at index `i` and discard it. |
| `len(s)` | Return the current length. |
| `low(s)` | Return `0`. |
| `high(s)` | Return `len - 1`. |
| `indexOf(s, v)` | Return `Option[int64]` with the index of the first match. |
| `items(s)` | Generator yielding `lent T` for each element. |
| `mitems(s)` | Generator yielding `mut lent T` for each element. |
| `toString(s)` | Convert to string representation (requires `T: Printable`). |
| `unsafe { get_unchecked(s, i) }` | Element access without bounds checking. |
### Implementation note
`seq[T]` stores its payload through an internal `Buffer[T]` owner cell. Element
borrows and [iterator](iterators.md) yields are anchored to the buffer storage
owner rather than the seq header. If growth moves the raw payload, the buffer
swaps to a new owner so old element borrows go stale cleanly instead of silently
dangling into moved memory.
`seq[T]` is a runtime collection. [Compile-time evaluation](../compile-time.md#ctfe-limitations)
rejects it because CTFE does not permit heap-backed sequence storage.
## Double-ended queue (`deque[T]`)
`deque[T]` is a ring-buffer-backed double-ended queue with O(1) amortized push/pop
at both ends and O(1) random access by index:
```peon
var d = newDeque[int64]();
d.pushBack(1);
d.pushBack(2);
d.pushFront(0);
print(d[0][]); # 0
print(d.popFront()); # 0
print(d.popBack()); # 2
```
### API
| Function | Description |
|----------|-------------|
| `newDeque[T](capacity = 4)` | Create a new deque with optional initial capacity. |
| `pushBack(d, v)` | Add element to the back. |
| `pushFront(d, v)` | Add element to the front. |
| `popFront(d)` | Remove and return the front element. Panics if empty. |
| `popBack(d)` | Remove and return the back element. Panics if empty. |
| `peekFront(d)` | View the front element without removing (`lent T` or `mut lent T`). |
| `peekBack(d)` | View the back element without removing (`lent T` or `mut lent T`). |
| `len(d)` | Return the current length. |
| `high(d)` | Return `len - 1`. |
| `isEmpty(d)` | Return whether the deque is empty. |
| `items(d)` | Generator yielding `lent T` for each element. |
| `mitems(d)` | Generator yielding `mut lent T` for each element. |
| `toString(d)` | Convert to string representation (requires `T: Printable`). |
| `unsafe { get_unchecked(d, i) }` | Element access without bounds checking. |
Indexing with `d[i]` and `d[i] = v` is also supported, with the same borrow
semantics as `seq[T]`.

View File

@@ -0,0 +1,21 @@
# Standard Library Reference
[Back to Manual](../index.md)
All programs implicitly `import std`, which re-exports the entire standard library.
Individual modules can also be imported directly (e.g. `import net`, `import cinterop`).
## Modules
- [Built-in Functions](builtins.md) -- `print`, `panic`, `borrow`, `clone`, `new`, `sizeof`, allocation, etc.
- [Types](types.md) -- `Option[T]`, `Result[T, E]`, primitive type details
- [Collections](collections.md) -- `array[N, T]`, `seq[T]`, `deque[T]`
- [Iterators](iterators.md) -- `Generator`, `GeneratorState`, `Iterator`, `Iterable` protocols
- [Math](math.md) -- constants (`pi`, `tau`, `e`) and functions (`sqrt`, `sin`, `cos`, etc.)
- [Strings](strings.md) -- `concat`, `join`, `+`, `+=`
- [Ranges](ranges.md) -- `InclusiveRange`, `ExclusiveRange`, `..`, `..<`
- [Async Runtime](async.md) -- `runAsync`, `AsyncCompletion`, timing/cancellation helpers, `WaitQueue`
- [Networking](net.md) -- sockets, `getAddrInfo`, `readSome`/`writeSome`
- [Time](time.md) -- `cpuTime`
- [Synchronization](sync.md) -- `Event`, `LIFOQueue`, `FIFOQueue`
- [C Interop Types](../c-interop.md) -- `cint`, `cstring`, `csize`, etc. (documented in the language manual)

View File

@@ -0,0 +1,96 @@
# Iterators and Generators
[Back to Standard Library](index.md) | [Back to Manual](../index.md)
## Iterator interfaces
The standard library defines a hierarchy of iterator and iterable
[interfaces](../interfaces.md) used by [`for` loops](../control-flow.md#for-loops):
```peon
iface Iterator[T] {
fn next(mut self): Option[T];
}
iface BorrowIterator[lent T] from Iterator[T] {
# Yields borrowed elements
}
iface MutBorrowIterator[mut lent T] from Iterator[T] {
# Yields mutable borrowed elements
}
```
`Iterator` is the base cursor protocol. `BorrowIterator` and
`MutBorrowIterator` are subtypes for iterators that yield borrowed or
mutable-borrowed elements.
Collection-side adapters produce iterators:
```peon
iface Iterable[T] {
fn iter(lent self): Iterator[T];
}
iface BorrowIterable[lent T] {
fn items(lent self): BorrowIterator[lent T];
}
iface MutBorrowIterable[mut lent T] {
fn mitems(mut self): MutBorrowIterator[mut lent T];
}
```
Types can participate in `for` loops by implementing the direct iterator
protocol (`Iterator[T]`) or one of the collection adapter protocols.
## Generators
`Generator[Yield, Send, Return]` is the built-in generator type. It implements
`Iterator[Yield]`. Generators are declared with the `generator` keyword
(see [Concurrency -- Generators](../concurrency.md#generators)):
```peon
generator fn range(start: int64, stop: int64): Generator[int64, void, void] {
var i = start;
while i < stop {
yield i;
i = i + 1;
}
}
```
- `Yield` -- the type produced by `yield`.
- `Send` -- the type callers send back on each resumption (`void` if none).
- `Return` -- the final return type when the generator completes (`void` for
generators that simply exhaust).
## `GeneratorState[Yield, Return]`
The low-level result of advancing a generator:
```peon
type GeneratorState[Yield, Return] = enum {
Yielded { value: Yield; },
Complete { value: Return; }
}
```
## Advancement functions
| Function | Description |
|----------|-------------|
| `start(g)` | Start a generator, returning `GeneratorState[Y, R]`. |
| `resume(g, v)` | Resume a generator with send value `v`, returning `GeneratorState[Y, R]`. |
| `next(it)` | Advance any iterator or generator, returning `Option[Y]`. Wraps start/resume for the common case. |
```peon
var g = range(0, 3);
match next(g) {
case Some(v) { print(v); } # 0
case None { }
}
```
For generator delegation with `yield from`, borrow safety rules, and
`#pragma[lentFrom]`, see [Concurrency -- Generators](../concurrency.md#generators).

View File

@@ -0,0 +1,47 @@
# Math
[Back to Standard Library](index.md) | [Back to Manual](../index.md)
Mathematical constants and functions. Available through the implicit `import std`.
## Constants
| Name | Value | Description |
|------|-------|-------------|
| `pi` | 3.141592653589793 | Ratio of circumference to diameter |
| `tau` | 6.283185307179586 | 2 * pi |
| `e` | 2.718281828459045 | Euler's number |
## Functions
All functions are overloaded for both `float64` and `float32`.
| Function | Description |
|----------|-------------|
| `min(a, b)` | Return the smaller of two values. Generic over `Number`. |
| `max(a, b)` | Return the larger of two values. Generic over `Number`. |
| `clamp(value, low, high)` | Clamp `value` to the range `[low, high]`. Generic over `Number`. |
| `sqrt(x)` | Square root. |
| `exp(x)` | Exponential function (e^x). |
| `ln(x)` | Natural logarithm. |
| `log(x, base)` | Logarithm with arbitrary base. Computed as `ln(x) / ln(base)`. |
| `sin(x)` | Sine. |
| `cos(x)` | Cosine. |
| `tan(x)` | Tangent. Computed as `sin(x) / cos(x)`. |
| `atan2(y, x)` | Two-argument arctangent. |
## Arithmetic operators
The standard library also provides built-in arithmetic operators for all numeric
types, including wrapping variants:
| Function | Description |
|----------|-------------|
| `wrapping_add(a, b)` | Addition with overflow wrap. |
| `wrapping_sub(a, b)` | Subtraction with overflow wrap. |
| `wrapping_mul(a, b)` | Multiplication with overflow wrap. |
| `wrapping_neg(a)` | Negation with overflow wrap. |
| `wrapping_div(a, b)` | Division with overflow wrap. |
| `wrapping_rem(a, b)` | Remainder with overflow wrap. |
The `**` power operator is defined for integer types.

132
docs/manual/stdlib/net.md Normal file
View File

@@ -0,0 +1,132 @@
# Networking
[Back to Standard Library](index.md) | [Back to Manual](../index.md)
The `net` module provides async socket I/O on top of the
[async runtime](async.md). Import it explicitly:
```peon
import net;
```
## Types
### `Fd`
A file descriptor, aliased to `int32`.
### `SocketFamily`
```peon
type SocketFamily = enum {
AnyFamily = 0,
Unix,
Inet,
Inet6
}
```
### `SocketKind`
```peon
type SocketKind = enum {
AnyKind = 0,
Stream,
Datagram
}
```
### `IOError`
```peon
type IOError = object with Printable, ImplicitCopy {
code: int32;
}
```
| Method | Description |
|--------|-------------|
| `errorCode(e)` | Return the raw error code. |
| `wouldBlock(e)` | Check if `EWOULDBLOCK`/`EAGAIN`. |
| `interrupted(e)` | Check if `EINTR`. |
| `inProgress(e)` | Check if `EINPROGRESS`. |
| `toString(e)` | String representation. |
### `SocketPair`
```peon
type SocketPair = object with ImplicitCopy {
left: Fd;
right: Fd;
}
```
| Method | Description |
|--------|-------------|
| `left(p)` | Return the left file descriptor. |
| `right(p)` | Return the right file descriptor. |
### `SocketAddress`
A resolved network address with `family`, `kind`, `protocol`, `addressLen`, and
opaque `storage`.
| Method | Description |
|--------|-------------|
| `family(a)` | Return the `SocketFamily`. |
| `kind(a)` | Return the `SocketKind`. |
| `protocol(a)` | Return the protocol number. |
| `addressLen(a)` | Return the address length. |
### `AddressInfoError`
| Method | Description |
|--------|-------------|
| `code(e)` | Return the GAI error code. |
| `toString(e)` | Human-readable error string. |
## Socket operations
| Function | Description |
|----------|-------------|
| `socket(family, kind, protocol)` | Create a non-blocking socket. Returns `Result[Fd, IOError]`. |
| `socketPair(family, kind, protocol)` | Create a connected socket pair. Returns `Result[SocketPair, IOError]`. |
| `close(fd)` | Close a file descriptor. Returns `Result[int32, IOError]`. |
| `setNonBlocking(fd)` | Set a file descriptor to non-blocking mode. |
| `bind(fd, address, addressLen)` | Bind a socket to an address. |
| `listen(fd, backlog)` | Mark a socket as listening. |
| `socketError(fd)` | Return the pending socket error as `IOError`. |
## Async I/O
All of these are `async fn` and must be called from an
[async context](../concurrency.md):
| Function | Description |
|----------|-------------|
| `connect(fd, address)` | Connect to a `SocketAddress`. Returns `Result[int32, IOError]`. |
| `connect(fd, ptr, len)` | Connect to a raw address. |
| `accept(fd, ptr, len)` | Accept a connection. Returns `Result[Fd, IOError]`. |
| `readSome(fd, buffer, count)` | Read up to `count` bytes. Returns `Result[int64, IOError]`. |
| `writeSome(fd, buffer, count)` | Write up to `count` bytes. Returns `Result[int64, IOError]`. |
All I/O functions handle `EWOULDBLOCK` and `EINTR` internally, using
[`waitReadable`/`waitWritable`](async.md#io-waiting) to suspend until the
descriptor is ready.
## Address resolution
```peon
async fn getAddrInfo(host: string, port: int64): Result[seq[SocketAddress], AddressInfoError]
async fn getAddrInfo(host: string, port: int64, family: SocketFamily,
kind: SocketKind, protocol: int64): Result[seq[SocketAddress], AddressInfoError]
```
Resolve a hostname to a sequence of `SocketAddress` values. The short form
defaults to `AnyFamily`, `AnyKind`, protocol `0`.
```peon
import net;
let addrs = runAsync(getAddrInfo("localhost", 80, Inet, Stream, 0)).unwrap();
```

View File

@@ -0,0 +1,46 @@
# Ranges
[Back to Standard Library](index.md) | [Back to Manual](../index.md)
Range types for integer iteration. Available through the implicit `import std`.
## Types
```peon
type InclusiveRange[T: Integer] = object with Iterable[T] {
start: T;
stop: T;
}
type ExclusiveRange[T: Integer] = object with Iterable[T] {
start: T;
stop: T;
}
type range[T] = InclusiveRange[T] | ExclusiveRange[T];
```
Both range types implement [`Iterable[T]`](iterators.md#iterator-interfaces),
making them usable in [`for` loops](../control-flow.md#for-loops).
## Operators
| Operator | Description |
|----------|-------------|
| `a .. b` | Create an inclusive range from `a` to `b` (both endpoints included). |
| `a ..< b` | Create an exclusive range from `a` to `b` (`b` excluded). |
## Usage
```peon
for i in 0 ..< 5 {
print(i); # 0, 1, 2, 3, 4
}
for i in 1 .. 3 {
print(i); # 1, 2, 3
}
```
Ranges produce generators via `iter()`, so they integrate with the standard
iterator protocol.

View File

@@ -0,0 +1,42 @@
# Strings
[Back to Standard Library](index.md) | [Back to Manual](../index.md)
String manipulation utilities. Available through the implicit `import std`.
For string escape sequences and literal syntax, see [Basics -- Strings](../basics.md#strings).
## Functions
| Function | Description |
|----------|-------------|
| `concat(a, b)` | Concatenate two strings. Pure function. |
| `join(parts, sep)` | Join a `seq[string]` with a separator string. |
| `join(parts)` | Join a `seq[string]` with no separator. |
| `join(parts, sep)` | Join a `seq[T: Printable]` with a separator (converts elements via `toString`). |
## Operators
| Operator | Description |
|----------|-------------|
| `a + b` | Concatenate two strings. Equivalent to `concat(a, b)`. |
| `a += b` | Append `b` to mutable string `a` in place. |
```peon
let greeting = "hello" + " " + "world";
var msg = "hi";
msg += "!";
print(msg); # hi!
```
## String indexing
Strings are immutable. Indexing returns an owned `char` value:
```peon
let text = "abc";
print(text[1]); # b
print(len(text)); # 3
print(low(text)); # 0
print(high(text)); # 2
```

View File

@@ -0,0 +1,86 @@
# Synchronization
[Back to Standard Library](index.md) | [Back to Manual](../index.md)
Async synchronization primitives for inter-task communication. These are
re-exported through `import std`.
All blocking operations in this module are `async fn` and require an
[async context](../concurrency.md).
## Event
A simple signal that tasks can wait on:
```peon
var evt = Event();
# In one task:
await evt.wait();
# In another task:
evt.set();
```
| Function | Description |
|----------|-------------|
| `Event()` | Construct a new unsignaled event. |
| `set(evt)` | Signal the event, waking all waiting tasks. No-op if already set. |
| `reset(evt)` | Reset to unsignaled. Panics if tasks are still waiting. |
| `isSet(evt)` | Return whether the event is currently signaled. |
| `wait(evt)` | `async fn` -- suspend until the event is signaled. If already signaled, yields once (checkpoint) and returns immediately. |
`Event` implements `Copy`. Cloning an event creates a fresh unsignaled copy with
an empty wait queue.
## Async queues
Bounded or unbounded queues for passing values between async tasks. When a max
size is set, `push` blocks if the queue is full and `pop` blocks if the queue
is empty.
### `LIFOQueue[T]` (stack)
Last-in, first-out ordering. Backed by a [`seq[T]`](collections.md#sequences):
```peon
var stack = newLIFOQueue[int64](maxSize = 10);
# Producer task:
await stack.push(42);
# Consumer task:
let value = await stack.pop();
```
| Function | Description |
|----------|-------------|
| `newLIFOQueue[T](maxSize = 0)` | Create a LIFO queue. `maxSize = 0` means unbounded. |
| `len(q)` | Return the current number of elements. |
| `high(q)` | Return `len - 1`. |
| `push(q, v)` | `async fn` -- push a value. Blocks if at capacity. |
| `pop(q)` | `async fn` -- pop a value. Blocks if empty. |
### `FIFOQueue[T]`
First-in, first-out ordering. Backed by a [`deque[T]`](collections.md#double-ended-queue):
```peon
var queue = newFIFOQueue[int64](maxSize = 10);
# Producer task:
await queue.push(42);
# Consumer task:
let value = await queue.pop();
```
| Function | Description |
|----------|-------------|
| `newFIFOQueue[T](maxSize = 0)` | Create a FIFO queue. `maxSize = 0` means unbounded. |
| `len(q)` | Return the current number of elements. |
| `push(q, v)` | `async fn` -- push a value. Blocks if at capacity. |
| `pop(q)` | `async fn` -- pop a value. Blocks if empty. |
Both queue types use [`WaitQueue`](async.md#waitqueue) internally to park and
wake tasks.

View File

@@ -0,0 +1,29 @@
# Time
[Back to Standard Library](index.md) | [Back to Manual](../index.md)
The `time` module provides CPU time measurement. Import it explicitly:
```peon
import time;
```
## Functions
| Function | Description |
|----------|-------------|
| `cpuTime()` | Return elapsed CPU time in seconds as `float64`. |
Implemented via the C standard library's `clock()` divided by `CLOCKS_PER_SEC`.
```peon
import time;
let start = cpuTime();
# ... do work ...
let elapsed = cpuTime() - start;
print(elapsed);
```
For async-aware timing (wall-clock sleep, deadlines), see the
[async runtime](async.md#timing-and-sleep).

138
docs/manual/stdlib/types.md Normal file
View File

@@ -0,0 +1,138 @@
# Option and Result
[Back to Standard Library](index.md) | [Back to Manual](../index.md)
The standard library provides two generic sum types for error handling and
optional values, available through the implicit `import std`.
## `Option[T]`
```peon
type Option[T] = enum {
Some { value: T; },
None
}
```
An optional value: either `Some` containing a value, or `None`.
### Constructors
| Function | Description |
|----------|-------------|
| `some(value)` | Create a `Some` variant wrapping `value`. |
| `none(T)` | Create a `None` variant for the given type. Takes a `typevar`. |
```peon
var maybe = some(42);
var nothing = none(int);
```
### Methods
| Function | Description |
|----------|-------------|
| `get(self)` | Extract the value. Panics on `None`. |
| `?` (postfix) | Unwrap `Some` or early-return `None`. See [Operators -- The `?` operator](../operators.md#the--operator-and-pragmatry). |
### Pattern matching
```peon
match maybe {
case Some(v) { print(v); }
case None { print("nothing"); }
}
```
See [Control Flow -- Pattern matching](../control-flow.md#pattern-matching) for full
match syntax.
## `Result[T, E]`
```peon
type Result[T, E] = enum {
Ok { value: T; },
Err { error: E; }
}
```
A value that is either a successful `Ok` or an error `Err`.
### Constructors
| Function | Description |
|----------|-------------|
| `Ok(value = v)` | Create an `Ok` variant. |
| `Err(error = e)` | Create an `Err` variant. |
| `Ok()` | Create a void-payload `Ok` (for `Result[void, E]`). |
```peon
let ok: Result[int64, string] = Ok(value = 7);
let err: Result[int64, string] = Err(error = "failed");
let done: Result[void, string] = Ok();
```
### Methods
| Function | Description |
|----------|-------------|
| `unwrap(result)` | Extract the `Ok` value. Panics on `Err`. |
| `unwrap(result, msg)` | Extract the `Ok` value. Panics with `msg` on `Err`. |
| `?` (postfix) | Unwrap `Ok` or early-return `Err`. See [Operators -- The `?` operator](../operators.md#the--operator-and-pragmatry). |
```peon
print(unwrap(ok)); # 7
unwrap(err, "boom"); # Panics with "boom"
```
## The `?` operator
Both `Option[T]` and `Result[T, E]` carry `#pragma[try]` and support the postfix
`?` operator for concise error propagation:
```peon
fn parse(input: string): Option[int64] {
# ...
}
fn process(input: string): Option[int64] {
let n = parse(input)?; # Unwraps Some, or returns None
return some(n + 1);
}
```
```peon
fn readFile(path: string): Result[string, string] {
# ...
}
fn processFile(path: string): Result[int64, string] {
let contents = readFile(path)?; # Unwraps Ok, or returns Err
return Ok(value = len(contents));
}
```
For the full `?` operator semantics and how to define custom try-compatible types,
see [Operators -- The `?` operator and `#pragma[try]`](../operators.md#the--operator-and-pragmatry).
## `AsyncCompletion[T]`
Returned by [`runAsync(...)`](async.md#runasync):
```peon
type AsyncCompletion[T] = enum {
Completed { value: T; },
Cancelled
}
```
| Function | Description |
|----------|-------------|
| `unwrap(result)` | Extract the `Completed` value. Panics on `Cancelled`. |
```peon
match runAsync(child()) {
case Completed(value) { print(value); }
case Cancelled { print("cancelled"); }
}
```

View File

@@ -209,158 +209,17 @@ type Bad = enum {
## Standard library types
The standard library provides `Option[T]` and `Result[T, E]`:
The standard library provides several important types built on top of the enum and
object systems described above. For full API documentation, see the
[Standard Library Reference](stdlib/index.md):
```peon
var some42 = some(42);
var noneInt = none(int);
let done: Result[void, string] = Ok();
match done {
case Ok { print("done"); }
case Err(error) { print(error); }
}
```
Both `Option[T]` and `Result[T, E]` support the [`?` operator](operators.md#the--operator-and-pragmatry)
for concise error propagation.
- [`Option[T]` and `Result[T, E]`](stdlib/types.md) -- sum types for optional values
and error handling, with [`?` operator](operators.md#the--operator-and-pragmatry) support
- [`array[N, T]`, `seq[T]`, `deque[T]`](stdlib/collections.md) -- static arrays,
growable sequences, and double-ended queues
- [`Generator`, `Iterator`, `Iterable`](stdlib/iterators.md) -- iterator protocols
for [`for` loops](control-flow.md#for-loops)
- [`net` module](stdlib/net.md) -- async networking with sockets and address resolution
- [`Event`, `LIFOQueue`, `FIFOQueue`](stdlib/sync.md) -- async synchronization primitives
For pattern matching on enum types, see [Control Flow -- Pattern matching](control-flow.md#pattern-matching).
### Static arrays
The built-in `array[N, T]` type constructor creates fixed-size arrays. Arrays can be
spelled directly, named with a type alias, or inferred from an array literal:
```
type IntVec = array[3, int64];
var a = IntVec(1, 2, 3);
var b = [1, 2, 3, 4]; # Inferred as array[4, int64]
print(a[0]); # 1
a[0] = 9;
print(len(a)); # 3
print(a[2]); # 3
```
Array access is bounds-checked at runtime when `boundChecks` is enabled
(see [Compile-Time Features -- Config symbols](compile-time.md#config-symbols)). Out-of-bounds
access panics.
Plain arrays (non-ref) are value types. Assignment moves the array -- to avoid implicit
copies, the source becomes inaccessible after the move:
```
var a = [1, 2, 3];
var b = a; # a is moved into b
b[0] = 9;
# print(a[0]); # Error: a has been moved
print(b[0]); # 9
```
To create an independent copy, use `clone` explicitly:
```
var a = [1, 2, 3];
var b = clone(a); # Explicit copy
b[0] = 9;
print(a[0]); # 1 -- a is unchanged
```
Ref arrays are heap-allocated and can be mutably borrowed:
```
type RefVec = ref array[2, int64];
var a = RefVec(4, 5);
var b = mut borrow(a);
b[1] = 7;
print(a[1]); # 7 -- a and b share the same data
```
### Sequences (`seq[T]`)
The stdlib provides `seq[T]` as a growable collection:
```peon
type Box = object {
value: int64;
}
var boxes = @[Box(value = 1), Box(value = 2)];
let first: mut lent Box = boxes[0];
first.value = 9;
var ints = @[1, 2, 3];
ints[1] = 7;
print(ints[1][]); # Scalar reads use whole-deref
```
Important `seq` indexing semantics:
- `value[index]` returns a borrow, not an owned `T`.
- Immutable indexing yields `lent T`.
- Indexing through a mutable borrow of `seq[T]` yields `mut lent T`.
- `value[index] = newValue` returns `mut lent T`.
- `unsafe { value.get_unchecked(index) }` returns the same borrow shapes as
`value[index]`, but skips the bounds check for that one access.
- When the element is a scalar or you need an owned value, use whole-deref:
`value[index][]`.
`seq[T]` is a runtime collection. It is available in native code, but compile-time
evaluation rejects it because CTFE does not permit heap-backed sequence storage.
Field access works directly through borrows, so `boxes[0].value` is valid.
Implementation note: `seq[T]` stores its payload through an internal `buffer:
Buffer[T]`
owner cell instead of keeping only a raw pointer in the sequence header. This is
what allows element borrows and iterator yields to stay tied to the backing
storage owner. If growth moves the raw payload, the buffer can swap to a new
owner so old element borrows go stale cleanly instead of silently dangling into
moved memory.
Sequences support `append` and standard queries:
```peon
var s = @[1, 2, 3];
s.append(4);
print(len(s)); # 4
print(s[3][]); # 4
```
The `@` prefix operator converts a static array to a `seq`:
```peon
var arr = [1, 2, 3];
var s = @arr; # seq[int64] with the same elements
```
### Networking (`net`)
The standard library also provides networking in `net`:
```peon
import net;
let pair = socketPair(Unix, Stream, 0).unwrap();
let addrs = runAsync(getAddrInfo("localhost", 80, Inet, Stream, 0)).unwrap();
```
The public socket-related value types are real enums:
- `SocketFamily`: `AnyFamily`, `Unix`, `Inet`, `Inet6`
- `SocketKind`: `AnyKind`, `Stream`, `Datagram`
The public address-resolution surface is:
- `getAddrInfo(host, port)`
- `getAddrInfo(host, port, family, kind, protocol)`
`host` is a `string`, `port` and `protocol` are `int64`, and `family` / `kind`
use those enums instead of raw C constants.