improvements to poly struct parameter lookups
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 4 Jan 2022 16:05:57 +0000 (10:05 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 4 Jan 2022 16:05:57 +0000 (10:05 -0600)
core/builtin.onyx
core/container/iter.onyx
core/container/map.onyx
include/utils.h
scripts/run_tests.onyx
src/checker.c
src/onyxrun.c
src/symres.c
src/utils.c

index 5bdb96417001a30855fac029ce5320a2c8d27659..1993aa7857a580111c17f4ed2b07c9552a879530 100644 (file)
@@ -151,9 +151,9 @@ cfree   :: (ptr: rawptr) do raw_free(context.allocator, ptr);
 }
 
 
-Iterator :: struct (T: type_expr) {
+Iterator :: struct (Iter_Type: type_expr) {
     data:  rawptr;
-    next:  (data: rawptr) -> (T, bool);
+    next:  (data: rawptr) -> (Iter_Type, bool);
     close: (data: rawptr) -> void = null_proc;
 }
 
index 60697ad63483e3148b610098cabb59ea651b3100..6c90382747e890558c914ee30521a2d4bba8a0ba 100644 (file)
@@ -618,4 +618,4 @@ parallel_for :: #match {}
             #insert body;
         }
     }
-}
\ No newline at end of file
+}
index 8d0e6b68443cc3d6702dbd0ad5238603a27d1f22..5a2c9ade528f5ddda2e6de7035cd62b0a6c29149 100644 (file)
@@ -21,16 +21,16 @@ package core.map
     }
 }
 
