overloaded procedures are more powerful; bugfixes
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 8 Sep 2021 23:37:36 +0000 (18:37 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 8 Sep 2021 23:37:36 +0000 (18:37 -0500)
bin/onyx
include/astnodes.h
include/errors.h
src/astnodes.c
src/checker.c
src/errors.c
src/utils.c
src/wasm.c
tests/named_arguments_test
tests/named_arguments_test.onyx

index 878738106bf2d562850938ee6dcecb94d040ee49..89f949768f848bf9905667ff3e952adf8c4b5c69 100755 (executable)
Binary files a/bin/onyx and b/bin/onyx differ
index 9aa31d08d48b164b1c7f28450859db761f79e6ad..c11c782f29ad9c6f7d2ab3628f59845696774693 100644 (file)
@@ -3,6 +3,7 @@
 
 #include "lex.h"
 #include "types.h"
+#include "errors.h"
 
 #define AST_NODES              \
     NODE(Node)                 \
@@ -507,6 +508,9 @@ typedef struct Arguments Arguments;
 struct Arguments {
     bh_arr(AstTyped *) values;
     bh_arr(AstNamedValue *) named_values;
+
+    // How many arguments were not baked.
+    i32 used_argument_count;
 };
 
 
@@ -1364,6 +1368,9 @@ void arguments_copy(Arguments* dest, Arguments* src);
 void arguments_clone(Arguments* dest, Arguments* src);
 void arguments_deep_clone(bh_allocator a, Arguments* dest, Arguments* src);
 void arguments_remove_baked(Arguments* args);
+b32 check_arguments_against_type(Arguments* args, TypeFunction* func_type, VarArgKind* va_kind,
+                                 OnyxToken* location, char* func_name, struct OnyxError* error);
+i32 function_get_minimum_argument_count(TypeFunction* type, Arguments* args);
 
 // GROSS: Using void* to avoid having to cast everything.
 const char* node_get_type_name(void* node);
index 41aebddeb3850240ef816ab750e3029072126866..6d85fe6b50afd0b5a4038bbb44e06818eb74447f 100644 (file)
@@ -24,7 +24,9 @@ typedef struct OnyxErrors {
 extern OnyxErrors msgs;
 
 void onyx_errors_init(bh_arr(bh_file_contents)* files);
+void onyx_submit_error(OnyxError error);
 void onyx_report_error(OnyxFilePos pos, char * format, ...);
+void onyx_submit_warning(OnyxError error);
 void onyx_report_warning(OnyxFilePos pos, char* format, ...);
 void onyx_errors_print();
 b32  onyx_has_errors();
index b8ae2c6c5fb1ee68732f3308b4f0144777a20cfe..109ddf3bdc7d67a0f52f4b62dec2db8ab661be07 100644 (file)
@@ -969,6 +969,8 @@ void arguments_initialize(Arguments* args) {
         args->values[i] = NULL;
         args->named_values[i] = NULL;
     }
+
+    args->used_argument_count = -1;
 }
 
 void arguments_ensure_length(Arguments* args, u32 count) {
@@ -983,20 +985,24 @@ void arguments_ensure_length(Arguments* args, u32 count) {
 }
 
 void arguments_copy(Arguments* dest, Arguments* src) {
+    dest->used_argument_count = -1;
     dest->named_values = src->named_values;
     
-    arguments_ensure_length(dest, bh_arr_length(src->values));
+    bh_arr_grow(dest->values, (u32) bh_arr_length(src->values));
+    bh_arr_set_length(dest->values, (u32) bh_arr_length(src->values));
     bh_arr_each(AstTyped*, arg, dest->values) *arg = NULL;
     fori (i, 0, bh_arr_length(src->values)) dest->values[i] = src->values[i];
 }
 
 // In clone, the named_values are not copied. This is used in find_matching_overload_by_arguments since it doesn't need them to be copied.
 void arguments_clone(Arguments* dest, Arguments* src) {
+    dest->used_argument_count = -1;
     dest->named_values = src->named_values;
     dest->values = bh_arr_copy(global_heap_allocator, src->values);
 }
 
 void arguments_deep_clone(bh_allocator a, Arguments* dest, Arguments* src) {
+    dest->used_argument_count = -1;
     dest->values = NULL;
     dest->named_values = NULL;
 
index becae7ad2188bc5755974e5fcb82673decae29c1..3340b2e6f577c548c0ee4d8590c8af4b90ebe4b3 100644 (file)
@@ -419,22 +419,6 @@ CheckStatus check_argument(AstArgument** parg) {
     return Check_Success;
 }
 
-static i32 non_baked_argument_count(Arguments* args) {
-    i32 count = 0;
-
-    bh_arr_each(AstTyped *, actual, args->values) {
-        assert((*actual)->kind == Ast_Kind_Argument);
-        if (!((AstArgument *) (*actual))->is_baked) count++;
-    }
-
-    bh_arr_each(AstNamedValue *, named_value, args->named_values) {
-        assert((*named_value)->value->kind == Ast_Kind_Argument);
-        if (!((AstArgument *) (*named_value)->value)->is_baked) count++;
-    }
-
-    return count;
-}
-
 static CheckStatus check_resolve_callee(AstCall* call, AstTyped** effective_callee) {
     if (call->kind == Ast_Kind_Intrinsic_Call) return Check_Success;
 
@@ -505,12 +489,6 @@ static CheckStatus check_resolve_callee(AstCall* call, AstTyped** effective_call
     return Check_Success;
 }
 
-typedef enum ArgState {
-    AS_Expecting_Exact,
-    AS_Expecting_Typed_VA,
-    AS_Expecting_Untyped_VA,
-} ArgState;
-
 CheckStatus check_call(AstCall** pcall) {
     // All the things that need to be done when checking a call node.
     //      1. Ensure the callee is not a symbol
@@ -540,13 +518,7 @@ CheckStatus check_call(AstCall** pcall) {
     AstFunction* callee=NULL;
     CHECK(resolve_callee, call, (AstTyped **) &callee);
 
-    // CLEANUP maybe make function_get_expected_arguments?
-    i32 non_vararg_param_count = (i32) callee->type->Function.param_count;
-    if (non_vararg_param_count > 0 &&
-        callee->type->Function.params[callee->type->Function.param_count - 1] == builtin_vararg_type_type)
-        non_vararg_param_count--;
-
-    i32 arg_count = bh_max(non_vararg_param_count, non_baked_argument_count(&call->args));
+    i32 arg_count = function_get_minimum_argument_count(&callee->type->Function, &call->args);
     arguments_ensure_length(&call->args, arg_count);
 
     char* err_msg = NULL;
@@ -622,103 +594,14 @@ CheckStatus check_call(AstCall** pcall) {
         YIELD(call->token->pos, "Waiting for auto-return type to be solved.");
     }
 
-    Type **formal_params = callee->type->Function.params;
-
-    Type* variadic_type = NULL;
-    AstParam* variadic_param = NULL;
-
-    // SPEED CLEANUP: Caching the any type here.
-    Type* any_type = type_build_from_ast(context.ast_alloc, builtin_any_type);
-
-    ArgState arg_state = AS_Expecting_Exact;
-    u32 arg_pos = 0;
-    while (1) {
-        switch (arg_state) {
-            case AS_Expecting_Exact: {
-                if (arg_pos >= callee->type->Function.param_count) goto type_checking_done;
-
-                if (formal_params[arg_pos]->kind == Type_Kind_VarArgs) {
-                    variadic_type = formal_params[arg_pos]->VarArgs.elem;
-                    variadic_param = &callee->params[arg_pos];
-                    arg_state = AS_Expecting_Typed_VA;
-                    continue;
-                }
-
-                if ((i16) arg_pos == callee->type->Function.vararg_arg_pos) {
-                    arg_state = AS_Expecting_Untyped_VA;
-                    continue;
-                }
-
-                if (arg_pos >= (u32) bh_arr_length(arg_arr)) goto type_checking_done;
-                if (!unify_node_and_type(&arg_arr[arg_pos]->value, formal_params[arg_pos])) {
-                    ERROR_(arg_arr[arg_pos]->token->pos,
-                            "The procedure '%s' expects a value of type '%s' for %d%s parameter, got '%s'.",
-                            get_function_name(callee),
-                            type_get_name(formal_params[arg_pos]),
-                            arg_pos + 1,
-                            bh_num_suffix(arg_pos + 1),
-                            node_get_type_name(arg_arr[arg_pos]->value));
-                }
-
-                arg_arr[arg_pos]->va_kind = VA_Kind_Not_VA;
-                break;
-            }
-
-            case AS_Expecting_Typed_VA: {
-                if (variadic_type->id == any_type->id) call->va_kind = VA_Kind_Any;
-                if (arg_pos >= (u32) bh_arr_length(arg_arr)) goto type_checking_done;
-
-                if (variadic_type->id == any_type->id) {
-                    resolve_expression_type(arg_arr[arg_pos]->value);
-                    arg_arr[arg_pos]->va_kind = VA_Kind_Any; 
-                    break;
-                }
-
-                call->va_kind = VA_Kind_Typed;
-
-                if (!unify_node_and_type(&arg_arr[arg_pos]->value, variadic_type)) {
-                    onyx_report_error(arg_arr[arg_pos]->token->pos,
-                            "The procedure '%s' expects a value of type '%s' for the variadic parameter, '%b', got '%s'.",
-                            get_function_name(callee),
-                            type_get_name(variadic_type),
-                            variadic_param->local->token->text,
-                            variadic_param->local->token->length,
-                            node_get_type_name(arg_arr[arg_pos]->value));
-                    return Check_Error;
-                }
-
-                arg_arr[arg_pos]->va_kind = VA_Kind_Typed;
-                break;
-            }
-
-            case AS_Expecting_Untyped_VA: {
-                call->va_kind = VA_Kind_Untyped;
-
-                if (arg_pos >= (u32) bh_arr_length(arg_arr)) goto type_checking_done;
-
-                resolve_expression_type(arg_arr[arg_pos]->value);
-                if (arg_arr[arg_pos]->value->type == NULL) {
-                    ERROR(arg_arr[arg_pos]->token->pos, "Unable to resolve type for argument.");
-                }
-
-                arg_arr[arg_pos]->va_kind = VA_Kind_Untyped;
-                break;
-            }
-        }
-
-        arg_pos++;
+    OnyxError error;
+    if (!check_arguments_against_type(&call->args, &callee->type->Function, &call->va_kind,
+            call->token, get_function_name(callee), &error)) {
+        onyx_submit_error(error);
+        return Check_Error;
     }
 
-type_checking_done:
-
-    call->flags |= Ast_Flag_Has_Been_Checked;
-
-    if (arg_pos < callee->type->Function.needed_param_count)
-        ERROR(call->token->pos, "Too few arguments to function call.");
-
-    if (arg_pos < (u32) arg_count)
-        ERROR(call->token->pos, "Too many arguments to function call.");
-
+    call->flags   |= Ast_Flag_Has_Been_Checked;
     callee->flags |= Ast_Flag_Function_Used;
 
     if (call->kind == Ast_Kind_Call && call->callee->kind == Ast_Kind_Macro) {
@@ -741,8 +624,13 @@ static AstCall* binaryop_try_operator_overload(AstBinaryOp* binop) {
 
     Arguments args = ((Arguments) { NULL, NULL });
     bh_arr_new(global_heap_allocator, args.values, 2);
-    bh_arr_push(args.values, binop->left);
-    bh_arr_push(args.values, binop->right);
+    bh_arr_push(args.values, (AstTyped *) make_argument(context.ast_alloc, binop->left));
+    bh_arr_push(args.values, (AstTyped *) make_argument(context.ast_alloc, binop->right));
+
+    u32 current_checking_level_store = current_checking_level;
+    check_argument((AstArgument **) &args.values[0]);
+    check_argument((AstArgument **) &args.values[1]);
+    current_checking_level = current_checking_level_store;
 
     if (binop_is_assignment(binop->operation)) {
         args.values[0] = (AstTyped *) make_address_of(context.ast_alloc, binop->left);
@@ -755,6 +643,11 @@ static AstCall* binaryop_try_operator_overload(AstBinaryOp* binop) {
         if (cs == Check_Error) {
             return NULL;
         }
+
+        args.values[0] = (AstTyped *) make_argument(context.ast_alloc, args.values[0]);
+        current_checking_level_store = current_checking_level;
+        check_argument((AstArgument **) &args.values[0]);
+        current_checking_level = current_checking_level_store;
     }
 
     b32 should_yield = 0;
@@ -774,9 +667,6 @@ static AstCall* binaryop_try_operator_overload(AstBinaryOp* binop) {
     implicit_call->callee = overload;
     implicit_call->va_kind = VA_Kind_Not_VA;
 
-    bh_arr_each(AstTyped *, arg, args.values)
-        *arg = (AstTyped *) make_argument(context.ast_alloc, *arg);
-
     implicit_call->args = args;
     return implicit_call;
 }
index 0a0745210ce35139bb4be83a5c14195b0554937a..0b9f16d3dad5f643ea963e1f223dae18e1e7a799 100644 (file)
@@ -79,6 +79,10 @@ void onyx_clear_errors() {
     bh_arr_set_length(errors.errors, 0);
 }
 
+void onyx_submit_error(OnyxError error) {
+    bh_arr_push(errors.errors, error);
+}
+
 void onyx_report_error(OnyxFilePos pos, char * format, ...) {
 
     va_list vargs;
@@ -94,6 +98,19 @@ void onyx_report_error(OnyxFilePos pos, char * format, ...) {
     bh_arr_push(errors.errors, err);
 }
 
+void onyx_submit_warning(OnyxError error) {
+    bh_file_contents file_contents = { 0 };
+    bh_arr_each(bh_file_contents, fc, *errors.file_contents) {
+        if (!strcmp(fc->filename, error.pos.filename)) {
+            file_contents = *fc;
+            break;
+        }
+    }
+
+    print_detailed_message(&error, &file_contents);
+}
+
+// This definitely doesn't do what I thought it did?
 void onyx_report_warning(OnyxFilePos pos, char* format, ...) {
     va_list vargs;
     va_start(vargs, format);
index 017ed8c5bf8fa9d2fea7ea535cba431fda743143..7c63d9c9baad0c28cbec25a9cf963c587e19efa4 100644 (file)
@@ -6,6 +6,7 @@
 #include "errors.h"
 #include "parser.h"
 #include "astnodes.h"
+#include "errors.h"
 
 bh_scratch global_scratch;
 bh_allocator global_scratch_allocator;
@@ -366,36 +367,14 @@ AstTyped* find_matching_overload_by_arguments(bh_arr(OverloadOption) overloads,
         }
         assert(overload->type->kind == Type_Kind_Function);
 
+        arguments_remove_baked(&args);
+        arguments_ensure_length(&args, function_get_minimum_argument_count(&overload->type->Function, &args));
+
         // NOTE: If the arguments cannot be placed successfully in the parameters list
         if (!fill_in_arguments(&args, (AstNode *) overload, NULL)) continue;
-
-        TypeFunction* ol_type = &overload->type->Function;
-        if (bh_arr_length(args.values) < (i32) ol_type->needed_param_count) continue;
-
-        b32 all_arguments_work = 1;
-        fori (i, 0, bh_arr_length(args.values)) {
-            if (i >= ol_type->param_count) {
-                all_arguments_work = 0;
-                break;
-            }
-
-            Type* type_to_match = ol_type->params[i];
-            AstTyped** value    = &args.values[i];
-
-            if (type_to_match->kind == Type_Kind_VarArgs) type_to_match = type_to_match->VarArgs.elem;
-            if ((*value)->kind == Ast_Kind_Argument) {
-                // :ArgumentResolvingIsComplicated
-                if (((AstArgument *) (*value))->is_baked) continue;
-                value = &((AstArgument *) *value)->value;
-            }
-
-            if (!unify_node_and_type_(value, type_to_match, 0)) {
-                all_arguments_work = 0;
-                break;
-            }
-        }
-
-        if (all_arguments_work) {
+        
+        VarArgKind va_kind;
+        if (check_arguments_against_type(&args, &overload->type->Function, &va_kind, NULL, NULL, NULL)) {
             matched_overload = node;
             break;
         }
@@ -692,6 +671,33 @@ static i32 maximum_argument_count(AstNode* provider) {
     return 0x7fffffff;
 }
 
+static i32 non_baked_argument_count(Arguments* args) {
+    if (args->used_argument_count >= 0) return args->used_argument_count;
+
+    i32 count = 0;
+
+    bh_arr_each(AstTyped *, actual, args->values) {
+        if ((*actual)->kind != Ast_Kind_Argument) count++;
+        else if (!((AstArgument *) (*actual))->is_baked) count++;
+    }
+
+    bh_arr_each(AstNamedValue *, named_value, args->named_values) {
+        if ((*named_value)->value->kind != Ast_Kind_Argument) count++;
+        else if (!((AstArgument *) (*named_value)->value)->is_baked) count++;
+    }
+
+    args->used_argument_count = count;
+    return count;
+}
+
+i32 function_get_minimum_argument_count(TypeFunction* type, Arguments* args) {
+    i32 non_vararg_param_count = (i32) type->param_count;
+    if (non_vararg_param_count > 0 && type->params[type->param_count - 1] == builtin_vararg_type_type)
+        non_vararg_param_count--;
+
+    return bh_max(non_vararg_param_count, non_baked_argument_count(args));
+}
+
 // 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(Arguments* args, AstNode* provider, char** err_msg) {
@@ -735,6 +741,7 @@ b32 fill_in_arguments(Arguments* args, AstNode* provider, char** err_msg) {
 
             // assert(idx < bh_arr_length(args->values));
             if (idx >= bh_arr_length(args->values)) {
+                if (err_msg) *err_msg = bh_aprintf(global_scratch_allocator, "Error placing value with name '%s' at index '%d'.", named_value->token->text, idx);
                 token_toggle_end(named_value->token);
                 return 0;
             }
@@ -754,20 +761,159 @@ b32 fill_in_arguments(Arguments* args, AstNode* provider, char** err_msg) {
     fori (idx, 0, bh_arr_length(args->values)) {
         if (args->values[idx] == NULL) args->values[idx] = (AstTyped *) lookup_default_value_by_idx(provider, idx);
         if (args->values[idx] == NULL) {
-            *err_msg = bh_aprintf(global_scratch_allocator, "No value given for %d%s argument.", idx + 1, bh_num_suffix(idx + 1));
+            if (err_msg) *err_msg = bh_aprintf(global_scratch_allocator, "No value given for %d%s argument.", idx + 1, bh_num_suffix(idx + 1));
             success = 0;
         }
     }
 
     i32 maximum_arguments = maximum_argument_count(provider);
     if (bh_arr_length(args->values) > maximum_arguments) {
-        *err_msg = bh_aprintf(global_scratch_allocator, "Too many values provided. Expected at most %d.", maximum_arguments);
+        if (err_msg) *err_msg = bh_aprintf(global_scratch_allocator, "Too many values provided. Expected at most %d.", maximum_arguments);
         success = 0;
     }
 
     return success;
 }
 
+
+//
+// Argument checking
+//
+
+typedef enum ArgState {
+    AS_Expecting_Exact,
+    AS_Expecting_Typed_VA,
+    AS_Expecting_Untyped_VA,
+} ArgState;
+
+b32 check_arguments_against_type(Arguments* args, TypeFunction* func_type, VarArgKind* va_kind,
+                                 OnyxToken* location, char* func_name, OnyxError* error) {
+    b32 permanent = location != NULL;
+    if (func_name == NULL) func_name = "UNKNOWN FUNCTION";
+
+    bh_arr(AstArgument *) arg_arr = (bh_arr(AstArgument *)) args->values;
+    i32 arg_count = function_get_minimum_argument_count(func_type, args);
+
+    Type **formal_params = func_type->params;
+    Type* variadic_type = NULL;
+    i64 any_type_id = type_build_from_ast(context.ast_alloc, builtin_any_type)->id;
+
+    ArgState arg_state = AS_Expecting_Exact;
+    u32 arg_pos = 0;
+    while (1) {
+        switch (arg_state) {
+            case AS_Expecting_Exact: {
+                if (arg_pos >= func_type->param_count) goto type_checking_done;
+
+                if (formal_params[arg_pos]->kind == Type_Kind_VarArgs) {
+                    variadic_type = formal_params[arg_pos]->VarArgs.elem;
+                    arg_state = AS_Expecting_Typed_VA;
+                    continue;
+                }
+
+                if ((i16) arg_pos == func_type->vararg_arg_pos) {
+                    arg_state = AS_Expecting_Untyped_VA;
+                    continue;
+                }
+
+                if (arg_pos >= (u32) bh_arr_length(arg_arr)) goto type_checking_done;
+
+                assert(arg_arr[arg_pos]->kind == Ast_Kind_Argument);
+                if (!unify_node_and_type_(&arg_arr[arg_pos]->value, formal_params[arg_pos], permanent)) {
+                    if (error != NULL) {
+                        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,
+                                type_get_name(formal_params[arg_pos]),
+                                arg_pos + 1,
+                                bh_num_suffix(arg_pos + 1),
+                                node_get_type_name(arg_arr[arg_pos]->value));
+                    }
+                    return 0;
+                }
+
+                arg_arr[arg_pos]->va_kind = VA_Kind_Not_VA;
+                break;
+            }
+
+            case AS_Expecting_Typed_VA: {
+                if (variadic_type->id == any_type_id) *va_kind = VA_Kind_Any;
+
+                if (arg_pos >= (u32) bh_arr_length(arg_arr)) goto type_checking_done;
+
+                if (variadic_type->id == any_type_id) {
+                    resolve_expression_type(arg_arr[arg_pos]->value);
+                    arg_arr[arg_pos]->va_kind = VA_Kind_Any; 
+                    break;
+                }
+
+                *va_kind = VA_Kind_Typed;
+
+                assert(arg_arr[arg_pos]->kind == Ast_Kind_Argument);
+                if (!unify_node_and_type_(&arg_arr[arg_pos]->value, variadic_type, permanent)) {
+                    if (error != NULL) {
+                        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 the variadic parameter, got '%s'.",
+                            func_name,
+                            type_get_name(variadic_type),
+                            node_get_type_name(arg_arr[arg_pos]->value));
+                    }
+                    return 0;
+                }
+
+                arg_arr[arg_pos]->va_kind = VA_Kind_Typed;
+                break;
+            }
+
+            case AS_Expecting_Untyped_VA: {
+                *va_kind = VA_Kind_Untyped;
+
+                if (arg_pos >= (u32) bh_arr_length(arg_arr)) goto type_checking_done;
+
+                assert(arg_arr[arg_pos]->kind == Ast_Kind_Argument);
+                resolve_expression_type(arg_arr[arg_pos]->value);
+                if (arg_arr[arg_pos]->value->type == NULL) {
+                    if (error != NULL) {
+                        error->pos = arg_arr[arg_pos]->token->pos;
+                        error->text = "Unable to resolve type for argument.";
+                    }
+                    return 0;
+                }
+
+                arg_arr[arg_pos]->va_kind = VA_Kind_Untyped;
+                break;
+            }
+        }
+
+        arg_pos++;
+    }
+
+type_checking_done:
+    if (arg_pos < func_type->needed_param_count) {
+        if (error != NULL) {
+            error->pos = location->pos;
+            error->text = "Too few arguments to function call.";
+        }
+        return 0;
+    }
+
+    if (arg_pos < (u32) arg_count) {
+        if (error != NULL) {
+            error->pos = location->pos;
+            error->text = bh_aprintf(global_heap_allocator, "Too many arguments to function call. %d %d", arg_pos, arg_count);
+        }
+        return 0;
+    }
+
+    return 1;
+}
+        
+
+
+
+
 //
 // String parsing helpers
 //
index 144deaba57dcff46ad13f248ac879f4216a0d320..43125c52531ccb9a65edf02f48ba7cce8f520623 100644 (file)
@@ -2845,20 +2845,20 @@ EMIT_FUNC(return, AstReturn* ret) {
     // Clear the normal deferred statements
     emit_deferred_stmts(mod, &code);
 
-    // Clear the rest of the deferred statements
-    if (bh_arr_length(mod->deferred_stmts) > 0) {
-        i32 i = bh_arr_length(mod->deferred_stmts) - 1;
-        while (i >= 0) {
-            emit_deferred_stmt(mod, &code, mod->deferred_stmts[i]);
-            i--;
-        }
-    }
-
     i64 jump_label = get_structured_jump_label(mod, Jump_Type_Return, 1);
     if (jump_label >= 0) {
         WIL(WI_JUMP, jump_label);
 
     } else {
+        // Clear the rest of the deferred statements
+        if (bh_arr_length(mod->deferred_stmts) > 0) {
+            i32 i = bh_arr_length(mod->deferred_stmts) - 1;
+            while (i >= 0) {
+                emit_deferred_stmt(mod, &code, mod->deferred_stmts[i]);
+                i--;
+            }
+        }
+
         // Make a patch for the two instructions needed to restore the stack pointer
         SUBMIT_PATCH(mod->stack_leave_patches, 0);
         WI(WI_NOP);
index 2942784dcb16a991babf6a9e39d4a6e396675772..e7cf58fba06eea3c4114cf6994449f3b4318e235 100644 (file)
@@ -26,3 +26,6 @@ MATCHED Z: 10
 =========================
 false true false true true false true
 true false false true true false true
+MATCHED X
+MATCHED Y
+MATCHED Z [ 10, 40, 90 ]
index 7b1bcc26b33c7420a5f13a163071b6add2d7b96e..a2a7d58d36d82eee47049e70875b98ee592cb3f9 100644 (file)
@@ -73,13 +73,13 @@ main :: (args: [] cstr) {
 
 
     // This currently does not work and would require a lot of rewriting of compiler internals to make work.
-    // named_baked_overloaded_parameters :: proc {
-    //     ($T: type_expr, x: T)      do { println("MATCHED X"); },
-    //     ($T: type_expr, y: [$N] T) do { println("MATCHED X"); },
-    //     ($T: type_expr, z: T)      do { println("MATCHED X"); },
-    // }
-
-    // named_baked_overloaded_parameters(i32, 10);
-    // named_baked_overloaded_parameters(i32, u32.[ 10, 20, 30 ]);
-    // named_baked_overloaded_parameters(i32, z = u32.[ 10, 20, 30 ]);
+    named_baked_overloaded_parameters :: #match {
+        ($T: type_expr, x: T)      { println("MATCHED X"); },
+        ($T: type_expr, y: [$N] T) { println("MATCHED Y"); },
+        ($T: type_expr, z: [$N] T) { printf("MATCHED Z {}\n", z); },
+    }
+
+    named_baked_overloaded_parameters(i32, 10);
+    named_baked_overloaded_parameters(i32, u32.[ 10, 20, 30 ]);
+    named_baked_overloaded_parameters(i32, z = u32.[ 10, 40, 90 ]);
 }