From: Brendan Hansen Date: Mon, 17 Aug 2020 03:32:32 +0000 (-0500) Subject: added default initial values to struct; added named values to struct literals X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=50f108c5c186fcb96efb54ca3a482ef154a1e591;p=onyx.git added default initial values to struct; added named values to struct literals --- diff --git a/core/test.onyx b/core/test.onyx index 07b11f28..8520d89b 100644 --- a/core/test.onyx +++ b/core/test.onyx @@ -1,6 +1,8 @@ package core +use package memory { null } + Buffer :: struct { - length: u32; - data: rawptr; + length : u32 = 0; + data : rawptr = null; } \ No newline at end of file diff --git a/docs/plan b/docs/plan index c113975b..88ef7965 100644 --- a/docs/plan +++ b/docs/plan @@ -170,8 +170,11 @@ HOW: [X] local variable allocator - [ ] Struct literals - + [X] Struct literals + X All members specified means names not required + X Named member initialization + X Default values on structs so they don't have to be named + [ ] #union on structs [ ] #align on structs @@ -187,7 +190,7 @@ HOW: a := 2 b := 5 a, b = b, a; - + [ ] All code paths return correct value [ ] Type parameterized structs diff --git a/include/onyxastnodes.h b/include/onyxastnodes.h index 4334b4b4..df3cda9e 100644 --- a/include/onyxastnodes.h +++ b/include/onyxastnodes.h @@ -41,6 +41,7 @@ typedef struct AstPointerType AstPointerType; typedef struct AstFunctionType AstFunctionType; typedef struct AstArrayType AstArrayType; typedef struct AstStructType AstStructType; +typedef struct AstStructMember AstStructMember; typedef struct AstEnumType AstEnumType; typedef struct AstEnumValue AstEnumValue; typedef struct AstTypeAlias AstTypeAlias; @@ -282,7 +283,14 @@ struct AstFieldAccess { AstTyped_base; AstTyped *expr; u64 offset; }; struct AstSizeOf { AstTyped_base; AstType *so_type; u64 size; }; struct AstAlignOf { AstTyped_base; AstType *ao_type; u64 alignment; }; struct AstFileContents { AstTyped_base; OnyxToken *filename; }; -struct AstStructLiteral { AstTyped_base; AstTyped *stnode; bh_arr(AstTyped *) values; }; +struct AstStructLiteral { + AstTyped_base; + + AstTyped *stnode; + + bh_arr(AstStructMember *) named_values; + bh_arr(AstTyped *) values; +}; // Intruction Node struct AstReturn { AstNode_base; AstTyped* expr; }; @@ -330,13 +338,17 @@ struct AstArrayType { AstType_base; AstType* elem; AstTyped *count_expr; }; struct AstStructType { AstType_base; - bh_arr(AstTyped *) members; + bh_arr(AstStructMember *) members; // NOTE: Used to cache the actual type, since building // a struct type is kind of complicated and should // only happen once. Type *stcache; }; +struct AstStructMember { + AstTyped_base; + AstTyped* initial_value; +}; struct AstEnumType { AstType_base; Scope *scope; diff --git a/include/onyxmsgs.h b/include/onyxmsgs.h index 1f78243b..0e9ada8f 100644 --- a/include/onyxmsgs.h +++ b/include/onyxmsgs.h @@ -30,6 +30,8 @@ typedef enum MsgType { Msg_Type_Duplicate_Member, Msg_Type_No_Field, + Msg_Type_Duplicate_Value, + Msg_Type_Field_No_Value, Msg_Type_Unresolved_Type, Msg_Type_Unresolved_Symbol, diff --git a/onyx b/onyx index dbe7cd69..d7ff95ab 100755 Binary files a/onyx and b/onyx differ diff --git a/progs/stack_based.onyx b/progs/stack_based.onyx index c85c1610..372f5814 100644 --- a/progs/stack_based.onyx +++ b/progs/stack_based.onyx @@ -150,13 +150,15 @@ start :: proc #export { mag_squared(varr[2]) |> print(); v1 := Vec3 .{ 1, 2, 4 }; - v2 := *vadd(Vec3.{4, 3, 2}, Vec3.{1, 1, 1}); + v2 := *vadd(v1, Vec3.{ 1, 2, 4 }); print(v2.x); print(v2.y); print(v2.z); - buf := core.Buffer.{ 16, null }; + buf := core.Buffer.{ + length = 16, + }; } vadd :: proc (v1: Vec3, v2: Vec3) -> ^Vec3 { diff --git a/src/onyxchecker.c b/src/onyxchecker.c index ed4e045e..1fb90483 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -987,7 +987,7 @@ CHECK(struct, AstStructType* s_node) { return 1; } - bh_arr_each(AstTyped *, member, s_node->members) { + bh_arr_each(AstStructMember *, member, s_node->members) { token_toggle_end((*member)->token); if (bh_table_has(i32, mem_set, (*member)->token->text)) { diff --git a/src/onyxmsgs.c b/src/onyxmsgs.c index c5ad22d1..516375ad 100644 --- a/src/onyxmsgs.c +++ b/src/onyxmsgs.c @@ -28,6 +28,8 @@ static const char* msg_formats[] = { "duplicate declaration of struct member '%s'", "field '%s' does not exist on '%s'", + "duplicate value for struct member '%b'", + "no value provided for field '%b'", "unable to resolve type for symbol '%b'", "unable to resolve symbol '%b'", diff --git a/src/onyxparser.c b/src/onyxparser.c index 39763fac..69942803 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -193,6 +193,7 @@ static b32 parse_possible_struct_literal(OnyxParser* parser, AstTyped** ret) { AstStructLiteral* sl = make_node(AstStructLiteral, Ast_Kind_Struct_Literal); sl->token = parser->curr; bh_arr_new(global_heap_allocator, sl->values, 4); + bh_arr_new(global_heap_allocator, sl->named_values, 4); if (symbol2 != NULL) { AstTyped *package = make_node(AstTyped, Ast_Kind_Symbol); @@ -210,11 +211,31 @@ static b32 parse_possible_struct_literal(OnyxParser* parser, AstTyped** ret) { } expect_token(parser, '{'); + b32 is_named = ((parser->curr + 1)->type == '='); + + OnyxToken* name = NULL; while (parser->curr->type != '}') { if (parser->hit_unexpected_token) break; + if (is_named) { + name = expect_token(parser, Token_Type_Symbol); + expect_token(parser, '='); + } else { + name = NULL; + } + AstTyped *expr = parse_expression(parser); - bh_arr_push(sl->values, expr); + + if (is_named) { + AstStructMember* sm = make_node(AstStructMember, Ast_Kind_Struct_Member); + sm->token = name; + sm->initial_value = expr; + + bh_arr_push(sl->named_values, sm); + + } else { + bh_arr_push(sl->values, expr); + } if (parser->curr->type != '}') expect_token(parser, ','); @@ -1114,11 +1135,17 @@ static AstStructType* parse_struct(OnyxParser* parser) { while (parser->curr->type != '}') { if (parser->hit_unexpected_token) return s_node; - AstTyped* mem = make_node(AstTyped, Ast_Kind_Struct_Member); + AstStructMember* mem = make_node(AstStructMember, Ast_Kind_Struct_Member); mem->token = expect_token(parser, Token_Type_Symbol); expect_token(parser, ':'); mem->type_node = parse_type(parser); + + if (parser->curr->type == '=') { + consume_token(parser); + mem->initial_value = parse_expression(parser); + } + expect_token(parser, ';'); bh_arr_push(s_node->members, mem); diff --git a/src/onyxsymres.c b/src/onyxsymres.c index 40ad2738..87fa5a61 100644 --- a/src/onyxsymres.c +++ b/src/onyxsymres.c @@ -91,8 +91,11 @@ static AstType* symres_type(AstType* type) { s_node->flags |= Ast_Flag_Type_Is_Resolved; - bh_arr_each(AstTyped *, member, s_node->members) { + bh_arr_each(AstStructMember *, member, s_node->members) { (*member)->type_node = symres_type((*member)->type_node); + if ((*member)->initial_value != NULL) { + symres_expression(&(*member)->initial_value); + } } return type; @@ -215,6 +218,49 @@ static void symres_struct_literal(AstStructLiteral* sl) { } sl->type_node = (AstType *) sl->stnode; + sl->type = type_build_from_ast(semstate.allocator, sl->type_node); + + if (bh_arr_length(sl->named_values) > 0) { + bh_arr_set_length(sl->values, sl->type->Struct.mem_count); + + StructMember s; + bh_arr_each(AstStructMember *, smem, sl->named_values) { + token_toggle_end((*smem)->token); + if (!type_struct_lookup_member(sl->type, (*smem)->token->text, &s)) { + onyx_message_add(Msg_Type_No_Field, + (*smem)->token->pos, + (*smem)->token->text, type_get_name(sl->type)); + return; + } + token_toggle_end((*smem)->token); + + if (sl->values[s.idx] != NULL) { + onyx_message_add(Msg_Type_Duplicate_Value, + (*smem)->token->pos, + (*smem)->token->text, (*smem)->token->length); + return; + } + + sl->values[s.idx] = (*smem)->initial_value; + } + + AstStructType* st = (AstStructType *) sl->type_node; + bh_arr_each(StructMember*, smem, sl->type->Struct.memarr) { + u32 idx = (*smem)->idx; + + if (sl->values[idx] == NULL) { + if (st->members[idx]->initial_value == NULL) { + onyx_message_add(Msg_Type_Field_No_Value, + sl->token->pos, + st->members[idx]->token->text, + st->members[idx]->token->length); + return; + } + + sl->values[idx] = st->members[idx]->initial_value; + } + } + } bh_arr_each(AstTyped *, expr, sl->values) symres_expression(expr); } @@ -369,7 +415,7 @@ static void symres_function(AstFunction* func) { st = (AstStructType *) ((AstPointerType *) param->type_node)->elem; } - bh_arr_each(AstTyped *, mem, st->members) { + bh_arr_each(AstStructMember *, mem, st->members) { AstFieldAccess* fa = onyx_ast_node_new(semstate.node_allocator, sizeof(AstFieldAccess), Ast_Kind_Field_Access); fa->token = (*mem)->token; fa->type_node = (*mem)->type_node; diff --git a/src/onyxtypes.c b/src/onyxtypes.c index f683b292..cd6cfd06 100644 --- a/src/onyxtypes.c +++ b/src/onyxtypes.c @@ -281,7 +281,7 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) { u32 offset = 0; u32 alignment = 1, mem_alignment; u32 idx = 0; - bh_arr_each(AstTyped *, member, s_node->members) { + bh_arr_each(AstStructMember *, member, s_node->members) { (*member)->type = type_build_from_ast(alloc, (*member)->type_node); // TODO: Add alignment checking here @@ -308,7 +308,7 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) { // NOTE: Need to do a second pass because the references to the // elements of the table may change if the internal arrays of the // table need to be resized. - bh_arr_each(AstTyped *, member, s_node->members) { + bh_arr_each(AstStructMember *, member, s_node->members) { token_toggle_end((*member)->token); bh_arr_push(s_type->Struct.memarr, &bh_table_get(StructMember, s_type->Struct.members, (*member)->token->text)); token_toggle_end((*member)->token);