From: Brendan Hansen Date: Fri, 8 Jan 2021 19:58:28 +0000 (-0600) Subject: polymorphic structures have compile time known arguments X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=9f3fbd7445337c7979edbde7b90da6e5c00dd706;p=onyx.git polymorphic structures have compile time known arguments --- diff --git a/bin/onyx b/bin/onyx index e5324355..ab0104e3 100755 Binary files a/bin/onyx and b/bin/onyx differ diff --git a/core/map.onyx b/core/map.onyx index 74fc99ed..5d05c0da 100644 --- a/core/map.onyx +++ b/core/map.onyx @@ -4,7 +4,7 @@ use package core { printf } use package core.array as array use package core.string as string -Map :: struct ($K, $V) { +Map :: struct (K: type_expr, V: type_expr) { hashes : [..] i32; entries : [..] MapEntry(K, V); @@ -12,10 +12,10 @@ Map :: struct ($K, $V) { default_value : V; } -MapEntry :: struct ($K, $T) { +MapEntry :: struct (K: type_expr, V: type_expr) { next : i32; key : K; - value : T; + value : V; } init :: proc (use map: ^Map($K, $V), dv: V = ~~0, hash_count: i32 = 16) { diff --git a/include/onyxastnodes.h b/include/onyxastnodes.h index 42485c5a..aadbb47a 100644 --- a/include/onyxastnodes.h +++ b/include/onyxastnodes.h @@ -50,6 +50,7 @@ typedef struct AstVarArgType AstVarArgType; typedef struct AstStructType AstStructType; typedef struct AstStructMember AstStructMember; typedef struct AstPolyStructType AstPolyStructType; +typedef struct AstPolyStructParam AstPolyStructParam; typedef struct AstPolyCallType AstPolyCallType; typedef struct AstEnumType AstEnumType; typedef struct AstEnumValue AstEnumValue; @@ -630,11 +631,14 @@ struct AstStructMember { AstTyped_base; AstTyped* initial_value; }; +struct AstPolyStructParam { + AstTyped_base; +}; struct AstPolyStructType { AstType_base; Scope *scope; - bh_arr(OnyxToken *) poly_params; + bh_arr(AstPolyStructParam) poly_params; bh_table(AstStructType *) concrete_structs; AstStructType* base_struct; @@ -643,7 +647,9 @@ struct AstPolyCallType { AstType_base; AstType* callee; - bh_arr(AstType *) params; + + // NOTE: These nodes can be either AstTypes, or AstTyped expressions. + bh_arr(AstNode *) params; }; struct AstEnumType { AstType_base; @@ -745,6 +751,7 @@ struct AstPolyParam { }; typedef enum PolySolutionKind { + PSK_Undefined, PSK_Type, PSK_Value, } PolySolutionKind; @@ -905,6 +912,9 @@ extern AstBasicType basic_type_rawptr; extern AstBasicType basic_type_int_unsized; extern AstBasicType basic_type_float_unsized; +// :TypeExprHack +extern AstNode type_expr_symbol; + extern AstNode builtin_package_node; extern AstNumLit builtin_heap_start; extern AstGlobal builtin_stack_top; @@ -953,7 +963,7 @@ AstFunction* polymorphic_proc_solidify(AstPolyProc* pp, bh_arr(AstPolySolution) AstNode* polymorphic_proc_try_solidify(AstPolyProc* pp, bh_arr(AstPolySolution) slns, OnyxFilePos pos); -AstStructType* polymorphic_struct_lookup(AstPolyStructType* ps_type, bh_arr(Type *) params, OnyxFilePos pos); +AstStructType* polymorphic_struct_lookup(AstPolyStructType* ps_type, bh_arr(AstPolySolution) slns, OnyxFilePos pos); // NOTE: Useful inlined functions static inline b32 is_lval(AstNode* node) { diff --git a/include/onyxtypes.h b/include/onyxtypes.h index 526eddcb..9d951021 100644 --- a/include/onyxtypes.h +++ b/include/onyxtypes.h @@ -88,7 +88,7 @@ typedef struct StructMember { u16 alignment, mem_count; \ bh_table(StructMember) members; \ bh_arr(StructMember *) memarr; \ - bh_arr(Type *) poly_args; \ + bh_arr(struct AstPolySolution) poly_sln; \ }) \ TYPE_KIND(Array, struct { u32 size; u32 count; Type *elem; }) \ TYPE_KIND(Slice, struct { Type *ptr_to_data; }) \ diff --git a/onyx.exe b/onyx.exe index 432a5a5e..4f9b9084 100644 Binary files a/onyx.exe and b/onyx.exe differ diff --git a/src/onyxbuiltins.c b/src/onyxbuiltins.c index 54b2553f..2eb3edc8 100644 --- a/src/onyxbuiltins.c +++ b/src/onyxbuiltins.c @@ -38,6 +38,10 @@ static OnyxToken builtin_stack_top_token = { Token_Type_Symbol, 11, "__stack_to AstNumLit builtin_heap_start = { Ast_Kind_NumLit, Ast_Flag_Const, &builtin_heap_start_token, NULL, (AstType *) &basic_type_rawptr, NULL, 0 }; AstGlobal builtin_stack_top = { Ast_Kind_Global, Ast_Flag_Const | Ast_Flag_Global_Stack_Top, &builtin_stack_top_token, NULL, (AstType *) &basic_type_rawptr, NULL }; +// :TypeExprHack +static OnyxToken type_expr_token = { Token_Type_Symbol, 9, "type_expr", { 0 } }; +AstNode type_expr_symbol = { Ast_Kind_Basic_Type, 0, &type_expr_token, NULL }; + AstType *builtin_string_type; AstType *builtin_range_type; Type *builtin_range_type_type; @@ -59,6 +63,7 @@ const BuiltinSymbol builtin_symbols[] = { { NULL, "f32", (AstNode *) &basic_type_f32 }, { NULL, "f64", (AstNode *) &basic_type_f64 }, { NULL, "rawptr", (AstNode *) &basic_type_rawptr }, + { NULL, "type_expr", (AstNode *) &type_expr_symbol }, { "simd", "i8x16", (AstNode *) &basic_type_i8x16 }, { "simd", "i16x8", (AstNode *) &basic_type_i16x8 }, diff --git a/src/onyxchecker.c b/src/onyxchecker.c index 39428feb..54f074b2 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -46,6 +46,8 @@ CheckStatus check_function_header(AstFunction* func); CheckStatus check_memres_type(AstMemRes* memres); CheckStatus check_memres(AstMemRes* memres); +static inline void fill_in_type(AstTyped* node); + static inline void fill_in_array_count(AstType* type_node) { if (type_node == NULL) return; @@ -61,8 +63,24 @@ static inline void fill_in_array_count(AstType* type_node) { } } +static inline void fill_in_poly_call_args(AstType* type_node) { + if (type_node == NULL) return; + if (type_node->kind != Ast_Kind_Poly_Call_Type) return; + + AstPolyCallType* pctype = (AstPolyCallType *) type_node; + + bh_arr_each(AstNode *, param, pctype->params) { + if (!node_is_type(*param)) { + check_expression((AstTyped **) param); + resolve_expression_type((AstTyped *) *param); + fill_in_type((AstTyped *) *param); + } + } +} + static inline void fill_in_type(AstTyped* node) { fill_in_array_count(node->type_node); + fill_in_poly_call_args(node->type_node); if (node->type == NULL) node->type = type_build_from_ast(semstate.allocator, node->type_node); @@ -952,7 +970,7 @@ CheckStatus check_struct_literal(AstStructLiteral* sl) { token_toggle_end((*smem)->token); if (s.included_through_use) { - onyx_report_error((*smem)->token->pos, "Cannot specify value for member '%s', whic was included through a 'use' statement.", s.name); + onyx_report_error((*smem)->token->pos, "Cannot specify value for member '%s', which was included through a 'use' statement.", s.name); return Check_Error; } @@ -969,7 +987,7 @@ CheckStatus check_struct_literal(AstStructLiteral* sl) { u32 idx = (*smem)->idx; if (sl->values[idx] == NULL) { - if ((*smem)->initial_value == NULL) { + if (*(*smem)->initial_value == NULL) { onyx_report_error(sl->token->pos, "No value was given for the field '%s'.", (*smem)->name); return Check_Error; } diff --git a/src/onyxclone.c b/src/onyxclone.c index 85d71863..9d04ebe6 100644 --- a/src/onyxclone.c +++ b/src/onyxclone.c @@ -335,8 +335,8 @@ AstNode* ast_clone(bh_allocator a, void* n) { pcd->params = NULL; bh_arr_new(global_heap_allocator, pcd->params, bh_arr_length(pcs->params)); - bh_arr_each(AstType *, param, pcs->params) { - bh_arr_push(pcd->params, (AstType *) ast_clone(a, *param)); + bh_arr_each(AstNode *, param, pcs->params) { + bh_arr_push(pcd->params, ast_clone(a, *param)); } break; diff --git a/src/onyxparser.c b/src/onyxparser.c index 9af7c208..a35f11b3 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -1515,13 +1515,13 @@ static AstType* parse_type(OnyxParser* parser) { if (parser->curr->type == '(') { OnyxToken* paren_token = expect_token(parser, '('); - bh_arr(AstType *) params = NULL; + bh_arr(AstNode *) params = NULL; bh_arr_new(global_heap_allocator, params, 2); while (parser->curr->type != ')') { if (parser->hit_unexpected_token) break; - AstType* t = parse_type(parser); + AstNode* t = (AstNode *) parse_type(parser); bh_arr_push(params, t); if (parser->curr->type != ')') @@ -1587,15 +1587,22 @@ static AstStructType* parse_struct(OnyxParser* parser) { if (parser->curr->type == '(') { consume_token(parser); - bh_arr(OnyxToken *) poly_params = NULL; + bh_arr(AstPolyStructParam) poly_params = NULL; bh_arr_new(global_heap_allocator, poly_params, 1); - while (parser->curr->type == '$') { - consume_token(parser); + while (parser->curr->type != ')') { if (parser->hit_unexpected_token) return NULL; OnyxToken* sym_token = expect_token(parser, Token_Type_Symbol); - bh_arr_push(poly_params, sym_token); + expect_token(parser, ':'); + + AstType* param_type = parse_type(parser); + + bh_arr_push(poly_params, ((AstPolyStructParam) { + .token = sym_token, + .type_node = param_type, + .type = NULL, + })); if (parser->curr->type != ')') expect_token(parser, ','); diff --git a/src/onyxsymres.c b/src/onyxsymres.c index 4ae95bfe..3f9feb93 100644 --- a/src/onyxsymres.c +++ b/src/onyxsymres.c @@ -192,6 +192,11 @@ AstType* symres_type(AstType* type) { AstPolyStructType* pst_node = (AstPolyStructType *) type; pst_node->scope = scope_create(semstate.node_allocator, semstate.curr_scope, pst_node->token->pos); + bh_arr_each(AstPolyStructParam, param, pst_node->poly_params) { + param->type_node = symres_type(param->type_node); + param->type = type_build_from_ast(semstate.node_allocator, param->type_node); + } + return type; } @@ -200,8 +205,12 @@ AstType* symres_type(AstType* type) { pc_node->callee = symres_type(pc_node->callee); - bh_arr_each(AstType *, param, pc_node->params) { - *param = symres_type(*param); + bh_arr_each(AstNode *, param, pc_node->params) { + if (node_is_type(*param)) { + *param = (AstNode *) symres_type((AstType *) *param); + } else { + symres_expression((AstTyped **) param); + } } return type; @@ -814,28 +823,13 @@ static void symres_memres(AstMemRes** memres) { } static void symres_struct_defaults(AstType* t) { - switch (t->kind) { - case Ast_Kind_Struct_Type: { - AstStructType* st = (AstStructType *) t; - bh_arr_each(AstStructMember *, smem, st->members) { - if ((*smem)->initial_value != NULL) { - symres_expression(&(*smem)->initial_value); - } - } - break; - } - - case Ast_Kind_Poly_Struct_Type: { - AstPolyStructType* st = (AstPolyStructType *) t; - bh_arr_each(AstStructMember *, smem, st->base_struct->members) { - if ((*smem)->initial_value != NULL) { - symres_expression(&(*smem)->initial_value); - } - } - break; + if (t->kind != Ast_Kind_Struct_Type) return; + + AstStructType* st = (AstStructType *) t; + bh_arr_each(AstStructMember *, smem, st->members) { + if ((*smem)->initial_value != NULL) { + symres_expression(&(*smem)->initial_value); } - - default: break; } } diff --git a/src/onyxtypes.c b/src/onyxtypes.c index e23f163e..5eaea925 100644 --- a/src/onyxtypes.c +++ b/src/onyxtypes.c @@ -475,15 +475,27 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) { AstPolyStructType* ps_type = (AstPolyStructType *) pc_type->callee; - bh_arr(Type *) param_types = NULL; - bh_arr_new(global_heap_allocator, param_types, bh_arr_length(pc_type->params)); - bh_arr_each(AstType *, ptype, pc_type->params) { - bh_arr_push(param_types, type_build_from_ast(alloc, *ptype)); + bh_arr(AstPolySolution) slns = NULL; + 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)) { + bh_arr_push(slns, ((AstPolySolution) { + .kind = PSK_Type, + .type = type_build_from_ast(alloc, (AstType *) *given), + })); + } else { + bh_arr_push(slns, ((AstPolySolution) { + .kind = PSK_Value, + .value = (AstTyped *) *given, + })); + } } - AstStructType* concrete = polymorphic_struct_lookup(ps_type, param_types, pc_type->token->pos); + AstStructType* concrete = polymorphic_struct_lookup(ps_type, slns, pc_type->token->pos); - bh_arr_free(param_types); + // This should be copied in the previous function. + // CLEANUP: Maybe don't copy it and just use this one since it is allocated on the heap? + bh_arr_free(slns); return type_build_from_ast(alloc, (AstType *) concrete); } diff --git a/src/onyxutils.c b/src/onyxutils.c index aa9b4f37..1813e98a 100644 --- a/src/onyxutils.c +++ b/src/onyxutils.c @@ -450,10 +450,11 @@ static PolySolveResult solve_poly_type(AstNode* target, AstType* type_expr, Type bh_arr(PolySolveElem) elem_queue = NULL; bh_arr_new(global_heap_allocator, elem_queue, 4); - PolySolveResult result = { -1, { NULL } }; + PolySolveResult result = { PSK_Undefined, { NULL } }; bh_arr_push(elem_queue, ((PolySolveElem) { .type_expr = type_expr, + .kind = PSK_Type, .actual = actual })); @@ -463,11 +464,10 @@ static PolySolveResult solve_poly_type(AstNode* target, AstType* type_expr, Type if (elem.type_expr == (AstType *) target) { result.kind = elem.kind; - if (result.kind == PSK_Type) { - result.actual = elem.actual; - } else { - result.value = elem.value; - } + + assert(elem.kind != PSK_Undefined); + if (result.kind == PSK_Type) result.actual = elem.actual; + if (result.kind == PSK_Value) result.value = elem.value; break; } @@ -556,16 +556,25 @@ static PolySolveResult solve_poly_type(AstNode* target, AstType* type_expr, Type case Ast_Kind_Poly_Call_Type: { if (elem.actual->kind != Type_Kind_Struct) break; - if (bh_arr_length(elem.actual->Struct.poly_args) != bh_arr_length(((AstPolyCallType *) elem.type_expr)->params)) break; + if (bh_arr_length(elem.actual->Struct.poly_sln) != bh_arr_length(((AstPolyCallType *) elem.type_expr)->params)) break; AstPolyCallType* pt = (AstPolyCallType *) elem.type_expr; fori (i, 0, bh_arr_length(pt->params)) { - bh_arr_push(elem_queue, ((PolySolveElem) { - .type_expr = pt->params[i], - .kind = PSK_Type, - .actual = elem.actual->Struct.poly_args[i], - })); + PolySolutionKind kind = elem.actual->Struct.poly_sln[i].kind; + if (kind == PSK_Type) { + bh_arr_push(elem_queue, ((PolySolveElem) { + .kind = kind, + .type_expr = (AstType *) pt->params[i], + .actual = elem.actual->Struct.poly_sln[i].type, + })); + } else { + bh_arr_push(elem_queue, ((PolySolveElem) { + .kind = kind, + .type_expr = (AstType *) pt->params[i], + .value = elem.actual->Struct.poly_sln[i].value, + })); + } } break; @@ -630,7 +639,7 @@ AstFunction* polymorphic_proc_lookup(AstPolyProc* pp, PolyProcLookupMethod pp_lo PolySolveResult resolved = solve_poly_type(param->poly_sym, param->type_expr, actual_type); switch (resolved.kind) { - case -1: + case PSK_Undefined: onyx_report_error(pos, "Unable to solve for polymoprhic variable '%b', using the type '%s'.", param->poly_sym->token->text, @@ -691,7 +700,7 @@ static char* build_poly_solution_key(AstPolySolution* sln) { } // NOTE: This returns a volatile string. Do not store it without copying it. -static char* build_polyproc_unique_key(bh_arr(AstPolySolution) slns) { +static char* build_poly_slns_unique_key(bh_arr(AstPolySolution) slns) { static char key_buf[1024]; fori (i, 0, 1024) key_buf[i] = 0; @@ -715,7 +724,7 @@ AstFunction* polymorphic_proc_solidify(AstPolyProc* pp, bh_arr(AstPolySolution) } // NOTE: Check if a version of this polyproc has already been created. - char* unique_key = build_polyproc_unique_key(slns); + char* unique_key = build_poly_slns_unique_key(slns); if (bh_table_has(AstFunction *, pp->concrete_funcs, unique_key)) { return bh_table_get(AstFunction *, pp->concrete_funcs, unique_key); } @@ -826,81 +835,160 @@ AstNode* polymorphic_proc_try_solidify(AstPolyProc* pp, bh_arr(AstPolySolution) } } +char* build_poly_struct_name(AstPolyStructType* ps_type, Type* cs_type) { + char name_buf[256]; + fori (i, 0, 256) name_buf[i] = 0; + + strncat(name_buf, ps_type->name, 255); + strncat(name_buf, "(", 255); + bh_arr_each(AstPolySolution, ptype, cs_type->Struct.poly_sln) { + if (ptype != cs_type->Struct.poly_sln) + strncat(name_buf, ", ", 255); + + // This logic will have to be other places as well. + + switch (ptype->kind) { + case PSK_Undefined: assert(0); break; + case PSK_Type: strncat(name_buf, type_get_name(ptype->type), 255); break; + case PSK_Value: { + // FIX + if (ptype->value->kind == Ast_Kind_NumLit) { + AstNumLit* nl = (AstNumLit *) ptype->value; + if (type_is_integer(nl->type)) { + strncat(name_buf, bh_bprintf("%l", nl->value.l), 127); + } else { + strncat(name_buf, "numlit (FIX ME)", 127); + } + } else { + strncat(name_buf, "", 127); + } + + break; + } + } + } + strncat(name_buf, ")", 255); + + return bh_aprintf(global_heap_allocator, "%s", name_buf); +} -AstStructType* polymorphic_struct_lookup(AstPolyStructType* ps_type, bh_arr(Type *) params, OnyxFilePos pos) { +AstStructType* polymorphic_struct_lookup(AstPolyStructType* ps_type, bh_arr(AstPolySolution) slns, OnyxFilePos pos) { // @Cleanup - assert(bh_arr_length(ps_type->poly_params) == bh_arr_length(params)); assert(ps_type->scope != NULL); if (ps_type->concrete_structs == NULL) { bh_table_init(global_heap_allocator, ps_type->concrete_structs, 16); } - scope_clear(ps_type->scope); + if (bh_arr_length(slns) < bh_arr_length(ps_type->poly_params)) { + onyx_report_error(pos, "Not enough arguments for polymorphic struct creation. Expected %d, got %d", + bh_arr_length(ps_type->poly_params), + bh_arr_length(slns)); - fori (i, 0, bh_arr_length(ps_type->poly_params)) { - if (params[i] == NULL) { - onyx_report_error((OnyxFilePos) { 0 }, "Type parameter is not a type."); - return NULL; + return NULL; + } + + i32 i = 0; + bh_arr_each(AstPolySolution, sln, slns) { + PolySolutionKind expected_kind = PSK_Undefined; + if ((AstNode *) ps_type->poly_params[i].type_node == &type_expr_symbol) { + expected_kind = PSK_Type; + } else { + expected_kind = PSK_Value; } - AstTypeRawAlias* raw = onyx_ast_node_new(semstate.node_allocator, sizeof(AstTypeRawAlias), Ast_Kind_Type_Raw_Alias); - raw->to = params[i]; + if (sln->kind != expected_kind) { + if (expected_kind == PSK_Type) + onyx_report_error(pos, "Expected type expression for %d%s argument.", i + 1, bh_num_suffix(i + 1)); - symbol_introduce(ps_type->scope, ps_type->poly_params[i], (AstNode *) raw); - } + if (expected_kind == PSK_Value) + onyx_report_error(pos, "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)); - char key_buf[1024]; - fori (i, 0, 1024) key_buf[i] = 0; - bh_table_each_start(AstNode *, ps_type->scope->symbols); - strncat(key_buf, key, 1023); - strncat(key_buf, "=", 1023); - strncat(key_buf, type_get_unique_name(((AstTypeRawAlias *) value)->to), 1023); - strncat(key_buf, ";", 1023); - bh_table_each_end; + return NULL; + } + + if (sln->kind == PSK_Value) { + if ((sln->value->flags & Ast_Flag_Comptime) == 0) { + onyx_report_error(pos, + "Expected compile-time known argument for '%b'.", + sln->poly_sym->token->text, + sln->poly_sym->token->length); + return NULL; + } - if (bh_table_has(AstStructType *, ps_type->concrete_structs, key_buf)) { - return bh_table_get(AstStructType *, ps_type->concrete_structs, key_buf); + if (!types_are_compatible(sln->value->type, ps_type->poly_params[i].type)) { + onyx_report_error(pos, "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; + } + } + + sln->poly_sym = (AstNode *) &ps_type->poly_params[i]; + i++; } - AstStructType* concrete_struct = (AstStructType *) ast_clone(semstate.node_allocator, ps_type->base_struct); + 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); + } - Scope* old_scope = semstate.curr_scope; - semstate.curr_scope = ps_type->scope; - concrete_struct = (AstStructType *) symres_type((AstType *) concrete_struct); - semstate.curr_scope = old_scope; + scope_clear(ps_type->scope); - if (onyx_has_errors()) goto has_error; - goto no_errors; + bh_arr_each(AstPolySolution, sln, slns) { + AstNode *node = NULL; + + switch (sln->kind) { + case PSK_Type: + node = onyx_ast_node_new(semstate.node_allocator, sizeof(AstTypeRawAlias), Ast_Kind_Type_Raw_Alias); + ((AstTypeRawAlias *) node)->to = sln->type; + break; -has_error: - // onyx_report_error(pos, "Error in polymorphic struct generated from this call site."); - return NULL; + case PSK_Value: + // CLEANUP: Maybe clone this? + node = (AstNode *) sln->value; + break; + } -no_errors: - bh_table_put(AstStructType *, ps_type->concrete_structs, key_buf, concrete_struct); + symbol_introduce(ps_type->scope, sln->poly_sym->token, node); + } - Type* cs_type = type_build_from_ast(semstate.node_allocator, (AstType *) concrete_struct); + AstStructType* concrete_struct = (AstStructType *) ast_clone(semstate.node_allocator, ps_type->base_struct); - cs_type->Struct.poly_args = NULL; - bh_arr_new(global_heap_allocator, cs_type->Struct.poly_args, bh_arr_length(params)); + 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, + }; - fori (i, 0, bh_arr_length(params)) bh_arr_push(cs_type->Struct.poly_args, params[i]); + 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 polymoprhic struct instantiation here."); + return NULL; + } - char name_buf[256]; - fori (i, 0, 256) name_buf[i] = 0; + bh_table_put(AstStructType *, ps_type->concrete_structs, unique_key, concrete_struct); - strncat(name_buf, ps_type->name, 255); - strncat(name_buf, "(", 255); - bh_arr_each(Type *, ptype, cs_type->Struct.poly_args) { - if (ptype != cs_type->Struct.poly_args) - strncat(name_buf, ", ", 255); + Type* cs_type = type_build_from_ast(semstate.node_allocator, (AstType *) concrete_struct); + cs_type->Struct.poly_sln = NULL; + bh_arr_new(global_heap_allocator, cs_type->Struct.poly_sln, bh_arr_length(slns)); - strncat(name_buf, type_get_name(*ptype), 255); - } - strncat(name_buf, ")", 255); - cs_type->Struct.name = bh_aprintf(semstate.node_allocator, "%s", name_buf); + fori (i, 0, bh_arr_length(slns)) bh_arr_push(cs_type->Struct.poly_sln, slns[i]); + cs_type->Struct.name = build_poly_struct_name(ps_type, cs_type); return concrete_struct; } diff --git a/tests/poly_structs_with_values b/tests/poly_structs_with_values new file mode 100644 index 00000000..3d8fae79 --- /dev/null +++ b/tests/poly_structs_with_values @@ -0,0 +1,6 @@ +12345 +12345 +12345 +12345 +1234 +Hello World! diff --git a/tests/poly_structs_with_values.onyx b/tests/poly_structs_with_values.onyx new file mode 100644 index 00000000..38eb53ec --- /dev/null +++ b/tests/poly_structs_with_values.onyx @@ -0,0 +1,27 @@ +#load "core/std/js" + +use package core + +main :: proc (args: [] cstr) { + + NewPolyStruct :: struct (T: type_expr, N: i32) { + x : [N] T; + y : [N] f32; + } + + nps : NewPolyStruct(i32, #value 4); + + for ^x: nps.x do *x = 12345; + for ^y: nps.y do *y = 67890; + + for x: nps.x do println(x); + + SimpleWithDefault :: struct (T: type_expr, default: str) { + x : T; + str_member : str = default; + } + + swd := .{ x = 1234 }; + println(swd.x); + println(swd.str_member); +} \ No newline at end of file diff --git a/tests/struct_robustness.onyx b/tests/struct_robustness.onyx index 2e3872a0..4e75fb46 100644 --- a/tests/struct_robustness.onyx +++ b/tests/struct_robustness.onyx @@ -105,7 +105,7 @@ main :: proc (args: [] cstr) { test_polymorphic :: proc () { println("\n\nTesting a polymorphic struct."); - PolyStruct :: struct ($T, $R) { + PolyStruct :: struct (T: type_expr, R: type_expr) { t_data : T; r_data : R; } @@ -124,7 +124,7 @@ main :: proc (args: [] cstr) { test_polymorphic_with_defaults :: proc () { println("\n\nTesting a polymorphic struct with default values."); - PolyStruct :: struct ($T, $R) { + PolyStruct :: struct (T: type_expr, R: type_expr) { t_data : T = 1234; r_data : R = 5678; } @@ -138,7 +138,7 @@ main :: proc (args: [] cstr) { test_polymorphic_union_with_use :: proc () { println("\n\nTesting a polymorphic union with use."); - PolyStruct :: struct ($T, $R) { + PolyStruct :: struct (T: type_expr, R: type_expr) { use container : struct #union { t_data : T; r_data : R; @@ -178,7 +178,7 @@ main :: proc (args: [] cstr) { test_polymorphic_union :: proc () { println("\n\nTesting a polymorphic union."); - PolyUnion :: struct ($T, $R) #union { + PolyUnion :: struct (T: type_expr, R: type_expr) #union { t_data : T; r_data : R; }