From: Brendan Hansen Date: Fri, 8 Oct 2021 03:39:24 +0000 (-0500) Subject: polymorphic struct information can be queried in type_info X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=93f9d2281b34889e7c184d7233491050ac0551d6;p=onyx.git polymorphic struct information can be queried in type_info --- diff --git a/core/type_info/helper.onyx b/core/type_info/helper.onyx index 48773cac..2bf52c36 100644 --- a/core/type_info/helper.onyx +++ b/core/type_info/helper.onyx @@ -82,6 +82,12 @@ write_type_name :: (writer: ^io.Writer, t: type_expr) { else do io.write_str(writer, ""); } + 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, ""); + } + 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; diff --git a/core/type_info/type_info.onyx b/core/type_info/type_info.onyx index 558ba45f..3df1cc63 100644 --- a/core/type_info/type_info.onyx +++ b/core/type_info/type_info.onyx @@ -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; diff --git a/include/types.h b/include/types.h index 9e2961b3..d1b9e51a 100644 --- a/include/types.h +++ b/include/types.h @@ -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; \ diff --git a/modules/js_events/js_events.onyx b/modules/js_events/js_events.onyx index 52bd996c..bb69ec41 100644 --- a/modules/js_events/js_events.onyx +++ b/modules/js_events/js_events.onyx @@ -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 { diff --git a/src/checker.c b/src/checker.c index 551dc161..dd01dec5 100644 --- a/src/checker.c +++ b/src/checker.c @@ -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]; diff --git a/src/clone.c b/src/clone.c index ac4a8932..f0e7cdec 100644 --- a/src/clone.c +++ b/src/clone.c @@ -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; diff --git a/src/types.c b/src/types.c index 7b8451de..58e3dc08 100644 --- a/src/types.c +++ b/src/types.c @@ -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; diff --git a/src/wasm_type_table.c b/src/wasm_type_table.c index 236602ca..b72fabab 100644 --- a/src/wasm_type_table.c +++ b/src/wasm_type_table.c @@ -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; + } } }