From: Brendan Hansen Date: Wed, 22 Jul 2020 15:15:13 +0000 (-0500) Subject: Added 'splatting' of struct members to call arguments X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=58f0dac22781486db3a6f411f145746be39ad2d8;p=onyx.git Added 'splatting' of struct members to call arguments --- diff --git a/include/onyxastnodes.h b/include/onyxastnodes.h index 7c80e385..e13af87d 100644 --- a/include/onyxastnodes.h +++ b/include/onyxastnodes.h @@ -331,11 +331,11 @@ struct AstOverloadedFunction { // processed later down the pipeline. typedef enum EntityType { Entity_Type_Unknown, + Entity_Type_String_Literal, + Entity_Type_Struct, Entity_Type_Function_Header, Entity_Type_Global_Header, Entity_Type_Expression, - Entity_Type_String_Literal, - Entity_Type_Struct, Entity_Type_Global, Entity_Type_Overloaded_Function, Entity_Type_Function, diff --git a/include/onyxtypes.h b/include/onyxtypes.h index cb21fb14..d90faefb 100644 --- a/include/onyxtypes.h +++ b/include/onyxtypes.h @@ -54,8 +54,18 @@ typedef struct StructMember { #define TYPE_KINDS \ TYPE_KIND(Basic, TypeBasic) \ TYPE_KIND(Pointer, struct { TypeBasic base; Type *elem; }) \ - TYPE_KIND(Function, struct { Type *return_type; u64 param_count; Type* params[]; }) \ - TYPE_KIND(Struct, struct { char* name; u32 size; u32 mem_count; bh_table(StructMember) members; }) \ + TYPE_KIND(Function, struct { \ + Type *return_type; \ + u64 param_count; \ + Type* params[]; \ + }) \ + TYPE_KIND(Struct, struct { \ + char* name; \ + u32 size; \ + u32 mem_count; \ + bh_table(StructMember) members; \ + bh_arr(StructMember *) memarr; \ + }) \ TYPE_KIND(Array, struct { u32 size; u32 count; Type *elem; }) typedef enum TypeKind { diff --git a/onyx b/onyx index 7e203020..8e1d6afe 100755 Binary files a/onyx and b/onyx differ diff --git a/progs/structs.onyx b/progs/structs.onyx index 1b20acc9..f07ef921 100644 --- a/progs/structs.onyx +++ b/progs/structs.onyx @@ -95,7 +95,7 @@ multi_arr :: proc #export "main2" { print(arr2[3][2]); // arr2[3][2] = 5; // (arr1[3] + 2 * 4) } - + Vec2 :: struct { x : i32; y : i32; @@ -133,6 +133,8 @@ proc #export "main" { v3.z = 1; print(v3.magnitude()); + vec2_splat(*v2, *(v3 as ^Vec2)); + print((1).minus(2)); } @@ -147,6 +149,14 @@ vec2_set :: proc (v: ^Vec2) { v.y = 5678; } +vec2_splat :: proc (vx: i32, vy: i32, other: i32, otherother: i32) { + print(vx); + print(vy); + + print(other); + print(otherother); +} + soa_test :: proc #export "main9" { // print(sizeof SOA); // 240 diff --git a/src/onyxchecker.c b/src/onyxchecker.c index 8ac0d5eb..34a75f2f 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -24,6 +24,7 @@ CHECK(global, AstGlobal* global); CHECK(function, AstFunction* func); CHECK(overloaded_function, AstOverloadedFunction* func); CHECK(struct, AstStructType* s_node); +CHECK(function_header, AstFunction* func); static inline void fill_in_type(AstTyped* node) { if (node->type == NULL) @@ -163,10 +164,40 @@ CHECK(call, AstCall* call) { return 1; } - // NOTE: Check arguments + // NOTE: Check arguments and splat structs + AstNode** prev_param = (AstNode **) &call->arguments; AstArgument* actual_param = call->arguments; while (actual_param != NULL) { if (check_expression((AstTyped *) actual_param)) return 1; + + // NOTE: Splat structures into multiple arguments + if (actual_param->type->kind == Type_Kind_Struct) { + bh_arr_each(StructMember *, smem, actual_param->type->Struct.memarr) { + AstFieldAccess* field = onyx_ast_node_new(semstate.node_allocator, sizeof(AstFieldAccess), Ast_Kind_Field_Access); + field->expr = actual_param->value; + + // HACK: Since dereferences are not used for struct types, we need a + // special case here. + if (field->expr->kind == Ast_Kind_Dereference) { + field->expr = ((AstDereference *) field->expr)->expr; + } + + field->offset = (*smem)->offset; + field->type = (*smem)->type; + + AstArgument* arg = onyx_ast_node_new(semstate.node_allocator, sizeof(AstArgument), Ast_Kind_Argument); + arg->value = (AstTyped *) field; + arg->type = field->type; + arg->token = actual_param->token; + arg->next = actual_param->next; + + *prev_param = (AstNode *) arg; + prev_param = (AstNode **) &arg->next; + } + } else { + prev_param = (AstNode **) &actual_param->next; + } + actual_param = (AstArgument *) actual_param->next; } @@ -641,56 +672,6 @@ CHECK(block, AstBlock* block) { } CHECK(function, AstFunction* func) { - for (AstLocal *param = func->params; param != NULL; param = (AstLocal *) param->next) { - fill_in_type((AstTyped *) param); - - if (param->type == NULL) { - onyx_message_add(Msg_Type_Literal, - param->token->pos, - "function parameter types must be known"); - return 1; - } - - if (param->type->Basic.size == 0) { - onyx_message_add(Msg_Type_Literal, - param->token->pos, - "function parameters must have non-void types"); - return 1; - } - } - - fill_in_type((AstTyped *) func); - - if ((func->flags & Ast_Flag_Exported) != 0) { - if ((func->flags & Ast_Flag_Foreign) != 0) { - onyx_message_add(Msg_Type_Literal, - func->token->pos, - "exporting a foreign function"); - return 1; - } - - if ((func->flags & Ast_Flag_Intrinsic) != 0) { - onyx_message_add(Msg_Type_Literal, - func->token->pos, - "exporting a intrinsic function"); - return 1; - } - - if ((func->flags & Ast_Flag_Inline) != 0) { - onyx_message_add(Msg_Type_Literal, - func->token->pos, - "exporting a inlined function"); - return 1; - } - - if (func->exported_name == NULL) { - onyx_message_add(Msg_Type_Literal, - func->token->pos, - "exporting function without a name"); - return 1; - } - } - semstate.expected_return_type = func->type->Function.return_type; if (func->body) { return check_block(func->body); @@ -749,6 +730,60 @@ CHECK(struct, AstStructType* s_node) { return 0; } +CHECK(function_header, AstFunction* func) { + for (AstLocal *param = func->params; param != NULL; param = (AstLocal *) param->next) { + fill_in_type((AstTyped *) param); + + if (param->type == NULL) { + onyx_message_add(Msg_Type_Literal, + param->token->pos, + "function parameter types must be known"); + return 1; + } + + if (param->type->Basic.size == 0) { + onyx_message_add(Msg_Type_Literal, + param->token->pos, + "function parameters must have non-void types"); + return 1; + } + } + + fill_in_type((AstTyped *) func); + + if ((func->flags & Ast_Flag_Exported) != 0) { + if ((func->flags & Ast_Flag_Foreign) != 0) { + onyx_message_add(Msg_Type_Literal, + func->token->pos, + "exporting a foreign function"); + return 1; + } + + if ((func->flags & Ast_Flag_Intrinsic) != 0) { + onyx_message_add(Msg_Type_Literal, + func->token->pos, + "exporting a intrinsic function"); + return 1; + } + + if ((func->flags & Ast_Flag_Inline) != 0) { + onyx_message_add(Msg_Type_Literal, + func->token->pos, + "exporting a inlined function"); + return 1; + } + + if (func->exported_name == NULL) { + onyx_message_add(Msg_Type_Literal, + func->token->pos, + "exporting function without a name"); + return 1; + } + } + + return 0; +} + CHECK(node, AstNode* node) { switch (node->kind) { case Ast_Kind_Function: return check_function((AstFunction *) node); @@ -766,9 +801,12 @@ CHECK(node, AstNode* node) { void onyx_type_check(ProgramInfo* program) { bh_arr_each(Entity, entity, program->entities) { switch (entity->type) { - case Entity_Type_Function: + case Entity_Type_Function_Header: if (entity->function->flags & Ast_Kind_Foreign) program->foreign_func_count++; + if (check_function_header(entity->function)) return; + break; + case Entity_Type_Function: if (check_function(entity->function)) return; break; @@ -792,7 +830,6 @@ void onyx_type_check(ProgramInfo* program) { case Entity_Type_String_Literal: break; - case Entity_Type_Function_Header: break; case Entity_Type_Global_Header: break; default: DEBUG_HERE; break; diff --git a/src/onyxmsgs.c b/src/onyxmsgs.c index 37f0fd97..a79f4e11 100644 --- a/src/onyxmsgs.c +++ b/src/onyxmsgs.c @@ -67,13 +67,13 @@ static void print_detailed_message(Message* msg, bh_file_contents* fc) { char* walker = msg->pos.line_start; while (*walker != '\n') linelength++, walker++; - i32 numlen = bh_printf(" %d |", msg->pos.line); + i32 numlen = bh_printf(" %d | ", msg->pos.line); bh_printf("%b\n", msg->pos.line_start, linelength); char* pointer_str = bh_alloc_array(global_scratch_allocator, char, linelength + numlen); memset(pointer_str, ' ', linelength + numlen); - memset(pointer_str + msg->pos.column + numlen, '~', msg->pos.length - 1); - pointer_str[msg->pos.column + numlen - 1] = '^'; + memset(pointer_str + msg->pos.column + numlen - 1, '~', msg->pos.length - 1); + pointer_str[msg->pos.column + numlen - 2] = '^'; pointer_str[msg->pos.column + numlen + msg->pos.length - 1] = 0; bh_printf("%s\n", pointer_str); diff --git a/src/onyxtypes.c b/src/onyxtypes.c index 4a56ecc5..dbd6db84 100644 --- a/src/onyxtypes.c +++ b/src/onyxtypes.c @@ -213,7 +213,9 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) { s_type->Struct.name = s_node->name; s_type->Struct.mem_count = bh_arr_length(s_node->members); + s_type->Struct.memarr = NULL; bh_table_init(global_heap_allocator, s_type->Struct.members, s_type->Struct.mem_count); + bh_arr_new(global_heap_allocator, s_type->Struct.memarr, s_type->Struct.mem_count); u32 offset = 0; u32 min_alignment = 1; @@ -229,6 +231,7 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) { token_toggle_end((*member)->token); bh_table_put(StructMember, s_type->Struct.members, (*member)->token->text, smem); + bh_arr_push(s_type->Struct.memarr, &bh_table_get(StructMember, s_type->Struct.members, (*member)->token->text)); token_toggle_end((*member)->token); offset += type_size_of((*member)->type);