wl/src/core/symbol.c
2026-01-13 20:51:00 -03:00

86 lines
1.8 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wolflisp.h>
#define ALIGN(n) (((n) + 7) & ~7)
static Sy *find(St *tab, const char *str, U32 hash, Z len) {
if (tab->capacity == 0)
return NULL;
Z ix = hash % tab->capacity;
for (Z i = 0; i < tab->capacity; i++) {
Sy *s = tab->data[ix];
if (!s)
return NULL;
if (s->hash == hash && s->len == len)
return s;
if (memcmp(s->data, str, len) == 0)
return s;
ix = (ix + 1) % tab->capacity;
}
return NULL;
}
static V resize(St *tab) {
Z cap = tab->capacity == 0 ? 16 : tab->capacity * 2;
Sy **nb = calloc(cap, sizeof(Sy *));
for (Z i = 0; i < tab->capacity; i++) {
if (tab->data[i]) {
Sy *s = tab->data[i];
Z ix = s->hash % cap;
while (nb[ix])
ix = (ix + 1) % cap;
nb[ix] = s;
}
}
if (tab->data != NULL)
free(tab->data);
tab->capacity = cap;
tab->data = nb;
}
static U32 hashstr(const char *data, Z len) {
U32 hash = 2166136261u;
for (Z i = 0; i < len; i++) {
hash ^= (uint8_t)data[i];
hash *= 16777619u;
}
return hash;
}
Sy *intern(St *tab, const char *str, Z len) {
if (len == 0)
len = strlen(str);
U32 hash = hashstr(str, len);
Sy *sym = find(tab, str, hash, len);
if (sym)
return sym;
sym = aligned_alloc(8, ALIGN(sizeof(Sy)));
if (!sym) {
fprintf(stderr, "failed to allocate memory for symbol\n");
abort();
}
sym->data = malloc(len);
memcpy(sym->data, str, len);
sym->len = len;
sym->hash = hash;
if (tab->count + 1 > tab->capacity)
resize(tab);
Z idx = hash % tab->capacity;
while (tab->data[idx] != NULL)
idx = (idx + 1) % tab->capacity;
tab->data[idx] = sym;
tab->count++;
return sym;
}
O symbol_make(In *in, const char *str) {
return BOX(TAG(intern(&in->symtab, str, 0), TAG_SYM));
}