-Map :: struct (K: type_expr, V: type_expr) where ValidKey(K)
-    [conv.Custom_Format.{ #solidify format_map {K=K, V=V} }]
+Map :: struct (Key_Type: type_expr, Value_Type: type_expr) where ValidKey(Key_Type)
+    [conv.Custom_Format.{ #solidify format_map {K=Key_Type, V=Value_Type} }]
 {
     allocator : Allocator;
 
     hashes  : [] i32;
-    entries : [..] Entry(K, V);
+    entries : [..] Entry(Key_Type, Value_Type);
 
     // The value provided by `map.get`, if nothing was found.
-    default_value : V;
+    default_value : Value_Type;
 
     Entry :: struct (K: type_expr, V: type_expr) {
         next  : i32;
@@ -71,7 +71,7 @@ free :: (use map: ^Map($K, $V)) {
     array.free(^entries);
 }
 
-put :: (use map: ^Map($K, $V), key: K, value: V) {
+put :: (use map: ^Map($K, $V), key: map.Key_Type, value: map.Value_Type) {
     if map.hashes.data == null do init(map);
     lr := lookup(map, key);
 
index beb916f75e46368e633d5acdfe8bdaef2f2f5a13..69a518d80c1a42cffc48384119470e227f108907 100644 (file)
@@ -25,6 +25,7 @@ AstNode* symbol_raw_resolve(Scope* start_scope, char* sym);
 AstNode* symbol_resolve(Scope* start_scope, OnyxToken* tkn);
 AstNode* try_symbol_raw_resolve_from_node(AstNode* node, char* symbol);
 AstNode* try_symbol_resolve_from_node(AstNode* node, OnyxToken* token);
+AstNode* try_symbol_raw_resolve_from_type(Type *type, char* symbol);
 
 void build_all_overload_options(bh_arr(OverloadOption) overloads, bh_imap* all_overloads);
 
index a017b07bb81ed5eb56f918fb4666ac631f61c52f..609bea2f8553f0dd09a1ac41a06bbe0136a80fbf 100644 (file)
@@ -201,4 +201,4 @@ main :: (args) => {
     } else {
         print_color(.Green, "SUCCESS\n");
     }
-}
\ No newline at end of file
+}
index 7474af58cb7f1891315183296e3d224dfa4b46d7..8157341a84810864ffb34e00b86405be29c43156 100644 (file)
@@ -92,7 +92,7 @@ CheckStatus check_temp_function_header(AstFunction* func);
 CheckStatus check_function_header(AstFunction* func);
 CheckStatus check_memres_type(AstMemRes* memres);
 CheckStatus check_memres(AstMemRes* memres);
-CheckStatus check_type(AstType* type);
+CheckStatus check_type(AstType** ptype);
 CheckStatus check_insert_directive(AstDirectiveInsert** pinsert);
 CheckStatus check_do_block(AstDoBlock** pdoblock);
 CheckStatus check_constraint(AstConstraint *constraint);
@@ -109,7 +109,7 @@ u32 current_checking_level=0;
 
 static inline void fill_in_type(AstTyped* node) {
     if (node->type == NULL) {
-        if (check_type(node->type_node) > Check_Errors_Start) return;
+        if (check_type(&node->type_node) > Check_Errors_Start) return;
 
         node->type = type_build_from_ast(context.ast_alloc, node->type_node);
     }
@@ -1409,7 +1409,7 @@ CheckStatus check_address_of(AstAddressOf** paof) {
         pt->elem      = (AstType *) expr;
         pt->__unused  = aof->next;
         *paof         = (AstAddressOf *) pt;
-        CHECK(type, (AstType *pt);
+        CHECK(type, (AstType **) &pt);
         return Check_Success;
     }
 
@@ -1557,9 +1557,12 @@ CheckStatus check_field_access(AstFieldAccess** pfield) {
                 return Check_Success;
             }
         }
+        
+        AstNode* n = try_symbol_raw_resolve_from_type(field->expr->type, field->field);
 
         AstType* type_node = field->expr->type->ast_type;
-        AstNode* n = try_symbol_raw_resolve_from_node((AstNode *) type_node, field->field);
+        if (!n) n = try_symbol_raw_resolve_from_node((AstNode *) type_node, field->field);
+
         if (n) {
             *pfield = (AstFieldAccess *) n;
             return Check_Success;
@@ -1631,7 +1634,7 @@ CheckStatus check_method_call(AstBinaryOp** pmcall) {
 }
 
 CheckStatus check_size_of(AstSizeOf* so) {
-    CHECK(type, so->so_ast_type);
+    CHECK(type, &so->so_ast_type);
 
     so->so_type = type_build_from_ast(context.ast_alloc, so->so_ast_type);
     if (so->so_type == NULL)
@@ -1644,7 +1647,7 @@ CheckStatus check_size_of(AstSizeOf* so) {
 }
 
 CheckStatus check_align_of(AstAlignOf* ao) {
-    CHECK(type, ao->ao_ast_type);
+    CHECK(type, &ao->ao_ast_type);
 
     ao->ao_type = type_build_from_ast(context.ast_alloc, ao->ao_ast_type);
     if (ao->ao_type == NULL)
@@ -1662,7 +1665,8 @@ CheckStatus check_expression(AstTyped** pexpr) {
         // This is to ensure that the type will exist when compiling. For example, a poly-call type
         // would have to wait for the entity to pass through, which the code generation does not know
         // about.
-        CHECK(type, (AstType *) expr);
+        CHECK(type, (AstType **) pexpr);
+        expr = *pexpr;
 
         // Don't try to construct a polystruct ahead of time because you can't.
         if (expr->kind != Ast_Kind_Poly_Struct_Type) {
@@ -1908,7 +1912,7 @@ CheckStatus check_statement(AstNode** pstmt) {
             AstTyped* typed_stmt = (AstTyped *) stmt;
             fill_in_type(typed_stmt);
             if (typed_stmt->type_node != NULL && typed_stmt->type == NULL) {
-                CHECK(type, typed_stmt->type_node);
+                CHECK(type, &typed_stmt->type_node);
 
                 if (!node_is_type((AstNode *) typed_stmt->type_node)) {
                     ERROR(stmt->token->pos, "Local's type is not a type.");
@@ -2048,7 +2052,7 @@ CheckStatus check_struct(AstStructType* s_node) {
 
     bh_arr_each(AstStructMember *, smem, s_node->members) {
         if ((*smem)->type_node != NULL) {
-            CHECK(type, (*smem)->type_node);
+            CHECK(type, &(*smem)->type_node);
         }
 
         if ((*smem)->type_node == NULL && (*smem)->initial_value != NULL) {
@@ -2195,7 +2199,7 @@ CheckStatus check_function_header(AstFunction* func) {
             // If the function has the no_error flag, then the type node should have it set too.
             // This allows for polymorphic structures with constraints to fail gracefully.
             local->type_node->flags |= (func->flags & Ast_Flag_Header_Check_No_Error);
-            CHECK(type, local->type_node);
+            CHECK(type, &local->type_node);
         }
 
         fill_in_type((AstTyped *) local);
@@ -2232,7 +2236,7 @@ CheckStatus check_function_header(AstFunction* func) {
         }
     }
 
-    if (func->return_type != NULL) CHECK(type, func->return_type);
+    if (func->return_type != NULL) CHECK(type, &func->return_type);
 
     if (func->constraints.constraints != NULL) {
         func->constraints.produce_errors = (func->flags & Ast_Flag_Header_Check_No_Error) == 0;
@@ -2246,7 +2250,7 @@ CheckStatus check_function_header(AstFunction* func) {
 }
 
 CheckStatus check_memres_type(AstMemRes* memres) {
-    CHECK(type, memres->type_node);
+    CHECK(type, &memres->type_node);
     fill_in_type((AstTyped *) memres);
     if (memres->type_node && !memres->type) YIELD(memres->token->pos, "Waiting for global type to be constructed.");
     return Check_Success;
@@ -2293,9 +2297,10 @@ CheckStatus check_memres(AstMemRes* memres) {
     return Check_Success;
 }
 
-CheckStatus check_type(AstType* type) {
-    if (type == NULL) return Check_Success;
-    
+CheckStatus check_type(AstType** ptype) {
+    if (ptype == NULL || *ptype == NULL) return Check_Success;
+
+    AstType* type = *ptype;
     AstType* original_type = type;
     while (type->kind == Ast_Kind_Type_Alias)
         type = ((AstTypeAlias *) type)->to;
@@ -2330,19 +2335,19 @@ CheckStatus check_type(AstType* type) {
             break;
         }
 
-        case Ast_Kind_Pointer_Type: CHECK(type, ((AstPointerType *) type)->elem); break;
-        case Ast_Kind_Slice_Type:   CHECK(type, ((AstSliceType *) type)->elem); break;
-        case Ast_Kind_DynArr_Type:  CHECK(type, ((AstDynArrType *) type)->elem); break;
-        case Ast_Kind_VarArg_Type:  CHECK(type, ((AstVarArgType *) type)->elem); break;
+        case Ast_Kind_Pointer_Type: CHECK(type, &((AstPointerType *) type)->elem); break;
+        case Ast_Kind_Slice_Type:   CHECK(type, &((AstSliceType *) type)->elem); break;
+        case Ast_Kind_DynArr_Type:  CHECK(type, &((AstDynArrType *) type)->elem); break;
+        case Ast_Kind_VarArg_Type:  CHECK(type, &((AstVarArgType *) type)->elem); break;
 
         case Ast_Kind_Function_Type: {
             AstFunctionType* ftype = (AstFunctionType *) type;
 
-            CHECK(type, ftype->return_type);
+            CHECK(type, &ftype->return_type);
 
             if (ftype->param_count > 0) {
                 fori (i, 0, (i64) ftype->param_count) {
-                    CHECK(type, ftype->params[i]);
+                    CHECK(type, &ftype->params[i]);
                 }
             }
             break;
@@ -2351,7 +2356,7 @@ CheckStatus check_type(AstType* type) {
         case Ast_Kind_Type_Compound: {
             AstCompoundType* ctype = (AstCompoundType *) type;
 
-            bh_arr_each(AstType *, type, ctype->types) CHECK(type, *type);
+            bh_arr_each(AstType *, type, ctype->types) CHECK(type, type);
             break;
         }
         
@@ -2364,6 +2369,17 @@ CheckStatus check_type(AstType* type) {
 
             break;
         }
+
+        case Ast_Kind_Field_Access: {
+            CHECK(field_access, (AstFieldAccess **) ptype);
+            type = *ptype;
+            original_type = type;
+
+            if (!node_is_type((AstNode *) type)) {
+                ERROR_(original_type->token->pos, "This field access did not resolve to be a type. It resolved to be a '%s'.", onyx_ast_node_kind_string(type->kind));
+            }
+            break;
+        }
     }
 
     type = original_type;
@@ -2768,7 +2784,7 @@ void check_entity(Entity* ent) {
             if (ent->type_alias->kind == Ast_Kind_Struct_Type)
                 cs = check_struct((AstStructType *) ent->type_alias);
             else
-                cs = check_type(ent->type_alias);
+                cs = check_type(&ent->type_alias);
             break;
 
         case Entity_Type_File_Contents: 
index edd2618b24f4ea134d631b857f802af2c50a4cdf..d8bf32b4b0980ff0c2d90a7e56249fe461cd7e26 100644 (file)
@@ -25,4 +25,4 @@ int main(int argc, char *argv[]) {
     data.data = wasm_data.data;
     data.length = wasm_data.length;
     return onyx_run_wasm(data, argc - 1, argv + 1);
-}
\ No newline at end of file
+}
index 5b611cd30b683d6f7b10ab7dc53e873115ab0c1c..c095b622e8626bef5cf049d88490d17cbb09d2fd 100644 (file)
@@ -145,9 +145,6 @@ static SymresStatus symres_type(AstType** type) {
         case Ast_Kind_Type_Alias: SYMRES(type, &((AstTypeAlias *) *type)->to); break;
         case Ast_Kind_Field_Access: {
             SYMRES(field_access, (AstFieldAccess **) type);
-
-            if (!node_is_type((AstNode *) *type))
-                onyx_report_error((*type)->token->pos, Error_Critical, "Field access did not result in a type. (%s)", onyx_ast_node_kind_string((*type)->kind));
             break;
         }
 
index 06e863bdab341a3678ae8c29215d2fd5ab278979..1f0b32daa581f5581a9047c39f79b70799ccfcec 100644 (file)
@@ -253,6 +253,32 @@ AstNode* try_symbol_resolve_from_node(AstNode* node, OnyxToken* token) {
     return result;
 }
 
+AstNode* try_symbol_raw_resolve_from_type(Type *type, char* symbol) {
+    while (type->kind == Type_Kind_Pointer) {
+        type = type->Pointer.elem; 
+    }
+
+    if (type->kind == Type_Kind_Struct) {
+        if (type->Struct.poly_sln == NULL) return NULL;
+
+        bh_arr_each(AstPolySolution, sln, type->Struct.poly_sln) {
+            if (token_text_equals(sln->poly_sym->token, symbol)) {
+                if (sln->kind == PSK_Type) {
+                    AstTypeRawAlias* alias = onyx_ast_node_new(context.ast_alloc, sizeof(AstTypeRawAlias), Ast_Kind_Type_Raw_Alias);
+                    alias->type = &basic_types[Basic_Kind_Type_Index];
+                    alias->to = sln->type;
+                    return (AstNode *) alias;
+
+                } else {
+                    return (AstNode *) sln->value;
+                }
+            }
+        }
+    }
+
+    return NULL;
+}
+
 void scope_clear(Scope* scope) {
     sh_new_arena(scope->symbols);
 }
@@ -764,6 +790,8 @@ TypeMatch check_arguments_against_type(Arguments* args, TypeFunction* func_type,
     b32 permanent = location != NULL;
     if (func_name == NULL) func_name = "UNKNOWN FUNCTION";
 
+    if (error) error->rank = Error_Critical;
+
     bh_arr(AstArgument *) arg_arr = (bh_arr(AstArgument *)) args->values;
     i32 arg_count = get_argument_buffer_size(func_type, args);
 
@@ -796,7 +824,7 @@ TypeMatch check_arguments_against_type(Arguments* args, TypeFunction* func_type,
                 if (tm == TYPE_MATCH_YIELD) return tm;
                 if (tm == TYPE_MATCH_FAILED) {
                     if (error != NULL) {
-                        error->pos = arg_arr[arg_pos]->token->pos,
+                        error->pos = arg_arr[arg_pos]->token->pos;
                         error->text = bh_aprintf(global_heap_allocator,
                                 "The procedure '%s' expects a value of type '%s' for %d%s parameter, got '%s'.",
                                 func_name,
@@ -1076,30 +1104,29 @@ all_types_peeled_off:
         }
 
         case Ast_Kind_Poly_Struct_Type: {
-            AstStructType* stype = ((AstPolyStructType *) node)->base_struct;
+            AstPolyStructType* pstype = (AstPolyStructType *) node;
+            AstStructType* stype = pstype->base_struct;
             u32 dist;
-            return find_closest_symbol_in_scope(stype->scope, sym, &dist);
-        }
+            char *closest =  find_closest_symbol_in_scope(stype->scope, sym, &dist);
 
-        case Ast_Kind_Poly_Call_Type: {
-            AstPolyCallType* pcall = (AstPolyCallType *) node;
-
-            u32 dist = 0x7fffffff;
-            char *closest = NULL;
-
-            Type *type = type_build_from_ast(context.ast_alloc, (AstType *) pcall);
-            assert(type);
+            bh_arr_each(AstPolyStructParam, param, pstype->poly_params) {
+                token_toggle_end(param->token);
+                u32 d = levenshtein_distance(param->token->text, sym);
 
-            bh_arr_each(StructMember *, mem, type->Struct.memarr) {
-                u32 d = levenshtein_distance((*mem)->name, sym);
                 if (d < dist) {
                     dist = d;
-                    closest = (*mem)->name;
+                    closest = bh_strdup(context.ast_alloc, param->token->text);
                 }
+                token_toggle_end(param->token);
             }
 
             return closest;
         }
+
+        case Ast_Kind_Poly_Call_Type: {
+            AstPolyCallType* pcall = (AstPolyCallType *) node;
+            return find_closest_symbol_in_node(pcall->callee, sym);
+        }
     }
 
     return NULL;