From 27ed00080018c2d2052dc8e22ae9c13e0e0b909b Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Thu, 29 Sep 2022 14:27:37 +0200 Subject: [PATCH] Resolving operator overloads functions --- core_ast.cpp | 2 ++ core_parsing.cpp | 1 - core_typechecking.cpp | 43 +++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 43 insertions(+), 3 deletions(-) diff --git a/core_ast.cpp b/core_ast.cpp index e9837bc..1a56955 100644 --- a/core_ast.cpp +++ b/core_ast.cpp @@ -269,6 +269,8 @@ struct Ast_Decl: Ast{ Intern_String name; Intern_String unique_name; // For code generation, currently only present on lambdas + U64 operator_overload_arguments_hash; + Ast_Scope *scope; Ast_Expr *typespec; union{ diff --git a/core_parsing.cpp b/core_parsing.cpp index 97fb240..d06889c 100644 --- a/core_parsing.cpp +++ b/core_parsing.cpp @@ -849,7 +849,6 @@ parse_decl(B32 is_global){ if(!expr->scope){ compiler_error(tname, "Operator overload doesn't have body"); } - if(!is_valid_operator_overload(pctx, tname->intern_val)){ compiler_error(tname, "This operator cannot be overloaded"); } diff --git a/core_typechecking.cpp b/core_typechecking.cpp index 9466d3a..1c7a676 100644 --- a/core_typechecking.cpp +++ b/core_typechecking.cpp @@ -251,11 +251,17 @@ type_array(Ast_Type *base, S64 size){ return result; } +inline U64 +calculate_hash_for_arguments(Array args){ + U64 result = 13; + For(args) result = hash_mix(result, hash_ptr(it)); + return result; +} + function Ast_Type * type_lambda(Ast *ast, Array return_vals, Array args){ Ast_Type *ret = type_try_tupling(return_vals, ast); - U64 hash_without_ret = 13; // @function_overloading scrap this if we changed course - For(args) hash_without_ret = hash_mix(hash_without_ret, hash_ptr(it)); + U64 hash_without_ret = calculate_hash_for_arguments(args); U64 hash = hash_mix(hash_ptr(ret), hash_without_ret); Ast_Type *result = (Ast_Type *)map_get(&pctx->type_map, hash); @@ -838,6 +844,39 @@ resolve_name(Ast_Scope *scope, Token *pos, Intern_String name, Search_Flag searc return decl; } +function Ast_Decl * +resolve_operator_overload(Ast_Scope *scope, Token *pos, Intern_String name, U64 argument_hash){ + + // Search for all possible candidates + Scratch scratch; + Scope_Search search = make_scope_search(scratch, scope, name); + search.exit_on_find = false; + scope_search(&search); + + if(search.results.len == 0){ + compiler_error(pos, "Failed to find matching operator overload for [%s] No operator of this kind is defined", name.str); + } + + // Resolve them until we hit a match + Array matching_ops = {scratch}; + For(search.results){ + resolve_decl(it); + if(it->type->func.hash_without_ret == argument_hash){ + matching_ops.add(it); + } + } + + if(matching_ops.len == 0){ + compiler_error(pos, "Failed to find matching operator overload for [%s]", name.str); + } + + if(matching_ops.len > 1){ + compiler_error(pos, "Found multiple matching operator overloads for [%s]", name.str); + } + + return matching_ops.data[0]; +} + function void insert_into_scope(Ast_Scope *scope, Ast_Decl *decl){ // This function is called when resolving statements