added auto-return type
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Mon, 23 Aug 2021 20:24:33 +0000 (15:24 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Mon, 23 Aug 2021 20:24:33 +0000 (15:24 -0500)
include/onyxastnodes.h
src/onyxastnodes.c
src/onyxbuiltins.c
src/onyxchecker.c
src/onyxparser.c
src/onyxtypes.c

index aa27da733d8b1806cad450412dfce63c765ea360..802fdea6b6077956b286c1a917ce6f3daa4b9e10 100644 (file)
@@ -1273,6 +1273,10 @@ extern AstBasicType basic_type_f32x4;
 extern AstBasicType basic_type_f64x2;
 extern AstBasicType basic_type_v128;
 
+// HACK
+// :AutoReturnType
+extern Type type_auto_return;
+extern AstBasicType basic_type_auto_return;
 
 extern OnyxToken builtin_package_token;
 extern AstNumLit builtin_heap_start;
index 409523f9fc18b1af7f6029dde1cc265a7693472e..97a031283812e8cb66411ba84d90b5401b3349fd 100644 (file)
@@ -561,6 +561,14 @@ b32 type_check_or_auto_cast(AstTyped** pnode, Type* type) {
     if (type->kind == Type_Kind_Function && (node->flags & Ast_Flag_Proc_Is_Null) != 0) return 1;
 
     if (types_are_compatible(node->type, type)) return 1;
+    // :AutoReturnType
+    if (node->type && node->type->kind == Type_Kind_Function
+        && node->type->Function.return_type == &type_auto_return
+        && type->kind == Type_Kind_Function) {
+
+        node->type->Function.return_type = type->Function.return_type;
+        return 1;
+    }
     if (node_is_auto_cast((AstNode *) node)) {
         char* dummy;
         Type* from_type = ((AstUnaryOp *) node)->expr->type;
index e33d011c826ee18dd35976cc557ed73d42507a85..8731a61972d575e79ea2fa9cbce376cd4a7478ec 100644 (file)
@@ -31,6 +31,11 @@ AstBasicType basic_type_f32x4 = { Ast_Kind_Basic_Type, 0, &simd_token, NULL, 0,
 AstBasicType basic_type_f64x2 = { Ast_Kind_Basic_Type, 0, &simd_token, NULL, 0, NULL, NULL, &basic_types[Basic_Kind_F64X2] };
 AstBasicType basic_type_v128  = { Ast_Kind_Basic_Type, 0, &simd_token, NULL, 0,  NULL, NULL, &basic_types[Basic_Kind_V128]  };
 
+// HACK
+// :AutoReturnType
+Type         type_auto_return = { 0 };
+AstBasicType basic_type_auto_return = { Ast_Kind_Basic_Type, 0, &simd_token, NULL, 0, NULL, NULL, &type_auto_return };
+
 OnyxToken builtin_package_token = { Token_Type_Symbol, 7, "builtin ", { 0 } };
 
 static OnyxToken builtin_heap_start_token = { Token_Type_Symbol, 12, "__heap_start ", { 0 } };
index f326877862a54d87d8c23a904f620ec8eec63324..945d25b90ef8fa1ad520da05f3c93bb5576a0c53 100644 (file)
@@ -108,25 +108,38 @@ static inline void fill_in_type(AstTyped* node) {
 }
 
 // HACK: This should be baked into a structure, not a global variable.
-static Type* expected_return_type = NULL;
+static Type** expected_return_type = NULL;
 
 CheckStatus check_return(AstReturn* retnode) {
     if (retnode->expr) {
         CHECK(expression, &retnode->expr);
 
-        if (!type_check_or_auto_cast(&retnode->expr, expected_return_type)) {
+        if (*expected_return_type == &type_auto_return) {
+            resolve_expression_type(retnode->expr);
+            if (retnode->expr->type == NULL) return Check_Yield_Macro;
+
+            *expected_return_type = retnode->expr->type;
+            return Check_Success;
+        }
+
+        if (!type_check_or_auto_cast(&retnode->expr, *expected_return_type)) {
             onyx_report_error(retnode->token->pos,
                     "Expected to return a value of type '%s', returning value of type '%s'.",
-                    type_get_name(expected_return_type),
+                    type_get_name(*expected_return_type),
                     node_get_type_name(retnode->expr));
             return Check_Error;
         }
 
     } else {
-        if (expected_return_type->Basic.size > 0) {
+        if (*expected_return_type == &type_auto_return) {
+            *expected_return_type = &basic_types[Basic_Kind_Void];
+            return Check_Success;
+        }
+
+        if ((*expected_return_type)->Basic.size > 0) {
             onyx_report_error(retnode->token->pos,
                 "Returning from non-void function without a value. Expected a value of type '%s'.",
-                type_get_name(expected_return_type));
+                type_get_name(*expected_return_type));
             return Check_Error;
         }
     }
@@ -593,8 +606,9 @@ CheckStatus check_call(AstCall** pcall) {
         token_toggle_end(callee->intrinsic_name);
     }
 
-    call->type = callee->type->Function.return_type;
     call->va_kind = VA_Kind_Not_VA;
+    call->type = callee->type->Function.return_type;
+    if (call->type == &type_auto_return) return Check_Yield_Macro;
 
     Type **formal_params = callee->type->Function.params;
 
@@ -1622,7 +1636,7 @@ CheckStatus check_expression(AstTyped** pexpr) {
     }
 
     if (expr->kind == Ast_Kind_Polymorphic_Proc) {
-        // Polymoprhic procedures do not need to be checked. Their concrete instantiations
+        // polymorphic procedures do not need to be checked. Their concrete instantiations
         // will be checked when they are created.
         return Check_Success;
     }
@@ -1914,17 +1928,20 @@ CheckStatus check_function(AstFunction* func) {
     if (func->flags & Ast_Flag_Already_Checked) return Check_Success;
     if (func->entity_header && func->entity_header->state < Entity_State_Code_Gen) return Check_Yield_Macro;
     
-    expected_return_type = func->type->Function.return_type;
+    expected_return_type = &func->type->Function.return_type;
     if (func->body) {
         CheckStatus status = check_block(func->body);
         if (status == Check_Error && func->generated_from)
             onyx_report_error(func->generated_from->pos, "Error in polymorphic procedure generated from this location.");
 
-        return status;
+        if (status != Check_Success) return status;
     }
-    
-    func->flags |= Ast_Flag_Already_Checked;
 
+    if (*expected_return_type == &type_auto_return) {
+        *expected_return_type = &basic_types[Basic_Kind_Void];
+    }
+
+    func->flags |= Ast_Flag_Already_Checked;
     return Check_Success;
 }
 
index aedca557b468d28b1b520084db87b34843a33eea..0892a6cd103749fd33225976a6493f8e3574e714 100644 (file)
@@ -2220,7 +2220,7 @@ static b32 parse_possible_quick_function_definition(OnyxParser* parser, AstTyped
 
     if (parser->curr->type == '{') {
         body_block = parse_block(parser, 1);
-        return_type = (AstType *) &basic_type_void;
+        return_type = (AstType *) &basic_type_auto_return;
 
     } else {
         AstTyped* body = parse_expression(parser, 0);
index eaa931fad764d2f89661fc260dc633d30571c9d5..b96fa9f959ba08030947c2deea50e010f6b62aeb 100644 (file)
@@ -84,6 +84,10 @@ b32 types_are_compatible_(Type* t1, Type* t2, b32 recurse_pointers) {
     if (t1 == NULL || t2 == NULL) return 0;
     if (t1->id == t2->id) return 1;
 
+    if (t1 == &type_auto_return || t2 == &type_auto_return) {
+        return 0;
+    }
+
     switch (t1->kind) {
         case Type_Kind_Basic:
             if (t2->kind == Type_Kind_Basic) {