polymorphic struct information can be queried in type_info
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 8 Oct 2021 03:39:24 +0000 (22:39 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 8 Oct 2021 03:39:24 +0000 (22:39 -0500)
core/type_info/helper.onyx
core/type_info/type_info.onyx
include/types.h
modules/js_events/js_events.onyx
src/checker.c
src/clone.c
src/types.c
src/wasm_type_table.c

index 48773cac8c13118ef359b093d130f6c4cfb451f2..2bf52c3651b1f2326f91ce5e6041d9a738a7a2a1 100644 (file)
@@ -82,6 +82,12 @@ write_type_name :: (writer: ^io.Writer, t: type_expr) {
             else                do io.write_str(writer, "<anonymous struct>");
         }
 
+        case .Polymorphic_Struct {
+            s := cast(^Type_Info_Polymorphic_Struct) info;
+            if s.name.count > 0 do io.write_str(writer, s.name);
+            else                do io.write_str(writer, "<anonymous polymorphic struct>");
+        }
+
         case .Compound {
             comp := cast(^Type_Info_Compound) info;
             io.write_str(writer, "(");
@@ -129,6 +135,13 @@ offset_of :: (T: type_expr, member: str) -> u32 {
     return 0;
 }
 
+struct_constructed_from :: (struct_type: type_expr, base_type: type_expr) -> bool {
+    struct_info := get_type_info(struct_type);
+    if struct_info.kind != .Struct do return false;
+
+    return (cast(^Type_Info_Struct) struct_info).constructed_from == base_type;
+}
+
 #operator == (t1: Type_Info_Function, t2: Type_Info_Function) -> bool {
     if t1.parameter_types.count != t2.parameter_types.count do return false;
     if t1.return_type           != t2.return_type           do return false;
index 558ba45fdc8e7658caa46ed52e71231128d809dd..3df1cc63eaffd6926d5467567ccc435a49b76eb6 100644 (file)
@@ -8,17 +8,18 @@ type_table : [] ^Type_Info;
 Type_Info :: struct {
     // This must match the order of the elements in onyxtypes.h
     Kind :: enum {
-        Invalid           :: 0x00; // Unused
-        Basic             :: 0x01;
-        Pointer           :: 0x02;
-        Function          :: 0x03;
-        Struct            :: 0x04;
-        Compound          :: 0x05;
-        Array             :: 0x06;
-        Slice             :: 0x07;
-        Dynamic_Array     :: 0x08;
-        Variadic_Argument :: 0x09;
-        Enum              :: 0x0a;
+        Invalid            :: 0x00; // Unused
+        Basic              :: 0x01;
+        Pointer            :: 0x02;
+        Function           :: 0x03;
+        Struct             :: 0x04;
+        Polymorphic_Struct :: 0x05;
+        Compound           :: 0x06;
+        Array              :: 0x07;
+        Slice              :: 0x08;
+        Dynamic_Array      :: 0x09;
+        Variadic_Argument  :: 0x0a;
+        Enum               :: 0x0b;
     }
 
     kind := Kind.Invalid;
@@ -145,12 +146,20 @@ Type_Info_Struct :: struct {
         tags: [] any;
     }
 
+    constructed_from: type_expr;
     name: str;
     members: [] Member;
     parameters: [] any;
     tags: [] any;
 }
 
+Type_Info_Polymorphic_Struct :: struct {
+    use base : Type_Info;
+
+    name: str;
+    tags: [] any;
+}
+
 Type_Info_Compound :: struct {
     use base : Type_Info;
 
index 9e2961b3b33eadc30c94e818bf54dcb5e4e425dc..d1b9e51a0f26882c668fc6e72fc69d0f7d63ab81 100644 (file)
@@ -109,6 +109,10 @@ struct TypeWithOffset {
         struct AstType *constructed_from;                         \
         bh_arr(struct AstTyped *) meta_tags;                      \
     })                                                            \
+    TYPE_KIND(PolyStruct, struct {                                \
+        char* name;                                               \
+        bh_arr(struct AstTyped *) meta_tags;                      \
+    })                                                            \
     TYPE_KIND(Compound, struct {                                  \
         u32 count;                                                \
         u32 size;                                                 \
index 52bd996ca51678bef95cd66a934e992208f65174..bb69ec41a165fabecbef76a9f4b7e6a9d6ed0ca8 100644 (file)
@@ -49,7 +49,7 @@ KeyboardEvent :: struct {
         SHIFT :: 0x08;
     }
 
-    get_name :: (use e: ^KeyboardEvent) -> str do return str.{ ~~keyname, ~~keyname_count };
+    get_name :: (use e: ^KeyboardEvent) => str.{ ~~keyname, ~~keyname_count };
 }
 
 MouseEvent :: struct {
index 551dc161480d72f305957f2333d26cffabdad7c2..dd01dec5caa12f5fe20b79f7c765ad877c16e5ca 100644 (file)
@@ -1503,6 +1503,8 @@ CheckStatus check_expression(AstTyped** pexpr) {
             if (type_build_from_ast(context.ast_alloc, (AstType*) expr) == NULL) {
                 YIELD(expr->token->pos, "Trying to construct type.");
             }
+        } else {
+            type_build_from_ast(context.ast_alloc, (AstType*) expr);
         }
 
         expr->type = &basic_types[Basic_Kind_Type_Index];
index ac4a8932b3c0ba7ba82e6929769026062af04587..f0e7cdec1107ed2829421c645ea981d362ac1277 100644 (file)
@@ -315,14 +315,31 @@ AstNode* ast_clone(bh_allocator a, void* n) {
                 bh_arr_push(ds->members, (AstStructMember *) ast_clone(a, *smem));
             }
 
+            ds->meta_tags = NULL;
+            bh_arr_new(global_heap_allocator, ds->meta_tags, bh_arr_length(ss->meta_tags));
+            bh_arr_each(AstTyped *, tag, ss->meta_tags) {
+                bh_arr_push(ds->meta_tags, (AstTyped *) ast_clone(a, *tag));
+            }
+
             ds->stcache = NULL;
             break;
         }
 
-        case Ast_Kind_Struct_Member:
+        case Ast_Kind_Struct_Member: {
             C(AstStructMember, type_node);
             C(AstStructMember, initial_value);
+
+            AstStructMember *ds = (AstStructMember *) nn;
+            AstStructMember *ss = (AstStructMember *) node;
+
+            ds->meta_tags = NULL;
+            bh_arr_new(global_heap_allocator, ds->meta_tags, bh_arr_length(ss->meta_tags));
+            bh_arr_each(AstTyped *, tag, ss->meta_tags) {
+                bh_arr_push(ds->meta_tags, (AstTyped *) ast_clone(a, *tag));
+            }
+
             break;
+        }
 
         case Ast_Kind_Poly_Call_Type: {
             AstPolyCallType* pcd = (AstPolyCallType *) nn;
index 7b8451de37fb6b45c6b1001296425a9e51ab6d4c..58e3dc08aae1720207f62febd7a3ba6bd5833c69 100644 (file)
@@ -498,12 +498,21 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) {
         case Ast_Kind_Type_Raw_Alias:
             return ((AstTypeRawAlias *) type_node)->to;
 
-        case Ast_Kind_Poly_Struct_Type:
+        case Ast_Kind_Poly_Struct_Type: {
             //onyx_report_error(type_node->token->pos,
             //    "This structure is polymorphic, which means you need to provide arguments to it to make it a concrete structure. "
             //    "This error message is probably in the wrong place, so look through your code for uses of this struct.");
+
+            if (type_node->type_id != 0) return NULL;
+
+            Type* p_type = type_create(Type_Kind_PolyStruct, alloc, 0);
+            p_type->ast_type = type_node;
+            p_type->PolyStruct.name = ((AstPolyStructType *) type_node)->name;
+            p_type->PolyStruct.meta_tags = ((AstPolyStructType *) type_node)->base_struct->meta_tags;
+
+            type_register(p_type);
             return NULL;
-            break;
+        }
 
         case Ast_Kind_Poly_Call_Type: {
             AstPolyCallType* pc_type = (AstPolyCallType *) type_node;
index 236602ca0e54287cfc40e8e10b5b5296d3cef7ac..b72fabab910421136e782421b1fd29303ae13939 100644 (file)
@@ -388,7 +388,13 @@ u64 build_type_table(OnyxWasmModule* module) {
                 bh_buffer_write_u32(&table_buffer, type->kind);
                 bh_buffer_write_u32(&table_buffer, type_size_of(type));
                 bh_buffer_write_u32(&table_buffer, type_alignment_of(type));
-                bh_buffer_write_u32(&table_buffer, 0);
+
+                if (type->Struct.constructed_from != NULL) {
+                    bh_buffer_write_u32(&table_buffer, type->Struct.constructed_from->type_id);
+                } else {
+                    bh_buffer_write_u32(&table_buffer, 0);
+                }
+
                 PATCH;
                 bh_buffer_write_u64(&table_buffer, name_base);
                 bh_buffer_write_u64(&table_buffer, name_length);
@@ -404,6 +410,59 @@ u64 build_type_table(OnyxWasmModule* module) {
 
                 break;
             }
+
+            case Type_Kind_PolyStruct: {
+                u32* tag_locations = bh_alloc_array(global_scratch_allocator, u32, bh_arr_length(type->PolyStruct.meta_tags));
+                memset(tag_locations, 0, sizeof(u32) * bh_arr_length(type->PolyStruct.meta_tags));
+
+                u32 name_base = table_buffer.length;
+                u32 name_length = strlen(type->PolyStruct.name);
+                bh_buffer_append(&table_buffer, type->PolyStruct.name, name_length);
+
+                i32 i = 0;
+                bh_arr_each(AstTyped *, tag, type->PolyStruct.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));
+                    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 tags_base = table_buffer.length;
+                u32 tags_count = bh_arr_length(type->PolyStruct.meta_tags);
+
+                fori (i, 0, tags_count) {
+                    PATCH;
+                    bh_buffer_write_u64(&table_buffer, tag_locations[i]);
+                    bh_buffer_write_u64(&table_buffer, type->PolyStruct.meta_tags[i]->type->id);
+                }
+
+                bh_buffer_align(&table_buffer, 8);
+                table_info[type_idx] = table_buffer.length;
+                bh_buffer_write_u32(&table_buffer, type->kind);
+                bh_buffer_write_u32(&table_buffer, 0);
+                bh_buffer_write_u32(&table_buffer, 0);
+                bh_buffer_write_u32(&table_buffer, 0);
+                PATCH;
+                bh_buffer_write_u64(&table_buffer, name_base);
+                bh_buffer_write_u64(&table_buffer, name_length);
+                PATCH;
+                bh_buffer_write_u64(&table_buffer, tags_base);
+                bh_buffer_write_u64(&table_buffer, tags_count);
+
+                break;
+            }
         }
     }