added default initial values to struct; added named values to struct literals
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Mon, 17 Aug 2020 03:32:32 +0000 (22:32 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Mon, 17 Aug 2020 03:32:32 +0000 (22:32 -0500)
core/test.onyx
docs/plan
include/onyxastnodes.h
include/onyxmsgs.h
onyx
progs/stack_based.onyx
src/onyxchecker.c
src/onyxmsgs.c
src/onyxparser.c
src/onyxsymres.c
src/onyxtypes.c

index 07b11f28c8a25f7aaf88284131597e095021981e..8520d89b210166abdc1d390f16652f350b2ed242 100644 (file)
@@ -1,6 +1,8 @@
 package core
 
+use package memory { null }
+
 Buffer :: struct {
-       length: u32;
-       data: rawptr;
+       length : u32    = 0;
+       data   : rawptr = null;
 }
\ No newline at end of file
index c113975bf3a18ca716e885d5ecd60351dbc05ba9..88ef79653a2c669a90170a52a028acd6555ecda4 100644 (file)
--- a/docs/plan
+++ b/docs/plan
@@ -170,8 +170,11 @@ HOW:
 
         [X] local variable allocator
 
-        [ ] Struct literals
-
+        [X] Struct literals
+            X All members specified means names not required
+            X Named member initialization
+            X Default values on structs so they don't have to be named
+            
         [ ] #union on structs
 
         [ ] #align on structs
@@ -187,7 +190,7 @@ HOW:
             a := 2
             b := 5
             a, b = b, a;
-            
+
         [ ] All code paths return correct value
 
         [ ] Type parameterized structs
index 4334b4b433fd3b23cefb4ed5d909e7c7e2c8e575..df3cda9ebab518776dc62f47180ed0dc6738857e 100644 (file)
@@ -41,6 +41,7 @@ typedef struct AstPointerType AstPointerType;
 typedef struct AstFunctionType AstFunctionType;
 typedef struct AstArrayType AstArrayType;
 typedef struct AstStructType AstStructType;
+typedef struct AstStructMember AstStructMember;
 typedef struct AstEnumType AstEnumType;
 typedef struct AstEnumValue AstEnumValue;
 typedef struct AstTypeAlias AstTypeAlias;
@@ -282,7 +283,14 @@ struct AstFieldAccess   { AstTyped_base; AstTyped *expr; u64 offset; };
 struct AstSizeOf        { AstTyped_base; AstType *so_type; u64 size; };
 struct AstAlignOf       { AstTyped_base; AstType *ao_type; u64 alignment; };
 struct AstFileContents  { AstTyped_base; OnyxToken *filename; };
-struct AstStructLiteral { AstTyped_base; AstTyped *stnode; bh_arr(AstTyped *) values; };
+struct AstStructLiteral {
+    AstTyped_base;
+
+    AstTyped *stnode;
+
+    bh_arr(AstStructMember *) named_values;
+    bh_arr(AstTyped *) values;
+};
 
 // Intruction Node
 struct AstReturn        { AstNode_base; AstTyped* expr; };
@@ -330,13 +338,17 @@ struct AstArrayType     { AstType_base; AstType* elem; AstTyped *count_expr; };
 struct AstStructType {
     AstType_base;
 
-    bh_arr(AstTyped *) members;
+    bh_arr(AstStructMember *) members;
 
     // NOTE: Used to cache the actual type, since building
     // a struct type is kind of complicated and should
     // only happen once.
     Type *stcache;
 };
+struct AstStructMember {
+    AstTyped_base;
+    AstTyped* initial_value;
+};
 struct AstEnumType {
     AstType_base;
     Scope *scope;
index 1f78243bf8a96deb9d80edb16fcabc85320ccbd1..0e9ada8ff756a298a0b5ffce4a6fb5eedec4999a 100644 (file)
@@ -30,6 +30,8 @@ typedef enum MsgType {
 
     Msg_Type_Duplicate_Member,
     Msg_Type_No_Field,
+    Msg_Type_Duplicate_Value,
+    Msg_Type_Field_No_Value,
 
     Msg_Type_Unresolved_Type,
     Msg_Type_Unresolved_Symbol,
diff --git a/onyx b/onyx
index dbe7cd69373f698c4e87bc9b6fa5bb84fb21731b..d7ff95ab2a909cec13542542eb66909a9ebebf37 100755 (executable)
Binary files a/onyx and b/onyx differ
index c85c16105e9de45cca0ed3035dafd40d719b0172..372f58144eb829aaae537bbbf41d800e65e5a08f 100644 (file)
@@ -150,13 +150,15 @@ start :: proc #export {
     mag_squared(varr[2]) |> print();
 
     v1 := Vec3 .{ 1, 2, 4 };
-    v2 := *vadd(Vec3.{4, 3, 2}, Vec3.{1, 1, 1});
+    v2 := *vadd(v1, Vec3.{ 1, 2, 4 });
   
     print(v2.x);
     print(v2.y);
     print(v2.z);
 
-    buf := core.Buffer.{ 16, null };
+    buf := core.Buffer.{
+        length = 16,
+    };
 }
 
 vadd :: proc (v1: Vec3, v2: Vec3) -> ^Vec3 {
index ed4e045e5ee98c2ff1a860542643b6ce4e0a8ca8..1fb9048326849963432ae8a7040b11aaac7a23d9 100644 (file)
@@ -987,7 +987,7 @@ CHECK(struct, AstStructType* s_node) {
         return 1;
     }
 
-    bh_arr_each(AstTyped *, member, s_node->members) {
+    bh_arr_each(AstStructMember *, member, s_node->members) {
         token_toggle_end((*member)->token);
 
         if (bh_table_has(i32, mem_set, (*member)->token->text)) {
index c5ad22d13fbc87938eae0cb20f9358e85a5c0b5e..516375ad880874f27b72382ac17b1e0cece8553e 100644 (file)
@@ -28,6 +28,8 @@ static const char* msg_formats[] = {
 
     "duplicate declaration of struct member '%s'",
     "field '%s' does not exist on '%s'",
+    "duplicate value for struct member '%b'",
+    "no value provided for field '%b'",
 
     "unable to resolve type for symbol '%b'",
     "unable to resolve symbol '%b'",
index 39763fac8af1aed2a445ae446f16a42f3e127d07..699428031bc3a43b082884a4e525694405a17dfc 100644 (file)
@@ -193,6 +193,7 @@ static b32 parse_possible_struct_literal(OnyxParser* parser, AstTyped** ret) {
     AstStructLiteral* sl = make_node(AstStructLiteral, Ast_Kind_Struct_Literal);
     sl->token = parser->curr;
     bh_arr_new(global_heap_allocator, sl->values, 4);
+    bh_arr_new(global_heap_allocator, sl->named_values, 4);
 
     if (symbol2 != NULL) {
         AstTyped *package = make_node(AstTyped, Ast_Kind_Symbol);
@@ -210,11 +211,31 @@ static b32 parse_possible_struct_literal(OnyxParser* parser, AstTyped** ret) {
     }
 
     expect_token(parser, '{');
+    b32 is_named = ((parser->curr + 1)->type == '=');
+
+    OnyxToken* name = NULL;
     while (parser->curr->type != '}') {
         if (parser->hit_unexpected_token) break;
 
+        if (is_named) {
+            name = expect_token(parser, Token_Type_Symbol);
+            expect_token(parser, '=');
+        } else {
+            name = NULL;
+        }
+
         AstTyped *expr = parse_expression(parser);
-        bh_arr_push(sl->values, expr);
+
+        if (is_named) {
+            AstStructMember* sm = make_node(AstStructMember, Ast_Kind_Struct_Member);
+            sm->token = name;
+            sm->initial_value = expr;
+
+            bh_arr_push(sl->named_values, sm);
+            
+        } else {
+            bh_arr_push(sl->values, expr);
+        }
 
         if (parser->curr->type != '}')
             expect_token(parser, ',');
@@ -1114,11 +1135,17 @@ static AstStructType* parse_struct(OnyxParser* parser) {
     while (parser->curr->type != '}') {
         if (parser->hit_unexpected_token) return s_node;
 
-        AstTyped* mem = make_node(AstTyped, Ast_Kind_Struct_Member);
+        AstStructMember* mem = make_node(AstStructMember, Ast_Kind_Struct_Member);
 
         mem->token = expect_token(parser, Token_Type_Symbol);
         expect_token(parser, ':');
         mem->type_node = parse_type(parser);
+
+        if (parser->curr->type == '=') {
+            consume_token(parser);
+            mem->initial_value = parse_expression(parser);
+        }
+
         expect_token(parser, ';');
 
         bh_arr_push(s_node->members, mem);
index 40ad2738ae9621e650d779487f5b655c42226c72..87fa5a6102cd079505f38a2bb2854bbb116dc629 100644 (file)
@@ -91,8 +91,11 @@ static AstType* symres_type(AstType* type) {
 
         s_node->flags |= Ast_Flag_Type_Is_Resolved;
 
-        bh_arr_each(AstTyped *, member, s_node->members) {
+        bh_arr_each(AstStructMember *, member, s_node->members) {
             (*member)->type_node = symres_type((*member)->type_node);
+            if ((*member)->initial_value != NULL) {
+                symres_expression(&(*member)->initial_value);
+            }
         }
 
         return type;
@@ -215,6 +218,49 @@ static void symres_struct_literal(AstStructLiteral* sl) {
     }
 
     sl->type_node = (AstType *) sl->stnode;
+    sl->type = type_build_from_ast(semstate.allocator, sl->type_node);
+
+    if (bh_arr_length(sl->named_values) > 0) {
+        bh_arr_set_length(sl->values, sl->type->Struct.mem_count);
+
+        StructMember s;
+        bh_arr_each(AstStructMember *, smem, sl->named_values) {
+            token_toggle_end((*smem)->token);
+            if (!type_struct_lookup_member(sl->type, (*smem)->token->text, &s)) {
+                onyx_message_add(Msg_Type_No_Field,
+                        (*smem)->token->pos,
+                        (*smem)->token->text, type_get_name(sl->type));
+                return;
+            }
+            token_toggle_end((*smem)->token);
+
+            if (sl->values[s.idx] != NULL) {
+                onyx_message_add(Msg_Type_Duplicate_Value,
+                        (*smem)->token->pos,
+                        (*smem)->token->text, (*smem)->token->length);
+                return;
+            }
+
+            sl->values[s.idx] = (*smem)->initial_value;
+        }
+
+        AstStructType* st = (AstStructType *) sl->type_node;
+        bh_arr_each(StructMember*, smem, sl->type->Struct.memarr) {
+            u32 idx = (*smem)->idx;
+
+            if (sl->values[idx] == NULL) {
+                if (st->members[idx]->initial_value == NULL) {
+                    onyx_message_add(Msg_Type_Field_No_Value,
+                            sl->token->pos,
+                            st->members[idx]->token->text,
+                            st->members[idx]->token->length);
+                    return;
+                }
+                
+                sl->values[idx] = st->members[idx]->initial_value;
+            }
+        }
+    }
 
     bh_arr_each(AstTyped *, expr, sl->values) symres_expression(expr);
 }
@@ -369,7 +415,7 @@ static void symres_function(AstFunction* func) {
                     st = (AstStructType *) ((AstPointerType *) param->type_node)->elem;
                 }
 
-                bh_arr_each(AstTyped *, mem, st->members) {
+                bh_arr_each(AstStructMember *, mem, st->members) {
                     AstFieldAccess* fa = onyx_ast_node_new(semstate.node_allocator, sizeof(AstFieldAccess), Ast_Kind_Field_Access);
                     fa->token = (*mem)->token;
                     fa->type_node = (*mem)->type_node;
index f683b292dff0b05bc42e40aa5a671eed8335fd83..cd6cfd06dc19f5594dde0efca80b38b074de9b80 100644 (file)
@@ -281,7 +281,7 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) {
             u32 offset = 0;
             u32 alignment = 1, mem_alignment;
             u32 idx = 0;
-            bh_arr_each(AstTyped *, member, s_node->members) {
+            bh_arr_each(AstStructMember *, member, s_node->members) {
                 (*member)->type = type_build_from_ast(alloc, (*member)->type_node);
 
                 // TODO: Add alignment checking here
@@ -308,7 +308,7 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) {
             // NOTE: Need to do a second pass because the references to the
             // elements of the table may change if the internal arrays of the
             // table need to be resized.
-            bh_arr_each(AstTyped *, member, s_node->members) {
+            bh_arr_each(AstStructMember *, member, s_node->members) {
                 token_toggle_end((*member)->token);
                 bh_arr_push(s_type->Struct.memarr, &bh_table_get(StructMember, s_type->Struct.members, (*member)->token->text));
                 token_toggle_end((*member)->token);