diff --git a/base.cpp b/base.cpp index e71163a..c79a87a 100644 --- a/base.cpp +++ b/base.cpp @@ -143,6 +143,7 @@ struct String{ U8 *str; S64 len; }; +global String string_null = {(U8 *)"null", 4}; union Intern_String{ // Basically just String String s; @@ -157,12 +158,6 @@ struct Allocator { Deallocate *deallocate; }; -global String string_null = {(U8 *)"null", 4}; -#include -#define STB_SPRINTF_IMPLEMENTATION -#include "stb_sprintf.h" -#define snprintf stbsp_snprintf - //----------------------------------------------------------------------------- // Utilities //----------------------------------------------------------------------------- @@ -527,606 +522,3 @@ arena_sub(Arena *base, size_t size, String debug_name) { result.len = 0; return result; } - -//----------------------------------------------------------------------------- -// Array -//----------------------------------------------------------------------------- -template -struct Array{ - Allocator *allocator; - T *data; - S64 cap; - S64 len; - - T *push_empty(S64 count = 1){ - grow(count); - T *result = data + len; - len += count; - return result; - } - - T *push_empty_zero(S64 count = 1){ - T *result = push_empty(count); - memory_zero(result, count*sizeof(T)); - return result; - } - - void grow(S64 required_size){ - if(cap == 0){ - S64 new_cap = max(required_size*2, (S64)16); - data = allocate_array(allocator, T, new_cap); - cap = new_cap; - } - else if(len + required_size > cap){ - U64 new_cap = max(cap * 2, len+required_size+1); - T *new_data = allocate_array(allocator, T, new_cap); - memory_copy(new_data, data, cap*sizeof(T)); - deallocate(allocator, data); - data = new_data; - cap = new_cap; - } - } - - S64 get_index(T *item){ - assert((data <= item) && ((data + len) > item)); - size_t offset = item - data; - return (S64)offset; - } - - void add(Array items){ - For(items){ - add(it); - } - } - - void add(T item){ - grow(1); - data[len++] = item; - } - - S64 addi(T item){ - S64 result = len; - grow(1); - data[len++] = item; - return result; - } - - void unordered_remove(T *item){ - assert(len > 0); - assert((data <= item) && ((data + len) > item)); - *item = data[--len]; - } - - void init(Allocator *a, S64 size = 16){ - allocator = a; - data = allocate_array(a, T, size); - cap = size; - } - - Array copy(Allocator *a){ - Array result = {}; - result.len = len; - result.cap = len*2; - result.allocator = a; - result.data = allocate_array(a, T, result.cap); - memory_copy(result.data, data, sizeof(T)*result.len); - return result; - } - - Array tight_copy(Allocator *a){ - Array result = {}; - result.len = len; - result.cap = len; - result.allocator = 0; - result.data = allocate_array(a, T, len); - memory_copy(result.data, data, sizeof(T)*len); - return result; - } - - force_inline B32 is_last(T *item){ return item == last(); } - force_inline B32 is_first(T *item){ return item == begin(); } - force_inline void clear(){ len = 0; } - force_inline T pop() { return data[--len]; } - force_inline T *last() { return data + len - 1; } - force_inline T *begin() { return data; } - force_inline T *end () { return data + len; } - force_inline T &operator[](S64 i){ assert(i >= 0 && i < cap); return data[i]; } - - struct Array_Iter{ - Array *array; - S64 i; - T *item; - - force_inline void next(){ i+=1; item = &array->data[i]; } - force_inline B32 is_valid(){ return i < array->len; } - }; - - force_inline Array_Iter iter(){ return {this, 0, begin()};} - #define For_It_Named(array, it) for(auto it = (array).iter(); it.is_valid(); it.next()) - #define For_It(array) For_It_Named(array, it) -}; - - -template -CORE_Static Array -array_make(Allocator *a, S64 size = 16){ - Array result = {}; - result.init(a, size); - return result; -} - -#include "base_string.cpp" - -//----------------------------------------------------------------------------- -// Defer -// http://www.gingerbill.org/article/2015/08/19/defer-in-cpp/ -//----------------------------------------------------------------------------- -template -struct Defer_Scope { - F f; - Defer_Scope(F f) : f(f) {} - ~Defer_Scope() { f(); } -}; - -template -Defer_Scope defer_func(F f) { - return Defer_Scope(f); -} -#define DEFER_1(x, y) x##y -#define DEFER_2(x, y) DEFER_1(x, y) -#define DEFER_3(x) DEFER_2(x, __COUNTER__) -#define defer(code) auto DEFER_3(_defer_) = defer_func([&](){code;}) - -//----------------------------------------------------------------------------- -// Map -//----------------------------------------------------------------------------- -struct Map_Key_Value{ - int occupied; - U64 key; - void *value; -}; - -struct Map{ - Allocator *allocator; - Map_Key_Value *data; - S64 len; - S64 cap; -}; -CORE_Static void map_insert(Map *map, U64 key, void *val); - -CORE_Static void -map_grow(Map *map, S64 new_size){ - new_size = max((S64)16, new_size); - assert(new_size > map->cap); - assert(is_pow2(new_size)); - assert(map->allocator); - - Map new_map = {}; - new_map.data = allocate_array(map->allocator, Map_Key_Value, new_size); - new_map.cap = new_size; - new_map.allocator = map->allocator; - - for(S64 i = 0; i < map->cap; i++){ - if(map->data[i].occupied){ - map_insert(&new_map, map->data[i].key, map->data[i].value); - } - } - if(map->data) deallocate(map->allocator, map->data); - *map = new_map; -} - -CORE_Static Map -map_make(Allocator *a, S64 size){ - Map result = {a}; - map_grow(&result, size); - return result; -} - -CORE_Static void -map_insert(Map *map, U64 key, void *val){ - assert(val); - assert(key); - // if(key == 0) key+=1; - - if((2*map->len) + 1 > map->cap){ - map_grow(map, 2*map->cap); - } - - U64 hash = hash_u64(key); - U64 index = wrap_around_pow2(hash, map->cap); - U64 i = index; - for(;;){ - if(map->data[i].occupied == false){ - map->len++; - map->data[i].occupied = true; - map->data[i].key = key; - map->data[i].value = val; - return; - } - else if(map->data[i].key == key){ - map->data[i].value = val; - return; - } - - i = wrap_around_pow2(i+1, map->cap); - if(i == map->cap){ - return; - } - } -} - -CORE_Static Map_Key_Value * -map_base_get(Map *map, U64 key){ - if(map->len == 0) return 0; - assert(key); - - U64 hash = hash_u64(key); - U64 index = wrap_around_pow2(hash, map->cap); - U64 i = index; - for(;;){ - if(map->data[i].key == key){ - return map->data + i; - } - else if(map->data[i].key == 0){ - return 0; - } - - i = wrap_around_pow2(i+1, map->cap); - if(i == map->cap){ - return 0; - } - } -} - -CORE_Static void * -map_get(Map *map, U64 key){ - Map_Key_Value *result = map_base_get(map, key); - if(result && result->occupied) return result->value; - return 0; -} - -CORE_Static void * -map_remove(Map *map, U64 key){ - Map_Key_Value *kv = map_base_get(map, key); - if(kv){ - kv->occupied = false; - return kv->value; - } - return 0; -} - -CORE_Static void * -map_get(Map *map, void *pointer){ - return map_get(map, (U64)pointer); -} - -CORE_Static void * -map_get(Map *map, Intern_String string){ - return map_get(map, hash_string(string.s)); -} - -CORE_Static void -map_insert(Map *map, void *key, void *value){ - map_insert(map, (U64)key, value); -} - -CORE_Static void -map_insert(Map *map, Intern_String key, void *value){ - map_insert(map, hash_string(key.s), value); -} - -//----------------------------------------------------------------------------- -// String intern -//----------------------------------------------------------------------------- -struct Intern_Table{ - Allocator *string_allocator; - Map map; - U8 *first_keyword; - U8 *last_keyword; -}; - -CORE_Static Intern_Table -intern_table_make(Allocator *string_allocator, Allocator *map_allocator, S64 initial_size = 32){ - Intern_Table result = {}; - result.map = map_make(map_allocator, initial_size); - result.string_allocator = string_allocator; - return result; -} - -CORE_Static Intern_String -intern_string(Intern_Table *t, String string){ - assert(t->string_allocator); - U64 hash = hash_string(string); - U8 *slot = (U8 *)map_get(&t->map, hash); - if(slot){ - // @todo: Is this a cast bug: *(slot-sizeof(S64))? slot is u8 so truncates? - Intern_String result = {{slot, *(slot-sizeof(S64))}}; - return result; - } - - S64 *len_address = (S64 *)allocate_size(t->string_allocator, string.len+1+sizeof(S64), false); - *len_address = string.len; - - U8 *string_address = (U8 *)(len_address + 1); - memory_copy(string_address, string.str, string.len); - string_address[string.len] = 0; - - map_insert(&t->map, hash, string_address); - Intern_String result = {{string_address, *len_address}}; - - return result; -} - -//----------------------------------------------------------------------------- -// Array List -// @todo(krzosa): If even one item got removed from block -// the block should go on free list -//----------------------------------------------------------------------------- -const int LIST_DEFAULT_BLOCK_SIZE = 32; -const int LIST_DEFAULT_ALLOCATION_MUL = 2; - -template -struct List_Node{ - List_Node *next; - List_Node *prev; - int cap; - int len; - T data[]; -}; - -template -struct List{ - int block_size = 0; - int allocation_multiplier = 0; - List_Node *first = 0; - List_Node *last = 0; - List_Node *first_free = 0; -}; - -template -List_Node *list_allocate_node(Allocator *arena, int size){ - auto node = (List_Node *)allocate_size(arena, sizeof(List_Node) + size*sizeof(T), false); - node->cap = size; - node->len = 0; - node->next = 0; - node->prev = 0; - return node; -} - -template -void list_allocate_free_node(Allocator *arena, List *list, int size){ - List_Node *node = list_allocate_node(arena, size); - DLL_STACK_ADD(list->first_free, node); -} - -template -void list_make_sure_there_is_room_for_item_count(Allocator *arena, List *list, int item_count){ - if(list->last == 0 || list->last->len + item_count > list->last->cap){ - // Not enough space we need to get a new block - List_Node *node = 0; - - // Iterate the free list to check if we have a block of required size there - For_Linked_List(list->first_free){ - if(it->cap >= item_count){ - DLL_STACK_REMOVE(list->first_free, it); - node = it; - node->len = 0; - break; - } - } - - // We don't have a block on the free list need to allocate - if(!node){ - // Set default values if not initialized - if(!list->allocation_multiplier) list->allocation_multiplier = LIST_DEFAULT_ALLOCATION_MUL; - if(!list->block_size) list->block_size = LIST_DEFAULT_BLOCK_SIZE; - - if(item_count > list->block_size) - list->block_size = item_count*2; - node = list_allocate_node(arena, list->block_size); - list->block_size *= list->allocation_multiplier; - } - - assert(node); - DLL_QUEUE_ADD_LAST(list->first, list->last, node); - } -} - -template -T *list_get(List *list, int index, List_Node **node = 0, int *in_block_index = 0){ - if(list){ - int i = 0; - For_Linked_List(list->first){ - int lookup_i = index - i; - if(lookup_i < it->len) { - if(node) *node = it; - if(in_block_index) *in_block_index = lookup_i; - return it->data + lookup_i; - } - i += it->len; - } - } - return 0; -} - -template -T *getp(List *list, int index){ - return list_get(list, index); -} - -template -T get(List *list, int index){ - return *list_get(list, index); -} - -template -void add(Allocator *arena, List *list, T item){ - list_make_sure_there_is_room_for_item_count(arena, list, 1); - list->last->data[list->last->len++] = item; -} - -template -T *add_size(Allocator *arena, List *list, int count = 1, int zero_memory = 0){ - list_make_sure_there_is_room_for_item_count(arena, list, count); - T *result = list->last->data + list->last->len; - list->last->len += count; - - if(zero_memory){ - memory_zero(result, sizeof(T)*count); - } - - return result; -} - -template -void list_free_node(List *list, List_Node *node){ -#if 1 - // Make sure it's actually in list list - bool found = false; - For_Linked_List(list->first){ - if(it == node){ - found = true; - break; - } - } - assert(found); -#endif - - DLL_QUEUE_REMOVE(list->first, list->last, node); - DLL_STACK_ADD(list->first_free, node); -} - -template -void clear(List *list){ - memory_zero(list, sizeof(List)); -} - -template -int length(List *list){ - int result = 0; - For_Linked_List(list->first){ - result += it->len; - } - return result; -} - -template -void free_all_nodes(List *list){ - assert(!list->last->next); - assert(!list->first->prev); - list->last->next = list->first_free; - if(list->first_free) list->first_free->prev = list->last; - list->first_free = list->first; - list->last = list->first = 0; -} - -template -T ordered_remove(List *list, int index){ - List_Node *node; int in_block_index; - T *data = list_get(list, index, &node, &in_block_index); - - assert_message(data, "Trying to unordered_remove element that's outside of the List"); - if(!data) - return {}; - - T result = *data; - - // Check if we need to deallocate the block - if(node->len == 1) { - list_free_node(list, node); - return result; - } - - // We need to move part of the block to fill the new empty spot - int right_count = (--node->len) - in_block_index; - memory_copy(data, data+1, sizeof(T)*right_count); - return result; -} - -template -T unordered_remove(List *list, int index){ - List_Node *node; - T *data = list_get(list, index, &node); - - assert_message(data, "Trying to unordered_remove element that's outside of the List"); - if(!data) - return {}; - - assert(node->len); - assert(node->cap); - - // Swap - T result = *data; - *data = node->data[node->len - 1]; - - node->len -= 1; - if(node->len == 0){ - list_free_node(list, node); - } - - return result; -} - -template -T pop(List *list){ - assert(list->last != 0); - assert(list->last->len > 0); - T result = list->last->data[--list->last->len]; - if(list->last->len == 0){ - list_free_node(list, list->last); - } - return result; -} - -template -T *merge(Allocator *arena, List *list){ - int len = length(list); - T *result = allocate_size(arena, T, len, false); - - int i = 0; - For_Linked_List(list->first){ - memory_copy(result + i, it->data, it->len*sizeof(T)); - i += it->len; - } - - return result; -} - -template -struct List_Iter{ - T *item; - int index; - List_Node *node; - int node_index; -}; - -template -void advance(List_Iter *iter){ - if(!iter->node) return; - - if(iter->node_index + 1 >= iter->node->len){ - iter->node = iter->node->next; - iter->node_index = -1; - iter->item = 0; - } - - if(iter->node){ - iter->node_index += 1; - iter->index += 1; - iter->item = iter->node->data + iter->node_index; - } -} - -template -List_Iter iterate(List *list){ - List_Iter result = {}; - result.node = list->first; - result.index = result.node_index = -1; - advance(&result); - return result; -} - -template -bool should_we_continue(List_Iter *iter){ - return iter->item != 0; -} diff --git a/core_arena.cpp b/base_arena.cpp similarity index 98% rename from core_arena.cpp rename to base_arena.cpp index 614264f..cc1bc88 100644 --- a/core_arena.cpp +++ b/base_arena.cpp @@ -1,4 +1,4 @@ -constexpr size_t ARENA_BLOCK_SIZE = mib(1); +constexpr size_t ARENA_BLOCK_SIZE = mib(4); constexpr size_t ARENA_ALIGNMENT = 8; struct Scratch_Arena : Allocator { diff --git a/base_data_structures.cpp b/base_data_structures.cpp new file mode 100644 index 0000000..2013d09 --- /dev/null +++ b/base_data_structures.cpp @@ -0,0 +1,581 @@ + +//----------------------------------------------------------------------------- +// Array +//----------------------------------------------------------------------------- +template +struct Array{ + Allocator *allocator; + T *data; + S64 cap; + S64 len; + + T *push_empty(S64 count = 1){ + grow(count); + T *result = data + len; + len += count; + return result; + } + + T *push_empty_zero(S64 count = 1){ + T *result = push_empty(count); + memory_zero(result, count*sizeof(T)); + return result; + } + + void grow(S64 required_size){ + if(cap == 0){ + S64 new_cap = max(required_size*2, (S64)16); + data = allocate_array(allocator, T, new_cap); + cap = new_cap; + } + else if(len + required_size > cap){ + U64 new_cap = max(cap * 2, len+required_size+1); + T *new_data = allocate_array(allocator, T, new_cap); + memory_copy(new_data, data, cap*sizeof(T)); + deallocate(allocator, data); + data = new_data; + cap = new_cap; + } + } + + S64 get_index(T *item){ + assert((data <= item) && ((data + len) > item)); + size_t offset = item - data; + return (S64)offset; + } + + void add(Array items){ + For(items){ + add(it); + } + } + + void add(T item){ + grow(1); + data[len++] = item; + } + + S64 addi(T item){ + S64 result = len; + grow(1); + data[len++] = item; + return result; + } + + void unordered_remove(T *item){ + assert(len > 0); + assert((data <= item) && ((data + len) > item)); + *item = data[--len]; + } + + void init(Allocator *a, S64 size = 16){ + allocator = a; + data = allocate_array(a, T, size); + cap = size; + } + + Array copy(Allocator *a){ + Array result = {}; + result.len = len; + result.cap = len*2; + result.allocator = a; + result.data = allocate_array(a, T, result.cap); + memory_copy(result.data, data, sizeof(T)*result.len); + return result; + } + + Array tight_copy(Allocator *a){ + Array result = {}; + result.len = len; + result.cap = len; + result.allocator = 0; + result.data = allocate_array(a, T, len); + memory_copy(result.data, data, sizeof(T)*len); + return result; + } + + force_inline B32 is_last(T *item){ return item == last(); } + force_inline B32 is_first(T *item){ return item == begin(); } + force_inline void clear(){ len = 0; } + force_inline T pop() { return data[--len]; } + force_inline T *last() { return data + len - 1; } + force_inline T *begin() { return data; } + force_inline T *end () { return data + len; } + force_inline T &operator[](S64 i){ assert(i >= 0 && i < cap); return data[i]; } + + struct Array_Iter{ + Array *array; + S64 i; + T *item; + + force_inline void next(){ i+=1; item = &array->data[i]; } + force_inline B32 is_valid(){ return i < array->len; } + }; + + force_inline Array_Iter iter(){ return {this, 0, begin()};} +#define For_It_Named(array, it) for(auto it = (array).iter(); it.is_valid(); it.next()) +#define For_It(array) For_It_Named(array, it) +}; + + +template +CORE_Static Array +array_make(Allocator *a, S64 size = 16){ + Array result = {}; + result.init(a, size); + return result; +} + +//----------------------------------------------------------------------------- +// Map +//----------------------------------------------------------------------------- +struct Map_Key_Value{ + int occupied; + U64 key; + void *value; +}; + +struct Map{ + Allocator *allocator; + Map_Key_Value *data; + S64 len; + S64 cap; +}; +CORE_Static void map_insert(Map *map, U64 key, void *val); + +CORE_Static void + map_grow(Map *map, S64 new_size){ + new_size = max((S64)16, new_size); + assert(new_size > map->cap); + assert(is_pow2(new_size)); + assert(map->allocator); + + Map new_map = {}; + new_map.data = allocate_array(map->allocator, Map_Key_Value, new_size); + new_map.cap = new_size; + new_map.allocator = map->allocator; + + for(S64 i = 0; i < map->cap; i++){ + if(map->data[i].occupied){ + map_insert(&new_map, map->data[i].key, map->data[i].value); + } + } + if(map->data) deallocate(map->allocator, map->data); + *map = new_map; +} + +CORE_Static Map + map_make(Allocator *a, S64 size){ + Map result = {a}; + map_grow(&result, size); + return result; +} + +CORE_Static void + map_insert(Map *map, U64 key, void *val){ + assert(val); + assert(key); + // if(key == 0) key+=1; + + if((2*map->len) + 1 > map->cap){ + map_grow(map, 2*map->cap); + } + + U64 hash = hash_u64(key); + U64 index = wrap_around_pow2(hash, map->cap); + U64 i = index; + for(;;){ + if(map->data[i].occupied == false){ + map->len++; + map->data[i].occupied = true; + map->data[i].key = key; + map->data[i].value = val; + return; + } + else if(map->data[i].key == key){ + map->data[i].value = val; + return; + } + + i = wrap_around_pow2(i+1, map->cap); + if(i == map->cap){ + return; + } + } +} + +CORE_Static Map_Key_Value * + map_base_get(Map *map, U64 key){ + if(map->len == 0) return 0; + assert(key); + + U64 hash = hash_u64(key); + U64 index = wrap_around_pow2(hash, map->cap); + U64 i = index; + for(;;){ + if(map->data[i].key == key){ + return map->data + i; + } + else if(map->data[i].key == 0){ + return 0; + } + + i = wrap_around_pow2(i+1, map->cap); + if(i == map->cap){ + return 0; + } + } +} + +CORE_Static void * + map_get(Map *map, U64 key){ + Map_Key_Value *result = map_base_get(map, key); + if(result && result->occupied) return result->value; + return 0; +} + +CORE_Static void * + map_remove(Map *map, U64 key){ + Map_Key_Value *kv = map_base_get(map, key); + if(kv){ + kv->occupied = false; + return kv->value; + } + return 0; +} + +CORE_Static void * + map_get(Map *map, void *pointer){ + return map_get(map, (U64)pointer); +} + +CORE_Static void * + map_get(Map *map, Intern_String string){ + return map_get(map, hash_string(string.s)); +} + +CORE_Static void + map_insert(Map *map, void *key, void *value){ + map_insert(map, (U64)key, value); +} + +CORE_Static void + map_insert(Map *map, Intern_String key, void *value){ + map_insert(map, hash_string(key.s), value); +} + +//----------------------------------------------------------------------------- +// String intern +//----------------------------------------------------------------------------- +struct Intern_Table{ + Allocator *string_allocator; + Map map; + U8 *first_keyword; + U8 *last_keyword; +}; + +CORE_Static Intern_Table + intern_table_make(Allocator *string_allocator, Allocator *map_allocator, S64 initial_size = 32){ + Intern_Table result = {}; + result.map = map_make(map_allocator, initial_size); + result.string_allocator = string_allocator; + return result; +} + +CORE_Static Intern_String + intern_string(Intern_Table *t, String string){ + assert(t->string_allocator); + U64 hash = hash_string(string); + U8 *slot = (U8 *)map_get(&t->map, hash); + if(slot){ + // @todo: Is this a cast bug: *(slot-sizeof(S64))? slot is u8 so truncates? + Intern_String result = {{slot, *(slot-sizeof(S64))}}; + return result; + } + + S64 *len_address = (S64 *)allocate_size(t->string_allocator, string.len+1+sizeof(S64), false); + *len_address = string.len; + + U8 *string_address = (U8 *)(len_address + 1); + memory_copy(string_address, string.str, string.len); + string_address[string.len] = 0; + + map_insert(&t->map, hash, string_address); + Intern_String result = {{string_address, *len_address}}; + + return result; +} + +//----------------------------------------------------------------------------- +// Array List +// @todo(krzosa): If even one item got removed from block +// the block should go on free list +//----------------------------------------------------------------------------- +const int LIST_DEFAULT_BLOCK_SIZE = 32; +const int LIST_DEFAULT_ALLOCATION_MUL = 2; + +template +struct List_Node{ + List_Node *next; + List_Node *prev; + int cap; + int len; + T data[]; +}; + +template +struct List{ + int block_size = 0; + int allocation_multiplier = 0; + List_Node *first = 0; + List_Node *last = 0; + List_Node *first_free = 0; +}; + +template +List_Node *list_allocate_node(Allocator *arena, int size){ + auto node = (List_Node *)allocate_size(arena, sizeof(List_Node) + size*sizeof(T), false); + node->cap = size; + node->len = 0; + node->next = 0; + node->prev = 0; + return node; +} + +template +void list_allocate_free_node(Allocator *arena, List *list, int size){ + List_Node *node = list_allocate_node(arena, size); + DLL_STACK_ADD(list->first_free, node); +} + +template +void list_make_sure_there_is_room_for_item_count(Allocator *arena, List *list, int item_count){ + if(list->last == 0 || list->last->len + item_count > list->last->cap){ + // Not enough space we need to get a new block + List_Node *node = 0; + + // Iterate the free list to check if we have a block of required size there + For_Linked_List(list->first_free){ + if(it->cap >= item_count){ + DLL_STACK_REMOVE(list->first_free, it); + node = it; + node->len = 0; + break; + } + } + + // We don't have a block on the free list need to allocate + if(!node){ + // Set default values if not initialized + if(!list->allocation_multiplier) list->allocation_multiplier = LIST_DEFAULT_ALLOCATION_MUL; + if(!list->block_size) list->block_size = LIST_DEFAULT_BLOCK_SIZE; + + if(item_count > list->block_size) + list->block_size = item_count*2; + node = list_allocate_node(arena, list->block_size); + list->block_size *= list->allocation_multiplier; + } + + assert(node); + DLL_QUEUE_ADD_LAST(list->first, list->last, node); + } +} + +template +T *list_get(List *list, int index, List_Node **node = 0, int *in_block_index = 0){ + if(list){ + int i = 0; + For_Linked_List(list->first){ + int lookup_i = index - i; + if(lookup_i < it->len) { + if(node) *node = it; + if(in_block_index) *in_block_index = lookup_i; + return it->data + lookup_i; + } + i += it->len; + } + } + return 0; +} + +template +T *getp(List *list, int index){ + return list_get(list, index); +} + +template +T get(List *list, int index){ + return *list_get(list, index); +} + +template +void add(Allocator *arena, List *list, T item){ + list_make_sure_there_is_room_for_item_count(arena, list, 1); + list->last->data[list->last->len++] = item; +} + +template +T *add_size(Allocator *arena, List *list, int count = 1, int zero_memory = 0){ + list_make_sure_there_is_room_for_item_count(arena, list, count); + T *result = list->last->data + list->last->len; + list->last->len += count; + + if(zero_memory){ + memory_zero(result, sizeof(T)*count); + } + + return result; +} + +template +void list_free_node(List *list, List_Node *node){ +#if 1 + // Make sure it's actually in list list + bool found = false; + For_Linked_List(list->first){ + if(it == node){ + found = true; + break; + } + } + assert(found); +#endif + + DLL_QUEUE_REMOVE(list->first, list->last, node); + DLL_STACK_ADD(list->first_free, node); +} + +template +void clear(List *list){ + memory_zero(list, sizeof(List)); +} + +template +int length(List *list){ + int result = 0; + For_Linked_List(list->first){ + result += it->len; + } + return result; +} + +template +void free_all_nodes(List *list){ + assert(!list->last->next); + assert(!list->first->prev); + list->last->next = list->first_free; + if(list->first_free) list->first_free->prev = list->last; + list->first_free = list->first; + list->last = list->first = 0; +} + +template +T ordered_remove(List *list, int index){ + List_Node *node; int in_block_index; + T *data = list_get(list, index, &node, &in_block_index); + + assert_message(data, "Trying to unordered_remove element that's outside of the List"); + if(!data) + return {}; + + T result = *data; + + // Check if we need to deallocate the block + if(node->len == 1) { + list_free_node(list, node); + return result; + } + + // We need to move part of the block to fill the new empty spot + int right_count = (--node->len) - in_block_index; + memory_copy(data, data+1, sizeof(T)*right_count); + return result; +} + +template +T unordered_remove(List *list, int index){ + List_Node *node; + T *data = list_get(list, index, &node); + + assert_message(data, "Trying to unordered_remove element that's outside of the List"); + if(!data) + return {}; + + assert(node->len); + assert(node->cap); + + // Swap + T result = *data; + *data = node->data[node->len - 1]; + + node->len -= 1; + if(node->len == 0){ + list_free_node(list, node); + } + + return result; +} + +template +T pop(List *list){ + assert(list->last != 0); + assert(list->last->len > 0); + T result = list->last->data[--list->last->len]; + if(list->last->len == 0){ + list_free_node(list, list->last); + } + return result; +} + +template +T *merge(Allocator *arena, List *list){ + int len = length(list); + T *result = allocate_size(arena, T, len, false); + + int i = 0; + For_Linked_List(list->first){ + memory_copy(result + i, it->data, it->len*sizeof(T)); + i += it->len; + } + + return result; +} + +template +struct List_Iter{ + T *item; + int index; + List_Node *node; + int node_index; +}; + +template +void advance(List_Iter *iter){ + if(!iter->node) return; + + if(iter->node_index + 1 >= iter->node->len){ + iter->node = iter->node->next; + iter->node_index = -1; + iter->item = 0; + } + + if(iter->node){ + iter->node_index += 1; + iter->index += 1; + iter->item = iter->node->data + iter->node_index; + } +} + +template +List_Iter iterate(List *list){ + List_Iter result = {}; + result.node = list->first; + result.index = result.node_index = -1; + advance(&result); + return result; +} + +template +bool should_we_continue(List_Iter *iter){ + return iter->item != 0; +} diff --git a/base_string.cpp b/base_string.cpp index a54e403..90294d2 100644 --- a/base_string.cpp +++ b/base_string.cpp @@ -459,7 +459,6 @@ string_from_cstring(char *string){ return result; } -#include "core_arena.cpp" // @! Move this include struct String_Replace { String find; String replace; diff --git a/core_compiler.cpp b/core_compiler.cpp index ab222cd..28c8ffc 100644 --- a/core_compiler.cpp +++ b/core_compiler.cpp @@ -1,20 +1,21 @@ CORE_Static void -core_init_compiler(Core_Ctx *ctx, Arena *perm, Allocator *heap) { +core_init_compiler(Core_Ctx *ctx, Allocator *allocator) { ctx->init_ctx_time_begin = os_time(); pctx = ctx; - ctx->scratch = allocate_scratch_arena(perm, mib(1)); - ctx->perm = perm; - ctx->heap = heap; - ctx->type_map = map_make(heap, 2048); + ctx->perm_push_only = make_push_arena(allocator); + ctx->perm = &ctx->perm_push_only; + ctx->scratch = allocate_scratch_arena(ctx->perm, mib(1)); + ctx->heap = allocator; + ctx->type_map = map_make(ctx->heap, 2048); ctx->gen = {ctx->perm}; ctx->helper_builder = {ctx->perm}; ctx->scope_ids = 1; bigint_allocator = ctx->perm; arena_init(&ctx->stage_arena, "Compiler stage arena"_s); - ctx->tokens = array_make(heap, 4096 * 4); - ctx->interns = intern_table_make(ctx->perm, heap, 2048); + ctx->tokens = array_make(ctx->heap, 4096 * 4); + ctx->interns = intern_table_make(ctx->perm, ctx->heap, 2048); /*#import meta for i in meta.keywords: @@ -97,9 +98,8 @@ core_init_compiler(Core_Ctx *ctx, Arena *perm, Allocator *heap) { CORE_Static void core_bootstrap_compiler(Allocator *allocator) { Core_Ctx *ctx = allocate_struct(allocator, Core_Ctx); - assert((uintptr_t)allocator->allocate == (uintptr_t)arena_push_size); - core_init_compiler(ctx, (Arena *)allocator, allocator); + core_init_compiler(ctx, allocator); } CORE_Static void @@ -300,6 +300,8 @@ compile_file(Arena *arena, String filename, U32 compile_flags = COMPILE_NULL) { B32 r = os_write_file("program.c"_s, result); assert(r); + F64 total_compiler_time = os_time() - pctx->total_time; + log_info_no_nl("%f - ", total_compiler_time); Scratch_Arena *scratch = pctx->scratch; Scratch_Scope _scope(scratch); diff --git a/core_compiler.h b/core_compiler.h index cd15ff4..bf28814 100644 --- a/core_compiler.h +++ b/core_compiler.h @@ -21,7 +21,8 @@ struct Lex_Stream{ }; struct Core_Ctx{ - Arena *perm; // Stores: AST, tokens, interns + Push_Arena perm_push_only; + Push_Arena *perm; // Stores: AST, tokens, interns Allocator *heap; Scratch_Arena *scratch; diff --git a/core_main.cpp b/core_main.cpp index e89601b..ca1c3fb 100644 --- a/core_main.cpp +++ b/core_main.cpp @@ -258,7 +258,15 @@ For modules it's a bit different cause they should be distributed as valid. */ #include "base.cpp" + +#define STB_SPRINTF_IMPLEMENTATION +#include "stb_sprintf.h" + #include "base_unicode.cpp" +#include "base_arena.cpp" +#include "base_data_structures.cpp" +#include "base_string.cpp" + #include "os.h" #if OS_WINDOWS #include "os_windows.cpp" diff --git a/core_types.cpp b/core_types.cpp index c3966d3..23293ea 100644 --- a/core_types.cpp +++ b/core_types.cpp @@ -58,7 +58,7 @@ force_inline B32 is_numeric(Ast_Type *type){ // Hash consed types //----------------------------------------------------------------------------- CORE_Static Ast_Type * -type_new(Arena *allocator, Ast_Type_Kind kind, size_t size, size_t align){ +type_new(Allocator *allocator, Ast_Type_Kind kind, size_t size, size_t align){ Ast_Type *result = allocate_struct(allocator, Ast_Type, true); result->kind = kind; result->size = size; @@ -69,7 +69,7 @@ type_new(Arena *allocator, Ast_Type_Kind kind, size_t size, size_t align){ } CORE_Static Ast_Type * -type_copy(Arena *a, Ast_Type *type){ +type_copy(Allocator *a, Ast_Type *type){ // @warning: This changes type id !!!! Ast_Type *result = allocate_struct(a, Ast_Type); memory_copy(result, type, sizeof(Ast_Type)); @@ -324,7 +324,7 @@ typename_base(String_Builder *sb, Ast_Type *type){ } CORE_Static String -get_typename(Arena *a, Ast_Type *type){ +get_typename(Allocator *a, Ast_Type *type){ pctx->helper_builder.addf("["); typename_base(&pctx->helper_builder, type); pctx->helper_builder.addf("]"); diff --git a/os_windows.cpp b/os_windows.cpp index b5d91c6..651fad2 100644 --- a/os_windows.cpp +++ b/os_windows.cpp @@ -1,3 +1,4 @@ +#include //----------------------------------------------------------------------------- // Memory