From: Brendan Hansen Date: Fri, 6 Aug 2021 14:33:23 +0000 (-0500) Subject: struct member defaults are now available at runtime X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=3f2c108105a7276a7d40e0b315290225cddabae8;p=onyx.git struct member defaults are now available at runtime --- diff --git a/bin/onyx b/bin/onyx index 569f3fa0..1799b4fd 100755 Binary files a/bin/onyx and b/bin/onyx differ diff --git a/core/builtin.onyx b/core/builtin.onyx index 0787429b..0a33897c 100644 --- a/core/builtin.onyx +++ b/core/builtin.onyx @@ -189,5 +189,5 @@ any :: struct { } -// Represents a code block. Not constructable outside of using a '#{}' block. +// Represents a code block. Not constructable outside of using a '#code' directive. Code :: struct {} \ No newline at end of file diff --git a/core/container/array.onyx b/core/container/array.onyx index c1d64feb..30b7aa0a 100644 --- a/core/container/array.onyx +++ b/core/container/array.onyx @@ -345,6 +345,20 @@ find_ptr :: (arr: ^[..] $T, value: T) -> ^T { return null; } +first :: #match { + (arr: ^[..] $T, predicate: (T) -> bool) -> ^T { + first((#type [] T).{ arr.data, arr.count }, predicate); + }, + + (arr: [] $T, predicate: (T) -> bool) -> ^T { + for ^it: arr { + if predicate(*it) do return it; + } + + return null; + }, +} + count_where :: #match { (arr: ^[..] $T, predicate: (T) -> bool) -> u32 { count: u32 = 0; diff --git a/core/type_info/helper.onyx b/core/type_info/helper.onyx index 7801d82d..f0bc2ad9 100644 --- a/core/type_info/helper.onyx +++ b/core/type_info/helper.onyx @@ -127,4 +127,17 @@ offset_of :: (T: type_expr, member: str) -> u32 { // Should this return something else if the member was not found? return 0; -} \ No newline at end of file +} + +#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; + if t1.is_variadic != t2.is_variadic do return false; + + while i := 0; i < t1.parameter_types.count { + @Robustness // This does not handle nested procedure types + if t1.parameter_types[i] != t2.parameter_types[i] do return false; + } + + return true; +} diff --git a/core/type_info/type_info.onyx b/core/type_info/type_info.onyx index b51afe89..d49dce44 100644 --- a/core/type_info/type_info.onyx +++ b/core/type_info/type_info.onyx @@ -136,7 +136,11 @@ Type_Info_Struct :: struct { type: type_expr; used: bool; - has_default: bool; + default: rawptr; // Pointer to the initial value of the same type as the member. + // null if no default value is given, or if it is not compile time known. + + // As another thought. This could become a thunk that get the default value + // at runtime or returns the value. } name: str; diff --git a/src/onyxtypes.c b/src/onyxtypes.c index 70098f3f..125461ab 100644 --- a/src/onyxtypes.c +++ b/src/onyxtypes.c @@ -43,6 +43,7 @@ static bh_imap type_pointer_map; static bh_imap type_slice_map; static bh_imap type_dynarr_map; static bh_imap type_vararg_map; +static bh_table(u64) type_func_map; static Type* type_create(TypeKind kind, bh_allocator a, u32 extra_type_pointer_count) { Type* type = bh_alloc(a, sizeof(Type) + sizeof(Type *) * extra_type_pointer_count); @@ -65,6 +66,7 @@ void types_init() { bh_imap_init(&type_slice_map, global_heap_allocator, 255); bh_imap_init(&type_dynarr_map, global_heap_allocator, 255); bh_imap_init(&type_vararg_map, global_heap_allocator, 255); + bh_table_init(global_heap_allocator, type_func_map, 64); fori (i, 0, Basic_Kind_Count) type_register(&basic_types[i]); } @@ -262,7 +264,18 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) { if (func_type->Function.params[i] == NULL) return NULL; } + char* name = (char *) type_get_unique_name(func_type); + if (bh_table_has(u64, type_func_map, name)) { + u64 id = bh_table_get(u64, type_func_map, name); + Type* existing_type = (Type *) bh_imap_get(&type_map, id); + + // LEAK LEAK LEAK the func_type that is created + return existing_type; + } + type_register(func_type); + bh_table_put(u64, type_func_map, name, func_type->id); + return func_type; } @@ -594,7 +607,19 @@ Type* type_build_function_type(bh_allocator alloc, AstFunction* func) { } } + // CopyPaste from above in type_build_from_ast + char* name = (char *) type_get_unique_name(func_type); + if (bh_table_has(u64, type_func_map, name)) { + u64 id = bh_table_get(u64, type_func_map, name); + Type* existing_type = (Type *) bh_imap_get(&type_map, id); + + // LEAK LEAK LEAK the func_type that is created + return existing_type; + } + type_register(func_type); + bh_table_put(u64, type_func_map, name, func_type->id); + return func_type; } @@ -770,22 +795,42 @@ const char* type_get_unique_name(Type* type) { case Type_Kind_DynArray: return bh_aprintf(global_scratch_allocator, "[..] %s", type_get_unique_name(type->DynArray.ptr_to_data->Pointer.elem)); case Type_Kind_Function: { - char buf[512]; - fori (i, 0, 512) buf[i] = 0; + char buf[1024]; + memset(buf, 0, 1024); - strncat(buf, "(", 511); + strncat(buf, "(", 1023); fori (i, 0, type->Function.param_count) { - strncat(buf, type_get_unique_name(type->Function.params[i]), 511); + strncat(buf, type_get_unique_name(type->Function.params[i]), 1023); + + if (i >= type->Function.needed_param_count) + strncat(buf, "?", 1023); + if (i != type->Function.param_count - 1) - strncat(buf, ", ", 511); + strncat(buf, ", ", 1023); } - strncat(buf, ") -> ", 511); - strncat(buf, type_get_unique_name(type->Function.return_type), 511); + strncat(buf, ") -> ", 1023); + strncat(buf, type_get_unique_name(type->Function.return_type), 1023); + + return bh_aprintf(global_scratch_allocator, "%s", buf); + } + + case Type_Kind_Compound: { + char buf[1024]; + memset(buf, 0, 1024); + + strncat(buf, "(", 1023); + fori (i, 0, type->Compound.count) { + strncat(buf, type_get_unique_name(type->Compound.types[i]), 1023); + if (i != type->Compound.count - 1) + strncat(buf, ", ", 1023); + } + strncat(buf, ")", 1023); return bh_aprintf(global_scratch_allocator, "%s", buf); } + default: return "unknown"; } } diff --git a/src/onyxutils.c b/src/onyxutils.c index 2fddfdb5..be16d9f6 100644 --- a/src/onyxutils.c +++ b/src/onyxutils.c @@ -1085,6 +1085,7 @@ AstTyped* find_matching_overload_by_arguments(bh_arr(OverloadOption) overloads, if (overload == NULL) continue; if (overload->kind != Ast_Kind_Function) continue; if (overload->type == NULL) continue; + assert(overload->type->kind == Type_Kind_Function); // NOTE: If the arguments cannot be placed successfully in the parameters list if (!fill_in_arguments(&args, (AstNode *) overload, NULL)) continue; diff --git a/src/onyxwasm.c b/src/onyxwasm.c index 9a6af364..e2e63bc9 100644 --- a/src/onyxwasm.c +++ b/src/onyxwasm.c @@ -266,6 +266,7 @@ EMIT_FUNC(enter_structured_block, StructuredBlockType sbt); EMIT_FUNC_NO_ARGS(leave_structured_block); static void emit_raw_data(OnyxWasmModule* mod, ptr data, AstTyped* node); +static b32 emit_raw_data_(OnyxWasmModule* mod, ptr data, AstTyped* node); #include "onyxwasm_intrinsics.c" #include "onyxwasm_type_table.c" @@ -3181,6 +3182,16 @@ static void emit_string_literal(OnyxWasmModule* mod, AstStrLit* strlit) { } static void emit_raw_data(OnyxWasmModule* mod, ptr data, AstTyped* node) { + if (!emit_raw_data_(mod, data, node)) { + onyx_report_error(node->token->pos, + "Cannot generate constant data for '%s'.", + onyx_ast_node_kind_string(node->kind)); + } +} + +static b32 emit_raw_data_(OnyxWasmModule* mod, ptr data, AstTyped* node) { + b32 retval = 1; + switch (node->kind) { case Ast_Kind_Array_Literal: { AstArrayLiteral* al = (AstArrayLiteral *) node; @@ -3189,7 +3200,7 @@ static void emit_raw_data(OnyxWasmModule* mod, ptr data, AstTyped* node) { i32 elem_size = type_size_of(al->type->Array.elem); bh_arr_each(AstTyped *, expr, al->values) { - emit_raw_data(mod, bh_pointer_add(data, i * elem_size), *expr); + retval &= emit_raw_data_(mod, bh_pointer_add(data, i * elem_size), *expr); i++; } @@ -3200,11 +3211,15 @@ static void emit_raw_data(OnyxWasmModule* mod, ptr data, AstTyped* node) { AstStructLiteral* sl = (AstStructLiteral *) node; Type* sl_type = sl->type; - assert(sl_type->kind == Type_Kind_Struct); + // ROBUSTNESS: Handle cases for slices and dynamic arrays + if (sl_type->kind != Type_Kind_Struct) { + retval = 0; + break; + } i32 i = 0; bh_arr_each(AstTyped *, expr, sl->args.values) { - emit_raw_data(mod, bh_pointer_add(data, sl_type->Struct.memarr[i]->offset), *expr); + retval &= emit_raw_data_(mod, bh_pointer_add(data, sl_type->Struct.memarr[i]->offset), *expr); i++; } @@ -3225,7 +3240,7 @@ static void emit_raw_data(OnyxWasmModule* mod, ptr data, AstTyped* node) { case Ast_Kind_Enum_Value: { AstEnumValue* ev = (AstEnumValue *) node; - emit_raw_data(mod, data, (AstTyped *) ev->value); + retval &= emit_raw_data_(mod, data, (AstTyped *) ev->value); break; } @@ -3252,41 +3267,42 @@ static void emit_raw_data(OnyxWasmModule* mod, ptr data, AstTyped* node) { case Basic_Kind_I8: case Basic_Kind_U8: *((i8 *) data) = (i8) ((AstNumLit *) node)->value.i; - return; + return retval; case Basic_Kind_I16: case Basic_Kind_U16: *((i16 *) data) = (i16) ((AstNumLit *) node)->value.i; - return; + return retval; case Basic_Kind_I32: case Basic_Kind_U32: *((i32 *) data) = ((AstNumLit *) node)->value.i; - return; + return retval; case Basic_Kind_I64: case Basic_Kind_U64: case Basic_Kind_Rawptr: *((i64 *) data) = ((AstNumLit *) node)->value.l; - return; + return retval; case Basic_Kind_F32: *((f32 *) data) = ((AstNumLit *) node)->value.f; - return; + return retval; case Basic_Kind_F64: *((f64 *) data) = ((AstNumLit *) node)->value.d; - return; + return retval; default: break; } //fallthrough } - default: onyx_report_error(node->token->pos, - "Cannot generate constant data for '%s'.", - onyx_ast_node_kind_string(node->kind)); + + default: retval = 0; } + + return retval; } static void emit_memory_reservation(OnyxWasmModule* mod, AstMemRes* memres) { diff --git a/src/onyxwasm_type_table.c b/src/onyxwasm_type_table.c index c8bf7238..4daf9d1c 100644 --- a/src/onyxwasm_type_table.c +++ b/src/onyxwasm_type_table.c @@ -12,10 +12,14 @@ u64 build_type_table(OnyxWasmModule* module) { // This is the data behind the "type_table" slice in type_info.onyx u32 type_count = bh_arr_length(type_map.entries) + 1; u64* table_info = bh_alloc_array(global_heap_allocator, u64, type_count); // HACK + memset(table_info, 0, type_count * sizeof(u64)); bh_buffer table_buffer; bh_buffer_init(&table_buffer, global_heap_allocator, 4096); + // Write a "NULL" at the beginning so nothing will have to point to the first byte of the buffer. + bh_buffer_write_u64(&table_buffer, 0); + bh_arr_each(bh__imap_entry, type_entry, type_map.entries) { u64 type_idx = type_entry->key; Type* type = (Type *) type_entry->value; @@ -169,6 +173,8 @@ u64 build_type_table(OnyxWasmModule* module) { TypeStruct* s = &type->Struct; u32* name_locations = bh_alloc_array(global_scratch_allocator, u32, s->mem_count); 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); + memset(value_locations, 0, s->mem_count * sizeof(u32)); u32 i = 0; bh_arr_each(StructMember*, pmem, s->memarr) { @@ -211,6 +217,44 @@ u64 build_type_table(OnyxWasmModule* module) { } } + bh_buffer_align(&table_buffer, 8); + + i = 0; + bh_arr_each(StructMember*, pmem, s->memarr) { + StructMember* mem = *pmem; + + if (mem->initial_value == NULL || *mem->initial_value == NULL) { + i++; + continue; + } + + AstTyped* value = *mem->initial_value; + assert(value->type); + + if ((value->flags & Ast_Flag_Comptime) == 0) { + // onyx_report_warning(value->token->pos, "Warning: skipping generating default value for '%s' in '%s' because it is not compile-time known.\n", mem->name, s->name); + i++; + continue; + } + + u32 size = type_size_of(value->type); + bh_buffer_align(&table_buffer, type_alignment_of(value->type)); + + bh_buffer_grow(&table_buffer, table_buffer.length + size); + u8* buffer = table_buffer.data + table_buffer.length; + + if (!emit_raw_data_(module, buffer, value)) { + // Failed to generate raw data + // onyx_report_warning(value->token->pos, "Warning: failed to generate default value for '%s' in '%s'.\n", mem->name, s->name); + value_locations[i++] = 0; + + } else { + // Success + value_locations[i++] = table_buffer.length; + table_buffer.length += size; + } + } + bh_buffer_align(&table_buffer, 8); u32 members_base = table_buffer.length; @@ -218,7 +262,8 @@ u64 build_type_table(OnyxWasmModule* module) { bh_arr_each(StructMember*, pmem, s->memarr) { StructMember* mem = *pmem; - u32 name_loc = name_locations[i++]; + u32 name_loc = name_locations[i]; + u32 value_loc = value_locations[i++]; bh_buffer_align(&table_buffer, 8); PATCH; @@ -227,7 +272,10 @@ u64 build_type_table(OnyxWasmModule* module) { bh_buffer_write_u32(&table_buffer, mem->offset); bh_buffer_write_u32(&table_buffer, mem->type->id); bh_buffer_write_byte(&table_buffer, mem->used ? 1 : 0); - bh_buffer_write_byte(&table_buffer, mem->initial_value != NULL ? 1 : 0); + + bh_buffer_align(&table_buffer, 8); + PATCH; + bh_buffer_write_u64(&table_buffer, value_loc); } bh_buffer_align(&table_buffer, 8); @@ -291,7 +339,10 @@ u64 build_type_table(OnyxWasmModule* module) { } bh_arr_each(u32, patch_loc, base_patch_locations) { - *(u64 *) (bh_pointer_add(table_buffer.data, *patch_loc)) += offset; + u64* loc = bh_pointer_add(table_buffer.data, *patch_loc); + if (*loc == 0) continue; + + *loc += offset; } WasmDatum type_info_data = {