// // Environment. // typedef struct EnvEntry { Object *symbol; Object *value; } EnvEntry; typedef struct Environment { struct Environment *parent; EnvEntry *buf; size_t size; size_t cap; } Environment; static Environment *global_env; #define ENV_BUF_CAP 8 Environment * env_create(Environment *parent) { Environment *env = malloc(sizeof(Environment)); env->parent = parent; env->buf = NULL; env->size = 0; env->cap = ENV_BUF_CAP; return env; } void env_add_symbol(Environment *env, Object *symbol, Object *value) { if (symbol->type != OBJ_TYPE_SYMBOL) { error_push((Error){ .type = ERR_TYPE_RUNTIME, .value = ERR_NOT_A_SYMBOL, .line = 0, .col = 0, }); return; } if (env->buf == NULL) { env->size = 0; env->cap = ENV_BUF_CAP; env->buf = malloc(env->cap * sizeof(EnvEntry)); } else if (env->size == env->cap) { env->cap *= 2; env->buf = realloc(env->buf, env->cap * sizeof(EnvEntry)); } env->buf[env->size++] = (EnvEntry){symbol, value}; } bool obj_eq(Object *a, Object* b) { if (a->type != b->type) { return false; } switch (a->type) { case OBJ_TYPE_FIXNUM: { return a->fixnum == b->fixnum; } break; case OBJ_TYPE_STRING: { if (a->string_n != b->string_n) { return false; } for (size_t i = 0; i < a->string_n; i++) { if (a->string[i] != b->string[i]) { return false; } } } break; case OBJ_TYPE_SYMBOL: { if (a->symbol_n != b->symbol_n) { return false; } for (size_t i = 0; i < a->symbol_n; i++) { if (a->symbol[i] != b->symbol[i]) { return false; } } } break; case OBJ_TYPE_PAIR: { // TODO: needs evaluation of parameters... } break; default: { return a == b; } break; } return true; } Object * env_lookup(Environment *env, Object *symbol) { while (env != NULL) { for (size_t i = 0; i < env->size; i++) { EnvEntry entry = env->buf[i]; if (obj_eq(symbol, entry.symbol)) { return entry.value; } } env = env->parent; } return obj_err; } // TODO: Free env function.