struct member defaults are now available at runtime
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 6 Aug 2021 14:33:23 +0000 (09:33 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 6 Aug 2021 14:33:23 +0000 (09:33 -0500)
bin/onyx
core/builtin.onyx
core/container/array.onyx
core/type_info/helper.onyx
core/type_info/type_info.onyx
src/onyxtypes.c
src/onyxutils.c
src/onyxwasm.c
src/onyxwasm_type_table.c

index 569f3fa03ceb384e9583567668ba5de7d7d92e46..1799b4fdaab30c473fee7e85559e4705a974bffc 100755 (executable)
Binary files a/bin/onyx and b/bin/onyx differ
index 0787429ba43c9e839548a04e0e484954a0fa30b7..0a33897c07fa7f43d5d285a458583e7b17fd5a48 100644 (file)
@@ -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
index c1d64feb3ed5c63d47af62807e89bb2c18149596..30b7aa0a418b6ebc18a14bb8730bf306668cd3f5 100644 (file)
@@ -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;
index 7801d82d4617bbf6e3605f57888f411e3cddd2c8..f0bc2ad907e67d16d38ee2bd7c4d89bc90d34335 100644 (file)
@@ -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;
+}
index b51afe89cdfe12ab5aa3f51dc875ee27a197aea9..d49dce44609a9e7b29f85609409d60c1eb14fc45 100644 (file)
@@ -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;
index 70098f3f5a855611f975dcebf9df752c4ea0914d..125461ab8df332ca584bd76d29cb6c91dbb0ea56 100644 (file)
@@ -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";
     }
 }
index 2fddfdb531f68ebfd6ea65f171fc12312900573c..be16d9f600a3d99996a6ec7a5d632724cdad431a 100644 (file)
@@ -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;
index 9a6af36422b4e3d571d739bce033e9f76a35a9a1..e2e63bc947c074fd26e2ed234a123e1153231713 100644 (file)
@@ -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) {
index c8bf7238726fc7ad6f35bbc97a51f629ff6e24b8..4daf9d1c530b6f63d1e8125a07d7c736b46a1516 100644 (file)
@@ -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 = {