Initial commit of dem beast./plot.py

This commit is contained in:
2025-12-02 06:54:32 +01:00
commit c9cf356cbd
58 changed files with 9092 additions and 0 deletions
+462
View File
@@ -0,0 +1,462 @@
#define _POSIX_C_SOURCE 200809L
#include "semantic.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
static void _rava_semantic_error(RavaSemanticAnalyzer_t *analyzer, const char *message, int line, int col);
static bool _rava_semantic_analyze_node(RavaSemanticAnalyzer_t *analyzer, RavaASTNode_t *node);
static RavaType_t* _rava_semantic_check_expression(RavaSemanticAnalyzer_t *analyzer, RavaASTNode_t *expr);
RavaSemanticAnalyzer_t* rava_semantic_analyzer_create() {
RavaSemanticAnalyzer_t *analyzer = calloc(1, sizeof(RavaSemanticAnalyzer_t));
analyzer->symbol_table = rava_symbol_table_create();
analyzer->error_message = NULL;
analyzer->had_error = false;
analyzer->error_count = 0;
return analyzer;
}
void rava_semantic_analyzer_destroy(RavaSemanticAnalyzer_t *analyzer) {
if (!analyzer) return;
rava_symbol_table_destroy(analyzer->symbol_table);
free(analyzer->error_message);
free(analyzer);
}
static void _rava_semantic_error(RavaSemanticAnalyzer_t *analyzer, const char *message, int line, int col) {
analyzer->had_error = true;
analyzer->error_count++;
if (analyzer->error_message) free(analyzer->error_message);
analyzer->error_message = malloc(512);
snprintf(analyzer->error_message, 512, "Semantic error at line %d, column %d: %s",
line, col, message);
}
static RavaType_t* _rava_semantic_resolve_type(RavaSemanticAnalyzer_t *analyzer, RavaASTNode_t *type_node) {
(void)analyzer;
if (!type_node || type_node->type != RAVA_AST_TYPE) return NULL;
RavaType_t *base_type = rava_type_from_name(type_node->data.type.type_name);
if (type_node->data.type.is_array) {
return rava_type_create_array(base_type, type_node->data.type.array_dimensions);
}
return base_type;
}
static bool _rava_semantic_analyze_class(RavaSemanticAnalyzer_t *analyzer, RavaASTNode_t *class_node) {
if (class_node->type != RAVA_AST_CLASS_DECL) return false;
char *class_name = class_node->data.class_decl.name;
RavaType_t *class_type = rava_type_create_class(class_name);
RavaSymbol_t *class_symbol = rava_symbol_create(RAVA_SYMBOL_CLASS, class_name, class_type);
class_symbol->modifiers = class_node->data.class_decl.modifiers;
class_symbol->modifiers_count = class_node->data.class_decl.modifiers_count;
class_symbol->declaration = class_node;
if (!rava_symbol_table_define(analyzer->symbol_table, class_symbol)) {
_rava_semantic_error(analyzer, "Class already defined", class_node->line, class_node->column);
rava_symbol_destroy(class_symbol);
return false;
}
rava_symbol_table_enter_scope(analyzer->symbol_table, class_name);
for (size_t i = 0; i < class_node->children_count; i++) {
_rava_semantic_analyze_node(analyzer, class_node->children[i]);
}
rava_symbol_table_exit_scope(analyzer->symbol_table);
return !analyzer->had_error;
}
static bool _rava_semantic_analyze_method(RavaSemanticAnalyzer_t *analyzer, RavaASTNode_t *method_node) {
if (method_node->type != RAVA_AST_METHOD_DECL) return false;
char *method_name = method_node->data.method_decl.name;
RavaType_t *return_type = _rava_semantic_resolve_type(analyzer, method_node->data.method_decl.return_type);
RavaSymbol_t *method_symbol = rava_symbol_create(RAVA_SYMBOL_METHOD, method_name, return_type);
method_symbol->modifiers = method_node->data.method_decl.modifiers;
method_symbol->modifiers_count = method_node->data.method_decl.modifiers_count;
method_symbol->declaration = method_node;
if (!rava_symbol_table_define(analyzer->symbol_table, method_symbol)) {
char error_msg[256];
snprintf(error_msg, sizeof(error_msg), "Method '%s' already defined", method_name);
_rava_semantic_error(analyzer, error_msg, method_node->line, method_node->column);
rava_symbol_destroy(method_symbol);
return false;
}
rava_symbol_table_enter_scope(analyzer->symbol_table, method_name);
for (size_t i = 0; i < method_node->children_count; i++) {
RavaASTNode_t *child = method_node->children[i];
if (child->type == RAVA_AST_PARAM_DECL) {
char *param_name = child->data.var_decl.name;
RavaType_t *param_type = _rava_semantic_resolve_type(analyzer, child->data.var_decl.type);
RavaSymbol_t *param_symbol = rava_symbol_create(RAVA_SYMBOL_PARAMETER, param_name, param_type);
param_symbol->declaration = child;
if (!rava_symbol_table_define(analyzer->symbol_table, param_symbol)) {
char error_msg[256];
snprintf(error_msg, sizeof(error_msg), "Parameter '%s' already defined", param_name);
_rava_semantic_error(analyzer, error_msg, child->line, child->column);
rava_symbol_destroy(param_symbol);
}
} else if (child->type == RAVA_AST_BLOCK_STMT) {
_rava_semantic_analyze_node(analyzer, child);
}
}
rava_symbol_table_exit_scope(analyzer->symbol_table);
return !analyzer->had_error;
}
static bool _rava_semantic_analyze_field(RavaSemanticAnalyzer_t *analyzer, RavaASTNode_t *field_node) {
if (field_node->type != RAVA_AST_FIELD_DECL) return false;
char *field_name = field_node->data.var_decl.name;
RavaType_t *field_type = _rava_semantic_resolve_type(analyzer, field_node->data.var_decl.type);
RavaSymbol_t *field_symbol = rava_symbol_create(RAVA_SYMBOL_FIELD, field_name, field_type);
field_symbol->declaration = field_node;
if (!rava_symbol_table_define(analyzer->symbol_table, field_symbol)) {
char error_msg[256];
snprintf(error_msg, sizeof(error_msg), "Field '%s' already defined", field_name);
_rava_semantic_error(analyzer, error_msg, field_node->line, field_node->column);
rava_symbol_destroy(field_symbol);
return false;
}
if (field_node->data.var_decl.initializer) {
RavaType_t *init_type = _rava_semantic_check_expression(analyzer, field_node->data.var_decl.initializer);
if (init_type && !rava_type_is_assignable_to(init_type, field_type)) {
char error_msg[256];
snprintf(error_msg, sizeof(error_msg),
"Cannot assign '%s' to field of type '%s'",
rava_type_to_string(init_type),
rava_type_to_string(field_type));
_rava_semantic_error(analyzer, error_msg, field_node->line, field_node->column);
}
}
return !analyzer->had_error;
}
static bool _rava_semantic_analyze_var_decl(RavaSemanticAnalyzer_t *analyzer, RavaASTNode_t *var_node) {
if (var_node->type != RAVA_AST_VAR_DECL) return false;
char *var_name = var_node->data.var_decl.name;
RavaType_t *var_type = _rava_semantic_resolve_type(analyzer, var_node->data.var_decl.type);
RavaSymbol_t *var_symbol = rava_symbol_create(RAVA_SYMBOL_VARIABLE, var_name, var_type);
var_symbol->declaration = var_node;
if (!rava_symbol_table_define(analyzer->symbol_table, var_symbol)) {
char error_msg[256];
snprintf(error_msg, sizeof(error_msg), "Variable '%s' already defined", var_name);
_rava_semantic_error(analyzer, error_msg, var_node->line, var_node->column);
rava_symbol_destroy(var_symbol);
return false;
}
if (var_node->data.var_decl.initializer) {
RavaType_t *init_type = _rava_semantic_check_expression(analyzer, var_node->data.var_decl.initializer);
if (init_type && !rava_type_is_assignable_to(init_type, var_type)) {
char error_msg[256];
snprintf(error_msg, sizeof(error_msg),
"Cannot assign '%s' to variable of type '%s'",
rava_type_to_string(init_type),
rava_type_to_string(var_type));
_rava_semantic_error(analyzer, error_msg, var_node->line, var_node->column);
}
}
return !analyzer->had_error;
}
static RavaType_t* _rava_semantic_check_expression(RavaSemanticAnalyzer_t *analyzer, RavaASTNode_t *expr) {
if (!expr) return NULL;
switch (expr->type) {
case RAVA_AST_LITERAL_EXPR: {
switch (expr->data.literal.literal_type) {
case RAVA_TOKEN_LITERAL_INTEGER:
return rava_type_create_primitive(RAVA_TYPE_INT);
case RAVA_TOKEN_LITERAL_LONG:
return rava_type_create_primitive(RAVA_TYPE_LONG);
case RAVA_TOKEN_LITERAL_FLOAT:
return rava_type_create_primitive(RAVA_TYPE_FLOAT);
case RAVA_TOKEN_LITERAL_DOUBLE:
return rava_type_create_primitive(RAVA_TYPE_DOUBLE);
case RAVA_TOKEN_LITERAL_STRING:
return rava_type_create_class("String");
case RAVA_TOKEN_LITERAL_CHARACTER:
return rava_type_create_primitive(RAVA_TYPE_CHAR);
case RAVA_TOKEN_LITERAL_TRUE:
case RAVA_TOKEN_LITERAL_FALSE:
return rava_type_create_primitive(RAVA_TYPE_BOOLEAN);
case RAVA_TOKEN_LITERAL_NULL:
return rava_type_create_primitive(RAVA_TYPE_NULL);
default:
return NULL;
}
}
case RAVA_AST_IDENTIFIER_EXPR: {
char *name = expr->data.identifier.name;
if (strcmp(name, "System") == 0) {
return rava_type_from_name("System");
}
if (strcmp(name, "Files") == 0) {
return rava_type_from_name("Files");
}
RavaSymbol_t *symbol = rava_symbol_table_resolve(analyzer->symbol_table, name);
if (!symbol) {
char error_msg[256];
snprintf(error_msg, sizeof(error_msg), "Undefined identifier '%s'", name);
_rava_semantic_error(analyzer, error_msg, expr->line, expr->column);
return NULL;
}
return symbol->type;
}
case RAVA_AST_BINARY_EXPR: {
RavaType_t *left_type = _rava_semantic_check_expression(analyzer, expr->data.binary.left);
RavaType_t *right_type = _rava_semantic_check_expression(analyzer, expr->data.binary.right);
if (!left_type || !right_type) return NULL;
if (expr->data.binary.op >= RAVA_BINOP_EQ && expr->data.binary.op <= RAVA_BINOP_GE) {
return rava_type_create_primitive(RAVA_TYPE_BOOLEAN);
}
if (expr->data.binary.op == RAVA_BINOP_AND || expr->data.binary.op == RAVA_BINOP_OR) {
if (left_type->kind != RAVA_TYPE_BOOLEAN || right_type->kind != RAVA_TYPE_BOOLEAN) {
_rava_semantic_error(analyzer, "Logical operators require boolean operands",
expr->line, expr->column);
return NULL;
}
return rava_type_create_primitive(RAVA_TYPE_BOOLEAN);
}
return rava_type_binary_result(left_type, right_type);
}
case RAVA_AST_UNARY_EXPR: {
return _rava_semantic_check_expression(analyzer, expr->data.unary.operand);
}
case RAVA_AST_ASSIGN_EXPR: {
RavaType_t *target_type = _rava_semantic_check_expression(analyzer, expr->data.assign.target);
RavaType_t *value_type = _rava_semantic_check_expression(analyzer, expr->data.assign.value);
if (target_type && value_type && !rava_type_is_assignable_to(value_type, target_type)) {
char error_msg[256];
snprintf(error_msg, sizeof(error_msg),
"Cannot assign '%s' to '%s'",
rava_type_to_string(value_type),
rava_type_to_string(target_type));
_rava_semantic_error(analyzer, error_msg, expr->line, expr->column);
}
return target_type;
}
case RAVA_AST_CALL_EXPR: {
_rava_semantic_check_expression(analyzer, expr->data.call.callee);
for (size_t i = 0; i < expr->data.call.arguments_count; i++) {
_rava_semantic_check_expression(analyzer, expr->data.call.arguments[i]);
}
if (expr->data.call.callee->type == RAVA_AST_MEMBER_ACCESS_EXPR) {
RavaASTNode_t *member = expr->data.call.callee;
const char *method = member->data.member_access.member;
if (member->data.member_access.object->type == RAVA_AST_IDENTIFIER_EXPR &&
strcmp(member->data.member_access.object->data.identifier.name, "Files") == 0) {
if (strcmp(method, "read") == 0) {
return rava_type_create_class("String");
} else if (strcmp(method, "write") == 0 || strcmp(method, "exists") == 0 ||
strcmp(method, "delete") == 0) {
return rava_type_create_primitive(RAVA_TYPE_BOOLEAN);
}
}
if (member->data.member_access.object->type == RAVA_AST_IDENTIFIER_EXPR &&
strcmp(member->data.member_access.object->data.identifier.name, "System") == 0) {
if (strcmp(method, "currentTimeMillis") == 0 || strcmp(method, "nanoTime") == 0) {
return rava_type_create_primitive(RAVA_TYPE_LONG);
}
}
if (strcmp(method, "length") == 0) {
return rava_type_create_primitive(RAVA_TYPE_INT);
} else if (strcmp(method, "charAt") == 0) {
return rava_type_create_primitive(RAVA_TYPE_CHAR);
} else if (strcmp(method, "equals") == 0) {
return rava_type_create_primitive(RAVA_TYPE_BOOLEAN);
} else if (strcmp(method, "compareTo") == 0) {
return rava_type_create_primitive(RAVA_TYPE_INT);
}
}
return rava_type_create_primitive(RAVA_TYPE_INT);
}
case RAVA_AST_MEMBER_ACCESS_EXPR: {
_rava_semantic_check_expression(analyzer, expr->data.member_access.object);
return rava_type_create_primitive(RAVA_TYPE_INT);
}
case RAVA_AST_ARRAY_ACCESS_EXPR: {
RavaType_t *array_type = _rava_semantic_check_expression(analyzer, expr->data.array_access.array);
RavaType_t *index_type = _rava_semantic_check_expression(analyzer, expr->data.array_access.index);
if (index_type && index_type->kind != RAVA_TYPE_INT && index_type->kind != RAVA_TYPE_LONG) {
_rava_semantic_error(analyzer, "Array index must be an integer", expr->line, expr->column);
}
if (array_type && array_type->kind == RAVA_TYPE_ARRAY) {
return array_type->data.array.element_type;
}
return rava_type_create_primitive(RAVA_TYPE_INT);
}
case RAVA_AST_NEW_EXPR: {
RavaType_t *type = _rava_semantic_resolve_type(analyzer, expr->data.new_expr.type);
for (size_t i = 0; i < expr->data.new_expr.arguments_count; i++) {
RavaType_t *arg_type = _rava_semantic_check_expression(analyzer, expr->data.new_expr.arguments[i]);
if (type && type->kind == RAVA_TYPE_ARRAY && arg_type) {
if (arg_type->kind != RAVA_TYPE_INT && arg_type->kind != RAVA_TYPE_LONG) {
_rava_semantic_error(analyzer, "Array size must be an integer", expr->line, expr->column);
}
}
}
return type;
}
default:
return NULL;
}
}
static bool _rava_semantic_analyze_statement(RavaSemanticAnalyzer_t *analyzer, RavaASTNode_t *stmt) {
if (!stmt) return true;
switch (stmt->type) {
case RAVA_AST_BLOCK_STMT:
for (size_t i = 0; i < stmt->children_count; i++) {
_rava_semantic_analyze_node(analyzer, stmt->children[i]);
}
return true;
case RAVA_AST_IF_STMT: {
RavaType_t *cond_type = _rava_semantic_check_expression(analyzer, stmt->data.if_stmt.condition);
if (cond_type && cond_type->kind != RAVA_TYPE_BOOLEAN) {
_rava_semantic_error(analyzer, "If condition must be boolean", stmt->line, stmt->column);
}
_rava_semantic_analyze_node(analyzer, stmt->data.if_stmt.then_stmt);
if (stmt->data.if_stmt.else_stmt) {
_rava_semantic_analyze_node(analyzer, stmt->data.if_stmt.else_stmt);
}
return true;
}
case RAVA_AST_WHILE_STMT: {
RavaType_t *cond_type = _rava_semantic_check_expression(analyzer, stmt->data.while_stmt.condition);
if (cond_type && cond_type->kind != RAVA_TYPE_BOOLEAN) {
_rava_semantic_error(analyzer, "While condition must be boolean", stmt->line, stmt->column);
}
_rava_semantic_analyze_node(analyzer, stmt->data.while_stmt.body);
return true;
}
case RAVA_AST_FOR_STMT:
if (stmt->data.for_stmt.init) {
if (stmt->data.for_stmt.init->type == RAVA_AST_VAR_DECL) {
_rava_semantic_analyze_node(analyzer, stmt->data.for_stmt.init);
} else {
_rava_semantic_check_expression(analyzer, stmt->data.for_stmt.init);
}
}
if (stmt->data.for_stmt.condition) {
RavaType_t *cond_type = _rava_semantic_check_expression(analyzer, stmt->data.for_stmt.condition);
if (cond_type && cond_type->kind != RAVA_TYPE_BOOLEAN) {
_rava_semantic_error(analyzer, "For condition must be boolean", stmt->line, stmt->column);
}
}
if (stmt->data.for_stmt.update) {
_rava_semantic_check_expression(analyzer, stmt->data.for_stmt.update);
}
_rava_semantic_analyze_node(analyzer, stmt->data.for_stmt.body);
return true;
case RAVA_AST_RETURN_STMT:
if (stmt->data.return_stmt.value) {
_rava_semantic_check_expression(analyzer, stmt->data.return_stmt.value);
}
return true;
case RAVA_AST_EXPR_STMT:
if (stmt->children_count > 0) {
_rava_semantic_check_expression(analyzer, stmt->children[0]);
}
return true;
case RAVA_AST_VAR_DECL:
return _rava_semantic_analyze_var_decl(analyzer, stmt);
default:
return true;
}
}
static bool _rava_semantic_analyze_node(RavaSemanticAnalyzer_t *analyzer, RavaASTNode_t *node) {
if (!node) return true;
switch (node->type) {
case RAVA_AST_COMPILATION_UNIT:
for (size_t i = 0; i < node->children_count; i++) {
_rava_semantic_analyze_node(analyzer, node->children[i]);
}
return true;
case RAVA_AST_CLASS_DECL:
return _rava_semantic_analyze_class(analyzer, node);
case RAVA_AST_METHOD_DECL:
return _rava_semantic_analyze_method(analyzer, node);
case RAVA_AST_FIELD_DECL:
return _rava_semantic_analyze_field(analyzer, node);
case RAVA_AST_CONSTRUCTOR_DECL:
return true;
default:
return _rava_semantic_analyze_statement(analyzer, node);
}
}
bool rava_semantic_analyze(RavaSemanticAnalyzer_t *analyzer, RavaASTNode_t *root) {
if (!analyzer || !root) return false;
_rava_semantic_analyze_node(analyzer, root);
return !analyzer->had_error;
}
RavaType_t* rava_semantic_get_expression_type(RavaSemanticAnalyzer_t *analyzer, RavaASTNode_t *expr) {
return _rava_semantic_check_expression(analyzer, expr);
}
+23
View File
@@ -0,0 +1,23 @@
#ifndef RAVA_SEMANTIC_H
#define RAVA_SEMANTIC_H
#include "../parser/parser.h"
#include "../types/types.h"
#include "symbol_table.h"
#include <stdbool.h>
typedef struct {
RavaSymbolTable_t *symbol_table;
char *error_message;
bool had_error;
int error_count;
} RavaSemanticAnalyzer_t;
RavaSemanticAnalyzer_t* rava_semantic_analyzer_create();
void rava_semantic_analyzer_destroy(RavaSemanticAnalyzer_t *analyzer);
bool rava_semantic_analyze(RavaSemanticAnalyzer_t *analyzer, RavaASTNode_t *root);
RavaType_t* rava_semantic_get_expression_type(RavaSemanticAnalyzer_t *analyzer, RavaASTNode_t *expr);
#endif
+139
View File
@@ -0,0 +1,139 @@
#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;
}
+61
View File
@@ -0,0 +1,61 @@
#ifndef RAVA_SYMBOL_TABLE_H
#define RAVA_SYMBOL_TABLE_H
#include "../types/types.h"
#include "../parser/parser.h"
#include <stddef.h>
#include <stdbool.h>
typedef enum {
RAVA_SYMBOL_CLASS,
RAVA_SYMBOL_METHOD,
RAVA_SYMBOL_FIELD,
RAVA_SYMBOL_VARIABLE,
RAVA_SYMBOL_PARAMETER
} RavaSymbolKind_e;
typedef struct RavaSymbol_t {
RavaSymbolKind_e kind;
char *name;
RavaType_t *type;
RavaModifier_e *modifiers;
size_t modifiers_count;
RavaASTNode_t *declaration;
size_t local_index;
struct RavaSymbol_t *next;
} RavaSymbol_t;
typedef struct RavaScope_t {
char *name;
RavaSymbol_t *symbols;
struct RavaScope_t *parent;
struct RavaScope_t **children;
size_t children_count;
size_t children_capacity;
} RavaScope_t;
typedef struct {
RavaScope_t *global_scope;
RavaScope_t *current_scope;
} RavaSymbolTable_t;
RavaSymbolTable_t* rava_symbol_table_create();
void rava_symbol_table_destroy(RavaSymbolTable_t *table);
RavaScope_t* rava_scope_create(const char *name, RavaScope_t *parent);
void rava_scope_destroy(RavaScope_t *scope);
void rava_symbol_table_enter_scope(RavaSymbolTable_t *table, const char *scope_name);
void rava_symbol_table_exit_scope(RavaSymbolTable_t *table);
RavaSymbol_t* rava_symbol_create(RavaSymbolKind_e kind, const char *name, RavaType_t *type);
void rava_symbol_destroy(RavaSymbol_t *symbol);
bool rava_symbol_table_define(RavaSymbolTable_t *table, RavaSymbol_t *symbol);
RavaSymbol_t* rava_symbol_table_resolve(RavaSymbolTable_t *table, const char *name);
RavaSymbol_t* rava_symbol_table_resolve_in_scope(RavaScope_t *scope, const char *name);
bool rava_symbol_has_modifier(RavaSymbol_t *symbol, RavaModifier_e modifier);
#endif