BROKEN BUILD; want to debug on windows
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 15 Jan 2021 00:05:36 +0000 (18:05 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 15 Jan 2021 00:05:36 +0000 (18:05 -0600)
bin/onyx
include/onyxastnodes.h
src/onyxchecker.c
src/onyxsymres.c
src/onyxutils.c

index 2137d52ebdf5dce7c577b66be2445761dd4c0faa..bb4dec3c8906134d0fb029a197d5ca05753b2e4e 100755 (executable)
Binary files a/bin/onyx and b/bin/onyx differ
index 5679e6d1a68eec16cd07989aac382d9181a9e6c2..825d2d966db1fceff05f0a1198fad0a690a97735 100644 (file)
@@ -993,7 +993,7 @@ Type* resolve_expression_type(AstTyped* node);
 b32 cast_is_legal(Type* from_, Type* to_, char** err_msg);
 char* get_function_name(AstFunction* func);
 
-b32 fill_in_arguments(bh_arr(AstNode *) values, bh_arr(AstNamedValue *) named_values, AstNode* provider);
+b32 fill_in_arguments(bh_arr(AstNode *) values, bh_arr(AstNamedValue *) named_values, AstNode* provider, char** err_msg);
 
 AstNumLit* make_int_literal(bh_allocator a, i64 value);
 AstNumLit* make_float_literal(bh_allocator a, f64 value);
index dbbe438022c996a5710220ae2bac5340e567fe02..f9640cad87fefc68fe28cbd672615d103e7935ed 100644 (file)
@@ -296,7 +296,7 @@ CheckStatus check_switch(AstSwitch* switchnode) {
     return 0;
 }
 
-static AstTyped* match_overloaded_function(bh_arr(AstTyped *) arg_arr, bh_arr(AstTyped *) overloads) {
+static AstTyped* match_overloaded_function(bh_arr(AstTyped *) arg_arr, bh_arr(AstNamedValue *) named_values, bh_arr(AstTyped *) overloads) {
     bh_arr_each(AstTyped *, node, overloads) {
         AstFunction* overload = NULL;
         if ((*node)->kind == Ast_Kind_Function) {
@@ -308,14 +308,29 @@ static AstTyped* match_overloaded_function(bh_arr(AstTyped *) arg_arr, bh_arr(As
 
         if (overload == NULL) continue;
 
-        fill_in_type((AstTyped *) overload);
+        bh_arr(AstTyped *) new_arg_arr = arg_arr;
+        if (named_values != NULL && bh_arr_length(named_values) > 0) {
+            new_arg_arr = NULL;
+            bh_arr_new(global_heap_allocator, new_arg_arr, bh_arr_length(arg_arr) + bh_arr_length(named_values));
+            fori (i, 0, bh_arr_length(arg_arr))
+                new_arg_arr[i] = arg_arr[i];
+
+            b32 values_place_correctly = fill_in_arguments(
+                (bh_arr(AstNode *)) new_arg_arr,
+                named_values,
+                (AstNode *) overload,
+                NULL);
+
+            if (!values_place_correctly) goto no_match;
+        }
 
+        fill_in_type((AstTyped *) overload);
         TypeFunction* ol_type = &overload->type->Function;
-        if (bh_arr_length(arg_arr) < (i32) ol_type->needed_param_count) continue;
+        if (bh_arr_length(new_arg_arr) < (i32) ol_type->needed_param_count) continue;
 
         i32 param_left = ol_type->param_count;
         Type** param_type = ol_type->params;
-        bh_arr_each(AstTyped*, arg, arg_arr) {
+        bh_arr_each(AstTyped*, arg, new_arg_arr) {
             if (param_left == 0) goto no_match;
             param_left--;
 
@@ -337,11 +352,28 @@ static AstTyped* match_overloaded_function(bh_arr(AstTyped *) arg_arr, bh_arr(As
         return (AstTyped *) *node;
 
 no_match:
+        if (named_values != NULL) 
+            bh_arr_free(new_arg_arr);
+
         continue;
     }
     return NULL;
 }
 
+CheckStatus check_argument(AstArgument** parg) {
+    CHECK(expression, (AstTyped **) parg);
+    (*parg)->type = (*parg)->value->type;
+
+    if ((*parg)->value->kind == Ast_Kind_Overloaded_Function) {
+        onyx_report_error((*parg)->token->pos,
+            "Cannot pass overloaded function '%b' as argument.",
+            (*parg)->value->token->text, (*parg)->value->token->length);
+        return Check_Error;
+    }
+
+    return Check_Success;
+}
+
 typedef enum ArgState {
     AS_Expecting_Exact,
     AS_Expecting_Typed_VA,
@@ -365,24 +397,17 @@ CheckStatus check_call(AstCall* call) {
     CHECK(expression, &call->callee);
     AstFunction* callee = (AstFunction *) call->callee;
 
-    bh_arr(AstArgument *) arg_arr = call->arg_arr;
-
     // NOTE: Check arguments
-    bh_arr_each (AstArgument *, actual, arg_arr) {
-        CHECK(expression, (AstTyped **) actual);
-        (*actual)->type = (*actual)->value->type;
-
-        if ((*actual)->value->kind == Ast_Kind_Overloaded_Function) {
-            onyx_report_error((*actual)->token->pos,
-                "Cannot pass overloaded function '%b' as argument.",
-                (*actual)->value->token->text, (*actual)->value->token->length);
-            return Check_Error;
-        }
-    }
+    bh_arr_each(AstArgument *, actual, call->arg_arr)
+        CHECK(argument, actual);
+
+    bh_arr_each(AstNamedValue *, named_value, call->named_args)
+        CHECK(argument, (AstArgument **) &(*named_value)->value);
 
     if (callee->kind == Ast_Kind_Overloaded_Function) {
         call->callee = match_overloaded_function(
             (bh_arr(AstTyped *)) call->arg_arr,
+            call->named_args,
             ((AstOverloadedFunction *) callee)->overloads);
 
         if (call->callee == NULL) {
@@ -396,6 +421,20 @@ CheckStatus check_call(AstCall* call) {
                     strncat(arg_str, ", ", 1023);
             }
 
+            if (bh_arr_length(call->named_args) > 0) {
+                bh_arr_each(AstNamedValue *, named_value, call->named_args) { 
+                    token_toggle_end((*named_value)->token);
+                    strncat(arg_str, (*named_value)->token->text, 1023);
+                    token_toggle_end((*named_value)->token);
+
+                    strncat(arg_str, "=", 1023);
+                    strncat(arg_str, type_get_name(((AstTyped *) (*named_value)->value)->type), 1023); // CHECK: this might say 'unknown'.
+
+                    if (named_value != &bh_arr_last(call->named_args))
+                        strncat(arg_str, ", ", 1023);
+                }
+            }
+
             onyx_report_error(call->token->pos, "unable to match overloaded function with provided argument types: (%s)", arg_str);
 
             bh_free(global_scratch_allocator, arg_str);
@@ -431,18 +470,26 @@ CheckStatus check_call(AstCall* call) {
         return Check_Error;
     }
 
-    if (callee->kind == Ast_Kind_Function) {
-        if (bh_arr_length(arg_arr) < bh_arr_length(callee->params)) {
-            while (bh_arr_length(arg_arr) < bh_arr_length(callee->params)
-                && callee->params[bh_arr_length(arg_arr)].default_value != NULL) {
-                AstTyped* dv = callee->params[bh_arr_length(arg_arr)].default_value;
+    i32 arg_count = bh_max(
+        bh_arr_length(call->arg_arr) + bh_arr_length(call->named_args),
+        (i32) callee->type->Function.param_count);
 
-                AstArgument* new_arg = make_argument(semstate.node_allocator, dv);
-                bh_arr_push(arg_arr, new_arg);
-            }
+    bh_arr_grow(call->arg_arr, arg_count);
+    fori (i, bh_arr_length(call->arg_arr), arg_count) call->arg_arr[i] = NULL;
+    bh_arr_set_length(call->arg_arr, arg_count);
+
+    {
+        char* err_msg = NULL;
+        fill_in_arguments((AstNode **) call->arg_arr, call->named_args, (AstNode *) callee, &err_msg);
+
+        if (err_msg != NULL) {
+            onyx_report_error(call->token->pos, err_msg);
+            return Check_Error;
         }
     }
 
+    bh_arr(AstArgument *) arg_arr = call->arg_arr;
+
     // NOTE: If we are calling an intrinsic function, translate the
     // call into an intrinsic call node.
     if (callee->flags & Ast_Flag_Intrinsic) {
@@ -723,7 +770,7 @@ static AstCall* binaryop_try_operator_overload(AstBinaryOp* binop) {
     bh_arr_push(args, binop->left);
     bh_arr_push(args, binop->right);
 
-    AstTyped* overload = match_overloaded_function(args, operator_overloads[binop->operation]);
+    AstTyped* overload = match_overloaded_function(args, NULL, operator_overloads[binop->operation]);
     if (overload == NULL) {
         bh_arr_free(args);
         return NULL;
@@ -968,7 +1015,11 @@ CheckStatus check_struct_literal(AstStructLiteral* sl) {
     bh_arr_grow(sl->values, mem_count);
     fori (i, bh_arr_length(sl->values), mem_count) sl->values[i] = NULL;
     bh_arr_set_length(sl->values, mem_count);
-    if (!fill_in_arguments((bh_arr(AstNode *)) sl->values, sl->named_values, (AstNode *) sl)) {
+
+    char* err_msg = NULL;
+    if (!fill_in_arguments((bh_arr(AstNode *)) sl->values, sl->named_values, (AstNode *) sl, &err_msg)) {
+        onyx_report_error(sl->token->pos, err_msg);
+        
         bh_arr_each(AstTyped *, value, sl->values) {
             if (*value == NULL) {
                 i32 member_idx = value - sl->values; // Pointer subtraction hack
index 71b90e084db78b86a9f6ef77ea46a2cd0555cec7..acb7c988358e2b96d891b9e138bfed713cce927a 100644 (file)
@@ -242,6 +242,9 @@ static void symres_call(AstCall* call) {
 
     bh_arr_each(AstArgument *, arg, call->arg_arr)
         symres_statement((AstNode **) arg);
+
+    bh_arr_each(AstNamedValue *, named_arg, call->named_args)
+        symres_statement(&(*named_arg)->value);
 }
 
 static void symres_size_of(AstSizeOf* so) {
index 4be805a6adbe0d8224ab844f4fa9b3d552311688..9c5ab5ab831f73fef5c0f770889d443b472b6ff9 100644 (file)
@@ -372,18 +372,33 @@ static bh_arr(AstPolySolution) find_polymorphic_slns(AstPolyProc* pp, PolyProcLo
         Type* actual_type;
 
         if (pp_lookup == PPLM_By_Call) {
-            if (param->idx >= (u64) bh_arr_length(((AstCall *) actual)->arg_arr)) {
-                if (err_msg) *err_msg = "Not enough arguments to polymorphic procedure.";
+            bh_arr(AstArgument *) arg_arr = ((AstCall *) actual)->arg_arr;
+            bh_arr(AstNamedValue *) named_values = ((AstCall *) actual)->named_args;
+
+            if (param->idx >= (u64) bh_arr_length(arg_arr)) {
+                // CLEANUP: This is a really long access chain.
+                OnyxToken* param_name = pp->base_func->params[param->idx].local->token;
+
+                bh_arr_each(AstNamedValue *, named_value, named_values) {
+                    if (token_equals(param_name, (*named_value)->token)) {
+                        actual_type = resolve_expression_type((AstTyped *) (*named_value)->value);
+                        break;
+                    }
+                }
+
+                // nocheckin
+                if (err_msg) *err_msg = "Not enough arguments to polymorphic procedure. This error message may not be entirely right.";
                 goto sln_not_found;
-            }
 
-            bh_arr(AstArgument *) arg_arr = ((AstCall *) actual)->arg_arr;
-            actual_type = resolve_expression_type(arg_arr[param->idx]->value);
+            } else {
+                actual_type = resolve_expression_type(arg_arr[param->idx]->value);
+            }
         }
 
         else if (pp_lookup == PPLM_By_Value_Array) {
             bh_arr(AstTyped *) arg_arr = (bh_arr(AstTyped *)) actual;
 
+            // nocheckin
             if ((i32) param->idx >= bh_arr_length(arg_arr)) {
                 if (err_msg) *err_msg = "Not enough arguments to polymorphic procedure.";
                 goto sln_not_found;
@@ -884,7 +899,8 @@ static AstNode* lookup_default_value_by_idx(AstNode* provider, i32 idx) {
         case Ast_Kind_Function: {
             AstFunction* func = (AstFunction *) provider;
 
-            return (AstNode *) func->params[idx].default_value;
+            AstArgument* arg = make_argument(semstate.node_allocator, func->params[idx].default_value);
+            return (AstNode *) arg;
         }
 
         default: return NULL;
@@ -893,22 +909,28 @@ static AstNode* lookup_default_value_by_idx(AstNode* provider, i32 idx) {
 
 // NOTE: The values array can be partially filled out, and is the resulting array.
 // Returns if all the values were filled in.
-b32 fill_in_arguments(bh_arr(AstNode *) values, bh_arr(AstNamedValue *) named_values, AstNode* provider) {
+b32 fill_in_arguments(bh_arr(AstNode *) values, bh_arr(AstNamedValue *) named_values, AstNode* provider, char** err_msg) {
     bh_arr_each(AstNamedValue *, p_named_value, named_values) {
         AstNamedValue* named_value = *p_named_value;
 
         token_toggle_end(named_value->token);
         i32 idx = lookup_idx_by_name(provider, named_value->token->text);
         if (idx == -1) {
-            onyx_report_error(provider->token->pos, "'%s' is not a valid named parameter here.", named_value->token->text);
+            if (err_msg) *err_msg = bh_aprintf(global_heap_allocator, "'%s' is not a valid named parameter here.", named_value->token->text);
             token_toggle_end(named_value->token);
             return 0;
         }
 
-        token_toggle_end(named_value->token);
-
         assert(idx < bh_arr_length(values));
+
+        if (values[idx] != NULL) {
+            if (err_msg) *err_msg = bh_aprintf(global_heap_allocator, "Multiple values given for parameter named '%s'.", named_value->token->text);
+            token_toggle_end(named_value->token);
+            return 0;
+        }
+
         values[idx] = named_value->value;
+        token_toggle_end(named_value->token);
     }
 
     b32 success = 1;