made explicit types on defaulted struct members optional
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Sun, 24 Jan 2021 17:32:44 +0000 (11:32 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Sun, 24 Jan 2021 17:32:44 +0000 (11:32 -0600)
there are bugs if you 'use' a structure with this though.

bin/onyx
onyx.exe
src/onyxchecker.c
src/onyxparser.c
src/onyxsymres.c
src/onyxtypes.c
src/onyxutils.c

index 74d7969d247fc2f379c677c13d5013f4027d02c6..c5b5e78d17dde5602e99bcb85a68c5f64fd632de 100755 (executable)
Binary files a/bin/onyx and b/bin/onyx differ
index 6949f75b40b039b4e4cd720a23ab428c6e9aa645..623482be9e94194e3603b651f580b888646476b1 100644 (file)
Binary files a/onyx.exe and b/onyx.exe differ
index 51b6b7d21907d6b5f0f098a8b745722f3388051b..74ee72f71fdd6c0587ed6534f164f0fb05416193 100644 (file)
@@ -1565,6 +1565,14 @@ CheckStatus check_overloaded_function(AstOverloadedFunction* func) {
 }
 
 CheckStatus check_struct(AstStructType* s_node) {
+    bh_arr_each(AstStructMember *, smem, s_node->members) {
+        if ((*smem)->type_node == NULL && (*smem)->initial_value != NULL) {
+            check_expression(&(*smem)->initial_value);
+            fill_in_type((*smem)->initial_value);
+            (*smem)->type = resolve_expression_type((*smem)->initial_value);
+        }
+    }
+
     // NOTE: fills in the stcache
     type_build_from_ast(context.ast_alloc, (AstType *) s_node);
     if (s_node->stcache == NULL) return Check_Error;
index 0dda66fa4c2ffefc0f55094e7276e42fa30a104c..7f3b6a67369eca52b359807d67f499ab19bdf67a 100644 (file)
@@ -1840,8 +1840,11 @@ static AstStructType* parse_struct(OnyxParser* parser) {
         }
 
         mem->token = expect_token(parser, Token_Type_Symbol);
+
         expect_token(parser, ':');
-        mem->type_node = parse_type(parser);
+        if (parser->curr->type != '=') {
+            mem->type_node = parse_type(parser);
+        }
 
         if (parser->curr->type == '=') {
             consume_token(parser);
index 8b4d61e57b0129dfa509a1128c8330ebea84b334..a755ae31520e27cddc32478a8687589c86d1d3d3 100644 (file)
@@ -120,27 +120,36 @@ AstType* symres_type(AstType* type) {
 
         fori (i, 0, bh_arr_length(s_node->members)) {
             AstStructMember *member = s_node->members[i];
-            member->type_node = symres_type(member->type_node);
 
-            if (!node_is_type((AstNode *) member->type_node)) {
-                onyx_report_error(member->token->pos, "Member type is not a type.");
-                return type;
-            }
-
-            if (member->flags & Ast_Flag_Struct_Mem_Used) {
-                AstStructType *used = (AstStructType *) member->type_node;
+            if (member->type_node) {
+                member->type_node = symres_type(member->type_node);
 
-                while (used->kind == Ast_Kind_Type_Alias) {
-                    // NOTE: Maybe not a struct type.
-                    used = (AstStructType *) ((AstTypeAlias *) used)->to;
+                if (!node_is_type((AstNode *) member->type_node)) {
+                    onyx_report_error(member->token->pos, "Member type is not a type.");
+                    return type;
                 }
 
-                if (used->kind != Ast_Kind_Struct_Type) {
-                    onyx_report_error(member->token->pos,
-                            "Can only 'use' members of struct type, got '%s'.",
-                            onyx_ast_node_kind_string(used->kind));
+                if (member->flags & Ast_Flag_Struct_Mem_Used) {
+                    AstType *used = (AstType *) member->type_node;
 
-                    return type;
+                    while (used->kind == Ast_Kind_Type_Alias) {
+                        used = ((AstTypeAlias *) used)->to;
+                    }
+
+                    b32 use_works = (used->kind == Ast_Kind_Struct_Type);
+
+                    if (used->kind == Ast_Kind_Type_Raw_Alias) {
+                        AstTypeRawAlias* alias = (AstTypeRawAlias *) used;
+                        use_works = (alias->to->kind == Type_Kind_Struct);
+                    }
+
+                    if (!use_works) {
+                        onyx_report_error(member->token->pos,
+                                "Can only 'use' members of struct type, got '%s'.",
+                                onyx_ast_node_kind_string(used->kind));
+
+                        return type;
+                    }
                 }
             }
         }
@@ -640,9 +649,6 @@ static void symres_block(AstBlock* block) {
 }
 
 void symres_function_header(AstFunction* func) {
-    if (func->scope == NULL)
-        func->scope = scope_create(context.ast_alloc, curr_scope, func->token->pos);
-
     func->flags |= Ast_Flag_Comptime;
 
     bh_arr_each(AstParam, param, func->params) {
@@ -692,6 +698,17 @@ void symres_function_header(AstFunction* func) {
         onyx_report_error(func->token->pos, "Return type is not a type.");
     }
 
+    bh_arr_each(AstParam, param, func->params) {
+        if (param->local->type_node != NULL) {
+            param->local->type_node = symres_type(param->local->type_node);
+        }
+    }
+}
+
+void symres_function(AstFunction* func) {
+    if (func->scope == NULL)
+        func->scope = scope_create(context.ast_alloc, curr_scope, func->token->pos);
+
     scope_enter(func->scope);
 
     bh_arr_each(AstParam, param, func->params) {
@@ -713,12 +730,7 @@ void symres_function_header(AstFunction* func) {
         //
         // The 'use t : T' member requires completely knowing the type of T, to know which
         // members should be brought in. At the moment, that requires completely building the
-        // type of Foo($T), which is not possible, because the defaulted member 'something_else'
-        // does not have a known type until the default memory gets checked and reduced.
-        if (param->local->type_node != NULL) {
-            param->local->type_node = symres_type(param->local->type_node);
-        }
-
+        // type of Foo($T).
         if (param->local->flags & Ast_Flag_Param_Use) {
             if (param->local->type_node != NULL && param->local->type == NULL) {
                 param->local->type = type_build_from_ast(context.ast_alloc, param->local->type_node);
@@ -739,6 +751,7 @@ void symres_function_header(AstFunction* func) {
 
             } else if (param->local->type != NULL) {
                 onyx_report_error(param->local->token->pos, "Can only 'use' structures or pointers to structures.");
+
             } else {
                 onyx_report_error(param->local->token->pos, "Cannot deduce type of parameter '%b'; Try adding it explicitly.",
                     param->local->token->text,
@@ -747,12 +760,6 @@ void symres_function_header(AstFunction* func) {
         }
     }
 
-    scope_leave();
-}
-
-void symres_function(AstFunction* func) {
-    scope_enter(func->scope);
-
     curr_function = func;
     symres_block(func->body);
 
index eefe755c9ec11dbfc780217aea28b88c3a40fa86..0b39bc40c8843aeb40a7ee1c22cc0c401fe2524b 100644 (file)
@@ -380,7 +380,14 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) {
             u32 alignment = 1, mem_alignment;
             u32 idx = 0;
             bh_arr_each(AstStructMember *, member, s_node->members) {
-                (*member)->type = type_build_from_ast(alloc, (*member)->type_node);
+                if ((*member)->type == NULL)
+                    (*member)->type = type_build_from_ast(alloc, (*member)->type_node);
+
+                if ((*member)->type == NULL) {
+                    onyx_report_error((*member)->token->pos, "Unable to resolve member type. Try adding it explicitly."); 
+                    s_node->stcache = NULL;
+                    return NULL;
+                }
 
                 mem_alignment = type_alignment_of((*member)->type);
                 if (mem_alignment <= 0) {
index a8a3a65f8ad6ab05e048e6e4cb15f661b0d02992..dc4dfdd636a4a671d0f71d32f05b4981d52f5a24 100644 (file)
@@ -971,6 +971,8 @@ AstStructType* polymorphic_struct_lookup(AstPolyStructType* ps_type, bh_arr(AstP
         .scope = ps_type->scope,
     };
 
+    entity_bring_to_state(&struct_entity, Entity_State_Check_Types);
+    entity_bring_to_state(&struct_default_entity, Entity_State_Check_Types);
     entity_bring_to_state(&struct_entity, Entity_State_Code_Gen);
     entity_bring_to_state(&struct_default_entity, Entity_State_Code_Gen);