Introducing List and changes in base
This commit is contained in:
@@ -108,7 +108,11 @@ Release :: (m: *Memory)
|
|||||||
|
|
||||||
- [ ] Function overloading
|
- [ ] Function overloading
|
||||||
|
|
||||||
- [ ] Operator overloading
|
- [x] Operator overloading
|
||||||
|
- [x] Binary operators
|
||||||
|
- [x] Unary operators
|
||||||
|
- [ ] Assignment expressions?
|
||||||
|
- [ ] Bulletproof
|
||||||
|
|
||||||
- [ ] Platforms
|
- [ ] Platforms
|
||||||
- [x] Windows
|
- [x] Windows
|
||||||
|
|||||||
594
base.cpp
594
base.cpp
@@ -344,93 +344,107 @@ operator!=(Intern_String a, Intern_String b){
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Very cool macros. Since these are macros it's recommended to wrap them
|
// Very cool macros. Since these are macros it's recommended to wrap them
|
||||||
// in a function and not use directly
|
// in a function and not use directly
|
||||||
//-----------------------------------------------------------------------------
|
//----- -----------------------------------------------------------------------
|
||||||
#define SLLQueuePushMod(f, l, n, next) \
|
#define SLL_QUEUE_ADD_MOD(f, l, n, next) \
|
||||||
do { \
|
do { \
|
||||||
if ((f) == 0) { \
|
if ((f) == 0) { \
|
||||||
(f) = (l) = (n); \
|
(f) = (l) = (n); \
|
||||||
} else { \
|
} else { \
|
||||||
(l) = (l)->next = (n); \
|
(l) = (l)->next = (n); \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
#define SLLQueuePush(f, l, n) SLLQueuePushMod(f, l, n, next)
|
#define SLL_QUEUE_ADD(f, l, n) SLL_QUEUE_ADD_MOD(f, l, n, next)
|
||||||
|
|
||||||
#define SLLStackPush(l, n) \
|
#define SLL_QUEUE_POP_FIRST_MOD(f, l, next) \
|
||||||
do { \
|
do { \
|
||||||
(n)->next = (l); \
|
if ((f) == (l)) { \
|
||||||
(l) = (n); \
|
(f) = (l) = 0; \
|
||||||
} while (0)
|
} else { \
|
||||||
|
(f) = (f)->next; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
#define SLL_QUEUE_POP_FIRST(f, l) SLL_QUEUE_POP_FIRST_MOD(f, l, next)
|
||||||
|
|
||||||
#define SLLStackPop(l, n) \
|
#define SLL_STACK_ADD_MOD(stack_base, new_stack_base, next) \
|
||||||
do { \
|
do { \
|
||||||
if (l) { \
|
(new_stack_base)->next = (stack_base); \
|
||||||
(n) = (l); \
|
(stack_base) = (new_stack_base); \
|
||||||
(l) = (l)->next; \
|
} while (0)
|
||||||
(n)->next = 0; \
|
#define SLL_STACK_ADD(stack_base, new_stack_base) SLL_STACK_ADD_MOD(stack_base, new_stack_base, next)
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define DLLQueueAddLastMod(f, l, node, next, prev) \
|
#define SLL_STACK_POP(stack_base) \
|
||||||
do { \
|
do { \
|
||||||
if ((f) == 0) { \
|
if (stack_base) { \
|
||||||
(f) = (l) = (node); \
|
auto(N) = (stack_base); \
|
||||||
(node)->prev = 0; \
|
(stack_base) = (stack_base)->next; \
|
||||||
(node)->next = 0; \
|
(N)->next = 0; \
|
||||||
} else { \
|
} \
|
||||||
(l)->next = (node); \
|
} while (0)
|
||||||
(node)->prev = (l); \
|
|
||||||
(node)->next = 0; \
|
|
||||||
(l) = (node); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
#define DLLQueueAddLast(f,l,node) DLLQueueAddLastMod(f,l,node,next,prev)
|
|
||||||
#define DLLQueueAdd(f,l,node) DLLQueueAddLast(f,l,node)
|
|
||||||
#define DLLQueueRemoveMod(first, last, node, next, prev) \
|
|
||||||
do { \
|
|
||||||
if ((first) == (last)) { \
|
|
||||||
assert_msg((node) == (first), "Macro assert failed"); \
|
|
||||||
(first) = (last) = 0; \
|
|
||||||
} else if ((last) == (node)) { \
|
|
||||||
(last) = (last)->prev; \
|
|
||||||
(last)->next = 0; \
|
|
||||||
} else if ((first) == (node)) { \
|
|
||||||
(first) = (first)->next; \
|
|
||||||
(first)->prev = 0; \
|
|
||||||
} else { \
|
|
||||||
(node)->prev->next = (node)->next; \
|
|
||||||
(node)->next->prev = (node)->prev; \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
#define DLLQueueRemove(first, last, node) DLLQueueRemoveMod(first, last, node, next, prev)
|
|
||||||
|
|
||||||
#define DLLFreeListAddMod(first, node, next, prev) \
|
#define DLL_QUEUE_ADD_LAST_MOD(f, l, node, next, prev) \
|
||||||
do { \
|
do { \
|
||||||
(node)->next = (first); \
|
if ((f) == 0) { \
|
||||||
if ((first)) \
|
(f) = (l) = (node); \
|
||||||
(first)->prev = (node); \
|
(node)->prev = 0; \
|
||||||
(first) = (node); \
|
(node)->next = 0; \
|
||||||
(node)->prev = 0; \
|
} else { \
|
||||||
} while (0)
|
(l)->next = (node); \
|
||||||
#define DLLFreeListAdd(first, node) DLLFreeListAddMod(first, node, next, prev)
|
(node)->prev = (l); \
|
||||||
#define DLLFreeListRemoveMod(first, node, next, prev) \
|
(node)->next = 0; \
|
||||||
do { \
|
(l) = (node); \
|
||||||
if ((node) == (first)) { \
|
} \
|
||||||
(first) = (first)->next; \
|
} while (0)
|
||||||
if ((first)) \
|
#define DLL_QUEUE_ADD_LAST(f, l, node) DLL_QUEUE_ADD_LAST_MOD(f, l, node, next, prev)
|
||||||
(first)->prev = 0; \
|
#define DLL_QUEUE_ADD(f, l, node) DLL_QUEUE_ADD_LAST(f, l, node)
|
||||||
} else { \
|
#define DLL_QUEUE_REMOVE_MOD(first, last, node, next, prev) \
|
||||||
(node)->prev->next = (node)->next; \
|
do { \
|
||||||
if ((node)->next) \
|
if ((first) == (last)) { \
|
||||||
(node)->next->prev = (node)->prev; \
|
assert_message((node) == (first), "Macro assert failed"); \
|
||||||
} \
|
(first) = (last) = 0; \
|
||||||
} while (0)
|
} else if ((last) == (node)) { \
|
||||||
#define DLLFreeListRemove(first, node) DLLFreeListRemoveMod(first, node, next, prev)
|
(last) = (last)->prev; \
|
||||||
|
(last)->next = 0; \
|
||||||
|
} else if ((first) == (node)) { \
|
||||||
|
(first) = (first)->next; \
|
||||||
|
(first)->prev = 0; \
|
||||||
|
} else { \
|
||||||
|
(node)->prev->next = (node)->next; \
|
||||||
|
(node)->next->prev = (node)->prev; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
#define DLL_QUEUE_REMOVE(first, last, node) DLL_QUEUE_REMOVE_MOD(first, last, node, next, prev)
|
||||||
|
|
||||||
#define For_List_It(a,it) for(auto *it = (a); it; it=it->next) // @todo: reference?
|
#define DLL_STACK_ADD_MOD(first, node, next, prev) \
|
||||||
#define For_List(a) For_List_It(a,it)
|
do { \
|
||||||
|
(node)->next = (first); \
|
||||||
|
if ((first)) \
|
||||||
|
(first)->prev = (node); \
|
||||||
|
(first) = (node); \
|
||||||
|
(node)->prev = 0; \
|
||||||
|
} while (0)
|
||||||
|
#define DLL_STACK_ADD(first, node) DLL_STACK_ADD_MOD(first, node, next, prev)
|
||||||
|
#define DLL_STACK_REMOVE_MOD(first, node, next, prev) \
|
||||||
|
do { \
|
||||||
|
if ((node) == (first)) { \
|
||||||
|
(first) = (first)->next; \
|
||||||
|
if ((first)) \
|
||||||
|
(first)->prev = 0; \
|
||||||
|
} else { \
|
||||||
|
(node)->prev->next = (node)->next; \
|
||||||
|
if ((node)->next) \
|
||||||
|
(node)->next->prev = (node)->prev; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
#define DLL_STACK_REMOVE(first, node) DLL_STACK_REMOVE_MOD(first, node, next, prev)
|
||||||
|
|
||||||
|
#define For_Linked_List_Named(a,it) for(auto *it = (a); it; it=it->next) // @todo: reference?
|
||||||
|
#define For_Linked_List(a) For_Linked_List_Named(a,it)
|
||||||
#define For_Named(a,it) for(auto &it : (a))
|
#define For_Named(a,it) for(auto &it : (a))
|
||||||
#define For(a) For_Named((a),it)
|
#define For(a) For_Named((a),it)
|
||||||
|
|
||||||
|
#define Iter_Named(list, it) for(auto it = iterate(list); should_we_continue(&it); advance(&it))
|
||||||
|
#define Iter(list) Iter_Named(list, it)
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Base Allocator stuff
|
// Base Allocator stuff
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@@ -642,7 +656,7 @@ win32_os_heap_create(B32 multithreaded, SizeU initial_size, SizeU max_size, Stri
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Log_Kind{Log_Kind_Normal, Log_Kind_Error};
|
enum Log_Kind{Log_Kind_Normal, Log_Kind_Error, Log_Kind_Trace};
|
||||||
typedef void Log_Proc(Log_Kind kind, String string, char *file, int line);
|
typedef void Log_Proc(Log_Kind kind, String string, char *file, int line);
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Thread Context
|
// Thread Context
|
||||||
@@ -787,9 +801,12 @@ thread_ctx_init(){
|
|||||||
// Logging
|
// Logging
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
#define log_info(...) handle_log_message(Log_Kind_Normal, __LINE__, __FILE__,##__VA_ARGS__)
|
#define log_info(...) handle_log_message(Log_Kind_Normal, __LINE__, __FILE__,##__VA_ARGS__)
|
||||||
|
#define log_trace(...) handle_log_message(Log_Kind_Trace, __LINE__, __FILE__,##__VA_ARGS__)
|
||||||
#define log_error(...) handle_log_message(Log_Kind_Error, __LINE__, __FILE__,##__VA_ARGS__)
|
#define log_error(...) handle_log_message(Log_Kind_Error, __LINE__, __FILE__,##__VA_ARGS__)
|
||||||
function void
|
function void
|
||||||
handle_log_message(Log_Kind kind, int line, const char *file, const char *str, ...){
|
handle_log_message(Log_Kind kind, int line, const char *file, const char *str, ...){
|
||||||
|
if(kind == Log_Kind_Trace) return;
|
||||||
|
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
STRING_FMT(scratch, str, message);
|
STRING_FMT(scratch, str, message);
|
||||||
if(thread_ctx.log_proc) thread_ctx.log_proc(kind, message, (char *)file, line);
|
if(thread_ctx.log_proc) thread_ctx.log_proc(kind, message, (char *)file, line);
|
||||||
@@ -1191,96 +1208,56 @@ arena_sub(Allocator *base, SizeU size, String debug_name) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
const int ARRAY_LIST_DEFAULT_CAP = 32;
|
//-----------------------------------------------------------------------------
|
||||||
const int ARRAY_LIST_DEFAULT_ALLOCATION_MUL = 2;
|
// Array List
|
||||||
template<class T> struct Array_List_Iter;
|
// @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<class T>
|
template<class T>
|
||||||
struct Array_Node{
|
struct List_Node{
|
||||||
Array_Node<T> *next;
|
List_Node<T> *next;
|
||||||
Array_Node<T> *prev;
|
List_Node<T> *prev;
|
||||||
int cap;
|
int cap;
|
||||||
int len;
|
int len;
|
||||||
T data[];
|
T data[];
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
struct Array_List{
|
struct List{
|
||||||
int block_size = 0;
|
int block_size = 0;
|
||||||
int allocation_multiplier = 0;
|
int allocation_multiplier = 0;
|
||||||
Array_Node<T> *first = 0;
|
List_Node<T> *first = 0;
|
||||||
Array_Node<T> *last = 0;
|
List_Node<T> *last = 0;
|
||||||
Array_Node<T> *first_free = 0;
|
List_Node<T> *first_free = 0;
|
||||||
|
|
||||||
// Iterator method
|
|
||||||
Array_List_Iter<T> iter();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
struct Array_List_Iter{
|
List_Node<T> *list_allocate_node(Arena *arena, int size){
|
||||||
T *item;
|
auto node = (List_Node<T> *)arena_push_size(arena, sizeof(List_Node<T>) + size*sizeof(T));
|
||||||
int index;
|
|
||||||
Array_Node<T> *node;
|
|
||||||
int node_index;
|
|
||||||
|
|
||||||
// Methods
|
|
||||||
void next();
|
|
||||||
force_inline B32 is_valid();
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
void Array_List_Iter<T>::next(){
|
|
||||||
if(node_index + 1 >= node->len){
|
|
||||||
node = node->next;
|
|
||||||
node_index = -1;
|
|
||||||
item = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(node){
|
|
||||||
node_index += 1;
|
|
||||||
index += 1;
|
|
||||||
item = node->data + node_index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
B32 Array_List_Iter<T>::is_valid(){
|
|
||||||
return item != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
Array_List_Iter<T> Array_List<T>::iter(){
|
|
||||||
Array_List_Iter<T> result = {};
|
|
||||||
result.node = this->first;
|
|
||||||
result.index = result.node_index = -1;
|
|
||||||
result.next();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
Array_Node<T> *array_allocate_node(Arena *arena, int size){
|
|
||||||
auto node = (Array_Node<T> *)arena_push_size(arena, sizeof(Array_Node<T>) + size*sizeof(T));
|
|
||||||
node->cap = size;
|
node->cap = size;
|
||||||
node->len = 0;
|
node->len = 0;
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
void array_alloc_free_node(Arena *arena, Array_List<T> *array, int size){
|
void list_allocate_free_node(Arena *arena, List<T> *list, int size){
|
||||||
Array_Node<T> *node = array_allocate_node<T>(arena, size);
|
List_Node<T> *node = list_allocate_node<T>(arena, size);
|
||||||
DLLFreeListAdd(array->first_free, node);
|
DLL_STACK_ADD(list->first_free, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
void make_sure_there_is_room_for_item_count(Arena *arena, Array_List<T> *array, int item_count){
|
void list_make_sure_there_is_room_for_item_count(Arena *arena, List<T> *list, int item_count){
|
||||||
if(array->last == 0 || array->last->len + item_count > array->last->cap){
|
if(list->last == 0 || list->last->len + item_count > list->last->cap){
|
||||||
// Not enough space we need to get a new block
|
// Not enough space we need to get a new block
|
||||||
Array_Node<T> *node = 0;
|
List_Node<T> *node = 0;
|
||||||
|
|
||||||
// Iterate the free list to check if we have a block of required size there
|
// Iterate the free list to check if we have a block of required size there
|
||||||
For_List(array->first_free){
|
For_Linked_List(list->first_free){
|
||||||
if(it->cap >= item_count){
|
if(it->cap >= item_count){
|
||||||
DLLFreeListRemove(array->first_free, it);
|
DLL_STACK_REMOVE(list->first_free, it);
|
||||||
node = it;
|
node = it;
|
||||||
node->len = 0;
|
node->len = 0;
|
||||||
break;
|
break;
|
||||||
@@ -1289,53 +1266,73 @@ void make_sure_there_is_room_for_item_count(Arena *arena, Array_List<T> *array,
|
|||||||
|
|
||||||
// We don't have a block on the free list need to allocate
|
// We don't have a block on the free list need to allocate
|
||||||
if(!node){
|
if(!node){
|
||||||
if(!array->allocation_multiplier) array->allocation_multiplier = ARRAY_LIST_DEFAULT_ALLOCATION_MUL;
|
// Set default values if not initialized
|
||||||
if(!array->block_size) array->block_size = ARRAY_LIST_DEFAULT_CAP;
|
if(!list->allocation_multiplier) list->allocation_multiplier = LIST_DEFAULT_ALLOCATION_MUL;
|
||||||
if(item_count > array->block_size)
|
if(!list->block_size) list->block_size = LIST_DEFAULT_BLOCK_SIZE;
|
||||||
array->block_size = item_count*2;
|
|
||||||
node = array_allocate_node<T>(arena, array->block_size);
|
if(item_count > list->block_size)
|
||||||
array->block_size *= array->allocation_multiplier;
|
list->block_size = item_count*2;
|
||||||
|
node = list_allocate_node<T>(arena, list->block_size);
|
||||||
|
list->block_size *= list->allocation_multiplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(node);
|
assert(node);
|
||||||
DLLQueueAddLast(array->first, array->last, node);
|
DLL_QUEUE_ADD_LAST(list->first, list->last, node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
T *array_get(Array_List<T> *array, int index){
|
T *list_get(List<T> *list, int index, List_Node<T> **node = 0, int *in_block_index = 0){
|
||||||
int i = 0;
|
if(list){
|
||||||
For_List(array->first){
|
int i = 0;
|
||||||
int lookup_i = index - i;
|
For_Linked_List(list->first){
|
||||||
if(lookup_i < it->len) {
|
int lookup_i = index - i;
|
||||||
return it->data + lookup_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;
|
||||||
}
|
}
|
||||||
i += it->cap;
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
void array_add(Arena *arena, Array_List<T> *array, T item){
|
T *getp(List<T> *list, int index){
|
||||||
make_sure_there_is_room_for_item_count(arena, array, 1);
|
return list_get(list, index);
|
||||||
array->last->data[array->last->len++] = item;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
T *array_alloc(Arena *arena, Array_List<T> *array, int count = 1){
|
T get(List<T> *list, int index){
|
||||||
make_sure_there_is_room_for_item_count(arena, array, count);
|
return *list_get(list, index);
|
||||||
T *result = array->last->data + array->last->len;
|
}
|
||||||
array->last->len += count;
|
|
||||||
|
template<class T>
|
||||||
|
void add(Arena *arena, List<T> *list, T item){
|
||||||
|
list_make_sure_there_is_room_for_item_count(arena, list, 1);
|
||||||
|
list->last->data[list->last->len++] = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
T *add_size(Arena *arena, List<T> *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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
void array_free_node(Array_List<T> *array, Array_Node<T> *node){
|
void list_free_node(List<T> *list, List_Node<T> *node){
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
// Make sure it's actually in array list
|
// Make sure it's actually in list list
|
||||||
B32 found = false;
|
bool found = false;
|
||||||
For_List(array->first){
|
For_Linked_List(list->first){
|
||||||
if(it == node){
|
if(it == node){
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
@@ -1344,197 +1341,142 @@ void array_free_node(Array_List<T> *array, Array_Node<T> *node){
|
|||||||
assert(found);
|
assert(found);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DLLQueueRemove(array->first, array->last, node);
|
DLL_QUEUE_REMOVE(list->first, list->last, node);
|
||||||
DLLFreeListAdd(array->first_free, node);
|
DLL_STACK_ADD(list->first_free, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
void array_free_all_nodes(Array_List<T> *array){
|
void clear(List<T> *list){
|
||||||
assert(!array->last->next);
|
memory_zero(list, sizeof(List<T>));
|
||||||
assert(!array->first->prev);
|
|
||||||
array->last->next = array->first_free;
|
|
||||||
if(array->first_free) array->first_free->prev = array->last;
|
|
||||||
array->first_free = array->first;
|
|
||||||
array->last = array->first = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
T array_ordered_remove(Array_List<T> *array, int index){
|
int length(List<T> *list){
|
||||||
Array_Node<T> *node = 0;
|
int result = 0;
|
||||||
int i = 0;
|
For_Linked_List(list->first){
|
||||||
T *item = 0;
|
result += it->len;
|
||||||
|
|
||||||
// Get node from array
|
|
||||||
For_List(array->first){
|
|
||||||
int lookup_i = index - i;
|
|
||||||
if(lookup_i < it->len) {
|
|
||||||
node = it;
|
|
||||||
i = lookup_i;
|
|
||||||
item = it->data + lookup_i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
i += it->cap;
|
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
assert(node);
|
template<class T>
|
||||||
assert(item);
|
void free_all_nodes(List<T> *list){
|
||||||
T result = *item;
|
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<class T>
|
||||||
|
T ordered_remove(List<T> *list, int index){
|
||||||
|
List_Node<T> *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
|
// Check if we need to deallocate the block
|
||||||
if(node->len == 1) {
|
if(node->len == 1) {
|
||||||
array_free_node(array, node);
|
list_free_node(list, node);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// We need to move part of the block to fill the new empty spot
|
// We need to move part of the block to fill the new empty spot
|
||||||
int right_count = (--node->len) - i;
|
int right_count = (--node->len) - in_block_index;
|
||||||
memory_copy(item, item+1, sizeof(T)*right_count);
|
memory_copy(data, data+1, sizeof(T)*right_count);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
T array_unordered_remove(Array_List<T> *array, int index){
|
T unordered_remove(List<T> *list, int index){
|
||||||
auto last = array->last;
|
List_Node<T> *node;
|
||||||
assert(last);
|
T *data = list_get(list, index, &node);
|
||||||
assert(last->data);
|
|
||||||
assert(last->len != 0);
|
|
||||||
T *indexed_value = array_get(array, index);
|
|
||||||
T *last_value = last->data + (last->len-1);
|
|
||||||
|
|
||||||
T temp = *indexed_value;
|
assert_message(data, "Trying to unordered_remove element that's outside of the List");
|
||||||
*indexed_value = *last_value;
|
if(!data)
|
||||||
*last_value = temp;
|
return {};
|
||||||
|
|
||||||
return array_pop(array);
|
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<class T>
|
template<class T>
|
||||||
T array_pop(Array_List<T> *array){
|
T pop(List<T> *list){
|
||||||
assert(array->last != 0);
|
assert(list->last != 0);
|
||||||
assert(array->last->len > 0);
|
assert(list->last->len > 0);
|
||||||
T result = array->last->data[--array->last->len];
|
T result = list->last->data[--list->last->len];
|
||||||
if(array->last->len == 0){
|
if(list->last->len == 0){
|
||||||
array_free_node(array, array->last);
|
list_free_node(list, list->last);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void array_print(Array_List<int> *array){
|
template<class T>
|
||||||
log_info("\nNodes: ");
|
T *merge(Arena *arena, List<T> *list){
|
||||||
for(Array_Node<int> *it = array->first; it; it=it->next){
|
int len = length(list);
|
||||||
log_info("%d", it->cap);
|
T *result = push_array(arena, T, len);
|
||||||
if(it->next) log_info("->");
|
|
||||||
}
|
int i = 0;
|
||||||
|
For_Linked_List(list->first){
|
||||||
log_info("\nFree: ");
|
memory_copy(result + i, it->data, it->len*sizeof(T));
|
||||||
for(Array_Node<int> *it = array->first_free; it; it=it->next){
|
i += it->len;
|
||||||
log_info("%d", it->cap);
|
|
||||||
if(it->next) log_info("->");
|
|
||||||
}
|
|
||||||
|
|
||||||
log_info("\nNodes_Reverse: ");
|
|
||||||
for(Array_Node<int> *it = array->last; it; it=it->prev){
|
|
||||||
log_info("%d", it->cap);
|
|
||||||
if(it->prev) log_info("<-");
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Make sure going backwards yields same results as going forward
|
|
||||||
//
|
|
||||||
Scratch scratch;
|
|
||||||
Array<Array_Node<int> *> nodes = {scratch};
|
|
||||||
for(Array_Node<int> *it = array->first; it; it=it->next){
|
|
||||||
nodes.add(it);
|
|
||||||
}
|
|
||||||
|
|
||||||
S32 array_i = nodes.len;
|
|
||||||
for(Array_Node<int> *it = array->last; it; it=it->prev){
|
|
||||||
Array_Node<int> *node_from_array = nodes.data[--array_i];
|
|
||||||
assert(it == node_from_array);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Same test but for free list
|
|
||||||
//
|
|
||||||
nodes.clear();
|
|
||||||
Array_Node<int> *last = 0;
|
|
||||||
for(auto it = array->first_free; it; it=it->next){
|
|
||||||
nodes.add(it);
|
|
||||||
if(!it->next) last = it;
|
|
||||||
}
|
|
||||||
|
|
||||||
array_i = nodes.len;
|
|
||||||
for(Array_Node<int> *it = last; it; it=it->prev){
|
|
||||||
Array_Node<int> *node_from_array = nodes.data[--array_i];
|
|
||||||
assert(it == node_from_array);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function void
|
template<class T>
|
||||||
test_array_list(){
|
struct List_Iter{
|
||||||
Scratch scratch;
|
T *item;
|
||||||
log_info("\nArray_List:%d Array_Node:%d Array:%d", (int)sizeof(Array_List<int>), (int)sizeof(Array_Node<int>), (int)sizeof(Array<int>));
|
int index;
|
||||||
|
List_Node<T> *node;
|
||||||
|
int node_index;
|
||||||
|
};
|
||||||
|
|
||||||
{
|
template<class T>
|
||||||
Array_List<int> array{32,1};
|
void advance(List_Iter<T> *iter){
|
||||||
for(int i = 0; i < 33; i++){
|
if(!iter->node) return;
|
||||||
array_add(scratch, &array, i);
|
|
||||||
}
|
|
||||||
assert(array_pop(&array) == 32);
|
|
||||||
assert(array_pop(&array) == 31);
|
|
||||||
array_add(scratch, &array, 31);
|
|
||||||
array_add(scratch, &array, 32);
|
|
||||||
assert(array_pop(&array) == 32);
|
|
||||||
assert(array_pop(&array) == 31);
|
|
||||||
|
|
||||||
array_add(scratch, &array, 31);
|
if(iter->node_index + 1 >= iter->node->len){
|
||||||
array_add(scratch, &array, 32);
|
iter->node = iter->node->next;
|
||||||
|
iter->node_index = -1;
|
||||||
array_unordered_remove(&array, 31);
|
iter->item = 0;
|
||||||
array_unordered_remove(&array, 31);
|
|
||||||
|
|
||||||
assert(array_pop(&array) == 30);
|
|
||||||
assert(array_pop(&array) == 29);
|
|
||||||
array_add(scratch, &array, 29);
|
|
||||||
array_add(scratch, &array, 30);
|
|
||||||
array_add(scratch, &array, 31);
|
|
||||||
array_add(scratch, &array, 32);
|
|
||||||
array_ordered_remove(&array, 32);
|
|
||||||
array_ordered_remove(&array, 0);
|
|
||||||
array_ordered_remove(&array, 16);
|
|
||||||
array_ordered_remove(&array, 29);
|
|
||||||
array_print(&array);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
if(iter->node){
|
||||||
Array_List<int> array;
|
iter->node_index += 1;
|
||||||
for(int i = 0; i < 100000; i++){
|
iter->index += 1;
|
||||||
array_add(scratch, &array, i);
|
iter->item = iter->node->data + iter->node_index;
|
||||||
}
|
|
||||||
|
|
||||||
For_It(array){
|
|
||||||
assert(it.index == *it.item);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(*array_get(&array, 22) == 22);
|
|
||||||
assert(*array_get(&array, 65) == 65);
|
|
||||||
assert(*array_get(&array, 200) == 200);
|
|
||||||
|
|
||||||
array_print(&array);
|
|
||||||
array_free_node(&array, array.last->prev);
|
|
||||||
array_free_node(&array, array.last->prev);
|
|
||||||
array_free_node(&array, array.last->prev);
|
|
||||||
array_free_node(&array, array.last->prev);
|
|
||||||
array_free_node(&array, array.last->prev->prev);
|
|
||||||
array_print(&array);
|
|
||||||
|
|
||||||
for(int i = 0; i < 10000; i++){
|
|
||||||
array_add(scratch, &array, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
array_print(&array);
|
|
||||||
}
|
}
|
||||||
// __debugbreak();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
List_Iter<T> iterate(List<T> *list){
|
||||||
|
List_Iter<T> result = {};
|
||||||
|
result.node = list->first;
|
||||||
|
result.index = result.node_index = -1;
|
||||||
|
advance(&result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
bool should_we_continue(List_Iter<T> *iter){
|
||||||
|
return iter->item != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -151,7 +151,7 @@ struct String_Builder{
|
|||||||
}
|
}
|
||||||
memory_zero(block, sizeof(String_Builder_Block)+1); // Also clear first byte of character data
|
memory_zero(block, sizeof(String_Builder_Block)+1); // Also clear first byte of character data
|
||||||
block->cap = size;
|
block->cap = size;
|
||||||
SLLQueuePush(first, last, block);
|
SLL_QUEUE_ADD(first, last, block);
|
||||||
}
|
}
|
||||||
|
|
||||||
void init(S64 size = 4096){
|
void init(S64 size = 4096){
|
||||||
@@ -219,7 +219,7 @@ string_flatten(Allocator *a, String_Builder *b, String_Builder_Flag flags = Stri
|
|||||||
// @Note(Krzosa): Compute size to allocate
|
// @Note(Krzosa): Compute size to allocate
|
||||||
S64 size = 1;
|
S64 size = 1;
|
||||||
if(is_flag_set(flags, String_Builder_Flag_AddSize)) size += sizeof(SizeU);
|
if(is_flag_set(flags, String_Builder_Flag_AddSize)) size += sizeof(SizeU);
|
||||||
For_List(b->first){
|
For_Linked_List(b->first){
|
||||||
size += it->len;
|
size += it->len;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -231,7 +231,7 @@ string_flatten(Allocator *a, String_Builder *b, String_Builder_Flag flags = Stri
|
|||||||
}
|
}
|
||||||
|
|
||||||
// @Note(Krzosa): Copy the content of each block into the string
|
// @Note(Krzosa): Copy the content of each block into the string
|
||||||
For_List(b->first){
|
For_Linked_List(b->first){
|
||||||
memory_copy(result.str + result.len, it->data, it->len);
|
memory_copy(result.str + result.len, it->data, it->len);
|
||||||
result.len += it->len;
|
result.len += it->len;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -250,7 +250,7 @@ struct Ast_Module: Ast_Scope{
|
|||||||
Ast_Module_State state;
|
Ast_Module_State state;
|
||||||
String absolute_base_folder;
|
String absolute_base_folder;
|
||||||
String absolute_file_path;
|
String absolute_file_path;
|
||||||
Array<Ast_File *> all_loaded_files;
|
List<Ast_File *> all_loaded_files;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Ast_File: Ast_Scope{
|
struct Ast_File: Ast_Scope{
|
||||||
|
|||||||
@@ -79,9 +79,10 @@ l->last_op = op_post_increment;
|
|||||||
}
|
}
|
||||||
|
|
||||||
function void
|
function void
|
||||||
parse_init(Parse_Ctx *ctx, Allocator *perm_allocator, Allocator *heap_allocator){
|
parse_init(Parse_Ctx *ctx, Arena *perm_allocator, Allocator *heap_allocator){
|
||||||
pctx = ctx;
|
pctx = ctx;
|
||||||
ctx->perm = perm_allocator;
|
ctx->perm = perm_allocator;
|
||||||
|
ctx->perm_arena = perm_allocator;
|
||||||
ctx->heap = heap_allocator;
|
ctx->heap = heap_allocator;
|
||||||
ctx->gen = {ctx->heap};
|
ctx->gen = {ctx->heap};
|
||||||
ctx->ordered_decls = {ctx->heap};
|
ctx->ordered_decls = {ctx->heap};
|
||||||
@@ -165,9 +166,8 @@ parse_all_modules(){
|
|||||||
Ast_Module *module = pctx->modules[i];
|
Ast_Module *module = pctx->modules[i];
|
||||||
if(module->state != MODULE_REGISTERED) continue;
|
if(module->state != MODULE_REGISTERED) continue;
|
||||||
|
|
||||||
for(S64 j = 0; j < module->all_loaded_files.len; j++){
|
Iter(&module->all_loaded_files){
|
||||||
Ast_File *file = module->all_loaded_files.data[j];
|
parse_file(*it.item);
|
||||||
parse_file(file);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(module != pctx->language_base_module)
|
if(module != pctx->language_base_module)
|
||||||
@@ -216,23 +216,22 @@ add_module(Token *pos, Intern_String filename, B32 command_line_module){
|
|||||||
|
|
||||||
For(pctx->modules){
|
For(pctx->modules){
|
||||||
if(string_compare(it->absolute_file_path, absolute_file_path)){
|
if(string_compare(it->absolute_file_path, absolute_file_path)){
|
||||||
// log_info("Returning registered module: %Q\n", absolute_file_path);
|
log_trace("Returning registered module: %Q\n", absolute_file_path);
|
||||||
return it;
|
return it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Module *result = ast_new(Ast_Module, AST_MODULE, pos, 0);
|
log_trace("Adding module: %Q\n", filename);
|
||||||
result->absolute_file_path = string_copy(pctx->perm, absolute_file_path);
|
Ast_Module *result = ast_new(Ast_Module, AST_MODULE, pos, 0);
|
||||||
|
result->absolute_file_path = string_copy(pctx->perm, absolute_file_path);
|
||||||
result->absolute_base_folder = string_copy(pctx->perm, absolute_base_folder);
|
result->absolute_base_folder = string_copy(pctx->perm, absolute_base_folder);
|
||||||
result->debug_name = string_skip_to_last_slash(result->absolute_file_path);
|
result->debug_name = string_skip_to_last_slash(result->absolute_file_path);
|
||||||
// log_info("Adding module: %Q\n", filename);
|
result->module = result; // @warning: self referential
|
||||||
result->module = result; // @warning: self referential
|
result->file = result; // @warning: self referential
|
||||||
result->file = result; // @warning: self referential
|
result->implicit_imports = {pctx->heap};
|
||||||
result->all_loaded_files = {pctx->heap};
|
result->decls = {pctx->heap};
|
||||||
result->implicit_imports = {pctx->heap};
|
result->parent_scope = 0;
|
||||||
result->decls = {pctx->heap};
|
result->scope_id = pctx->scope_ids++;
|
||||||
result->parent_scope = 0;
|
|
||||||
result->scope_id = pctx->scope_ids++;
|
|
||||||
|
|
||||||
register_ast_file(pos, result->absolute_file_path, result, GLOBAL_IMPLICIT_LOAD);
|
register_ast_file(pos, result->absolute_file_path, result, GLOBAL_IMPLICIT_LOAD);
|
||||||
pctx->modules.add(result);
|
pctx->modules.add(result);
|
||||||
@@ -243,10 +242,9 @@ function void
|
|||||||
resolve_everything_in_module(Ast_Module *module){
|
resolve_everything_in_module(Ast_Module *module){
|
||||||
if(module->state == MODULE_RESOLVED) return;
|
if(module->state == MODULE_RESOLVED) return;
|
||||||
resolving_time_begin = os_time();
|
resolving_time_begin = os_time();
|
||||||
for(S64 i = 0; i < module->all_loaded_files.len; i++){
|
Iter_Named(&module->all_loaded_files, file){
|
||||||
Ast_File *file = module->all_loaded_files[i];
|
For(file.item[0]->decls){
|
||||||
For(file->decls){
|
resolve_name(file.item[0], it->pos, it->name);
|
||||||
resolve_name(file, it->pos, it->name);
|
|
||||||
if(it->kind == AST_STRUCT){
|
if(it->kind == AST_STRUCT){
|
||||||
type_complete(it->type_val);
|
type_complete(it->type_val);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -158,6 +158,7 @@ struct Lexer{
|
|||||||
|
|
||||||
struct Parse_Ctx:Lexer{
|
struct Parse_Ctx:Lexer{
|
||||||
Allocator *perm; // Stores: AST, tokens, interns
|
Allocator *perm; // Stores: AST, tokens, interns
|
||||||
|
Arena *perm_arena;
|
||||||
Allocator *heap;
|
Allocator *heap;
|
||||||
Arena stage_arena;
|
Arena stage_arena;
|
||||||
|
|
||||||
|
|||||||
@@ -729,7 +729,7 @@ register_ast_file(Token *pos, String absolute_file_path, Ast_Module *module, B32
|
|||||||
For(pctx->files){
|
For(pctx->files){
|
||||||
if(string_compare(it->absolute_file_path, absolute_file_path)){
|
if(string_compare(it->absolute_file_path, absolute_file_path)){
|
||||||
if(module == it->module){
|
if(module == it->module){
|
||||||
// log_info("%Q :: Returning registered file: %Q\n", module->absolute_file_path, absolute_file_path);
|
log_trace("%Q :: Returning registered file: %Q\n", module->absolute_file_path, absolute_file_path);
|
||||||
file = it;
|
file = it;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -739,7 +739,7 @@ register_ast_file(Token *pos, String absolute_file_path, Ast_Module *module, B32
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(!file){
|
if(!file){
|
||||||
// log_info("%Q :: Registering file: %Q\n", module->absolute_file_path, absolute_file_path);
|
log_trace("%Q :: Registering file: %Q\n", module->absolute_file_path, absolute_file_path);
|
||||||
AST_NEW(File, FILE, 0, 0);
|
AST_NEW(File, FILE, 0, 0);
|
||||||
file = result;
|
file = result;
|
||||||
file->absolute_file_path = absolute_file_path;
|
file->absolute_file_path = absolute_file_path;
|
||||||
@@ -750,7 +750,7 @@ register_ast_file(Token *pos, String absolute_file_path, Ast_Module *module, B32
|
|||||||
file->implicit_imports = {pctx->heap};
|
file->implicit_imports = {pctx->heap};
|
||||||
file->pos = pos;
|
file->pos = pos;
|
||||||
file->debug_name = string_skip_to_last_slash(absolute_file_path);
|
file->debug_name = string_skip_to_last_slash(absolute_file_path);
|
||||||
file->module->all_loaded_files.add(file);
|
add(pctx->perm_arena, &file->module->all_loaded_files, file);
|
||||||
file->scope_id = pctx->scope_ids++;
|
file->scope_id = pctx->scope_ids++;
|
||||||
pctx->files.add(file);
|
pctx->files.add(file);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user