gc and cons pairs

This commit is contained in:
Lobo 2026-01-06 13:03:59 -03:00
parent d64b0f0a6f
commit fe9a8a7039
8 changed files with 217 additions and 10 deletions

81
symbol.c Normal file
View file

@ -0,0 +1,81 @@
#include <stdlib.h>
#include <string.h>
#include "wscm.h"
St syms = {0, 0, NULL};
static S *findsym(const char *str, Z len, U32 hash) {
if (syms.capacity == 0)
return NULL;
Z ix = hash % syms.capacity;
for (Z i = 0; i < syms.capacity; i++) {
S *s = syms.data[ix];
if (!s)
return NULL;
if (s->hash == hash && s->len == len)
return s;
ix = (ix + 1) % syms.capacity;
}
return NULL;
}
static void symtabresize(void) {
Z cap = syms.capacity;
if (cap == 0) {
syms.capacity = 16;
} else {
syms.capacity *= 2;
}
S **nb = calloc(syms.capacity, sizeof(S *));
for (Z i = 0; i < cap; i++) {
if (syms.data[i]) {
S *s = syms.data[i];
Z ix = s->hash % syms.capacity;
while (nb[ix])
ix = (ix + 1) % syms.capacity;
nb[ix] = s;
}
}
if (syms.data != NULL)
free(syms.data);
syms.data = nb;
}
U32 hashstring(const char *data, I len) {
U32 hash = 2166136261u;
for (I i = 0; i < len; i++) {
hash ^= (uint8_t)data[i];
hash *= 16777619u;
}
return hash;
}
S *intern(const char *str, I len) {
if (len < 0)
len = strlen(str);
U32 hash = hashstring(str, len);
S *s = findsym(str, len, hash);
if (s)
return s;
s = malloc(sizeof(S));
s->data = malloc(len);
memcpy(s->data, str, len);
s->len = len;
s->hash = hash;
if (syms.count + 1 > syms.capacity)
symtabresize();
Z ix = hash % syms.capacity;
while (syms.data[ix])
ix = (ix + 1) % syms.capacity;
syms.data[ix] = s;
syms.count++;
return s;
}