reimplementation (oupsi)
This commit is contained in:
parent
0572264f76
commit
1aec6085d9
27 changed files with 1213 additions and 21 deletions
84
src/symbol.c
Normal file
84
src/symbol.c
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <wolflisp.h>
|
||||
|
||||
#define ALIGN(n) (((n) + 7) & ~7)
|
||||
|
||||
static Sy *find(St *tab, 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;
|
||||
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, 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));
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue