changed: small bugfixes with edges of bad closures
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 21 Apr 2023 20:15:17 +0000 (15:15 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 21 Apr 2023 20:15:17 +0000 (15:15 -0500)
compiler/src/clone.c
compiler/src/symres.c

index d9b209ed6a82ee7419092bff7df8bc1ad7c2ce32..fc94a293308d78122e66aba79f71c44a5c701e93 100644 (file)
@@ -451,8 +451,17 @@ AstNode* ast_clone(bh_allocator a, void* n) {
             AstFunction* df = (AstFunction *) nn;
             AstFunction* sf = (AstFunction *) node;
 
+            // Check if we are cloning a function inside of a function.
             if (clone_depth > 1) {
-                if ((node->flags & Ast_Flag_Function_Is_Lambda) == 0 || !sf->captures) {
+                // If we are, and the inner function has a scope, this means that
+                // the inner function does not capture anything, and is not polymorphic.
+                // Therefore, it should be treated as a normal function and not cloned
+                // inside of this function.
+                // 
+                // If the inner function does not have a scope, that means that it is
+                // either polymorphic and/or it has captures. In either case, we have
+                // to clone the function internally below.
+                if (df->scope != NULL) {
                     clone_depth--;
                     return node;
                 }
@@ -511,6 +520,10 @@ AstNode* ast_clone(bh_allocator a, void* n) {
                 }    
             }
 
+            if (df->kind == Ast_Kind_Polymorphic_Proc) {
+                df->scope_to_lookup_captured_values = NULL;
+            }
+
             if (clone_depth > 1) {
                 sf->flags |= Ast_Flag_Function_Is_Lambda_Inside_PolyProc;
                 df->flags &= ~Ast_Flag_Function_Is_Lambda_Inside_PolyProc;
index 483cda9af188d71e0f274701a0de2c7d717c12d6..6478c882a96c35c9859c8745b497aaff76957270 100644 (file)
@@ -973,12 +973,12 @@ static SymresStatus symres_block(AstBlock* block) {
 SymresStatus symres_function_header(AstFunction* func) {
     func->flags |= Ast_Flag_Comptime;
 
-    if (func->captures && !func->scope_to_lookup_captured_values) {
-        if (!(func->flags & Ast_Flag_Function_Is_Lambda)) {
-            onyx_report_error(func->captures->token->pos, Error_Critical, "This procedure cannot capture values as it is not defined in an expression.");
-            return Symres_Error;
-        }
+    if (!(func->flags & Ast_Flag_Function_Is_Lambda) && func->captures) {
+        onyx_report_error(func->captures->token->pos, Error_Critical, "This procedure cannot capture values as it is not defined in an expression.");
+        return Symres_Error;
+    }
 
+    if (func->captures && !func->scope_to_lookup_captured_values) {
         if (func->flags & Ast_Flag_Function_Is_Lambda_Inside_PolyProc) return Symres_Complete;
 
         return Symres_Yield_Macro;
@@ -1028,7 +1028,7 @@ SymresStatus symres_function_header(AstFunction* func) {
             assert((*node)->kind == Ast_Kind_Static_If || (*node)->kind == Ast_Kind_File_Contents
                     || (*node)->kind == Ast_Kind_Function || (*node)->kind == Ast_Kind_Polymorphic_Proc);
 
-            // Need to current_scope->parent because current_scope is the function body scope.
+            // Need to use current_scope->parent because current_scope is the function body scope.
             Scope *scope = current_scope->parent;
 
             if ((*node)->kind == Ast_Kind_Static_If) {
@@ -1048,12 +1048,6 @@ SymresStatus symres_function_header(AstFunction* func) {
         bh_arr_set_length(func->nodes_that_need_entities_after_clone, 0);
     }
 
-    if (func->captures) {
-        SYMRES(capture_block, func->captures, func->scope_to_lookup_captured_values);
-    }
-
-    SYMRES(type, &func->return_type);
-
     if (func->deprecated_warning) {
         SYMRES(expression, (AstTyped **) &func->deprecated_warning);
     }
@@ -1063,6 +1057,12 @@ SymresStatus symres_function_header(AstFunction* func) {
         SYMRES(expression, &func->foreign.import_name);
     }
 
+    if (func->captures) {
+        SYMRES(capture_block, func->captures, func->scope_to_lookup_captured_values);
+    }
+
+    SYMRES(type, &func->return_type);
+
     scope_leave();
 
     return Symres_Success;
@@ -1374,6 +1374,8 @@ static SymresStatus symres_process_directive(AstNode* directive) {
             }
 
             SYMRES(expression, (AstTyped **) &add_overload->overload);
+            add_overload->overload->flags &= ~Ast_Flag_Function_Is_Lambda;
+
             add_overload_option(&ofunc->overloads, add_overload->order, add_overload->overload);
             break;
         }
@@ -1388,6 +1390,8 @@ static SymresStatus symres_process_directive(AstNode* directive) {
                 onyx_report_error(operator->token->pos, Error_Critical, "This cannot be used as an operator overload.");
                 return Symres_Error;
             }
+
+            overload->flags &= ~Ast_Flag_Function_Is_Lambda;
             
             // First try unary operator overloading
             // CLEANUP This is not written well at all...