feat: implement AST walker
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
#include <compiler/utils/fzl_const_pool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
bool fzl_consts_equal(fzl_const_t a, fzl_const_t b)
|
||||
{
|
||||
if (a.type != b.type)
|
||||
return false;
|
||||
|
||||
switch (a.type)
|
||||
{
|
||||
case FZL_CONSTTYPE_STRING:
|
||||
{
|
||||
if (a.as.string.length != b.as.string.length)
|
||||
return false;
|
||||
|
||||
return memcmp(a.as.string.chars, b.as.string.chars, a.as.string.length) ==
|
||||
0;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static uint32_t fzl_hash_const(fzl_const_t c)
|
||||
{
|
||||
uint32_t hash = 2166136261u;
|
||||
const uint8_t *data = NULL;
|
||||
size_t size = 0;
|
||||
|
||||
switch (c.type)
|
||||
{
|
||||
case FZL_CONSTTYPE_STRING:
|
||||
data = (const uint8_t *)&c.as.string.chars;
|
||||
size = c.as.string.length;
|
||||
break;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < size; i++)
|
||||
{
|
||||
hash ^= data[i];
|
||||
hash *= 16777619u;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
fzl_const_hash_pool_t *fzl_mkconstpool()
|
||||
{
|
||||
fzl_const_hash_pool_t *pool = malloc(sizeof(fzl_const_hash_pool_t));
|
||||
|
||||
pool->size = 0;
|
||||
pool->capacity = 8;
|
||||
pool->array = malloc(pool->capacity * sizeof(fzl_const_t));
|
||||
|
||||
pool->slots_count = 0;
|
||||
pool->slots_capacity = 16;
|
||||
pool->slots = malloc(pool->slots_capacity * sizeof(fzl_const_hash_slot_t));
|
||||
for (int i = 0; i < pool->slots_capacity; i++)
|
||||
pool->slots[i].pool_index = -1;
|
||||
|
||||
return pool;
|
||||
}
|
||||
|
||||
static void fzl_consts_pool_resize_hash(fzl_const_hash_pool_t *pool)
|
||||
{
|
||||
int old_capacity = pool->slots_capacity;
|
||||
fzl_const_hash_slot_t *old_slots = pool->slots;
|
||||
|
||||
pool->slots_capacity = old_capacity * 2;
|
||||
pool->slots = malloc(pool->slots_capacity * sizeof(fzl_const_hash_slot_t));
|
||||
for (int i = 0; i < pool->slots_capacity; i++)
|
||||
pool->slots[i].pool_index = -1;
|
||||
pool->slots_count = 0;
|
||||
|
||||
for (int i = 0; i < old_capacity; i++)
|
||||
{
|
||||
if (old_slots[i].pool_index == -1)
|
||||
continue;
|
||||
|
||||
int index_in_pool = old_slots[i].pool_index;
|
||||
fzl_const_t c = pool->array[index_in_pool];
|
||||
uint32_t hash = fzl_hash_const(c);
|
||||
|
||||
uint32_t bucket = hash & (pool->slots_capacity - 1);
|
||||
while (pool->slots[bucket].pool_index != -1)
|
||||
bucket = (bucket + 1) & (pool->slots_capacity - 1);
|
||||
|
||||
pool->slots[bucket].pool_index = index_in_pool;
|
||||
pool->slots_count++;
|
||||
}
|
||||
|
||||
free(old_slots);
|
||||
}
|
||||
|
||||
size_t fzl_consts_pool_add(fzl_const_hash_pool_t *pool, fzl_const_t c)
|
||||
{
|
||||
if (pool->slots_count * 4 >= pool->slots_capacity * 3)
|
||||
fzl_consts_pool_resize_hash(pool);
|
||||
|
||||
uint32_t hash = fzl_hash_const(c);
|
||||
uint32_t bucket = hash & (pool->slots_capacity - 1);
|
||||
|
||||
while (pool->slots[bucket].pool_index != -1)
|
||||
{
|
||||
size_t existing_index = pool->slots[bucket].pool_index;
|
||||
if (fzl_consts_equal(pool->array[existing_index], c))
|
||||
return existing_index;
|
||||
|
||||
bucket = (bucket + 1) & (pool->slots_capacity - 1);
|
||||
}
|
||||
|
||||
if (pool->size >= pool->capacity)
|
||||
{
|
||||
pool->capacity *= 2;
|
||||
pool->array = (fzl_const_t *)realloc(pool->array,
|
||||
pool->capacity * sizeof(fzl_const_t));
|
||||
}
|
||||
|
||||
size_t new_index = pool->size;
|
||||
pool->array[new_index] = c;
|
||||
pool->size++;
|
||||
|
||||
pool->slots[bucket].pool_index = new_index;
|
||||
pool->slots_count++;
|
||||
|
||||
return new_index;
|
||||
}
|
||||
|
||||
void fzl_consts_pool_free(fzl_const_hash_pool_t *pool)
|
||||
{
|
||||
if (!pool)
|
||||
return;
|
||||
|
||||
free(pool->array);
|
||||
free(pool->slots);
|
||||
free(pool);
|
||||
}
|
||||
Reference in New Issue
Block a user