#define _POSIX_C_SOURCE 200809L
#include "symbol_table.h"
#include <stdlib.h>
#include <string.h>
RavaSymbolTable_t* rava_symbol_table_create() {
RavaSymbolTable_t *table = malloc(sizeof(RavaSymbolTable_t));
table->global_scope = rava_scope_create("global", NULL);
table->current_scope = table->global_scope;
return table;
}
void rava_symbol_table_destroy(RavaSymbolTable_t *table) {
if (!table) return;
rava_scope_destroy(table->global_scope);
free(table);
}
RavaScope_t* rava_scope_create(const char *name, RavaScope_t *parent) {
RavaScope_t *scope = calloc(1, sizeof(RavaScope_t));
scope->name = strdup(name);
scope->symbols = NULL;
scope->parent = parent;
scope->children = NULL;
scope->children_count = 0;
scope->children_capacity = 0;
return scope;
}
void rava_scope_destroy(RavaScope_t *scope) {
if (!scope) return;
free(scope->name);
RavaSymbol_t *symbol = scope->symbols;
while (symbol) {
RavaSymbol_t *next = symbol->next;
rava_symbol_destroy(symbol);
symbol = next;
}
for (size_t i = 0; i < scope->children_count; i++) {
rava_scope_destroy(scope->children[i]);
}
free(scope->children);
free(scope);
}
void rava_symbol_table_enter_scope(RavaSymbolTable_t *table, const char *scope_name) {
RavaScope_t *new_scope = rava_scope_create(scope_name, table->current_scope);
if (table->current_scope->children_count >= table->current_scope->children_capacity) {
size_t new_capacity = table->current_scope->children_capacity == 0 ? 4 :
table->current_scope->children_capacity * 2;
table->current_scope->children = realloc(table->current_scope->children,
sizeof(RavaScope_t*) * new_capacity);
table->current_scope->children_capacity = new_capacity;
}
table->current_scope->children[table->current_scope->children_count++] = new_scope;
table->current_scope = new_scope;
}
void rava_symbol_table_exit_scope(RavaSymbolTable_t *table) {
if (table->current_scope->parent) {
table->current_scope = table->current_scope->parent;
}
}
RavaSymbol_t* rava_symbol_create(RavaSymbolKind_e kind, const char *name, RavaType_t *type) {
RavaSymbol_t *symbol = calloc(1, sizeof(RavaSymbol_t));
symbol->kind = kind;
symbol->name = strdup(name);
symbol->type = type;
symbol->modifiers = NULL;
symbol->modifiers_count = 0;
symbol->declaration = NULL;
symbol->next = NULL;
return symbol;
}
void rava_symbol_destroy(RavaSymbol_t *symbol) {
if (!symbol) return;
free(symbol->name);
rava_type_destroy(symbol->type);
free(symbol);
}
bool rava_symbol_table_define(RavaSymbolTable_t *table, RavaSymbol_t *symbol) {
if (!table || !symbol) return false;
if (rava_symbol_table_resolve_in_scope(table->current_scope, symbol->name)) {
return false;
}
symbol->next = table->current_scope->symbols;
table->current_scope->symbols = symbol;
return true;
}
RavaSymbol_t* rava_symbol_table_resolve(RavaSymbolTable_t *table, const char *name) {
if (!table || !name) return NULL;
RavaScope_t *scope = table->current_scope;
while (scope) {
RavaSymbol_t *symbol = rava_symbol_table_resolve_in_scope(scope, name);
if (symbol) return symbol;
scope = scope->parent;
}
return NULL;
}
RavaSymbol_t* rava_symbol_table_resolve_in_scope(RavaScope_t *scope, const char *name) {
if (!scope || !name) return NULL;
RavaSymbol_t *symbol = scope->symbols;
while (symbol) {
if (strcmp(symbol->name, name) == 0) {
return symbol;
}
symbol = symbol->next;
}
return NULL;
}
bool rava_symbol_has_modifier(RavaSymbol_t *symbol, RavaModifier_e modifier) {
if (!symbol) return false;
for (size_t i = 0; i < symbol->modifiers_count; i++) {
if (symbol->modifiers[i] == modifier) {
return true;
}
}
return false;
}