158 lines
2.8 KiB
C
158 lines
2.8 KiB
C
#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; 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;
|
|
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; 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;
|
|
}
|