struct method in type data; bug fixes
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Sat, 26 Feb 2022 21:55:13 +0000 (15:55 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Sat, 26 Feb 2022 21:55:13 +0000 (15:55 -0600)
core/string.onyx
core/type_info/helper.onyx
core/type_info/type_info.onyx
src/checker.c
src/wasm_type_table.h
tests/struct_use_pointer_member

index 80ba0b9090b8ea2aada9bead3df38ccd06893d3b..9da43aaae9384e7c87a52acbf3fe8c7c823b5c24 100644 (file)
@@ -192,7 +192,7 @@ strip_whitespace :: #match {
 
 strip_leading_whitespace :: #match {
     (s: ^str) {
-        while true do switch s.data[0] {
+        while s.count > 0 do switch s.data[0] {
             case #char " ", #char "\t", #char "\n", #char "\r" {
                 s.data += 1;
                 s.count -= 1;
index 70328ddeb5ad18d0da98eb31a2847298d9a88a01..358aeeb73094db9c86e2fadbc9705ed19963b859 100644 (file)
@@ -223,4 +223,33 @@ get_struct_by_name :: (name: str) -> type_expr {
     }
 
     return void;
-}
\ No newline at end of file
+}
+
+get_struct_method :: (type: type_expr, method_name: str) -> ^any {
+    info := cast(^Type_Info_Struct) get_type_info(type);
+    if info.kind != .Struct do return null;
+
+    for ^method: info.methods {
+        if method.name == method_name {
+            return ^method.func;
+        }
+    }
+
+    return null;
+}
+
+populate_struct_vtable :: (table: ^$Table_Type, struct_type: type_expr, safe := true) {
+    v_info := cast(^Type_Info_Struct) get_type_info(Table_Type);
+    if v_info.kind != .Struct do return;
+
+    for^ member: v_info.members {
+        if get_type_info(member.type).kind != .Function do continue;
+
+        struct_method := get_struct_method(struct_type, member.name);
+        if struct_method == null do continue;
+        if safe && struct_method.type != member.type do continue;
+
+        dest := cast(^()->void) (cast(^u8) table + member.offset);
+        *dest = *cast(^()->void) struct_method.data;
+    }
+}
index 2a256c5f127b1a0a1f28e1948c289f8b04272690..254753c13e537df1a87aeb07f9144ba66e29560e 100644 (file)
@@ -152,6 +152,12 @@ Type_Info_Struct :: struct {
     members: [] Member;
     parameters: [] any;
     tags: [] any;
+
+    Method :: struct {
+        name: str;
+        func: any;
+    }
+    methods: [] Method;
 }
 
 Type_Info_Polymorphic_Struct :: struct {
index eea13f55f65b1c8436041979674eeb170c0999a5..ca9afa830f6c7fb0cc45d123f0a621aedaa26b0b 100644 (file)
@@ -2133,6 +2133,15 @@ CheckStatus check_struct(AstStructType* s_node) {
         CHECK(constraint_context, &s_node->constraints, s_node->scope, pos);
     }
 
+    if (s_node->scope) {
+        fori (i, 0, shlen(s_node->scope->symbols)) {
+            AstNode* node = s_node->scope->symbols[i].value;
+            if (node->kind == Ast_Kind_Function) {
+                node->flags |= Ast_Flag_Function_Used;
+            }
+        }
+    }
+
     bh_arr_each(AstStructMember *, smem, s_node->members) {
         if ((*smem)->type_node != NULL) {
             CHECK(type, &(*smem)->type_node);
index b32e85516f1b8c75c6eaf53766120c342d7efeea..9fc5aa036805a78380f17a3f32853ea7b69bac0e 100644 (file)
@@ -1,6 +1,12 @@
 // This file is directly included in src/onxywasm.c
 // It is here purely to decrease the amount of clutter in the main file.
 
+typedef struct StructMethodData {
+    u32 name_loc;
+    u32 name_len;
+    u32 type;
+    u32 data_loc;
+} StructMethodData;
 
 u64 build_type_table(OnyxWasmModule* module) {
 
@@ -186,6 +192,7 @@ u64 build_type_table(OnyxWasmModule* module) {
                 memset(meta_locations, 0, s->mem_count * sizeof(u32));
                 memset(struct_tag_locations, 0, bh_arr_length(s->meta_tags) * sizeof(u32));
 
+                // Member names
                 u32 i = 0;
                 bh_arr_each(StructMember*, pmem, s->memarr) {
                     StructMember* mem = *pmem;
@@ -196,6 +203,7 @@ u64 build_type_table(OnyxWasmModule* module) {
 
                 bh_buffer_align(&table_buffer, 8);
 
+                // Polymorphic solutions
                 i = 0;
                 bh_arr_each(AstPolySolution, sln, s->poly_sln) {
                     bh_buffer_align(&table_buffer, 8);
@@ -229,6 +237,7 @@ u64 build_type_table(OnyxWasmModule* module) {
 
                 bh_buffer_align(&table_buffer, 8);
 
+                // Member default values
                 i = 0;
                 bh_arr_each(StructMember*, pmem, s->memarr) {
                     StructMember* mem = *pmem;
@@ -265,6 +274,7 @@ u64 build_type_table(OnyxWasmModule* module) {
                     }
                 }
 
+                // Member tags
                 i = 0;
                 bh_arr_each(StructMember*, pmem, s->memarr) {
                     StructMember* mem = *pmem;
@@ -313,6 +323,7 @@ u64 build_type_table(OnyxWasmModule* module) {
                 bh_buffer_align(&table_buffer, 8);
                 u32 members_base = table_buffer.length;
 
+                // Member array
                 i = 0;
                 bh_arr_each(StructMember*, pmem, s->memarr) {
                     StructMember* mem = *pmem;
@@ -334,6 +345,7 @@ u64 build_type_table(OnyxWasmModule* module) {
                 bh_buffer_align(&table_buffer, 8);
                 u32 params_base = table_buffer.length;
 
+                // Polymorphic solution any array
                 i = 0;
                 bh_arr_each(AstPolySolution, sln, s->poly_sln) {
                     WRITE_PTR(param_locations[i++]);
@@ -342,6 +354,7 @@ u64 build_type_table(OnyxWasmModule* module) {
                     else                       bh_buffer_write_u32(&table_buffer, sln->value->type->id);
                 }
 
+                // Struct tag array
                 i = 0;
                 bh_arr_each(AstTyped *, tag, s->meta_tags) {
                     AstTyped* value = *tag;                        
@@ -361,6 +374,54 @@ u64 build_type_table(OnyxWasmModule* module) {
                     i += 1;
                 }
 
+                // Struct methods
+                bh_arr(StructMethodData) method_data=NULL;
+                AstType *ast_type = type->ast_type;
+                if (ast_type->kind == Ast_Kind_Struct_Type) {
+                    AstStructType *struct_type  = (AstStructType *) ast_type;
+                    Scope*         struct_scope = struct_type->scope;
+
+                    if (struct_scope == NULL) goto no_methods;
+
+                    fori (i, 0, shlen(struct_scope->symbols)) {
+                        AstFunction* node = (AstFunction *) struct_scope->symbols[i].value;
+                        if (node->kind != Ast_Kind_Function) continue;
+                        assert(node->entity);
+                        assert(node->entity->function == node);
+
+                        // Name
+                        char *name = struct_scope->symbols[i].key;
+                        u32 name_loc = table_buffer.length;
+                        u32 name_len = strlen(name);
+                        bh_buffer_append(&table_buffer, name, name_len);
+
+                        // any data member
+                        bh_buffer_align(&table_buffer, 4);
+                        u32 data_loc = table_buffer.length;
+                        u32 func_idx = get_element_idx(module, node);
+                        bh_buffer_write_u32(&table_buffer, func_idx);
+                        
+                        bh_arr_push(method_data, ((StructMethodData) {
+                            .name_loc = name_loc,
+                            .name_len = name_len,
+                            .type     = node->type->id,
+                            .data_loc = data_loc,
+                        }));
+                    }
+                }
+
+                no_methods:
+
+                bh_buffer_align(&table_buffer, 4);
+                u32 method_data_base = table_buffer.length;
+
+                i = 0;
+                bh_arr_each(StructMethodData, method, method_data) {
+                    WRITE_SLICE(method->name_loc, method->name_len);
+                    WRITE_PTR(method->data_loc); 
+                    bh_buffer_write_u32(&table_buffer, method->type);
+                }
+
                 bh_buffer_align(&table_buffer, 8);
                 u32 struct_tag_base = table_buffer.length;
 
@@ -368,6 +429,7 @@ u64 build_type_table(OnyxWasmModule* module) {
                     WRITE_SLICE(struct_tag_locations[i], s->meta_tags[i]->type->id);
                 }
 
+                // Struct name
                 u32 name_base = 0;
                 u32 name_length = 0;
                 if (s->name) {
@@ -392,7 +454,9 @@ u64 build_type_table(OnyxWasmModule* module) {
                 WRITE_SLICE(members_base, s->mem_count);
                 WRITE_SLICE(params_base, bh_arr_length(s->poly_sln));
                 WRITE_SLICE(struct_tag_base, bh_arr_length(s->meta_tags));
+                WRITE_SLICE(method_data_base, bh_arr_length(method_data));
 
+                bh_arr_free(method_data);
                 break;
             }
 
index 96429d6f5981c6969942406357a450a6ae016ad8..a8fbd54615d01de00fd7857d373a150f8b8faa65 100644 (file)
@@ -1,2 +1,2 @@
 Hello, I am Billy!
-Go away!! func[6]
+Go away!! func[9]