typetui 0.2.1

A terminal-based typing test.
Documentation
main :: () {
    stack_array: [100]int;
    stack_array[0] = 42;
    print("Stack value: %\n", stack_array[0]);
    
    heap_size := 1024;
    heap_ptr := alloc(u8, heap_size);
    defer free(heap_ptr);
    
    memset(heap_ptr, 0, heap_size);
    
    heap_int := cast(*int) heap_ptr;
    heap_int.* = 12345;
    print("Heap value: %\n", heap_int.*);
    
    int_ptr := New(int);
    defer free(int_ptr);
    int_ptr.* = 100;
    print("Typed alloc: %\n", int_ptr.*);
    
    arr_ptr := NewArray(int, 10);
    defer free(arr_ptr);
    
    for 0..9 {
        arr_ptr[it] = it * 10;
    }
    print("Array allocation: ");
    for 0..9 {
        print("% ", arr_ptr[it]);
    }
    print("\n");
    
    str := sprint("Allocated string: %", 42);
    defer free(str);
    print("%\n", str);
    
    resizable: Resizable_Array(int);
    defer free(resizable);
    
    for 0..4 {
        array_add(*resizable, it * it);
    }
    print("Resizable array: %\n", resizable);
    
    arena: Arena;
    arena_init(*arena, 1024 * 1024);
    defer arena_free(*arena);
    
    arena_val := arena_alloc(*arena, int);
    arena_val.* = 999;
    print("Arena value: %\n", arena_val.*);
    
    temp1 := arena_alloc(*arena, int);
    temp2 := arena_alloc(*arena, float64);
    temp3 := arena_alloc(*arena, string);
    temp1.* = 1;
    temp2.* = 2.5;
    temp3.* = "hello";
    
    print("Arena values: %, %, %\n", temp1.*, temp2.*, temp3.*);
    
    pool: Pool;
    pool_init(*pool, size_of(int) * 100, size_of(int));
    defer pool_free(*pool);
    
    pool_val := pool_alloc(*pool, int);
    pool_val.* = 777;
    print("Pool value: %\n", pool_val.*);
    pool_free(*pool, pool_val);
    
    src: [10]int;
    dst: [10]int;
    
    for 0..9 src[it] = it * 2;
    
    memcpy(*dst, *src, size_of(int) * 10);
    print("After memcpy: ");
    for 0..9 print("% ", dst[it]);
    print("\n");
    
    old_size := 10;
    new_size := 20;
    old_ptr := alloc(int, old_size);
    
    for 0..old_size-1 old_ptr[it] = it;
    
    new_ptr := realloc(old_ptr, int, old_size, new_size);
    defer free(new_ptr);
    
    for old_size..new_size-1 new_ptr[it] = it * 10;
    
    print("After realloc: ");
    for 0..new_size-1 print("% ", new_ptr[it]);
    print("\n");
    
    aligned_ptr := alloc_aligned(u8, 1024, 64);
    defer free_aligned(aligned_ptr);
    print("Aligned pointer: % (aligned to 64: %)
", aligned_ptr, (cast(u64) aligned_ptr) % 64 == 0);
}

Arena :: struct {
    memory: *u8;
    size: s64;
    used: s64;
}

arena_init :: (arena: *Arena, size: s64) {
    arena.memory = alloc(u8, size);
    arena.size = size;
    arena.used = 0;
}

arena_alloc :: (arena: *Arena, $T: Type) -> *T {
    size := size_of(T);
    if arena.used + size > arena.size {
        assert(false, "Arena out of memory");
        return null;
    }
    
    result := cast(*T) (arena.memory + arena.used);
    arena.used += size;
    return result;
}

arena_free :: (arena: *Arena) {
    free(arena.memory);
    arena.* = .{};
}

Pool :: struct {
    memory: *u8;
    block_size: s64;
    total_blocks: s64;
    free_list: **u8;
}

pool_init :: (pool: *Pool, total_memory: s64, block_size: s64) {
    pool.memory = alloc(u8, total_memory);
    pool.block_size = block_size;
    pool.total_blocks = total_memory / block_size;
    
    for 0..pool.total_blocks-1 {
        block := pool.memory + it * block_size;
        cast(**u8, block).* = ifx it < pool.total_blocks - 1 then pool.memory + (it + 1) * block_size else null;
    }
    pool.free_list = pool.memory;
}

pool_alloc :: (pool: *Pool, $T: Type) -> *T {
    assert(pool.free_list != null, "Pool out of memory");
    result := cast(*T) pool.free_list;
    pool.free_list = cast(**u8) pool.free_list.*;
    return result;
}

pool_free :: (pool: *Pool, ptr: *void) {
    cast(**u8, ptr).* = pool.free_list;
    pool.free_list = ptr;
}

pool_free :: (pool: *Pool) {
    free(pool.memory);
    pool.* = .{};
}

#import "Basic";