Nitpick Built-in Collections & Data Structures

Nitpick provides several built-in, highly optimized data structures directly mapped as compiler intrinsics. This ensures guaranteed bounds checking, error handling, and deterministic behavior without needing an external standard library.

1. User Stack Builtins (astack)

A fast, memory-budgeted scope-bound LIFO stack accessed via opaque handles. Separate from the hardware call stack and the stack memory allocation keyword.

astack(capacity?)

Initializes a new stack in the current function scope. - capacity: optional int64, default 256 slots if omitted - Returns an opaque int64 handle representing the stack. - Multiple stacks can be instantiated in the same scope.

int64:st1 = astack(64i64);   // 64-slot stack
int64:st2 = astack();        // 256-slot default

apush(handle, value)

Push a typed value onto the specified stack. - Accepts standard primitive types and pointers. - Type tag stored automatically (no manual tag management). - Returns 0 on success, or -1 on overflow.

drop apush(st1, 42i64);
drop apush(st2, 3.14f64);

apop(handle)

Pop the top value from the specified stack. Destination type inferred from assignment context. - Returns the value directly (not wrapped in Result<T>). - On underflow (empty stack), returns the unknown sentinel state. Must be checked via ok(). - On type mismatch, it triggers failsafe() (e.g. USR_DATA_CORRUPT) rather than blindly bypassing it.

int64:n = apop(st1);
if (!(n is unknown)) {
    n = ok(n);
    // safe to use n
}

apeek(handle)

Non-destructive read of the top value. - Same context-typed semantics and error behavior as apop(). - Value remains on stack.

int64:top = apeek(st1);  // reads top without removing

Auto-Cleanup

Stacks are automatically destroyed on function return (explicit return or fallthrough). No manual cleanup needed.

2. Array List Builtins (alist)

A fast, memory-budgeted scope-bound dynamic array list accessed via opaque handles.

alist(capacity?)

Initializes a new array list in the current function scope. - capacity: optional int64, default 256 slots if omitted - Returns an opaque int64 handle representing the list.

Modification

Retrieval

Utility

int64:lst = alist();
drop alpush(lst, 100i32);
int32:val = alget(lst, 0i64);

3. Built-in Hash Table (ahash)

A fast, memory-budgeted hash table accessed via opaque handles.

int64:ht = ahash(1024i64);
ahset(ht, "username", "admin");
string:name = ahget(ht, "username");
if (!(name is unknown)) {
    name = ok(name);
    // safe to use name
}

4. Generational Handles (Handle<T> and arena<T>)

Nitpick rejects raw pointer use for dynamic graphs (which lead to Use-After-Free crashes) by enforcing Generational Indexes over Arena Allocators.

arena<Node>:my_arena;
Handle<Node>:h = my_arena.alloc(Node{val: 10i32});

// Safely access, resolving to Result<Node>
Result<Node>:n = my_arena.get(h);