From: Brendan Hansen Date: Thu, 3 Jun 2021 19:02:03 +0000 (-0500) Subject: MAYBE BREAKING CHANGE; Polymorphic structure types are no longer known immediately X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=9a4b2fab4d347bdd78928149998e78adb660934a;p=onyx.git MAYBE BREAKING CHANGE; Polymorphic structure types are no longer known immediately --- diff --git a/bin/onyx b/bin/onyx index 8c7dc830..201a94b1 100755 Binary files a/bin/onyx and b/bin/onyx differ diff --git a/core/stdio.onyx b/core/stdio.onyx index 7488a5a4..a81f1a4f 100644 --- a/core/stdio.onyx +++ b/core/stdio.onyx @@ -66,7 +66,7 @@ byte_dump :: (ptr: rawptr, byte_count: u32, bytes_per_line := 8) { temp[1] = map_to_ascii(val & 15); temp[2] = #char " "; - runtime.__output_string(.{ ~~temp, 3 }); + runtime.__output_string(~~temp); if i % bytes_per_line == (bytes_per_line - 1) do runtime.__output_string("\n"); } diff --git a/include/onyxastnodes.h b/include/onyxastnodes.h index 9dc4062f..ab98b606 100644 --- a/include/onyxastnodes.h +++ b/include/onyxastnodes.h @@ -701,6 +701,8 @@ struct AstStructType { struct Entity* entity_type; struct Entity* entity_defaults; + + b32 stcache_is_valid : 1; }; struct AstStructMember { AstTyped_base; @@ -988,8 +990,8 @@ typedef struct Entity { EntityState state; // TODO: Document this! - u16 macro_attempts; - u16 micro_attempts; + u32 macro_attempts; + u32 micro_attempts; b32 entered_in_queue : 1; diff --git a/src/onyxchecker.c b/src/onyxchecker.c index c78dc33d..2637ec5a 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -972,6 +972,8 @@ CheckStatus check_unaryop(AstUnaryOp** punop) { if (unaryop->operation == Unary_Op_Cast) { char* err; + if (unaryop->type == NULL) return Check_Yield_Macro; + if (!cast_is_legal(unaryop->expr->type, unaryop->type, &err)) { onyx_report_error(unaryop->token->pos, "Cast Error: %s", err); return Check_Error; @@ -1021,7 +1023,7 @@ CheckStatus check_struct_literal(AstStructLiteral* sl) { } fill_in_type((AstTyped *) sl); - if (sl->type == NULL) return Check_Error; + if (sl->type == NULL) return Check_Yield_Macro; } if (!type_is_structlike_strict(sl->type)) { @@ -1034,25 +1036,29 @@ CheckStatus check_struct_literal(AstStructLiteral* sl) { i32 mem_count = type_structlike_mem_count(sl->type); arguments_ensure_length(&sl->args, mem_count); - char* err_msg = NULL; - if (!fill_in_arguments(&sl->args, (AstNode *) sl, &err_msg)) { - onyx_report_error(sl->token->pos, err_msg); - - bh_arr_each(AstTyped *, value, sl->args.values) { - if (*value == NULL) { - i32 member_idx = value - sl->args.values; // Pointer subtraction hack - StructMember smem; - type_lookup_member_by_idx(sl->type, member_idx, &smem); - - onyx_report_error(sl->token->pos, - "Value not given for %d%s member, '%s', for type '%s'.", - member_idx + 1, bh_num_suffix(member_idx + 1), - smem.name, type_get_name(sl->type)); + // :Idempotency + if ((sl->flags & Ast_Flag_Has_Been_Checked) == 0) { + char* err_msg = NULL; + if (!fill_in_arguments(&sl->args, (AstNode *) sl, &err_msg)) { + onyx_report_error(sl->token->pos, err_msg); + + bh_arr_each(AstTyped *, value, sl->args.values) { + if (*value == NULL) { + i32 member_idx = value - sl->args.values; // Pointer subtraction hack + StructMember smem; + type_lookup_member_by_idx(sl->type, member_idx, &smem); + + onyx_report_error(sl->token->pos, + "Value not given for %d%s member, '%s', for type '%s'.", + member_idx + 1, bh_num_suffix(member_idx + 1), + smem.name, type_get_name(sl->type)); + } } - } - return Check_Error; + return Check_Error; + } } + sl->flags |= Ast_Flag_Has_Been_Checked; AstTyped** actual = sl->args.values; StructMember smem; @@ -1096,6 +1102,7 @@ CheckStatus check_struct_literal(AstStructLiteral* sl) { } CheckStatus check_array_literal(AstArrayLiteral* al) { + // :Idempotency if ((al->flags & Ast_Flag_Array_Literal_Typed) == 0) { if (al->atnode == NULL) return Check_Success; @@ -1105,7 +1112,7 @@ CheckStatus check_array_literal(AstArrayLiteral* al) { } fill_in_type((AstTyped *) al); - if (al->type == NULL) return Check_Error; + if (al->type == NULL) return Check_Yield_Macro; al->type = type_make_array(context.ast_alloc, al->type, bh_arr_length(al->values)); if (al->type == NULL || al->type->kind != Type_Kind_Array) { @@ -1128,6 +1135,13 @@ CheckStatus check_array_literal(AstArrayLiteral* al) { bh_arr_each(AstTyped *, expr, al->values) { CHECK(expression, expr); + // HACK HACK HACK + if ((*expr)->type == NULL && + (*expr)->entity != NULL && + (*expr)->entity->state <= Entity_State_Check_Types) { + return Check_Yield_Macro; + } + al->flags &= ((*expr)->flags & Ast_Flag_Comptime) | (al->flags &~ Ast_Flag_Comptime); if (!type_check_or_auto_cast(expr, elem_type)) { @@ -1353,21 +1367,25 @@ CheckStatus check_method_call(AstBinaryOp** mcall) { CHECK(expression, &(*mcall)->left); AstTyped* implicit_argument = (*mcall)->left; - - // Implicitly take the address of the value if it is not already a pointer type. - // This could be weird to think about semantically so some testing with real code - // would be good. - brendanfh 2020/02/05 - if (implicit_argument->type->kind != Type_Kind_Pointer) - implicit_argument = (AstTyped *) make_address_of(context.ast_alloc, implicit_argument); - - implicit_argument = (AstTyped *) make_argument(context.ast_alloc, implicit_argument); // Symbol resolution should have ensured that this is call node. AstCall* call_node = (AstCall *) (*mcall)->right; assert(call_node->kind == Ast_Kind_Call); - bh_arr_insertn(call_node->args.values, 0, 1); - call_node->args.values[0] = implicit_argument; + // :Idempotency + if (((*mcall)->flags & Ast_Flag_Has_Been_Checked) == 0) { + // Implicitly take the address of the value if it is not already a pointer type. + // This could be weird to think about semantically so some testing with real code + // would be good. - brendanfh 2020/02/05 + if (implicit_argument->type->kind != Type_Kind_Pointer) + implicit_argument = (AstTyped *) make_address_of(context.ast_alloc, implicit_argument); + + implicit_argument = (AstTyped *) make_argument(context.ast_alloc, implicit_argument); + + bh_arr_insertn(call_node->args.values, 0, 1); + call_node->args.values[0] = implicit_argument; + } + (*mcall)->flags |= Ast_Flag_Has_Been_Checked; CHECK(call, call_node); call_node->next = (*mcall)->next; @@ -1380,10 +1398,8 @@ CheckStatus check_size_of(AstSizeOf* so) { fill_in_array_count(so->so_ast_type); so->so_type = type_build_from_ast(context.ast_alloc, so->so_ast_type); - if (so->so_type == NULL) { - onyx_report_error(so->token->pos, "Error with type used here."); - return Check_Error; - } + if (so->so_type == NULL) return Check_Yield_Macro; + so->size = type_size_of(so->so_type); return Check_Success; @@ -1393,10 +1409,8 @@ CheckStatus check_align_of(AstAlignOf* ao) { fill_in_array_count(ao->ao_ast_type); ao->ao_type = type_build_from_ast(context.ast_alloc, ao->ao_ast_type); - if (ao->ao_type == NULL) { - onyx_report_error(ao->token->pos, "Error with type used here."); - return Check_Error; - } + if (ao->ao_type == NULL) return Check_Yield_Macro; + ao->alignment = type_alignment_of(ao->ao_type); return Check_Success; @@ -1555,9 +1569,12 @@ CheckStatus check_statement(AstNode** pstmt) { // in a block in order to efficiently allocate enough space and registers // for them all. Now with LocalAllocator, this is no longer necessary. // Therefore, locals stay in the tree and need to be passed along. - case Ast_Kind_Local: - fill_in_type((AstTyped *) stmt); + case Ast_Kind_Local: { + AstTyped* typed_stmt = (AstTyped *) stmt; + fill_in_type(typed_stmt); + if (typed_stmt->type_node != NULL && typed_stmt->type == NULL) return Check_Yield_Macro; return Check_Success; + } default: CHECK(expression, (AstTyped **) pstmt); @@ -1610,7 +1627,7 @@ CheckStatus check_function(AstFunction* func) { expected_return_type = func->type->Function.return_type; if (func->body) { CheckStatus status = check_block(func->body); - if (status != Check_Success && func->generated_from) + if (status == Check_Error && func->generated_from) onyx_report_error(func->generated_from->pos, "Error in polymorphic procedure generated from this location."); return status; @@ -1658,7 +1675,10 @@ CheckStatus check_struct(AstStructType* s_node) { bh_arr_each(AstStructMember *, smem, s_node->members) { if ((*smem)->type_node == NULL && (*smem)->initial_value != NULL) { CHECK(expression, &(*smem)->initial_value); + fill_in_type((*smem)->initial_value); + if ((*smem)->initial_value->type == NULL) return Check_Yield_Macro; + (*smem)->type = resolve_expression_type((*smem)->initial_value); if ((*smem)->type == NULL) { @@ -1757,13 +1777,12 @@ CheckStatus check_function_header(AstFunction* func) { if (local->type_node != NULL) CHECK(type, local->type_node); fill_in_type((AstTyped *) local); - if (local->type == NULL) { - onyx_report_error(param->local->token->pos, - "Unable to resolve type for parameter, '%b'", - local->token->text, - local->token->length); - return Check_Error; + // onyx_report_error(param->local->token->pos, + // "Unable to resolve type for parameter, '%b'", + // local->token->text, + // local->token->length); + return Check_Yield_Macro; } if (local->type->kind == Type_Kind_Compound) { @@ -1797,12 +1816,14 @@ CheckStatus check_function_header(AstFunction* func) { if (func->return_type != NULL) CHECK(type, func->return_type); func->type = type_build_function_type(context.ast_alloc, func); + if (func->type == NULL) return Check_Yield_Macro; return Check_Success; } CheckStatus check_memres_type(AstMemRes* memres) { fill_in_type((AstTyped *) memres); + if (memres->type_node && !memres->type) return Check_Yield_Macro; return Check_Success; } diff --git a/src/onyxtypes.c b/src/onyxtypes.c index bfb7b071..800ff538 100644 --- a/src/onyxtypes.c +++ b/src/onyxtypes.c @@ -227,17 +227,23 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) { AstFunctionType* ftype_node = (AstFunctionType *) type_node; u64 param_count = ftype_node->param_count; + Type* return_type = type_build_from_ast(alloc, ftype_node->return_type); + if (return_type == NULL) return NULL; + Type* func_type = bh_alloc(alloc, sizeof(Type) + sizeof(Type *) * param_count); func_type->kind = Type_Kind_Function; func_type->ast_type = type_node; func_type->Function.param_count = param_count; func_type->Function.needed_param_count = param_count; - func_type->Function.return_type = type_build_from_ast(alloc, ftype_node->return_type); + func_type->Function.return_type = return_type; if (param_count > 0) fori (i, 0, (i64) param_count) { func_type->Function.params[i] = type_build_from_ast(alloc, ftype_node->params[i]); + + // LEAK LEAK LEAK + if (func_type->Function.params[i] == NULL) return NULL; } return func_type; @@ -281,22 +287,31 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) { case Ast_Kind_Struct_Type: { AstStructType* s_node = (AstStructType *) type_node; - if (s_node->stcache != NULL) return s_node->stcache; + if (s_node->stcache != NULL && s_node->stcache_is_valid) return s_node->stcache; + + Type* s_type; + if (s_node->stcache == NULL) { + s_type = bh_alloc(alloc, sizeof(Type)); + s_node->stcache = s_type; - Type* s_type = bh_alloc(alloc, sizeof(Type)); - s_node->stcache = s_type; - s_type->kind = Type_Kind_Struct; - s_type->ast_type = type_node; + s_type->kind = Type_Kind_Struct; + s_type->ast_type = type_node; + s_type->Struct.name = s_node->name; + s_type->Struct.unique_id = next_unique_id++; + s_type->Struct.mem_count = bh_arr_length(s_node->members); + + } else { + s_type = s_node->stcache; + } - s_type->Struct.unique_id = next_unique_id++; - s_type->Struct.name = s_node->name; - s_type->Struct.mem_count = bh_arr_length(s_node->members); s_type->Struct.memarr = NULL; s_type->Struct.poly_sln = NULL; bh_table_init(global_heap_allocator, s_type->Struct.members, s_type->Struct.mem_count + 1); bh_arr_new(global_heap_allocator, s_type->Struct.memarr, s_type->Struct.mem_count); + s_node->stcache_is_valid = 1; + b32 is_union = (s_node->flags & Ast_Flag_Struct_Is_Union) != 0; u32 size = 0; u32 offset = 0; @@ -307,16 +322,15 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) { (*member)->type = type_build_from_ast(alloc, (*member)->type_node); if ((*member)->type == NULL) { - // :ExplicitTyping - // onyx_report_error((*member)->token->pos, "Unable to resolve member type. Try adding it explicitly."); - s_node->stcache = NULL; + // LEAK LEAK LEAK + s_node->stcache_is_valid = 0; return NULL; } mem_alignment = type_alignment_of((*member)->type); if (mem_alignment <= 0) { onyx_report_error((*member)->token->pos, "Invalid member type: %s", type_get_name((*member)->type)); - return s_type; + return NULL; } if (mem_alignment > alignment) alignment = mem_alignment; @@ -455,9 +469,14 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) { bh_arr_new(global_heap_allocator, slns, bh_arr_length(pc_type->params)); bh_arr_each(AstNode *, given, pc_type->params) { if (node_is_type(*given)) { + Type* param_type = type_build_from_ast(alloc, (AstType *) *given); + + // LEAK LEAK LEAK + if (param_type == NULL) return NULL; + bh_arr_push(slns, ((AstPolySolution) { .kind = PSK_Type, - .type = type_build_from_ast(alloc, (AstType *) *given), + .type = param_type, })); } else { bh_arr_push(slns, ((AstPolySolution) { @@ -492,6 +511,10 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) { fori (i, 0, type_count) { assert(ctype->types[i] != NULL); comp_type->Compound.types[i] = type_build_from_ast(alloc, ctype->types[i]); + + // LEAK LEAK LEAK + if (comp_type->Compound.types[i] == NULL) return NULL; + comp_type->Compound.size += bh_max(type_size_of(comp_type->Compound.types[i]), 4); } @@ -512,15 +535,19 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) { return NULL; } +// CLEANUP: This needs to be merged with the very similar code from up above. Type* type_build_function_type(bh_allocator alloc, AstFunction* func) { u64 param_count = bh_arr_length(func->params); + Type* return_type = type_build_from_ast(alloc, func->return_type); + if (return_type == NULL) return NULL; + Type* func_type = bh_alloc(alloc, sizeof(Type) + sizeof(Type *) * param_count); func_type->kind = Type_Kind_Function; func_type->Function.param_count = param_count; func_type->Function.needed_param_count = 0; - func_type->Function.return_type = type_build_from_ast(alloc, func->return_type); + func_type->Function.return_type = return_type; if (param_count > 0) { i32 i = 0; diff --git a/src/onyxutils.c b/src/onyxutils.c index 6717d882..b67a66f1 100644 --- a/src/onyxutils.c +++ b/src/onyxutils.c @@ -1225,50 +1225,29 @@ AstStructType* polymorphic_struct_lookup(AstPolyStructType* ps_type, bh_arr(AstP char* unique_key = build_poly_slns_unique_key(slns); if (bh_table_has(AstStructType *, ps_type->concrete_structs, unique_key)) { - return bh_table_get(AstStructType *, ps_type->concrete_structs, unique_key); - } + AstStructType* concrete_struct = bh_table_get(AstStructType *, ps_type->concrete_structs, unique_key); - scope_clear(ps_type->scope); - insert_poly_slns_into_scope(ps_type->scope, slns); + if (concrete_struct->entity_type->state < Entity_State_Check_Types) { + return NULL; + } - AstStructType* concrete_struct = (AstStructType *) ast_clone(context.ast_alloc, ps_type->base_struct); - bh_table_put(AstStructType *, ps_type->concrete_structs, unique_key, concrete_struct); + Type* cs_type = type_build_from_ast(context.ast_alloc, (AstType *) concrete_struct); + if (!cs_type) return NULL; - Entity struct_entity = { - .state = Entity_State_Resolve_Symbols, - .type = Entity_Type_Type_Alias, - .type_alias = (AstType *) concrete_struct, - .package = NULL, - .scope = ps_type->scope, - }; - Entity struct_default_entity = { - .state = Entity_State_Resolve_Symbols, - .type = Entity_Type_Struct_Member_Default, - .type_alias = (AstType *) concrete_struct, - .package = NULL, - .scope = ps_type->scope, - }; + if (cs_type->Struct.poly_sln == NULL) cs_type->Struct.poly_sln = bh_arr_copy(global_heap_allocator, slns); + if (cs_type->Struct.name == NULL) cs_type->Struct.name = build_poly_struct_name(ps_type, cs_type); - entity_bring_to_state(&struct_entity, Entity_State_Check_Types); - entity_bring_to_state(&struct_default_entity, Entity_State_Check_Types); - entity_bring_to_state(&struct_entity, Entity_State_Code_Gen); - entity_bring_to_state(&struct_default_entity, Entity_State_Code_Gen); - - if (onyx_has_errors()) { - onyx_report_error(pos, "Error in creating polymorphic struct instantiation here."); - bh_table_put(AstStructType *, ps_type->concrete_structs, unique_key, NULL); - return NULL; + return concrete_struct; } - Type* cs_type = type_build_from_ast(context.ast_alloc, (AstType *) concrete_struct); + Scope* sln_scope = scope_create(context.ast_alloc, ps_type->scope, ps_type->token->pos); + insert_poly_slns_into_scope(sln_scope, slns); - // CLEANUP: This should not be necessary since the only place this function can be - // called from is type_build_from_ast in the Ast_Kind_Poly_Call_Type case, which - // allocates the 'slns' array on the heap. So, duplicating it should not be necessary. - cs_type->Struct.poly_sln = bh_arr_copy(global_heap_allocator, slns); + AstStructType* concrete_struct = (AstStructType *) ast_clone(context.ast_alloc, ps_type->base_struct); + bh_table_put(AstStructType *, ps_type->concrete_structs, unique_key, concrete_struct); - cs_type->Struct.name = build_poly_struct_name(ps_type, cs_type); - return concrete_struct; + add_entities_for_node(NULL, (AstNode *) concrete_struct, sln_scope, NULL); + return NULL; } void entity_bring_to_state(Entity* ent, EntityState state) {