From: Brendan Hansen Date: Wed, 25 May 2022 22:18:30 +0000 (-0500) Subject: added fully anonymous struct literals X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=7d0099b928fabb2b5468016f3e24e5ebfae9135c;p=onyx.git added fully anonymous struct literals --- diff --git a/include/types.h b/include/types.h index 9ed77e53..5c2b5e69 100644 --- a/include/types.h +++ b/include/types.h @@ -188,6 +188,7 @@ extern Type basic_types[]; struct AstType; struct AstFunction; struct AstCompound; +struct AstStructLiteral; void types_init(); void types_dump_type_info(); @@ -196,6 +197,7 @@ b32 types_are_compatible(Type* t1, Type* t2); u32 type_size_of(Type* type); u32 type_alignment_of(Type* type); Type* type_build_from_ast(bh_allocator alloc, struct AstType* type_node); +Type* type_build_implicit_type_of_struct_literal(bh_allocator alloc, struct AstStructLiteral* lit); Type* type_build_function_type(bh_allocator alloc, struct AstFunction* func); Type* type_build_compound_type(bh_allocator alloc, struct AstCompound* compound); diff --git a/src/astnodes.c b/src/astnodes.c index a2068921..9fa20585 100644 --- a/src/astnodes.c +++ b/src/astnodes.c @@ -854,6 +854,26 @@ Type* resolve_expression_type(AstTyped* node) { } } + if (node->kind == Ast_Kind_Struct_Literal && node->type == NULL) { + AstStructLiteral* sl = (AstStructLiteral *) node; + assert(sl->stnode == NULL); + assert(sl->type_node == NULL); + + // If values without names are given to a struct literal without + // a type, then we cannot implicitly build the type of the struct + // literal, as the name of every member cannot be known. Maybe we + // could implicitly do something like _1, _2, ... for the members + // that we not given names? + if (bh_arr_length(sl->args.values) > 0) { + return NULL; + } + + sl->type = type_build_implicit_type_of_struct_literal(context.ast_alloc, sl); + if (sl->type) { + add_entities_for_node(NULL, (AstNode *) sl, NULL, NULL); + } + } + // If polymorphic procedures HAVE to have a type, most likely // because they are part of a `typeof` expression, they are // assigned a void type. This is cleared before the procedure @@ -1348,4 +1368,4 @@ AstPolyCallType* convert_call_to_polycall(AstCall* call) { } return pct; -} \ No newline at end of file +} diff --git a/src/checker.c b/src/checker.c index b170e534..ef038ecd 100644 --- a/src/checker.c +++ b/src/checker.c @@ -1202,12 +1202,17 @@ CheckStatus check_unaryop(AstUnaryOp** punop) { } CheckStatus check_struct_literal(AstStructLiteral* sl) { + if (sl->type == NULL) { // NOTE: This is used for automatically typed struct literals. If there is no provided // type for the struct literal, assume that it is passes successfully. When it is used // elsewhere, it will be added as an expression entity that will be processed once the // stnode is filled out. - if (sl->stnode == NULL) return Check_Success; + if (sl->stnode == NULL) { + CHECK(arguments, &sl->args); + + return Check_Success; + } CHECK(expression, &sl->stnode); if (!node_is_type((AstNode *) sl->stnode)) { @@ -1288,12 +1293,8 @@ CheckStatus check_struct_literal(AstStructLiteral* sl) { Type* formal = smem.type; CHECK(expression, actual); - - // HACK HACK HACK - if ((*actual)->type == NULL && - (*actual)->entity != NULL && - (*actual)->entity->state <= Entity_State_Check_Types) { - YIELD_((*actual)->token->pos, "Trying to resolve type of expression for member '%s'.", smem.name); + if ((*actual)->type == NULL && (*actual)->entity != NULL && (*actual)->entity->state <= Entity_State_Check_Types) { + YIELD((*actual)->token->pos, "Trying to resolve type of expression for member."); } TYPE_CHECK(actual, formal) { diff --git a/src/types.c b/src/types.c index ec750c46..50d59292 100644 --- a/src/types.c +++ b/src/types.c @@ -697,6 +697,80 @@ Type* type_build_compound_type(bh_allocator alloc, AstCompound* compound) { return comp_type; } +Type* type_build_implicit_type_of_struct_literal(bh_allocator alloc, AstStructLiteral* lit) { + Type* type = type_create(Type_Kind_Struct, alloc, 0); + type->ast_type = NULL; + type->Struct.name = NULL; + type->Struct.mem_count = bh_arr_length(lit->args.named_values); + type->Struct.meta_tags = NULL; + type->Struct.constructed_from = NULL; + type->Struct.status = SPS_Start; + type->Struct.poly_sln = NULL; + type_register(type); + + type->Struct.memarr = NULL; + sh_new_arena(type->Struct.members); + bh_arr_new(global_heap_allocator, type->Struct.memarr, type->Struct.mem_count); + + u32 size = 0; + u32 offset = 0; + u32 alignment = 1; + u32 idx = 0; + bh_arr_each(AstNamedValue *, pnv, lit->args.named_values) { + AstNamedValue *nv = *pnv; + + Type* member_type = resolve_expression_type(nv->value); + if (member_type == NULL) { + return NULL; + } + + u32 mem_alignment = type_alignment_of(member_type); + if (mem_alignment <= 0) { + return NULL; + } + + alignment = bh_max(alignment, mem_alignment); + + // Should these structs be packed or not? + bh_align(offset, mem_alignment); + + token_toggle_end(nv->token); + if (shgeti(type->Struct.members, nv->token->text) != -1) { + token_toggle_end(nv->token); + return NULL; + } + + StructMember *smem = bh_alloc_item(alloc, StructMember); + smem->offset = offset; + smem->type = member_type; + smem->idx = idx; + smem->name = bh_strdup(alloc, nv->token->text); + smem->token = nv->token; + smem->initial_value = &nv->value; + smem->meta_tags = NULL; + smem->included_through_use = 0; + smem->used = 0; + smem->use_through_pointer_index = -1; + shput(type->Struct.members, nv->token->text, smem); + bh_arr_push(type->Struct.memarr, smem); + token_toggle_end(nv->token); + + u32 type_size = type_size_of(member_type); + offset += type_size; + size = offset; + idx++; + } + + type->Struct.alignment = alignment; + type->Struct.size = size; + type->Struct.linear_members = NULL; + bh_arr_new(global_heap_allocator, type->Struct.linear_members, type->Struct.mem_count); + build_linear_types_with_offset(type, &type->Struct.linear_members, 0); + + type->Struct.status = SPS_Uses_Done; + return type; +} + Type* type_make_pointer(bh_allocator alloc, Type* to) { if (to == NULL) return NULL; if (to == (Type *) &node_that_signals_failure) return to; diff --git a/src/wasm_type_table.h b/src/wasm_type_table.h index d92537d7..6ce7112a 100644 --- a/src/wasm_type_table.h +++ b/src/wasm_type_table.h @@ -380,7 +380,7 @@ static u64 build_type_table(OnyxWasmModule* module) { // Struct methods bh_arr(StructMethodData) method_data=NULL; AstType *ast_type = type->ast_type; - if (ast_type->kind == Ast_Kind_Struct_Type) { + if (ast_type && ast_type->kind == Ast_Kind_Struct_Type) { AstStructType *struct_type = (AstStructType *) ast_type; Scope* struct_scope = struct_type->scope; diff --git a/tests/no_types b/tests/no_types new file mode 100644 index 00000000..8c64808f --- /dev/null +++ b/tests/no_types @@ -0,0 +1,40 @@ +{ x = 0.0990, y = 0.0950, vx = 9.8000, vy = 9.0000, ax = -20.0000, ay = -100.0000 } +{ x = 0.1959, y = 0.1799, vx = 9.6000, vy = 8.0000, ax = -20.0000, ay = -100.0000 } +{ x = 0.2910, y = 0.2549, vx = 9.4000, vy = 7.0000, ax = -20.0000, ay = -100.0000 } +{ x = 0.3840, y = 0.3200, vx = 9.2000, vy = 6.0000, ax = -20.0000, ay = -100.0000 } +{ x = 0.4750, y = 0.3750, vx = 9.0000, vy = 5.0000, ax = -20.0000, ay = -100.0000 } +{ x = 0.5640, y = 0.4200, vx = 8.8000, vy = 4.0000, ax = -20.0000, ay = -100.0000 } +{ x = 0.6510, y = 0.4549, vx = 8.6000, vy = 3.0000, ax = -20.0000, ay = -100.0000 } +{ x = 0.7360, y = 0.4799, vx = 8.4000, vy = 2.0000, ax = -20.0000, ay = -100.0000 } +{ x = 0.8190, y = 0.4950, vx = 8.2000, vy = 1.0000, ax = -20.0000, ay = -100.0000 } +{ x = 0.9000, y = 0.5000, vx = 8.0000, vy = 0.0000, ax = -20.0000, ay = -100.0000 } +{ x = 0.9790, y = 0.4950, vx = 7.8000, vy = -1.0000, ax = -20.0000, ay = -100.0000 } +{ x = 1.0560, y = 0.4799, vx = 7.6000, vy = -2.0000, ax = -20.0000, ay = -100.0000 } +{ x = 1.1310, y = 0.4549, vx = 7.4000, vy = -3.0000, ax = -20.0000, ay = -100.0000 } +{ x = 1.2040, y = 0.4200, vx = 7.2000, vy = -4.0000, ax = -20.0000, ay = -100.0000 } +{ x = 1.2750, y = 0.3750, vx = 7.0000, vy = -5.0000, ax = -20.0000, ay = -100.0000 } +{ x = 1.3440, y = 0.3200, vx = 6.8000, vy = -6.0000, ax = -20.0000, ay = -100.0000 } +{ x = 1.4110, y = 0.2549, vx = 6.6000, vy = -7.0000, ax = -20.0000, ay = -100.0000 } +{ x = 1.4760, y = 0.1799, vx = 6.4000, vy = -8.0000, ax = -20.0000, ay = -100.0000 } +{ x = 1.5390, y = 0.0949, vx = 6.2000, vy = -9.0000, ax = -20.0000, ay = -100.0000 } +{ x = 1.6000, y = 0.0000, vx = 0.3000, vy = 0.0000, ax = -20.0000, ay = -100.0000 } +{ x = 1.6020, y = 0.0000, vx = 0.0050, vy = 0.0000, ax = -20.0000, ay = -100.0000 } +{ x = 1.6010, y = 0.0000, vx = -0.0097, vy = 0.0000, ax = -20.0000, ay = -100.0000 } +{ x = 1.5999, y = 0.0000, vx = -0.0104, vy = 0.0000, ax = -20.0000, ay = -100.0000 } +{ x = 1.5988, y = 0.0000, vx = -0.0105, vy = 0.0000, ax = -20.0000, ay = -100.0000 } +{ x = 1.5977, y = 0.0000, vx = -0.0105, vy = 0.0000, ax = -20.0000, ay = -100.0000 } +{ x = 1.5966, y = 0.0000, vx = -0.0105, vy = 0.0000, ax = -20.0000, ay = -100.0000 } +{ x = 1.5955, y = 0.0000, vx = -0.0105, vy = 0.0000, ax = -20.0000, ay = -100.0000 } +{ x = 1.5944, y = 0.0000, vx = -0.0105, vy = 0.0000, ax = -20.0000, ay = -100.0000 } +{ x = 1.5933, y = 0.0000, vx = -0.0105, vy = 0.0000, ax = -20.0000, ay = -100.0000 } +{ x = 1.5922, y = 0.0000, vx = -0.0105, vy = 0.0000, ax = -20.0000, ay = -100.0000 } +{ x = 1.5911, y = 0.0000, vx = -0.0105, vy = 0.0000, ax = -20.0000, ay = -100.0000 } +{ x = 1.5900, y = 0.0000, vx = -0.0105, vy = 0.0000, ax = -20.0000, ay = -100.0000 } +{ x = 1.5889, y = 0.0000, vx = -0.0105, vy = 0.0000, ax = -20.0000, ay = -100.0000 } +{ x = 1.5877, y = 0.0000, vx = -0.0105, vy = 0.0000, ax = -20.0000, ay = -100.0000 } +{ x = 1.5866, y = 0.0000, vx = -0.0105, vy = 0.0000, ax = -20.0000, ay = -100.0000 } +{ x = 1.5855, y = 0.0000, vx = -0.0105, vy = 0.0000, ax = -20.0000, ay = -100.0000 } +{ x = 1.5844, y = 0.0000, vx = -0.0105, vy = 0.0000, ax = -20.0000, ay = -100.0000 } +{ x = 1.5833, y = 0.0000, vx = -0.0105, vy = 0.0000, ax = -20.0000, ay = -100.0000 } +{ x = 1.5822, y = 0.0000, vx = -0.0105, vy = 0.0000, ax = -20.0000, ay = -100.0000 } +{ x = 1.5811, y = 0.0000, vx = -0.0105, vy = 0.0000, ax = -20.0000, ay = -100.0000 } diff --git a/tests/no_types.onyx b/tests/no_types.onyx new file mode 100644 index 00000000..4bc7058f --- /dev/null +++ b/tests/no_types.onyx @@ -0,0 +1,33 @@ +// +// No types are written throughout this entire program. +// + +#load "core/std" + +use core + +main :: () { + object := .{ + x = 0.0, y = 0.0, + vx = 10.0, vy = 10.0, + ax = -20.0, ay = -100.0 + }; + + for 40 { + step_physics(^object, 0.01); + printf("{}\n", object); + } +} + +step_physics :: (obj, dt) => { + obj.x += 0.5 * obj.ax * dt * dt + obj.vx * dt; + obj.y += 0.5 * obj.ay * dt * dt + obj.vy * dt; + obj.vx += obj.ax * dt; + obj.vy += obj.ay * dt; + + if obj.y < 0 { + obj.y = 0; + obj.vy = 0; + obj.vx *= 0.05; + } +}