structs can have tags; some bugfixes
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 6 Oct 2021 19:43:54 +0000 (14:43 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 6 Oct 2021 19:43:54 +0000 (14:43 -0500)
12 files changed:
bin/onyx
core/type_info/type_info.onyx
include/astnodes.h
include/types.h
modules/immediate_mode/immediate_renderer.onyx
modules/ui/components/scrollable_region.onyx
src/checker.c
src/parser.c
src/symres.c
src/types.c
src/wasm.c
src/wasm_type_table.c

index e2c8f7cfa40673f4c3ac24581bedcea6b5fe4175..1012a7e8080be388fcb676b0a9964556564997dd 100755 (executable)
Binary files a/bin/onyx and b/bin/onyx differ
index 530c5f9cf5acb46d11ac32e603d3eecee227917c..558ba45fdc8e7658caa46ed52e71231128d809dd 100644 (file)
@@ -148,6 +148,7 @@ Type_Info_Struct :: struct {
     name: str;
     members: [] Member;
     parameters: [] any;
+    tags: [] any;
 }
 
 Type_Info_Compound :: struct {
index 68f84477bc4df76e94d545cc136b20a829572e4a..02f0c1be3bc9014eaddecbca722a482668de87ef 100644 (file)
@@ -772,6 +772,7 @@ struct AstStructType {
     char *name;
 
     bh_arr(AstStructMember *) members;
+    bh_arr(AstTyped *) meta_tags;
 
     u32 min_alignment, min_size;
 
index cb9fb30b0872bbd15eff6c258c67b8e6db634d83..9e2961b3b33eadc30c94e818bf54dcb5e4e425dc 100644 (file)
@@ -107,6 +107,7 @@ struct TypeWithOffset {
         bh_arr(struct AstPolySolution) poly_sln;                  \
         bh_arr(TypeWithOffset) linear_members;                    \
         struct AstType *constructed_from;                         \
+        bh_arr(struct AstTyped *) meta_tags;                      \
     })                                                            \
     TYPE_KIND(Compound, struct {                                  \
         u32 count;                                                \
index ccdf9acb887187dbc818d76f92b82d283444883a..03718ce380182acd58eaa2d9e5a41f9f2759983d 100644 (file)
@@ -313,9 +313,9 @@ Immediate_Renderer :: struct {
         new_w  := new_x1 - new_x0;
         new_h  := new_y1 - new_y0;
 
-        array.push(^scissor_stack, .{ new_x0, new_y0, new_w, new_h });
+        array.push(^scissor_stack, .{ new_x0, new_y0, new_w + 1, new_h + 1 });
 
-        gl.scissor(~~new_x0, window_height - ~~new_y1, ~~new_w, ~~new_h);
+        gl.scissor(~~new_x0, window_height - ~~new_y1, ~~math.ceil(new_w + 1), ~~math.ceil(new_h + 1));
     }
 
     pop_scissor :: (use ir: ^Immediate_Renderer) {
index eca3fd89e28d1f72d116a27e39c8c8b478eb00a7..c946319456669bc223cd8715a53c71b63df80714 100644 (file)
@@ -35,8 +35,9 @@ Scrollable_Region_Handle :: struct {
 }
 
 scrollable_region_start :: (use r: Rectangle, use src: Scrollable_Region_Controls = .{},
-                            site := #callsite, state: ^Scrollable_Region_State = null) -> Scrollable_Region_Handle {
-    hash := get_site_hash(site, 0);
+                            site := #callsite, increment := 0,
+                            state: ^Scrollable_Region_State = null) -> Scrollable_Region_Handle {
+    hash := get_site_hash(site, increment);
     x, y := Rectangle.top_left(r);
     width, height := Rectangle.dimensions(r);
 
index 642325df5e58c9a41d7bb56291a88b84b735bf05..57586d732c4bccaee0e4018399c2bc53f3542807 100644 (file)
@@ -1253,18 +1253,20 @@ CheckStatus check_address_of(AstAddressOf* aof) {
         YIELD(aof->token->pos, "Trying to resolve type of expression to take a reference.");
     }
 
-    if ((aof->expr->kind != Ast_Kind_Subscript
-            && aof->expr->kind != Ast_Kind_Dereference
-            && aof->expr->kind != Ast_Kind_Field_Access
-            && aof->expr->kind != Ast_Kind_Memres
-            && aof->expr->kind != Ast_Kind_Local)
-            || (aof->expr->flags & Ast_Flag_Cannot_Take_Addr) != 0) {
+    AstTyped* expr = (AstTyped *) strip_aliases((AstNode *) aof->expr);
+
+    if ((expr->kind != Ast_Kind_Subscript
+            && expr->kind != Ast_Kind_Dereference
+            && expr->kind != Ast_Kind_Field_Access
+            && expr->kind != Ast_Kind_Memres
+            && expr->kind != Ast_Kind_Local)
+            || (expr->flags & Ast_Flag_Cannot_Take_Addr) != 0) {
         ERROR(aof->token->pos, "Cannot take the address of something that is not an l-value.");
     }
 
-    aof->expr->flags |= Ast_Flag_Address_Taken;
+    expr->flags |= Ast_Flag_Address_Taken;
 
-    aof->type = type_make_pointer(context.ast_alloc, aof->expr->type);
+    aof->type = type_make_pointer(context.ast_alloc, expr->type);
 
     return Check_Success;
 }
@@ -1892,6 +1894,18 @@ CheckStatus check_struct_defaults(AstStructType* s_node) {
     if (s_node->entity_type && s_node->entity_type->state < Entity_State_Code_Gen)
         YIELD(s_node->token->pos, "Waiting for struct type to be constructed before checking defaulted members.");
 
+    if (s_node->meta_tags) {
+        bh_arr_each(AstTyped *, meta, s_node->meta_tags) {
+            CHECK(expression, meta);
+            resolve_expression_type(*meta);
+
+            if (((*meta)->flags & Ast_Flag_Comptime) == 0) {
+                onyx_report_error((*meta)->token->pos, "#tag expressions are expected to be compile-time known.");
+                return Check_Error;
+            }
+        }
+    }
+
     bh_arr_each(StructMember *, smem, s_node->stcache->Struct.memarr) {
         if ((*smem)->initial_value && *(*smem)->initial_value) {
             CHECK(expression, (*smem)->initial_value);
@@ -1912,7 +1926,7 @@ CheckStatus check_struct_defaults(AstStructType* s_node) {
                 resolve_expression_type(*meta);
 
                 if (((*meta)->flags & Ast_Flag_Comptime) == 0) {
-                    onyx_report_error((*meta)->token->pos, "#meta expression are expected to be compile-time known.");
+                    onyx_report_error((*meta)->token->pos, "#tag expressions are expected to be compile-time known.");
                     return Check_Error;
                 }
             }
@@ -2057,6 +2071,7 @@ CheckStatus check_memres(AstMemRes* memres) {
 CheckStatus check_type(AstType* type) {
     if (type == NULL) return Check_Success;
     
+    AstType* original_type = type;
     while (type->kind == Ast_Kind_Type_Alias)
         type = ((AstTypeAlias *) type)->to;
 
@@ -2126,6 +2141,12 @@ CheckStatus check_type(AstType* type) {
         }
     }
 
+    type = original_type;
+    while (type->kind == Ast_Kind_Type_Alias) {
+        type->flags |= Ast_Flag_Comptime;
+        type = ((AstTypeAlias *) type)->to;
+    }
+
     type->flags |= Ast_Flag_Already_Checked;
     return Check_Success;
 }
index f7bef603b32a7a440d30a197a2eaaa9ef93176d1..38762521007ef7a2f95723a5f55f4585ba8fea45 100644 (file)
@@ -1782,6 +1782,7 @@ static AstType* parse_type(OnyxParser* parser) {
                 case Token_Type_Literal_Float:
                 case Token_Type_Literal_True:
                 case Token_Type_Literal_False:
+                case '-':
                     *next_insertion = (AstType *) parse_expression(parser, 0);
                     next_insertion = NULL;
                     break;
@@ -1875,7 +1876,8 @@ static AstStructType* parse_struct(OnyxParser* parser) {
     }
 
     bh_arr_new(global_heap_allocator, s_node->members, 4);
-
+    
+    bh_arr(AstTyped *) struct_meta_tags=NULL;
     while (parser->curr->type == '#') {
         if (parser->hit_unexpected_token) return NULL;
 
@@ -1897,6 +1899,17 @@ static AstStructType* parse_struct(OnyxParser* parser) {
             s_node->min_size = numlit->value.i;
         }
 
+        else if (parse_possible_directive(parser, "tag")) {
+            expect_token(parser, '(');
+
+            AstTyped* expr = parse_expression(parser, 0);
+
+            if (struct_meta_tags == NULL) bh_arr_new(global_heap_allocator, struct_meta_tags, 1);
+            bh_arr_push(struct_meta_tags, expr);
+
+            expect_token(parser, ')');
+        }
+
         else {
             OnyxToken* directive_token = expect_token(parser, '#');
             OnyxToken* symbol_token = expect_token(parser, Token_Type_Symbol);
@@ -1905,6 +1918,8 @@ static AstStructType* parse_struct(OnyxParser* parser) {
         }
     }
 
+    s_node->meta_tags = struct_meta_tags;
+
     expect_token(parser, '{');
 
     b32 member_is_used = 0;
@@ -1933,12 +1948,14 @@ static AstStructType* parse_struct(OnyxParser* parser) {
         } else {
             bh_arr(AstTyped *) meta_tags=NULL;
             while (parse_possible_directive(parser, "tag")) {
+                expect_token(parser, '(');
+
                 AstTyped* expr = parse_expression(parser, 0);
 
                 if (meta_tags == NULL) bh_arr_new(global_heap_allocator, meta_tags, 1);
                 bh_arr_push(meta_tags, expr);
 
-                expect_token(parser, ';');
+                expect_token(parser, ')');
             }
 
             bh_arr_clear(member_list_temp);
index b771b308fe42d96c757eb5c47166690f34ee8553..97c7702ca9cbfdb0e9b3809a3fd31b95e7e5b4af 100644 (file)
@@ -1062,6 +1062,12 @@ static SymresStatus symres_struct_defaults(AstType* t) {
     AstStructType* st = (AstStructType *) t;
     if (st->scope) scope_enter(st->scope);
 
+    if (st->meta_tags) {
+        bh_arr_each(AstTyped *, meta, st->meta_tags) {
+            SYMRES(expression, meta);
+        }
+    }
+
     bh_arr_each(AstStructMember *, smem, st->members) {
         if ((*smem)->initial_value != NULL) {
             SYMRES(expression, &(*smem)->initial_value);
index f303b9f0adab532f025d56ed1ca194ad88079b70..7b8451de37fb6b45c6b1001296425a9e51ab6d4c 100644 (file)
@@ -330,6 +330,7 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) {
                 s_type->ast_type = type_node;
                 s_type->Struct.name = s_node->name;
                 s_type->Struct.mem_count = bh_arr_length(s_node->members);
+                s_type->Struct.meta_tags = s_node->meta_tags;
                 type_register(s_type);
 
                 s_type->Struct.memarr = NULL;
index 3d43d6c40c6b8deee48f7c4c4894fcef7d3a00a7..a28613173297804fb66a7fe9671def42b179952a 100644 (file)
@@ -491,6 +491,19 @@ EMIT_FUNC(assignment, AstBinaryOp* assign) {
         }
     }
 
+    if (lval->kind == Ast_Kind_Field_Access) {
+        AstFieldAccess* fa = (AstFieldAccess *) lval;
+        if (fa->expr->kind == Ast_Kind_Param && type_is_structlike_strict(fa->expr->type)) {
+            emit_expression(mod, &code, assign->right);
+
+            u64 localidx = bh_imap_get(&mod->local_map, (u64) fa->expr);
+            WIL(WI_LOCAL_SET, localidx + fa->idx);
+
+            *pcode = code;
+            return;
+        }
+    }
+
     if (lval->kind == Ast_Kind_Global) {
         emit_expression(mod, &code, assign->right);
 
@@ -2368,6 +2381,8 @@ EMIT_FUNC(do_block, AstDoBlock* doblock) {
 EMIT_FUNC(location_return_offset, AstTyped* expr, u64* offset_return) {
     bh_arr(WasmInstruction) code = *pcode;
 
+    expr = (AstTyped *) strip_aliases((AstNode *) expr);
+
     switch (expr->kind) {
         case Ast_Kind_Param:
         case Ast_Kind_Local: {
@@ -3305,6 +3320,12 @@ static void emit_raw_data(OnyxWasmModule* mod, ptr data, AstTyped* node) {
 static b32 emit_raw_data_(OnyxWasmModule* mod, ptr data, AstTyped* node) {
     b32 retval = 1;
 
+    if (node_is_type((AstNode *) node)) {
+        Type* constructed_type = type_build_from_ast(context.ast_alloc, (AstType *) node);
+        ((i32 *) data)[0] = constructed_type->id;
+        return 1;
+    }
+
     switch (node->kind) {
     case Ast_Kind_Array_Literal: {
         AstArrayLiteral* al = (AstArrayLiteral *) node;
index b7d46bbf7d347bb9ec4aed4baf4a798ec64ad09c..236602ca0e54287cfc40e8e10b5b5296d3cef7ac 100644 (file)
@@ -175,8 +175,10 @@ u64 build_type_table(OnyxWasmModule* module) {
                 u32* param_locations = bh_alloc_array(global_scratch_allocator, u32, bh_arr_length(s->poly_sln));
                 u32* value_locations = bh_alloc_array(global_scratch_allocator, u32, s->mem_count);
                 u32* meta_locations = bh_alloc_array(global_scratch_allocator, u32, s->mem_count);
+                u32* struct_tag_locations = bh_alloc_array(global_scratch_allocator, u32, bh_arr_length(s->meta_tags));
                 memset(value_locations, 0, s->mem_count * sizeof(u32));
                 memset(meta_locations, 0, s->mem_count * sizeof(u32));
+                memset(struct_tag_locations, 0, bh_arr_length(s->meta_tags) * sizeof(u32));
 
                 u32 i = 0;
                 bh_arr_each(StructMember*, pmem, s->memarr) {
@@ -345,6 +347,34 @@ u64 build_type_table(OnyxWasmModule* module) {
                     else                       bh_buffer_write_u32(&table_buffer, sln->value->type->id);
                 }
 
+                i = 0;
+                bh_arr_each(AstTyped *, tag, s->meta_tags) {
+                    AstTyped* value = *tag;                        
+                    assert(value->flags & Ast_Flag_Comptime);
+                    assert(value->type);
+
+                    u32 size = type_size_of(value->type);
+                    bh_buffer_align(&table_buffer, type_alignment_of(value->type));
+                    struct_tag_locations[i] = table_buffer.length;
+
+                    bh_buffer_grow(&table_buffer, table_buffer.length + size);
+                    u8* buffer = table_buffer.data + table_buffer.length;
+
+                    assert(emit_raw_data_(module, buffer, value));
+                    table_buffer.length += size;
+
+                    i += 1;
+                }
+
+                bh_buffer_align(&table_buffer, 8);
+                u32 struct_tag_base = table_buffer.length;
+
+                fori (i, 0, bh_arr_length(s->meta_tags)) {
+                    PATCH;
+                    bh_buffer_write_u64(&table_buffer, struct_tag_locations[i]);
+                    bh_buffer_write_u64(&table_buffer, s->meta_tags[i]->type->id);
+                }
+
                 u32 name_base = 0;
                 u32 name_length = 0;
                 if (s->name) {
@@ -368,6 +398,9 @@ u64 build_type_table(OnyxWasmModule* module) {
                 PATCH;
                 bh_buffer_write_u64(&table_buffer, params_base);
                 bh_buffer_write_u64(&table_buffer, bh_arr_length(s->poly_sln));
+                PATCH;
+                bh_buffer_write_u64(&table_buffer, struct_tag_base);
+                bh_buffer_write_u64(&table_buffer, bh_arr_length(s->meta_tags));
 
                 break;
             }