#include #include #include "builtins.h" #include "util.h" #define BUILTINS_BUCKETS 128 // Enough for ~100 builtins at <0.8 load factor typedef struct { intern_t key; // NULL = empty slot builtin_func_t *func; } builtin_slot_t; struct builtins { size_t size; // number of stored entries builtin_slot_t *slots; }; /* Simple pointer hash for interned strings */ static inline size_t hash_ptr(intern_t p) { return ((size_t)p) >> 3; } builtins_t *builtins_alloc(void) { builtins_t *b = malloc(sizeof(*b)); if (b == NULL) die("Out of memory: cannot allocate builtins table"); b->size = 0; b->slots = calloc(BUILTINS_BUCKETS, sizeof(builtin_slot_t)); if (!b->slots) { free(b); return NULL; } return b; } builtins_t *builtins_add(builtins_t *b, intern_t name, builtin_func_t *func) { if (b == NULL) return NULL; size_t idx = hash_ptr(name) % BUILTINS_BUCKETS; while (1) { if (b->slots[idx].key == NULL) { // empty slot → insert b->slots[idx].key = name; b->slots[idx].func = func; b->size++; return b; } else if (b->slots[idx].key == name) { // existing key → replace b->slots[idx].func = func; return b; } // linear probe idx = (idx + 1) % BUILTINS_BUCKETS; } } builtin_func_t *builtins_lookup(builtins_t *b, intern_t name) { if (b == NULL) return NULL; size_t idx = hash_ptr(name) % BUILTINS_BUCKETS; while (1) { if (b->slots[idx].key == NULL) { // empty → not found return NULL; } else if (b->slots[idx].key == name) { return b->slots[idx].func; } idx = (idx + 1) % BUILTINS_BUCKETS; } } void builtins_free(builtins_t *b) { if (b == NULL) return; free(b->slots); free(b); }