#include "sym.h" void sym_init(sym_t* self) { assert(self); self->env = NULL; } void sym_free(sym_t* self) { assert(self); if (self->env) { sym_free_env(self, self->env); free(self->env); } } void sym_free_env(sym_t* self, env_t* env) { assert(self); assert(env); if (env->parent) { sym_free_env(self, env->parent); free(env->parent); } for (size_t i=0; ientries.size; i++) { sym_entry_t* entry = env->entries.data[i]; free(entry->name); free(entry); } vec_free(&env->entries); } void sym_open_scope(sym_t* self) { assert(self); env_t* env = malloc(sizeof(env_t)); env->parent = NULL; vec_init(&env->entries); if (self->env == NULL) { self->env = env; } else { env->parent = self->env; self->env = env; } } void sym_close_scope(sym_t* self) { assert(self); assert(self->env); for (size_t i=0; ienv->entries.size; i++) { sym_entry_t* entry = self->env->entries.data[i]; free(entry->name); free(entry); } vec_free(&self->env->entries); env_t* parent = self->env->parent; free(self->env); self->env = parent; } int sym_declare(sym_t* self, char const* name, int addr, int is_const) { assert(self); assert(self->env); assert(name); if (sym_try_get_env_value(self,self->env, name) != NULL) { return 0; } sym_entry_t* entry = malloc(sizeof(sym_entry_t)); entry->name = strdup(name); entry->local_addr = addr; entry->is_const = is_const; vec_push(&self->env->entries, entry); return 1; } int sym_try_assign(sym_t* self, char const* name, int addr) { assert(self); assert(name); sym_entry_t* entry = sym_try_get_value(self, name); if (!entry) { return 0; } entry->local_addr = addr; return 1; } sym_entry_t* sym_try_get_value(sym_t* self, char const* name) { assert(self); assert(name); env_t* env = self->env; while (env) { sym_entry_t* entry = sym_try_get_env_value( self, env, name ); if (entry) { return entry; } env = env->parent; } return NULL; } sym_entry_t* sym_try_get_env_value(sym_t* self, env_t* env, char const* name) { assert(self); assert(env); assert(name); for (size_t i=0; ientries.size; i++) { sym_entry_t const* entry = ((sym_entry_t*) env->entries.data[i]); if (strcmp(entry->name, name) == 0) { return env->entries.data[i]; } } return NULL; }