use ct

Container types for Quadrate: dynamic arrays, queues, sets, hash maps, and pairs.

All container types manage their own memory. Mutating operations return an updated copy of the container that must be captured with ->. Always call release when you are done with a container to free its memory.

use ct

Vec<i64> { data = 0 len = 0 cap = 0 } -> v
v 10 push! -> v
v 20 push! -> v
v 0 get! print nl  // 10
v release

Vec\<T> - Dynamic Array

A growable array that doubles in capacity when full.

pub struct Vec<T> {
    data: ptr
    len: i64
    cap: i64
}

Create an empty vector:

Vec<i64> { data = 0 len = 0 cap = 0 } -> v

fn push

Append an element. Grows capacity automatically.

Signature: (v:Vec<T> elem:T -- v2:Vec<T>)!

Example:

v 42 push! -> v

fn pop

Remove and return the last element.

Signature: (v:Vec<T> -- elem:T v2:Vec<T>)!

Example:

v pop! -> v -> elem

fn get

Get element at index.

Signature: (v:Vec<T> idx:i64 -- elem:T)!

Example:

v 0 get! -> first

fn set

Replace element at index.

Signature: (v:Vec<T> idx:i64 elem:T -- v2:Vec<T>)!

Example:

v 0 100 set! -> v

fn length

Signature: (v:Vec<T> -- n:i64)

v length -> n

fn capacity

Get allocated capacity (may be larger than length).

Signature: (v:Vec<T> -- n:i64)


fn is_empty

Signature: (v:Vec<T> -- b:i64)

Returns 1 if the vector has no elements.


fn reset

Remove all elements but keep allocated memory.

Signature: (v:Vec<T> -- v2:Vec<T>)

v reset -> v
v length print nl  // 0

fn release

Free the vector's memory. Always call this when done.

Signature: (v:Vec<T> --)


Deque\<T> - Double-Ended Queue

O(1) push and pop from both ends, backed by a circular buffer.

pub struct Deque<T> {
    data: ptr
    head: i64
    tail: i64
    len: i64
    cap: i64
}

Create an empty deque:

Deque<i64> { data = 0 head = 0 tail = 0 len = 0 cap = 0 } -> d

fn push_back

Signature: (d:Deque<T> val:T -- d2:Deque<T>)!

d 42 push_back! -> d

fn push_front

Signature: (d:Deque<T> val:T -- d2:Deque<T>)!

d 10 push_front! -> d

fn pop_front

Remove and return the front element.

Signature: (d:Deque<T> -- val:T d2:Deque<T>)!

d pop_front! -> d -> val

fn pop_back

Remove and return the back element.

Signature: (d:Deque<T> -- val:T d2:Deque<T>)!

d pop_back! -> d -> val

fn peek_front

View front element without removing it.

Signature: (d:Deque<T> -- val:T)!


fn peek_back

View back element without removing it.

Signature: (d:Deque<T> -- val:T)!


fn length

Signature: (d:Deque<T> -- n:i64)


fn is_empty

Signature: (d:Deque<T> -- b:i64)


fn release

Signature: (d:Deque<T> --)


Queue\<T> - FIFO Queue

First-in, first-out queue backed by a circular buffer.

pub struct Queue<T> {
    data: ptr
    head: i64
    tail: i64
    len: i64
    cap: i64
}

Create an empty queue:

Queue<i64> { data = 0 head = 0 tail = 0 len = 0 cap = 0 } -> q

fn enqueue

Add an element to the back of the queue.

Signature: (q:Queue<T> val:T -- q2:Queue<T>)!

Example:

q 42 enqueue! -> q

fn dequeue

Remove and return the front element.

Signature: (q:Queue<T> -- val:T q2:Queue<T>)!

Example:

q dequeue! -> q -> val

fn peek

View front element without removing it.

Signature: (q:Queue<T> -- val:T)!


fn length

Signature: (q:Queue<T> -- n:i64)


fn is_empty

Signature: (q:Queue<T> -- b:i64)


fn release

Signature: (q:Queue<T> --)


Set - String Set

A set of unique strings with O(1) average-case lookup. Uses open addressing with linear probing and tombstone deletion.

pub struct Set {
    keys: ptr
    states: ptr
    len: i64
    cap: i64
}

Create an empty set:

Set { keys = 0 states = 0 len = 0 cap = 0 } -> s

