#include "cvm_core.h"
#include <stdlib.h>
#include <string.h>
static char *dup_str(const char *s) {
size_t n = strlen(s) + 1;
char *p = (char *)malloc(n);
if (!p) abort();
memcpy(p, s, n);
return p;
}
static unsigned long long hash_str(const char *s) {
unsigned long long h = 1469598103934665603ULL;
for (; *s; ++s) {
h ^= (unsigned char)*s;
h *= 1099511628211ULL;
}
return h;
}
void map_init(Map *m) {
m->cap = 64;
m->count = 0;
m->buckets = (MapNode **)calloc((size_t)m->cap, sizeof(MapNode *));
if (!m->buckets) abort();
}
void map_destroy(Map *m) {
for (int i = 0; i < m->cap; ++i) {
MapNode *n = m->buckets[i];
while (n) {
MapNode *nx = n->next;
free(n->key);
free(n);
n = nx;
}
}
free(m->buckets);
m->buckets = NULL;
m->cap = m->count = 0;
}
static void map_grow(Map *m) {
int ncap = m->cap * 2;
MapNode **nb = (MapNode **)calloc((size_t)ncap, sizeof(MapNode *));
if (!nb) abort();
for (int i = 0; i < m->cap; ++i) {
MapNode *n = m->buckets[i];
while (n) {
MapNode *nx = n->next;
unsigned long long h = hash_str(n->key) & (unsigned long long)(ncap - 1);
n->next = nb[h];
nb[h] = n;
n = nx;
}
}
free(m->buckets);
m->buckets = nb;
m->cap = ncap;
}
void map_set(Map *m, const char *key, void *value) {
unsigned long long h = hash_str(key) & (unsigned long long)(m->cap - 1);
for (MapNode *n = m->buckets[h]; n; n = n->next) {
if (strcmp(n->key, key) == 0) {
n->value = value;
return;
}
}
if (m->count + 1 > m->cap * 3 / 4) map_grow(m);
MapNode *n = (MapNode *)malloc(sizeof(MapNode));
if (!n) abort();
n->key = dup_str(key);
if (!n->key) abort();
n->value = value;
h = hash_str(key) & (unsigned long long)(m->cap - 1);
n->next = m->buckets[h];
m->buckets[h] = n;
m->count++;
}
void *map_get(Map *m, const char *key) {
unsigned long long h = hash_str(key) & (unsigned long long)(m->cap - 1);
for (MapNode *n = m->buckets[h]; n; n = n->next) {
if (strcmp(n->key, key) == 0) return n->value;
}
return NULL;
}
Env *env_new(Env *parent, Arena *a) {
(void)a;
Env *e = (Env *)malloc(sizeof(Env));
if (!e) abort();
e->parent = parent;
map_init(&e->vars);
return e;
}
void env_free(Env *e) {
if (!e) return;
map_destroy(&e->vars);
free(e);
}
Value *env_get(Env *e, const char *name) {
for (Env *c = e; c; c = c->parent) {
Value *v = (Value *)map_get(&c->vars, name);
if (v) return v;
}
return NULL;
}
void env_define(Env *e, const char *name, Value v, Arena *a) {
Value *slot = (Value *)arena_alloc(a, sizeof(Value));
*slot = v;
map_set(&e->vars, name, slot);
}
void env_assign(Env *e, const char *name, Value v, Arena *a) {
(void)a;
for (Env *c = e; c; c = c->parent) {
Value *slot = (Value *)map_get(&c->vars, name);
if (slot) {
*slot = v;
return;
}
}
env_define(e, name, v, a);
}
void env_link(Env *e, const char *name, Value *slot) {
map_set(&e->vars, name, slot);
}
Env *env_get_owner(Env *e, const char *name, Value **out) {
for (Env *c = e; c; c = c->parent) {
Value *v = (Value *)map_get(&c->vars, name);
if (v) { if (out) *out = v; return c; }
}
if (out) *out = NULL;
return NULL;
}
Env *env_root(Env *e) {
if (!e) return NULL;
while (e->parent) e = e->parent;
return e;
}