From: Brendan Hansen Date: Fri, 5 Feb 2021 15:26:44 +0000 (-0600) Subject: more robust symbol resolution with nested structs X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=c596c236299c572db0f93871f7020066030c206e;p=onyx.git more robust symbol resolution with nested structs --- diff --git a/bin/onyx b/bin/onyx index 3705eefb..54b3bfd9 100755 Binary files a/bin/onyx and b/bin/onyx differ diff --git a/core/map.onyx b/core/map.onyx index f3e143da..42a293cf 100644 --- a/core/map.onyx +++ b/core/map.onyx @@ -6,16 +6,16 @@ use package core.string as string Map :: struct (K: type_expr, V: type_expr) { hashes : [..] i32; - entries : [..] MapEntry(K, V); + entries : [..] Entry(K, V); // The value provided by `map.get`, if nothing was found. default_value : V; -} -MapEntry :: struct (K: type_expr, V: type_expr) { - next : i32; - key : K; - value : V; + Entry :: struct (K: type_expr, V: type_expr) { + next : i32; + key : K; + value : V; + } } make :: ($Key: type_expr, $Value: type_expr, default: Value = 0, hash_count: i32 = 16) -> Map(Key, Value) { @@ -46,7 +46,7 @@ put :: (use map: ^Map($K, $V), key: K, value: V) { return; } - entry : MapEntry(K, V); + entry : Map.Entry(K, V); entry.key = key; entry.value = value; entry.next = hashes[lr.hash_index]; diff --git a/include/onyxutils.h b/include/onyxutils.h index 50bc830d..312ed66a 100644 --- a/include/onyxutils.h +++ b/include/onyxutils.h @@ -20,6 +20,7 @@ void symbol_builtin_introduce(Scope* scope, char* sym, AstNode *node); void symbol_subpackage_introduce(Scope* scope, OnyxToken* sym, AstPackage *node); AstNode* symbol_raw_resolve(Scope* start_scope, char* sym); AstNode* symbol_resolve(Scope* start_scope, OnyxToken* tkn); +AstNode* try_symbol_resolve_from_node(AstNode* node, OnyxToken* token); u32 char_to_base16_value(char x); diff --git a/onyx.exe b/onyx.exe index 9da7accf..509874ee 100644 Binary files a/onyx.exe and b/onyx.exe differ diff --git a/src/onyxsymres.c b/src/onyxsymres.c index 0e663545..126135cc 100644 --- a/src/onyxsymres.c +++ b/src/onyxsymres.c @@ -95,9 +95,6 @@ AstType* symres_type(AstType* type) { s_node->flags |= Ast_Flag_Type_Is_Resolved; - // FIX: This is probably wrong for the long term. - if (s_node->scope) s_node->scope->parent = curr_scope; - { bh_table(i32) mem_set; bh_table_init(global_heap_allocator, mem_set, bh_arr_length(s_node->members)); @@ -121,6 +118,13 @@ AstType* symres_type(AstType* type) { bh_table_free(mem_set); } + if (s_node->scope) { + // FIX: This is probably wrong for the long term. + s_node->scope->parent = curr_scope; + + scope_enter(s_node->scope); + } + fori (i, 0, bh_arr_length(s_node->members)) { AstStructMember *member = s_node->members[i]; @@ -129,7 +133,7 @@ AstType* symres_type(AstType* type) { if (!node_is_type((AstNode *) member->type_node)) { onyx_report_error(member->token->pos, "Member type is not a type."); - return type; + goto struct_symres_done; } if (member->flags & Ast_Flag_Struct_Mem_Used) { @@ -150,13 +154,14 @@ AstType* symres_type(AstType* type) { onyx_report_error(member->token->pos, "Can only 'use' members of struct type, got '%s'.", onyx_ast_node_kind_string(used->kind)); - - return type; + goto struct_symres_done; } } } } +struct_symres_done: + if (s_node->scope) scope_leave(); return type; } @@ -280,50 +285,8 @@ static void symres_field_access(AstFieldAccess** fa) { symres_expression(&(*fa)->expr); if ((*fa)->expr == NULL) return; - // CLEANUP: There are way to many cases here that a too similar. - // It should be easy to clean all of these up. Also, I think that when - // that happens, it might be even easier to allow for 'use'ing members - // that are pointers to structures. - - if ((*fa)->expr->kind == Ast_Kind_Package) { - AstPackage* package = (AstPackage *) (*fa)->expr; - AstNode* n = symbol_resolve(package->package->scope, (*fa)->token); - if (n) { - // NOTE: not field access - *fa = (AstFieldAccess *) n; - return; - } - } - - if ((*fa)->expr->kind == Ast_Kind_Enum_Type) { - AstEnumType* etype = (AstEnumType *) (*fa)->expr; - AstNode* n = symbol_resolve(etype->scope, (*fa)->token); - if (n) { - // NOTE: not field access - *fa = (AstFieldAccess *) n; - return; - } - } - - if ((*fa)->expr->kind == Ast_Kind_Struct_Type) { - AstStructType* stype = (AstStructType *) (*fa)->expr; - AstNode* n = symbol_resolve(stype->scope, (*fa)->token); - if (n) { - // Note: not field access - *fa = (AstFieldAccess *) n; - return; - } - } - - if ((*fa)->expr->kind == Ast_Kind_Poly_Struct_Type) { - AstStructType* stype = ((AstPolyStructType *) (*fa)->expr)->base_struct; - AstNode* n = symbol_resolve(stype->scope, (*fa)->token); - if (n) { - // Note: not field access - *fa = (AstFieldAccess *) n; - return; - } - } + AstNode* resolution = try_symbol_resolve_from_node((AstNode *) (*fa)->expr, (*fa)->token); + if (resolution) *((AstNode **) fa) = resolution; } static void symres_compound(AstCompound* compound) { diff --git a/src/onyxutils.c b/src/onyxutils.c index b04cf5d3..9c6bd506 100644 --- a/src/onyxutils.c +++ b/src/onyxutils.c @@ -140,6 +140,44 @@ AstNode* symbol_resolve(Scope* start_scope, OnyxToken* tkn) { return res; } +AstNode* try_symbol_resolve_from_node(AstNode* node, OnyxToken* token) { + if (node->kind == Ast_Kind_Type_Raw_Alias) + node = (AstNode *) ((AstTypeRawAlias *) node)->to->ast_type; + + if (node->kind == Ast_Kind_Type_Alias) + node = (AstNode *) ((AstTypeAlias *) node)->to; + + // A single pointer can be dereferenced to lookup symbols in struct. + if (node->kind == Ast_Kind_Pointer_Type) + node = (AstNode *) ((AstPointerType *) node)->elem; + + if (!node) return NULL; + + switch (node->kind) { + case Ast_Kind_Package: { + AstPackage* package = (AstPackage *) node; + return symbol_resolve(package->package->scope, token); + } + + case Ast_Kind_Enum_Type: { + AstEnumType* etype = (AstEnumType *) node; + return symbol_resolve(etype->scope, token); + } + + case Ast_Kind_Struct_Type: { + AstStructType* stype = (AstStructType *) node; + return symbol_resolve(stype->scope, token); + } + + case Ast_Kind_Poly_Struct_Type: { + AstStructType* stype = ((AstPolyStructType *) node)->base_struct; + return symbol_resolve(stype->scope, token); + } + } + + return NULL; +} + void scope_clear(Scope* scope) { bh_table_clear(scope->symbols); }