diff --git a/src/checker.hpp b/src/checker.hpp index ab8fce3d8..6511dad32 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -406,13 +406,6 @@ gb_global AstPackage *intrinsics_pkg = nullptr; gb_global AstPackage *config_pkg = nullptr; -HashKey hash_node (Ast *node) { return hash_pointer(node); } -HashKey hash_ast_file (AstFile *file) { return hash_pointer(file); } -HashKey hash_entity (Entity *e) { return hash_pointer(e); } -HashKey hash_type (Type *t) { return hash_pointer(t); } -HashKey hash_decl_info(DeclInfo *decl) { return hash_pointer(decl); } - - // CheckerInfo API TypeAndValue type_and_value_of_expr (Ast *expr); Type * type_of_expr (Ast *expr); diff --git a/src/map.cpp b/src/map.cpp deleted file mode 100644 index cc91e51d4..000000000 --- a/src/map.cpp +++ /dev/null @@ -1,363 +0,0 @@ -// A `Map` is an unordered hash table which can allow for a key to point to multiple values -// with the use of the `multi_*` procedures. -// TODO(bill): I should probably allow the `multi_map_*` stuff to be #ifdefed out - -#define MAP_ENABLE_MULTI_MAP 1 - -#ifndef MAP_UTIL_STUFF -#define MAP_UTIL_STUFF -// NOTE(bill): This util stuff is the same for every `Map` - -typedef u32 MapIndex; - -struct MapFindResult { - MapIndex hash_index; - MapIndex entry_prev; - MapIndex entry_index; -}; - -enum : MapIndex { MAP_SENTINEL = ~(MapIndex)0 }; - - -struct HashKey { - u64 key; -}; -GB_STATIC_ASSERT(gb_size_of(u64) >= gb_size_of(void *)); - -gb_inline HashKey hashing_proc(void const *data, isize len) { - HashKey h = {}; - h.key = fnv64a(data, len); - return h; -} - -gb_inline HashKey hash_pointer(void const *ptr) { - HashKey h = {}; - h.key = cast(u64)cast(uintptr)ptr; - return h; -} - -gb_inline HashKey hash_integer(u64 u) { - HashKey h = {}; - h.key = u; - return h; -} -gb_inline HashKey hash_f64(f64 f) { - HashKey h = {}; - h.key = bit_cast(f); - return h; -} - -gb_inline bool hash_key_equal(HashKey a, HashKey b) { - return a.key == b.key; -} -gb_inline bool operator==(HashKey a, HashKey b) { return hash_key_equal(a, b); } -gb_inline bool operator!=(HashKey a, HashKey b) { return !hash_key_equal(a, b); } - -#endif - -template -struct MapEntry { - HashKey key; - MapIndex next; - T value; -}; - -template -struct Map { - Slice hashes; - Array > entries; -}; - - -template void map_init (Map *h, gbAllocator a, isize capacity = 16); -template void map_destroy (Map *h); -template T * map_get (Map *h, HashKey const &key); -template T & map_must_get (Map *h, HashKey const &key); -template void map_set (Map *h, HashKey const &key, T const &value); -template void map_remove (Map *h, HashKey const &key); -template void map_clear (Map *h); -template void map_grow (Map *h); -template void map_rehash (Map *h, isize new_count); -template void map_reserve (Map *h, isize cap); - -#if MAP_ENABLE_MULTI_MAP -// Mutlivalued map procedure -template MapEntry * multi_map_find_first(Map *h, HashKey const &key); -template MapEntry * multi_map_find_next (Map *h, MapEntry *e); - -template isize multi_map_count (Map *h, HashKey const &key); -template void multi_map_get_all (Map *h, HashKey const &key, T *items); -template void multi_map_insert (Map *h, HashKey const &key, T const &value); -template void multi_map_remove (Map *h, HashKey const &key, MapEntry *e); -template void multi_map_remove_all(Map *h, HashKey const &key); -#endif - -template -gb_inline void map_init(Map *h, gbAllocator a, isize capacity) { - capacity = next_pow2_isize(capacity); - slice_init(&h->hashes, a, capacity); - array_init(&h->entries, a, 0, capacity); - for (isize i = 0; i < capacity; i++) { - h->hashes.data[i] = MAP_SENTINEL; - } -} - -template -gb_inline void map_destroy(Map *h) { - slice_free(&h->hashes, h->entries.allocator); - array_free(&h->entries); -} - -template -gb_internal MapIndex map__add_entry(Map *h, HashKey const &key) { - MapEntry e = {}; - e.key = key; - e.next = MAP_SENTINEL; - array_add(&h->entries, e); - return cast(MapIndex)(h->entries.count-1); -} - -template -gb_internal MapFindResult map__find(Map *h, HashKey const &key) { - MapFindResult fr = {MAP_SENTINEL, MAP_SENTINEL, MAP_SENTINEL}; - if (h->hashes.count == 0) { - return fr; - } - fr.hash_index = cast(MapIndex)(key.key & (h->hashes.count-1)); - fr.entry_index = h->hashes.data[fr.hash_index]; - while (fr.entry_index != MAP_SENTINEL) { - if (hash_key_equal(h->entries.data[fr.entry_index].key, key)) { - return fr; - } - fr.entry_prev = fr.entry_index; - fr.entry_index = h->entries.data[fr.entry_index].next; - } - return fr; -} - -template -gb_internal MapFindResult map__find_from_entry(Map *h, MapEntry *e) { - MapFindResult fr = {MAP_SENTINEL, MAP_SENTINEL, MAP_SENTINEL}; - if (h->hashes.count == 0) { - return fr; - } - fr.hash_index = cast(MapIndex)(e->key.key & (h->hashes.count-1)); - fr.entry_index = h->hashes.data[fr.hash_index]; - while (fr.entry_index != MAP_SENTINEL) { - if (&h->entries.data[fr.entry_index] == e) { - return fr; - } - fr.entry_prev = fr.entry_index; - fr.entry_index = h->entries.data[fr.entry_index].next; - } - return fr; -} - -template -gb_internal b32 map__full(Map *h) { - return 0.75f * h->hashes.count <= h->entries.count; -} - -template -gb_inline void map_grow(Map *h) { - isize new_count = gb_max(h->hashes.count<<1, 16); - map_rehash(h, new_count); -} - -template -void map_reset_entries(Map *h) { - for (isize i = 0; i < h->hashes.count; i++) { - h->hashes.data[i] = MAP_SENTINEL; - } - for (isize i = 0; i < h->entries.count; i++) { - MapFindResult fr; - MapEntry *e = &h->entries.data[i]; - e->next = MAP_SENTINEL; - fr = map__find_from_entry(h, e); - if (fr.entry_prev == MAP_SENTINEL) { - h->hashes[fr.hash_index] = cast(MapIndex)i; - } else { - h->entries[fr.entry_prev].next = cast(MapIndex)i; - } - } -} - -template -void map_reserve(Map *h, isize cap) { - array_reserve(&h->entries, cap); - if (h->entries.count*2 < h->hashes.count) { - return; - } - slice_resize(&h->hashes, h->entries.allocator, cap*2); - map_reset_entries(h); -} - - -template -void map_rehash(Map *h, isize new_count) { - map_reserve(h, new_count); -} - -template -T *map_get(Map *h, HashKey const &key) { - isize index = map__find(h, key).entry_index; - if (index != MAP_SENTINEL) { - return &h->entries.data[index].value; - } - return nullptr; -} - -template -T &map_must_get(Map *h, HashKey const &key) { - isize index = map__find(h, key).entry_index; - GB_ASSERT(index != MAP_SENTINEL); - return h->entries.data[index].value; -} - -template -void map_set(Map *h, HashKey const &key, T const &value) { - MapIndex index; - MapFindResult fr; - if (h->hashes.count == 0) { - map_grow(h); - } - fr = map__find(h, key); - if (fr.entry_index != MAP_SENTINEL) { - index = fr.entry_index; - } else { - index = map__add_entry(h, key); - if (fr.entry_prev != MAP_SENTINEL) { - h->entries.data[fr.entry_prev].next = index; - } else { - h->hashes.data[fr.hash_index] = index; - } - } - h->entries.data[index].value = value; - - if (map__full(h)) { - map_grow(h); - } -} - - -template -void map__erase(Map *h, MapFindResult const &fr) { - MapFindResult last; - if (fr.entry_prev == MAP_SENTINEL) { - h->hashes.data[fr.hash_index] = h->entries.data[fr.entry_index].next; - } else { - h->entries.data[fr.entry_prev].next = h->entries.data[fr.entry_index].next; - } - if (fr.entry_index == h->entries.count-1) { - array_pop(&h->entries); - return; - } - h->entries.data[fr.entry_index] = h->entries.data[h->entries.count-1]; - array_pop(&h->entries); - - last = map__find(h, h->entries.data[fr.entry_index].key); - if (last.entry_prev != MAP_SENTINEL) { - h->entries.data[last.entry_prev].next = fr.entry_index; - } else { - h->hashes.data[last.hash_index] = fr.entry_index; - } -} - -template -void map_remove(Map *h, HashKey const &key) { - MapFindResult fr = map__find(h, key); - if (fr.entry_index != MAP_SENTINEL) { - map__erase(h, fr); - } -} - -template -gb_inline void map_clear(Map *h) { - array_clear(&h->entries); - for (isize i = 0; i < h->hashes.count; i++) { - h->hashes.data[i] = MAP_SENTINEL; - } -} - - -#if MAP_ENABLE_MULTI_MAP -template -MapEntry *multi_map_find_first(Map *h, HashKey const &key) { - isize i = map__find(h, key).entry_index; - if (i == MAP_SENTINEL) { - return nullptr; - } - return &h->entries.data[i]; -} - -template -MapEntry *multi_map_find_next(Map *h, MapEntry *e) { - isize i = e->next; - while (i != MAP_SENTINEL) { - if (hash_key_equal(h->entries.data[i].key, e->key)) { - return &h->entries.data[i]; - } - i = h->entries.data[i].next; - } - return nullptr; -} - -template -isize multi_map_count(Map *h, HashKey const &key) { - isize count = 0; - MapEntry *e = multi_map_find_first(h, key); - while (e != nullptr) { - count++; - e = multi_map_find_next(h, e); - } - return count; -} - -template -void multi_map_get_all(Map *h, HashKey const &key, T *items) { - isize i = 0; - MapEntry *e = multi_map_find_first(h, key); - while (e != nullptr) { - items[i++] = e->value; - e = multi_map_find_next(h, e); - } -} - -template -void multi_map_insert(Map *h, HashKey const &key, T const &value) { - MapFindResult fr; - MapIndex i; - if (h->hashes.count == 0) { - map_grow(h); - } - // Make - fr = map__find(h, key); - i = map__add_entry(h, key); - if (fr.entry_prev == MAP_SENTINEL) { - h->hashes.data[fr.hash_index] = i; - } else { - h->entries.data[fr.entry_prev].next = i; - } - h->entries.data[i].next = fr.entry_index; - h->entries.data[i].value = value; - // Grow if needed - if (map__full(h)) { - map_grow(h); - } -} - -template -void multi_map_remove(Map *h, HashKey const &key, MapEntry *e) { - MapFindResult fr = map__find_from_entry(h, e); - if (fr.entry_index != MAP_SENTINEL) { - map__erase(h, fr); - } -} - -template -void multi_map_remove_all(Map *h, HashKey const &key) { - while (map_get(h, key) != nullptr) { - map_remove(h, key); - } -} -#endif diff --git a/src/ptr_map.cpp b/src/ptr_map.cpp index 0a61d300f..19443d8a1 100644 --- a/src/ptr_map.cpp +++ b/src/ptr_map.cpp @@ -1,5 +1,14 @@ #define PTR_MAP_ENABLE_MULTI_MAP 1 +typedef u32 MapIndex; + +struct MapFindResult { + MapIndex hash_index; + MapIndex entry_prev; + MapIndex entry_index; +}; + +enum : MapIndex { MAP_SENTINEL = ~(MapIndex)0 }; template struct PtrMapEntry {