moka/lib/symtable.c

124 lines
2.3 KiB
C

#include "symtable.h"
void entry_init(struct entry* self,
char const* name,
size_t addr,
bool is_local)
{
assert(self);
self->name = strdup(name);
self->addr = addr;
self->is_local = is_local;
}
void entry_free(struct entry* self)
{
assert(self);
free(self->name);
}
void env_init(struct env* self, struct env* parent)
{
assert(self);
vec_init(&self->entries);
self->parent = parent;
}
void env_free(struct env* self)
{
assert(self);
if (self->parent)
{
env_free(self->parent);
free(self->parent);
self->parent = NULL;
}
vec_free_elements(&self->entries, (void*) entry_free);
vec_free(&self->entries);
}
struct entry* env_try_get(struct env* self, char* name)
{
assert(self);
assert(name);
for (size_t i=0; i<self->entries.size; i++)
{
struct entry* entry = self->entries.data[i];
if (strcmp(entry->name, name) == 0)
{
return entry;
}
}
if (self->parent)
{
return env_try_get(self->parent, name);
}
return NULL;
}
void symtable_init(struct symtable* self)
{
assert(self);
self->root = malloc(sizeof(struct env));
env_init(self->root, NULL);
}
void symtable_free(struct symtable* self)
{
assert(self);
env_free(self->root);
free(self->root);
}
void symtable_declare(struct symtable* self,
char* name,
size_t addr,
bool is_local)
{
assert(self);
assert(name);
assert(self->root);
struct entry* entry = malloc(sizeof(struct entry));
entry_init(entry, name, addr, is_local);
vec_push(&self->root->entries, entry);
}
struct entry* symtable_try_get(struct symtable* self, char* name)
{
assert(self);
assert(name);
return env_try_get(self->root, name);
}
void symtable_open_scope(struct symtable* self)
{
struct env* env = malloc(sizeof(struct env));
env_init(env, self->root);
self->root = env;
}
void symtable_close_scope(struct symtable* self)
{
assert(self);
assert(self->root);
struct env* env = self->root->parent;
self->root->parent = NULL;
env_free(self->root);
free(self->root);
self->root = env;
}