ccm/lib/sym.c

161 lines
2.9 KiB
C

#include "sym.h"
void sym_init(sym_t* self)
{
assert(self);
self->env = NULL;
self->id_counter = 0;
}
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; i<env->entries.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; i<self->env->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;
entry->id = self->id_counter;
vec_push(&self->env->entries, entry);
self->id_counter++;
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; i<env->entries.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;
}