Resolving operator overloads functions

This commit is contained in:
Krzosa Karol
2022-09-29 14:27:37 +02:00
parent 7ce3871a9e
commit 27ed000800
3 changed files with 43 additions and 3 deletions

View File

@@ -269,6 +269,8 @@ struct Ast_Decl: Ast{
Intern_String name; Intern_String name;
Intern_String unique_name; // For code generation, currently only present on lambdas Intern_String unique_name; // For code generation, currently only present on lambdas
U64 operator_overload_arguments_hash;
Ast_Scope *scope; Ast_Scope *scope;
Ast_Expr *typespec; Ast_Expr *typespec;
union{ union{

View File

@@ -849,7 +849,6 @@ parse_decl(B32 is_global){
if(!expr->scope){ if(!expr->scope){
compiler_error(tname, "Operator overload doesn't have body"); compiler_error(tname, "Operator overload doesn't have body");
} }
if(!is_valid_operator_overload(pctx, tname->intern_val)){ if(!is_valid_operator_overload(pctx, tname->intern_val)){
compiler_error(tname, "This operator cannot be overloaded"); compiler_error(tname, "This operator cannot be overloaded");
} }

View File

@@ -251,11 +251,17 @@ type_array(Ast_Type *base, S64 size){
return result; return result;
} }
inline U64
calculate_hash_for_arguments(Array<Ast_Type *> args){
U64 result = 13;
For(args) result = hash_mix(result, hash_ptr(it));
return result;
}
function Ast_Type * function Ast_Type *
type_lambda(Ast *ast, Array<Ast_Type *> return_vals, Array<Ast_Type *> args){ type_lambda(Ast *ast, Array<Ast_Type *> return_vals, Array<Ast_Type *> args){
Ast_Type *ret = type_try_tupling(return_vals, ast); Ast_Type *ret = type_try_tupling(return_vals, ast);
U64 hash_without_ret = 13; // @function_overloading scrap this if we changed course U64 hash_without_ret = calculate_hash_for_arguments(args);
For(args) hash_without_ret = hash_mix(hash_without_ret, hash_ptr(it));
U64 hash = hash_mix(hash_ptr(ret), hash_without_ret); U64 hash = hash_mix(hash_ptr(ret), hash_without_ret);
Ast_Type *result = (Ast_Type *)map_get(&pctx->type_map, hash); 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; 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<Ast_Decl *> 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 function void
insert_into_scope(Ast_Scope *scope, Ast_Decl *decl){ insert_into_scope(Ast_Scope *scope, Ast_Decl *decl){
// This function is called when resolving statements // This function is called when resolving statements