From f456d1caff29793a0981476771c79656f2121da0 Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Tue, 4 Jan 2022 10:05:57 -0600 Subject: [PATCH] improvements to poly struct parameter lookups --- core/builtin.onyx | 4 +-- core/container/iter.onyx | 2 +- core/container/map.onyx | 10 +++---- include/utils.h | 1 + scripts/run_tests.onyx | 2 +- src/checker.c | 62 +++++++++++++++++++++++++--------------- src/onyxrun.c | 2 +- src/symres.c | 3 -- src/utils.c | 57 ++++++++++++++++++++++++++---------- 9 files changed, 92 insertions(+), 51 deletions(-) diff --git a/core/builtin.onyx b/core/builtin.onyx index 5bdb9641..1993aa78 100644 --- a/core/builtin.onyx +++ b/core/builtin.onyx @@ -151,9 +151,9 @@ cfree :: (ptr: rawptr) do raw_free(context.allocator, ptr); } -Iterator :: struct (T: type_expr) { +Iterator :: struct (Iter_Type: type_expr) { data: rawptr; - next: (data: rawptr) -> (T, bool); + next: (data: rawptr) -> (Iter_Type, bool); close: (data: rawptr) -> void = null_proc; } diff --git a/core/container/iter.onyx b/core/container/iter.onyx index 60697ad6..6c903827 100644 --- a/core/container/iter.onyx +++ b/core/container/iter.onyx @@ -618,4 +618,4 @@ parallel_for :: #match {} #insert body; } } -} \ No newline at end of file +} diff --git a/core/container/map.onyx b/core/container/map.onyx index 8d0e6b68..5a2c9ade 100644 --- a/core/container/map.onyx +++ b/core/container/map.onyx @@ -21,16 +21,16 @@ package core.map } } -Map :: struct (K: type_expr, V: type_expr) where ValidKey(K) - [conv.Custom_Format.{ #solidify format_map {K=K, V=V} }] +Map :: struct (Key_Type: type_expr, Value_Type: type_expr) where ValidKey(Key_Type) + [conv.Custom_Format.{ #solidify format_map {K=Key_Type, V=Value_Type} }] { allocator : Allocator; hashes : [] i32; - entries : [..] Entry(K, V); + entries : [..] Entry(Key_Type, Value_Type); // The value provided by `map.get`, if nothing was found. - default_value : V; + default_value : Value_Type; Entry :: struct (K: type_expr, V: type_expr) { next : i32; @@ -71,7 +71,7 @@ free :: (use map: ^Map($K, $V)) { array.free(^entries); } -put :: (use map: ^Map($K, $V), key: K, value: V) { +put :: (use map: ^Map($K, $V), key: map.Key_Type, value: map.Value_Type) { if map.hashes.data == null do init(map); lr := lookup(map, key); diff --git a/include/utils.h b/include/utils.h index beb916f7..69a518d8 100644 --- a/include/utils.h +++ b/include/utils.h @@ -25,6 +25,7 @@ AstNode* symbol_raw_resolve(Scope* start_scope, char* sym); AstNode* symbol_resolve(Scope* start_scope, OnyxToken* tkn); AstNode* try_symbol_raw_resolve_from_node(AstNode* node, char* symbol); AstNode* try_symbol_resolve_from_node(AstNode* node, OnyxToken* token); +AstNode* try_symbol_raw_resolve_from_type(Type *type, char* symbol); void build_all_overload_options(bh_arr(OverloadOption) overloads, bh_imap* all_overloads); diff --git a/scripts/run_tests.onyx b/scripts/run_tests.onyx index a017b07b..609bea2f 100644 --- a/scripts/run_tests.onyx +++ b/scripts/run_tests.onyx @@ -201,4 +201,4 @@ main :: (args) => { } else { print_color(.Green, "SUCCESS\n"); } -} \ No newline at end of file +} diff --git a/src/checker.c b/src/checker.c index 7474af58..8157341a 100644 --- a/src/checker.c +++ b/src/checker.c @@ -92,7 +92,7 @@ CheckStatus check_temp_function_header(AstFunction* func); CheckStatus check_function_header(AstFunction* func); CheckStatus check_memres_type(AstMemRes* memres); CheckStatus check_memres(AstMemRes* memres); -CheckStatus check_type(AstType* type); +CheckStatus check_type(AstType** ptype); CheckStatus check_insert_directive(AstDirectiveInsert** pinsert); CheckStatus check_do_block(AstDoBlock** pdoblock); CheckStatus check_constraint(AstConstraint *constraint); @@ -109,7 +109,7 @@ u32 current_checking_level=0; static inline void fill_in_type(AstTyped* node) { if (node->type == NULL) { - if (check_type(node->type_node) > Check_Errors_Start) return; + if (check_type(&node->type_node) > Check_Errors_Start) return; node->type = type_build_from_ast(context.ast_alloc, node->type_node); } @@ -1409,7 +1409,7 @@ CheckStatus check_address_of(AstAddressOf** paof) { pt->elem = (AstType *) expr; pt->__unused = aof->next; *paof = (AstAddressOf *) pt; - CHECK(type, (AstType *) pt); + CHECK(type, (AstType **) &pt); return Check_Success; } @@ -1557,9 +1557,12 @@ CheckStatus check_field_access(AstFieldAccess** pfield) { return Check_Success; } } + + AstNode* n = try_symbol_raw_resolve_from_type(field->expr->type, field->field); AstType* type_node = field->expr->type->ast_type; - AstNode* n = try_symbol_raw_resolve_from_node((AstNode *) type_node, field->field); + if (!n) n = try_symbol_raw_resolve_from_node((AstNode *) type_node, field->field); + if (n) { *pfield = (AstFieldAccess *) n; return Check_Success; @@ -1631,7 +1634,7 @@ CheckStatus check_method_call(AstBinaryOp** pmcall) { } CheckStatus check_size_of(AstSizeOf* so) { - CHECK(type, so->so_ast_type); + CHECK(type, &so->so_ast_type); so->so_type = type_build_from_ast(context.ast_alloc, so->so_ast_type); if (so->so_type == NULL) @@ -1644,7 +1647,7 @@ CheckStatus check_size_of(AstSizeOf* so) { } CheckStatus check_align_of(AstAlignOf* ao) { - CHECK(type, ao->ao_ast_type); + CHECK(type, &ao->ao_ast_type); ao->ao_type = type_build_from_ast(context.ast_alloc, ao->ao_ast_type); if (ao->ao_type == NULL) @@ -1662,7 +1665,8 @@ CheckStatus check_expression(AstTyped** pexpr) { // This is to ensure that the type will exist when compiling. For example, a poly-call type // would have to wait for the entity to pass through, which the code generation does not know // about. - CHECK(type, (AstType *) expr); + CHECK(type, (AstType **) pexpr); + expr = *pexpr; // Don't try to construct a polystruct ahead of time because you can't. if (expr->kind != Ast_Kind_Poly_Struct_Type) { @@ -1908,7 +1912,7 @@ CheckStatus check_statement(AstNode** pstmt) { AstTyped* typed_stmt = (AstTyped *) stmt; fill_in_type(typed_stmt); if (typed_stmt->type_node != NULL && typed_stmt->type == NULL) { - CHECK(type, typed_stmt->type_node); + CHECK(type, &typed_stmt->type_node); if (!node_is_type((AstNode *) typed_stmt->type_node)) { ERROR(stmt->token->pos, "Local's type is not a type."); @@ -2048,7 +2052,7 @@ CheckStatus check_struct(AstStructType* s_node) { bh_arr_each(AstStructMember *, smem, s_node->members) { if ((*smem)->type_node != NULL) { - CHECK(type, (*smem)->type_node); + CHECK(type, &(*smem)->type_node); } if ((*smem)->type_node == NULL && (*smem)->initial_value != NULL) { @@ -2195,7 +2199,7 @@ CheckStatus check_function_header(AstFunction* func) { // If the function has the no_error flag, then the type node should have it set too. // This allows for polymorphic structures with constraints to fail gracefully. local->type_node->flags |= (func->flags & Ast_Flag_Header_Check_No_Error); - CHECK(type, local->type_node); + CHECK(type, &local->type_node); } fill_in_type((AstTyped *) local); @@ -2232,7 +2236,7 @@ CheckStatus check_function_header(AstFunction* func) { } } - if (func->return_type != NULL) CHECK(type, func->return_type); + if (func->return_type != NULL) CHECK(type, &func->return_type); if (func->constraints.constraints != NULL) { func->constraints.produce_errors = (func->flags & Ast_Flag_Header_Check_No_Error) == 0; @@ -2246,7 +2250,7 @@ CheckStatus check_function_header(AstFunction* func) { } CheckStatus check_memres_type(AstMemRes* memres) { - CHECK(type, memres->type_node); + CHECK(type, &memres->type_node); fill_in_type((AstTyped *) memres); if (memres->type_node && !memres->type) YIELD(memres->token->pos, "Waiting for global type to be constructed."); return Check_Success; @@ -2293,9 +2297,10 @@ CheckStatus check_memres(AstMemRes* memres) { return Check_Success; } -CheckStatus check_type(AstType* type) { - if (type == NULL) return Check_Success; - +CheckStatus check_type(AstType** ptype) { + if (ptype == NULL || *ptype == NULL) return Check_Success; + + AstType* type = *ptype; AstType* original_type = type; while (type->kind == Ast_Kind_Type_Alias) type = ((AstTypeAlias *) type)->to; @@ -2330,19 +2335,19 @@ CheckStatus check_type(AstType* type) { break; } - case Ast_Kind_Pointer_Type: CHECK(type, ((AstPointerType *) type)->elem); break; - case Ast_Kind_Slice_Type: CHECK(type, ((AstSliceType *) type)->elem); break; - case Ast_Kind_DynArr_Type: CHECK(type, ((AstDynArrType *) type)->elem); break; - case Ast_Kind_VarArg_Type: CHECK(type, ((AstVarArgType *) type)->elem); break; + case Ast_Kind_Pointer_Type: CHECK(type, &((AstPointerType *) type)->elem); break; + case Ast_Kind_Slice_Type: CHECK(type, &((AstSliceType *) type)->elem); break; + case Ast_Kind_DynArr_Type: CHECK(type, &((AstDynArrType *) type)->elem); break; + case Ast_Kind_VarArg_Type: CHECK(type, &((AstVarArgType *) type)->elem); break; case Ast_Kind_Function_Type: { AstFunctionType* ftype = (AstFunctionType *) type; - CHECK(type, ftype->return_type); + CHECK(type, &ftype->return_type); if (ftype->param_count > 0) { fori (i, 0, (i64) ftype->param_count) { - CHECK(type, ftype->params[i]); + CHECK(type, &ftype->params[i]); } } break; @@ -2351,7 +2356,7 @@ CheckStatus check_type(AstType* type) { case Ast_Kind_Type_Compound: { AstCompoundType* ctype = (AstCompoundType *) type; - bh_arr_each(AstType *, type, ctype->types) CHECK(type, *type); + bh_arr_each(AstType *, type, ctype->types) CHECK(type, type); break; } @@ -2364,6 +2369,17 @@ CheckStatus check_type(AstType* type) { break; } + + case Ast_Kind_Field_Access: { + CHECK(field_access, (AstFieldAccess **) ptype); + type = *ptype; + original_type = type; + + if (!node_is_type((AstNode *) type)) { + ERROR_(original_type->token->pos, "This field access did not resolve to be a type. It resolved to be a '%s'.", onyx_ast_node_kind_string(type->kind)); + } + break; + } } type = original_type; @@ -2768,7 +2784,7 @@ void check_entity(Entity* ent) { if (ent->type_alias->kind == Ast_Kind_Struct_Type) cs = check_struct((AstStructType *) ent->type_alias); else - cs = check_type(ent->type_alias); + cs = check_type(&ent->type_alias); break; case Entity_Type_File_Contents: diff --git a/src/onyxrun.c b/src/onyxrun.c index edd2618b..d8bf32b4 100644 --- a/src/onyxrun.c +++ b/src/onyxrun.c @@ -25,4 +25,4 @@ int main(int argc, char *argv[]) { data.data = wasm_data.data; data.length = wasm_data.length; return onyx_run_wasm(data, argc - 1, argv + 1); -} \ No newline at end of file +} diff --git a/src/symres.c b/src/symres.c index 5b611cd3..c095b622 100644 --- a/src/symres.c +++ b/src/symres.c @@ -145,9 +145,6 @@ static SymresStatus symres_type(AstType** type) { case Ast_Kind_Type_Alias: SYMRES(type, &((AstTypeAlias *) *type)->to); break; case Ast_Kind_Field_Access: { SYMRES(field_access, (AstFieldAccess **) type); - - if (!node_is_type((AstNode *) *type)) - onyx_report_error((*type)->token->pos, Error_Critical, "Field access did not result in a type. (%s)", onyx_ast_node_kind_string((*type)->kind)); break; } diff --git a/src/utils.c b/src/utils.c index 06e863bd..1f0b32da 100644 --- a/src/utils.c +++ b/src/utils.c @@ -253,6 +253,32 @@ AstNode* try_symbol_resolve_from_node(AstNode* node, OnyxToken* token) { return result; } +AstNode* try_symbol_raw_resolve_from_type(Type *type, char* symbol) { + while (type->kind == Type_Kind_Pointer) { + type = type->Pointer.elem; + } + + if (type->kind == Type_Kind_Struct) { + if (type->Struct.poly_sln == NULL) return NULL; + + bh_arr_each(AstPolySolution, sln, type->Struct.poly_sln) { + if (token_text_equals(sln->poly_sym->token, symbol)) { + if (sln->kind == PSK_Type) { + AstTypeRawAlias* alias = onyx_ast_node_new(context.ast_alloc, sizeof(AstTypeRawAlias), Ast_Kind_Type_Raw_Alias); + alias->type = &basic_types[Basic_Kind_Type_Index]; + alias->to = sln->type; + return (AstNode *) alias; + + } else { + return (AstNode *) sln->value; + } + } + } + } + + return NULL; +} + void scope_clear(Scope* scope) { sh_new_arena(scope->symbols); } @@ -764,6 +790,8 @@ TypeMatch check_arguments_against_type(Arguments* args, TypeFunction* func_type, b32 permanent = location != NULL; if (func_name == NULL) func_name = "UNKNOWN FUNCTION"; + if (error) error->rank = Error_Critical; + bh_arr(AstArgument *) arg_arr = (bh_arr(AstArgument *)) args->values; i32 arg_count = get_argument_buffer_size(func_type, args); @@ -796,7 +824,7 @@ TypeMatch check_arguments_against_type(Arguments* args, TypeFunction* func_type, if (tm == TYPE_MATCH_YIELD) return tm; if (tm == TYPE_MATCH_FAILED) { if (error != NULL) { - error->pos = arg_arr[arg_pos]->token->pos, + error->pos = arg_arr[arg_pos]->token->pos; error->text = bh_aprintf(global_heap_allocator, "The procedure '%s' expects a value of type '%s' for %d%s parameter, got '%s'.", func_name, @@ -1076,30 +1104,29 @@ all_types_peeled_off: } case Ast_Kind_Poly_Struct_Type: { - AstStructType* stype = ((AstPolyStructType *) node)->base_struct; + AstPolyStructType* pstype = (AstPolyStructType *) node; + AstStructType* stype = pstype->base_struct; u32 dist; - return find_closest_symbol_in_scope(stype->scope, sym, &dist); - } + char *closest = find_closest_symbol_in_scope(stype->scope, sym, &dist); - case Ast_Kind_Poly_Call_Type: { - AstPolyCallType* pcall = (AstPolyCallType *) node; - - u32 dist = 0x7fffffff; - char *closest = NULL; - - Type *type = type_build_from_ast(context.ast_alloc, (AstType *) pcall); - assert(type); + bh_arr_each(AstPolyStructParam, param, pstype->poly_params) { + token_toggle_end(param->token); + u32 d = levenshtein_distance(param->token->text, sym); - bh_arr_each(StructMember *, mem, type->Struct.memarr) { - u32 d = levenshtein_distance((*mem)->name, sym); if (d < dist) { dist = d; - closest = (*mem)->name; + closest = bh_strdup(context.ast_alloc, param->token->text); } + token_toggle_end(param->token); } return closest; } + + case Ast_Kind_Poly_Call_Type: { + AstPolyCallType* pcall = (AstPolyCallType *) node; + return find_closest_symbol_in_node(pcall->callee, sym); + } } return NULL; -- 2.25.1