docs: add documentation for method overloading patterns and usage examples
This commit is contained in:
+21
-1
@@ -123,14 +123,34 @@ static bool _rava_semantic_analyze_method(RavaSemanticAnalyzer_t *analyzer, Rava
|
||||
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);
|
||||
|
||||
size_t param_count = 0;
|
||||
for (size_t i = 0; i < method_node->children_count; i++) {
|
||||
if (method_node->children[i]->type == RAVA_AST_PARAM_DECL) {
|
||||
param_count++;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
method_symbol->param_count = param_count;
|
||||
|
||||
if (param_count > 0) {
|
||||
method_symbol->param_types = calloc(param_count, sizeof(RavaType_t*));
|
||||
size_t param_index = 0;
|
||||
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) {
|
||||
RavaType_t *param_type = _rava_semantic_resolve_type(analyzer, child->data.var_decl.type);
|
||||
method_symbol->param_types[param_index++] = rava_type_copy(param_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
snprintf(error_msg, sizeof(error_msg), "Method '%s' with this signature already defined", method_name);
|
||||
_rava_semantic_error(analyzer, error_msg, method_node->line, method_node->column);
|
||||
rava_symbol_destroy(method_symbol);
|
||||
return false;
|
||||
|
||||
+66
-2
@@ -92,14 +92,43 @@ void rava_symbol_destroy(RavaSymbol_t *symbol) {
|
||||
if (!symbol) return;
|
||||
free(symbol->name);
|
||||
rava_type_destroy(symbol->type);
|
||||
if (symbol->param_types) {
|
||||
for (size_t i = 0; i < symbol->param_count; i++) {
|
||||
rava_type_destroy(symbol->param_types[i]);
|
||||
}
|
||||
free(symbol->param_types);
|
||||
}
|
||||
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;
|
||||
if (symbol->kind == RAVA_SYMBOL_METHOD) {
|
||||
uint32_t h = _rava_symbol_hash(symbol->name);
|
||||
RavaSymbol_t *existing = table->current_scope->hash_table[h];
|
||||
while (existing) {
|
||||
if (strcmp(existing->name, symbol->name) == 0 &&
|
||||
existing->kind == RAVA_SYMBOL_METHOD) {
|
||||
if (existing->param_count == symbol->param_count) {
|
||||
bool same_signature = true;
|
||||
for (size_t i = 0; i < symbol->param_count; i++) {
|
||||
if (!rava_type_equals(existing->param_types[i], symbol->param_types[i])) {
|
||||
same_signature = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (same_signature) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
existing = existing->hash_next;
|
||||
}
|
||||
} else {
|
||||
if (rava_symbol_table_resolve_in_scope(table->current_scope, symbol->name)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
symbol->next = table->current_scope->symbols;
|
||||
@@ -151,3 +180,38 @@ bool rava_symbol_has_modifier(RavaSymbol_t *symbol, RavaModifier_e modifier) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool rava_symbol_signature_matches(RavaSymbol_t *method, RavaType_t **arg_types, size_t arg_count) {
|
||||
if (!method || method->kind != RAVA_SYMBOL_METHOD) return false;
|
||||
|
||||
if (method->param_count != arg_count) return false;
|
||||
|
||||
for (size_t i = 0; i < arg_count; i++) {
|
||||
if (!rava_type_is_assignable_to(arg_types[i], method->param_types[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
RavaSymbol_t* rava_symbol_table_resolve_method(RavaSymbolTable_t *table, const char *name, RavaType_t **arg_types, size_t arg_count) {
|
||||
if (!table || !name) return NULL;
|
||||
|
||||
RavaScope_t *scope = table->current_scope;
|
||||
while (scope) {
|
||||
uint32_t h = _rava_symbol_hash(name);
|
||||
RavaSymbol_t *symbol = scope->hash_table[h];
|
||||
while (symbol) {
|
||||
if (strcmp(symbol->name, name) == 0 &&
|
||||
symbol->kind == RAVA_SYMBOL_METHOD &&
|
||||
rava_symbol_signature_matches(symbol, arg_types, arg_count)) {
|
||||
return symbol;
|
||||
}
|
||||
symbol = symbol->hash_next;
|
||||
}
|
||||
scope = scope->parent;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -26,6 +26,9 @@ typedef struct RavaSymbol_t {
|
||||
RavaASTNode_t *declaration;
|
||||
size_t local_index;
|
||||
|
||||
RavaType_t **param_types;
|
||||
size_t param_count;
|
||||
|
||||
struct RavaSymbol_t *next;
|
||||
struct RavaSymbol_t *hash_next;
|
||||
} RavaSymbol_t;
|
||||
@@ -60,7 +63,9 @@ 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);
|
||||
RavaSymbol_t* rava_symbol_table_resolve_method(RavaSymbolTable_t *table, const char *name, RavaType_t **arg_types, size_t arg_count);
|
||||
|
||||
bool rava_symbol_has_modifier(RavaSymbol_t *symbol, RavaModifier_e modifier);
|
||||
bool rava_symbol_signature_matches(RavaSymbol_t *method, RavaType_t **arg_types, size_t arg_count);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user