}
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;
+ }
+}
// 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) {
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;
bh_buffer_align(&table_buffer, 8);
+ // Polymorphic solutions
i = 0;
bh_arr_each(AstPolySolution, sln, s->poly_sln) {
bh_buffer_align(&table_buffer, 8);
bh_buffer_align(&table_buffer, 8);
+ // Member default values
i = 0;
bh_arr_each(StructMember*, pmem, s->memarr) {
StructMember* mem = *pmem;
}
}
+ // Member tags
i = 0;
bh_arr_each(StructMember*, pmem, s->memarr) {
StructMember* mem = *pmem;
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;
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++]);
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;
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;
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) {
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;
}