added basic union types; force structs to be a particular alignment or size
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Mon, 17 Aug 2020 19:59:35 +0000 (14:59 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Mon, 17 Aug 2020 19:59:35 +0000 (14:59 -0500)
docs/plan
include/onyxastnodes.h
onyx
progs/stack_based.onyx
src/onyxparser.c
src/onyxtypes.c

index 88ef79653a2c669a90170a52a028acd6555ecda4..614d56fefeff9d2e38500e2ca6b14448a76328ed 100644 (file)
--- a/docs/plan
+++ b/docs/plan
@@ -175,12 +175,18 @@ HOW:
             X Named member initialization
             X Default values on structs so they don't have to be named
             
-        [ ] #union on structs
+        [X] #union on structs
 
-        [ ] #align on structs
+        [X] #align on structs
+
+        [X] #size on structs
 
         [ ] 'use' enums and packages at an arbitrary scope
 
+        [ ] 'when' statements
+            - Compile time conditions
+            - Only evalutate code blocks that evaluate to be true
+
         [ ] Array literals
 
         [ ] Top level variable initialization
index df3cda9ebab518776dc62f47180ed0dc6738857e..ca9e7499090c1bd5b114fd6cc8107e5a13aa6262 100644 (file)
@@ -159,6 +159,9 @@ typedef enum AstFlags {
 
     // Enum flags
     Ast_Flag_Enum_Is_Flags     = BH_BIT(11),
+
+    // Struct flags
+    Ast_Flag_Struct_Is_Union   = BH_BIT(12),
 } AstFlags;
 
 typedef enum UnaryOp {
@@ -340,6 +343,8 @@ struct AstStructType {
 
     bh_arr(AstStructMember *) members;
 
+    u32 min_alignment, min_size;
+
     // NOTE: Used to cache the actual type, since building
     // a struct type is kind of complicated and should
     // only happen once.
diff --git a/onyx b/onyx
index d1e7a979edff1b1246c050bdce805a73b001a00d..3e28fe9aca207135d442f747dd302c725ed494b0 100755 (executable)
Binary files a/onyx and b/onyx differ
index 3c8d28ff8b9db3ddb53743e6fd0fd3f1ca8ed4aa..5301b59af5891a6abba03ce709bb9cf5cb309449 100644 (file)
@@ -149,7 +149,7 @@ start :: proc #export {
     stupid_idea(1234)(1234) |> print();
 
     varr : [5] Vec3;
-    varr[2] = Vec3 .{4, 5, 6};
+    varr[2] = Vec3.{4, 5, 6};
 
     mag_squared(varr[2]) |> print();
 
@@ -160,16 +160,25 @@ start :: proc #export {
     print(v2.y);
     print(v2.z);
 
-    buf := core.Buffer.{
-        length = 16,
-    };
+    buf := core.Buffer.{ length = 16 };
+
+    un : UnionTest;
+    un.f = 1.25f;
+    print_hex(cast(u64) un.i);
 }
 
 vadd :: proc (v1: Vec3, v2: Vec3) -> ^Vec3 {
     out := cast(^Vec3) alloc(return_scratch_alloc, sizeof Vec3);
-    out.x = v1.x + v2.x;
-    out.y = v1.y + v2.y;
-    out.z = v1.z + v2.z;
+    *out = Vec3.{
+        x = v1.x + v2.x,
+        y = v1.y + v2.y,
+        z = v1.z + v2.z,
+    };
 
     return out;
+}
+
+UnionTest :: struct #union {
+    i : i32;
+    f : f32;
 }
\ No newline at end of file
index 699428031bc3a43b082884a4e525694405a17dfc..4d2b41e8cb410fd6990e0d931ca09dce0bdcf74f 100644 (file)
@@ -1131,6 +1131,37 @@ static AstStructType* parse_struct(OnyxParser* parser) {
 
     bh_arr_new(global_heap_allocator, s_node->members, 4);
 
+    while (parser->curr->type == '#') {
+        if (parser->hit_unexpected_token) return NULL;
+
+        if (parse_possible_directive(parser, "union")) {
+            s_node->flags |= Ast_Flag_Struct_Is_Union;
+        }
+
+        else if (parse_possible_directive(parser, "align")) {
+            AstNumLit* numlit = parse_int_literal(parser);
+            if (numlit == NULL) return NULL;
+
+            s_node->min_alignment = numlit->value.i;
+        }
+
+        else if (parse_possible_directive(parser, "size")) {
+            AstNumLit* numlit = parse_int_literal(parser);
+            if (numlit == NULL) return NULL;
+
+            s_node->min_size = numlit->value.i;
+        }
+
+        else {
+            OnyxToken* directive_token = expect_token(parser, '#');
+            OnyxToken* symbol_token = expect_token(parser, Token_Type_Symbol);
+
+            onyx_message_add(Msg_Type_Unknown_Directive,
+                    directive_token->pos,
+                    symbol_token->text, symbol_token->length);
+        }
+    }
+
     expect_token(parser, '{');
     while (parser->curr->type != '}') {
         if (parser->hit_unexpected_token) return s_node;
index cd6cfd06dc19f5594dde0efca80b38b074de9b80..7f1c6aa4542ee30e58ebe864bc42a8974e7b8ccb 100644 (file)
@@ -278,6 +278,8 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) {
             bh_table_init(global_heap_allocator, s_type->Struct.members, s_type->Struct.mem_count);
             bh_arr_new(global_heap_allocator, s_type->Struct.memarr, s_type->Struct.mem_count);
 
+            b32 is_union = (s_node->flags & Ast_Flag_Struct_Is_Union) != 0;
+            u32 size = 0;
             u32 offset = 0;
             u32 alignment = 1, mem_alignment;
             u32 idx = 0;
@@ -301,7 +303,11 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) {
                 bh_table_put(StructMember, s_type->Struct.members, (*member)->token->text, smem);
                 token_toggle_end((*member)->token);
 
-                offset += type_size_of((*member)->type);
+                u32 type_size = type_size_of((*member)->type);
+                if (!is_union) offset += type_size;
+                if (!is_union)   size += type_size;
+                else             size =  bh_max(size, type_size);
+
                 idx++;
             }
 
@@ -314,12 +320,15 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) {
                 token_toggle_end((*member)->token);
             }
 
+            alignment = bh_max(s_node->min_alignment, alignment);
             s_type->Struct.aligment = alignment;
 
-            if (offset % alignment != 0) {
-                offset += alignment - (offset % alignment);
+            if (size % alignment != 0) {
+                size += alignment - (size % alignment);
             }
-            s_type->Struct.size = offset;
+
+            size = bh_max(s_node->min_size, size);
+            s_type->Struct.size = size;
 
             return s_type;
         }