fn add

Add a string element. Duplicates are silently ignored.

Signature: (s:Set key:str -- s2:Set)!

Example:

s "alice" add! -> s
s "alice" add! -> s  // no effect, already present

fn contains

Check if a string is in the set.

Signature: (s:Set key:str -- exists:i64)

Output Type Description
exists i64 1 if found, 0 otherwise

Example:

s "alice" contains if { "found" print nl }

fn remove

Remove a string from the set. Errors if not found.

Signature: (s:Set key:str -- s2:Set)!


fn length

Signature: (s:Set -- n:i64)


fn is_empty

Signature: (s:Set -- b:i64)


fn release

Signature: (s:Set --)


Map\<V> - String-Keyed Hash Map

A hash map where keys are strings and values can be any type V. O(1) average-case lookup using open addressing with linear probing.

pub struct Map<V> {
    keys: ptr
    values: ptr
    states: ptr
    len: i64
    cap: i64
}

Create an empty map:

Map<i64> { keys = 0 values = 0 states = 0 len = 0 cap = 0 } -> m

fn insert

Insert or update a key-value pair.

Signature: (m:Map<V> key:str value:V -- m2:Map<V>)!

Example:

m "alice" 42 insert! -> m
m "alice" 99 insert! -> m  // overwrites, length stays 1

fn get

Look up a value by key. Errors if the key does not exist.

Signature: (m:Map<V> key:str -- value:V)!

Example:

m "alice" get! -> age

fn has

Check if a key exists without retrieving its value.

Signature: (m:Map<V> key:str -- exists:i64)

Output Type Description
exists i64 1 if found, 0 otherwise

Example:

m "alice" has if { "found" print nl }

fn remove

Remove a key. Errors if the key does not exist.

Signature: (m:Map<V> key:str -- m2:Map<V>)!


fn length

Signature: (m:Map<V> -- n:i64)


fn is_empty

Signature: (m:Map<V> -- b:i64)


fn release

Signature: (m:Map<V> --)


Pair\<T, U> - Two-Element Tuple

A generic pair holding two values of possibly different types.

pub struct Pair<T, U> {
    first: T
    second: U
}

Create a pair:

Pair<i64, i64> { first = 42 second = 99 } -> p

Accessing fields

Read fields with @:

p @first -> a
p @second -> b

fn first

Signature: (p:Pair<T,U> -- a:T)

fn second

Signature: (p:Pair<T,U> -- b:U)

fn unpack

Get both elements at once.

Signature: (p:Pair<T,U> -- a:T b:U)

Example:

p unpack -> b -> a

Complete example

use ct

fn main() {
    // Build a Vec of scores
    Vec<i64> { data = 0 len = 0 cap = 0 } -> scores
    scores 10 push! -> scores
    scores 20 push! -> scores
    scores 30 push! -> scores
    scores 1 get! print nl  // 20
    scores release

    // Use a Deque as a sliding window
    Deque<i64> { data = 0 head = 0 tail = 0 len = 0 cap = 0 } -> window
    window 1 push_back! -> window
    window 2 push_back! -> window
    window 3 push_back! -> window
    window pop_front! -> window -> oldest
    oldest print nl  // 1
    window release

    // Process jobs in order with a Queue
    Queue<i64> { data = 0 head = 0 tail = 0 len = 0 cap = 0 } -> jobs
    jobs 100 enqueue! -> jobs
    jobs 200 enqueue! -> jobs
    jobs dequeue! -> jobs -> job
    job print nl  // 100
    jobs release

    // Track unique visitors with a Set
    Set { keys = 0 states = 0 len = 0 cap = 0 } -> visitors
    visitors "alice" add! -> visitors
    visitors "bob" add! -> visitors
    visitors "alice" add! -> visitors  // duplicate, ignored
    visitors length print nl  // 2
    visitors release

    // Store ages in a Map
    Map<i64> { keys = 0 values = 0 states = 0 len = 0 cap = 0 } -> ages
    ages "alice" 30 insert! -> ages
    ages "bob" 25 insert! -> ages
    ages "alice" get! print nl  // 30
    ages release

    // Bundle two values with a Pair
    Pair<i64, i64> { first = 640 second = 480 } -> size
    size unpack -> h -> w
    w print " x " print h print nl  // 640 x 480
}