86 lines
1.8 KiB
C
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));
|
|
}
|