more robust symbol resolution with nested structs
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 5 Feb 2021 15:26:44 +0000 (09:26 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 5 Feb 2021 15:26:44 +0000 (09:26 -0600)
bin/onyx
core/map.onyx
include/onyxutils.h
onyx.exe
src/onyxsymres.c
src/onyxutils.c

index 3705eefbd27d343434fb7ec8923be949744bc31b..54b3bfd9b9cc7fa6687f00a274a8d38ea29372b0 100755 (executable)
Binary files a/bin/onyx and b/bin/onyx differ
index f3e143dad4f34d9b53afdda11f1b5c7520459dcf..42a293cfa34463899faa5b25c8af4b19acddd745 100644 (file)
@@ -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];
index 50bc830d616fb89b1a18c284d2794c2387f89273..312ed66a4056978566aa411982349132091fe34c 100644 (file)
@@ -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);
 
index 9da7accf9ae8d021b40a4e6adc2275be94b726c6..509874eeacfd103b65f662878ac20b4433e909c9 100644 (file)
Binary files a/onyx.exe and b/onyx.exe differ
index 0e663545925a92e2526ce2ef6e49034440e11c1f..126135cc1d3fa0815c1ab46e42cb8b65e1bd7095 100644 (file)
@@ -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) {
index b04cf5d359f55df38a008d4b4034fd9da0fb77d4..9c6bd506308393e80f301ed796869011f43739ed 100644 (file)
@@ -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);
 }