From: Brendan Hansen Date: Thu, 28 Apr 2022 21:37:13 +0000 (-0500) Subject: polymorphic structures are very powerful now X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=ba5cc206f99cca83b3ed47b6910733c479371723;p=onyx.git polymorphic structures are very powerful now --- diff --git a/include/astnodes.h b/include/astnodes.h index d5433347..f7cb2740 100644 --- a/include/astnodes.h +++ b/include/astnodes.h @@ -912,9 +912,13 @@ struct AstStructType { OnyxFilePos polymorphic_error_loc; ConstraintContext constraints; + bh_arr(AstType *) polymorphic_argument_types; + bh_arr(AstPolySolution) polymorphic_arguments; + b32 pending_type_is_valid : 1; b32 is_union : 1; b32 is_packed : 1; + b32 ready_to_build_type : 1; }; struct AstStructMember { AstTyped_base; diff --git a/src/checker.c b/src/checker.c index f788ddd6..5c4be2e1 100644 --- a/src/checker.c +++ b/src/checker.c @@ -1350,6 +1350,9 @@ CheckStatus check_range_literal(AstRangeLiteral** prange) { CHECK(expression, &range->low); CHECK(expression, &range->high); + builtin_range_type_type = type_build_from_ast(context.ast_alloc, builtin_range_type); + if (builtin_range_type_type == NULL) YIELD(range->token->pos, "Waiting for 'range' structure to be built."); + Type* expected_range_type = builtin_range_type_type; StructMember smem; @@ -2151,6 +2154,24 @@ CheckStatus check_struct(AstStructType* s_node) { if (s_node->entity_defaults && s_node->entity_defaults->state < Entity_State_Check_Types) YIELD(s_node->token->pos, "Waiting for struct member defaults to pass symbol resolution."); + if (s_node->polymorphic_argument_types) { + assert(s_node->polymorphic_arguments); + + fori (i, 0, (i64) bh_arr_length(s_node->polymorphic_argument_types)) { + Type *arg_type = type_build_from_ast(context.ast_alloc, s_node->polymorphic_argument_types[i]); + if (arg_type == NULL) YIELD(s_node->polymorphic_argument_types[i]->token->pos, "Waiting to build type for polymorph argument."); + + // nocheckin this is wrong... + if (s_node->polymorphic_arguments[i].value) { + TYPE_CHECK(&s_node->polymorphic_arguments[i].value, arg_type) { + ERROR_(s_node->polymorphic_arguments[i].value->token->pos, "Expected value of type %s, got %s.", + type_get_name(arg_type), + type_get_name(s_node->polymorphic_arguments[i].value->type)); + } + } + } + } + if (s_node->constraints.constraints) { s_node->constraints.produce_errors = (s_node->flags & Ast_Flag_Header_Check_No_Error) == 0; @@ -2192,6 +2213,7 @@ CheckStatus check_struct(AstStructType* s_node) { } // NOTE: fills in the pending_type. + s_node->ready_to_build_type = 1; type_build_from_ast(context.ast_alloc, (AstType *) s_node); if (s_node->pending_type == NULL || !s_node->pending_type_is_valid) YIELD(s_node->token->pos, "Waiting for type to be constructed."); diff --git a/src/polymorph.h b/src/polymorph.h index d7974ada..0185b8f3 100644 --- a/src/polymorph.h +++ b/src/polymorph.h @@ -1043,45 +1043,6 @@ Type* polymorphic_struct_lookup(AstPolyStructType* ps_type, bh_arr(AstPolySoluti i32 i = 0; bh_arr_each(AstPolySolution, sln, slns) { sln->poly_sym = (AstNode *) &ps_type->poly_params[i]; - - PolySolutionKind expected_kind = PSK_Undefined; - if ((AstNode *) ps_type->poly_params[i].type_node == (AstNode *) &basic_type_type_expr) { - expected_kind = PSK_Type; - } else { - expected_kind = PSK_Value; - } - - if (sln->kind != expected_kind) { - if (expected_kind == PSK_Type) - onyx_report_error(pos, Error_Critical, "Expected type expression for %d%s argument.", i + 1, bh_num_suffix(i + 1)); - - if (expected_kind == PSK_Value) - onyx_report_error(pos, Error_Critical, "Expected value expression of type '%s' for %d%s argument.", - type_get_name(ps_type->poly_params[i].type), - i + 1, bh_num_suffix(i + 1)); - - return NULL; - } - - if (sln->kind == PSK_Value) { - resolve_expression_type(sln->value); - - if ((sln->value->flags & Ast_Flag_Comptime) == 0) { - onyx_report_error(pos, Error_Critical, - "Expected compile-time known argument for '%b'.", - sln->poly_sym->token->text, - sln->poly_sym->token->length); - return NULL; - } - - if (!types_are_compatible(sln->value->type, ps_type->poly_params[i].type)) { - onyx_report_error(pos, Error_Critical, "Expected compile-time argument of type '%s', got '%s'.", - type_get_name(ps_type->poly_params[i].type), - type_get_name(sln->value->type)); - return NULL; - } - } - i++; } @@ -1113,8 +1074,18 @@ Type* polymorphic_struct_lookup(AstPolyStructType* ps_type, bh_arr(AstPolySoluti AstStructType* concrete_struct = (AstStructType *) ast_clone(context.ast_alloc, ps_type->base_struct); concrete_struct->polymorphic_error_loc = pos; BH_MASK_SET(concrete_struct->flags, !error_if_failed, Ast_Flag_Header_Check_No_Error); - shput(ps_type->concrete_structs, unique_key, concrete_struct); + + i64 arg_count = bh_arr_length(ps_type->poly_params); + bh_arr_new(global_heap_allocator, concrete_struct->polymorphic_argument_types, arg_count); + bh_arr_set_length(concrete_struct->polymorphic_argument_types, arg_count); + concrete_struct->polymorphic_arguments = bh_arr_copy(global_heap_allocator, slns); + + fori (i, 0, (i64) bh_arr_length(ps_type->poly_params)) { + concrete_struct->polymorphic_argument_types[i] = (AstType *) ast_clone(context.ast_alloc, ps_type->poly_params[i].type_node); + } + + shput(ps_type->concrete_structs, unique_key, concrete_struct); add_entities_for_node(NULL, (AstNode *) concrete_struct, sln_scope, NULL); return NULL; } diff --git a/src/symres.c b/src/symres.c index 503073a9..16963611 100644 --- a/src/symres.c +++ b/src/symres.c @@ -119,6 +119,21 @@ static SymresStatus symres_struct_type(AstStructType* s_node) { scope_enter(s_node->scope); } + if (s_node->polymorphic_argument_types) { + assert(s_node->polymorphic_arguments); + + SymresStatus ss = Symres_Success, result; + fori (i, 0, (i64) bh_arr_length(s_node->polymorphic_argument_types)) { + result = symres_type(&s_node->polymorphic_argument_types[i]); + if (result > ss) ss = result; + + if (s_node->polymorphic_arguments[i].value) { + result = symres_expression(&s_node->polymorphic_arguments[i].value); + if (result > ss) ss = result; + } + } + } + if (s_node->constraints.constraints) { bh_arr_each(AstConstraint *, constraint, s_node->constraints.constraints) { SYMRES(constraint, *constraint); @@ -190,19 +205,6 @@ static SymresStatus symres_type(AstType** type) { if (pst_node->scope == NULL) { pst_node->scope = scope_create(context.ast_alloc, pst_node->entity->scope, pst_node->token->pos); } - - bh_arr_each(AstPolyStructParam, param, pst_node->poly_params) { - SYMRES(type, ¶m->type_node); - param->type = type_build_from_ast(context.ast_alloc, param->type_node); - if (param->type == NULL) { - if (context.cycle_detected) { - onyx_report_error(param->token->pos, Error_Waiting_On, "Waiting for parameter type to be known."); - return Symres_Error; - } else { - return Symres_Yield_Macro; - } - } - } break; } @@ -494,10 +496,6 @@ static SymresStatus symres_expression(AstTyped** expr) { // :EliminatingSymres SYMRES(type, &builtin_range_type); (*expr)->type_node = builtin_range_type; - - // NOTE: This is a weird place to put this so maybe put it somewhere else eventually - // - brendanfh 2020/09/04 - builtin_range_type_type = type_build_from_ast(context.ast_alloc, builtin_range_type); break; case Ast_Kind_Function: diff --git a/src/types.c b/src/types.c index 9665af33..ec750c46 100644 --- a/src/types.c +++ b/src/types.c @@ -337,6 +337,7 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) { AstStructType* s_node = (AstStructType *) type_node; if (s_node->stcache != NULL) return s_node->stcache; if (s_node->pending_type != NULL && s_node->pending_type_is_valid) return s_node->pending_type; + if (!s_node->ready_to_build_type) return NULL; Type* s_type; if (s_node->pending_type == NULL) { diff --git a/src/wasm_type_table.h b/src/wasm_type_table.h index 27514284..b080855c 100644 --- a/src/wasm_type_table.h +++ b/src/wasm_type_table.h @@ -222,9 +222,12 @@ u64 build_type_table(OnyxWasmModule* module) { bh_buffer_grow(&table_buffer, table_buffer.length + size); u8* buffer = table_buffer.data + table_buffer.length; - emit_raw_data(module, buffer, sln->value); - table_buffer.length += size; - break; + if (emit_raw_data_(module, buffer, sln->value)) { + table_buffer.length += size; + break; + } + + // fallthrough } default: { diff --git a/tests/aoc-2020/day7.onyx b/tests/aoc-2020/day7.onyx index c5be6ba6..434e70fb 100644 --- a/tests/aoc-2020/day7.onyx +++ b/tests/aoc-2020/day7.onyx @@ -5,7 +5,7 @@ reader :: package core.string.reader BagGraph :: struct { nodes : [..] ^BagNode; - node_map : map.Map(str, #type ^BagNode); + node_map : map.Map(str, ^BagNode); } BagNode :: struct {