#include "environment.h" #include "gc.h" #include "errors.h" Environment * env_create(Environment *parent) { Environment *env = alloc_env(); env->parent = parent; env->marked = false; env->entries = NULL; array_init(env->entries, 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; } EnvEntry entry = (EnvEntry){symbol, value}; array_push(env->entries, entry); } Object * env_lookup(Environment *env, Object *symbol) { while (env != NULL) { for (size_t i = 0; i < array_size(env->entries); i++) { EnvEntry entry = env->entries[i]; if (obj_eq(symbol, entry.symbol)) { return entry.value; } } env = env->parent; } return obj_err; } Object * env_update(Environment *env, Object *symbol, Object *value) { while (env != NULL) { for (size_t i = 0; i < array_size(env->entries); i++) { EnvEntry entry = env->entries[i]; if (obj_eq(symbol, entry.symbol)) { env->entries[i].value = value; return obj_nil; } } env = env->parent; } error_push((Error){ .type = ERR_TYPE_RUNTIME, .value = ERR_SYMBOL_NOT_FOUND, }); return obj_err; } ssize_t env_index_current(Environment *env, Object *symbol) { for (size_t i = 0; i < array_size(env->entries); i++) { EnvEntry entry = env->entries[i]; if (obj_eq(symbol, entry.symbol)) { return i; } } return -1; } void env_add_or_update_current(Environment *env, Object *symbol, Object *value) { ssize_t index = env_index_current(env, symbol); if (index == -1) { env_add_symbol(env, symbol, value); } else { env->entries[index].value = value; } } Environment * env_extend(Environment *parent, Environment *extra) { Environment *env = parent; for (size_t i = 0; i < array_size(extra->entries); i++) { EnvEntry entry = extra->entries[i]; Environment *tmp = env; bool found = false; while (tmp != NULL) { if (env_index_current(tmp, entry.symbol) != -1) { found = true; break; } tmp = tmp->parent; } if (!found) { env_add_symbol(env, entry.symbol, entry.value); } } return env; }