Almost fix function overloading. Return var issues.

This commit is contained in:
2024-06-22 17:03:38 +02:00
parent d5fdaca1ca
commit d2614b3ba9
6 changed files with 65 additions and 74 deletions

View File

@@ -284,9 +284,6 @@ Use of undeclard symbol '%'.
record_error(checker, message, node.source_location, false);
}
foo :: (i : int, p : int) {}
foo :: (i : int, p : int, t : int) {}
no_matching_overload_found :: (checker : *Semantic_Checker, call : *AST_Node, overloads : *Defined_Symbol, arg_node : *AST_Node = null) {
builder : String_Builder;
init_string_builder(*builder,, temp);
@@ -339,6 +336,8 @@ no_matching_overload_found :: (checker : *Semantic_Checker, call : *AST_Node, ov
// foo :: (f : float) {} (file_path:line_num)
func_location := func_var.source_node.source_location;
indent(*builder, 2);
// @Incomplete(niels): We need a way to properly save the path of the declaration
print_to_builder(*builder, "% (%:%)\n", print_from_source_location(func_location), checker.path,
func_location.main_token.line);
@@ -573,7 +572,8 @@ type_mismatch :: (checker : *Semantic_Checker, usage_site : *AST_Node, expect_no
print_to_builder(*builder, "got:\n");
indent(*builder, 2);
print_to_builder(*builder, "%\n", print_from_source_location(got_var.source_node.parent.source_location));
print_to_builder(*builder, "%\n", print_from_source_location(got_var.source_node.source_location));
message := builder_to_string(*builder);
@@ -1097,18 +1097,6 @@ create_function_constraint :: (checker : *Semantic_Checker, node : *AST_Node) {
assert(false, "Compiler error. Functions should all be declared at this point in time.");
}
//@Note(niels): Constraint should be:
// X(X1, ..., Xn) { return E; }: [[X]] = ([[X1]], ..., [[Xn]]) -> [[E]]
// We return the type variable handle for X (the function name)
// @Incomplete(niels): In this case we will have a list of function overloads
// The list is most often of size 1, but in the case it is > 1
// we have overloads that we have to match against.
// This means our constraint gets slightly more complicated.
// At this point we could consider cheating and already matching the types
// at this point and finding the correct function variable.
// We can do this because technically we have already declared all functions at this point.
// So we don't have any unresolved types as of this point.
handle := find_result.type_variable;
if node.foreign_declaration {
return;
@@ -1309,12 +1297,6 @@ create_call_constraint :: (checker : *Semantic_Checker, node : *AST_Node, type_v
return;
}
// @Incomplete(niels): Fix overload resolution.
// Currently we don't have proper resolution. We don't even pick a proper function.
// We need to run through all functions in this find result, and match the arguments.
// If no overload is found, we have to print out all overloads and post mismatched arguments.
// If an overload is found we proceed as usual.
overload_found := false;
arg_node : *AST_Node = null;
@@ -1346,6 +1328,14 @@ create_call_constraint :: (checker : *Semantic_Checker, node : *AST_Node, type_v
return;
}
Type_Mismatch_Data :: struct {
lhs : Result;
rhs : Result;
}
mismatches : [..]Type_Mismatch_Data;
mismatches.allocator = temp;
for *func : find_result.functions {
if overload_found {
break;
@@ -1357,13 +1347,6 @@ create_call_constraint :: (checker : *Semantic_Checker, node : *AST_Node, type_v
continue;
}
if function.return_var > 0 {
return_var := h2tv(checker, function.return_var);
constrained_var := h2tv(checker, type_var);
constrained_var.type = return_var.type;
constrained_var.typename = return_var.typename;
}
if node.children.count == 0 && function.child_count == 0 {
overload_found = true;
break;
@@ -1374,31 +1357,40 @@ create_call_constraint :: (checker : *Semantic_Checker, node : *AST_Node, type_v
for arg : arg_vars {
function_param := function.children[it_index];
// @Incomplete(nb): Improve the error handling of this constraint.
// The usage site might be the call, but really the usage site
// is the variable, with the call around it.
// We could probably expand source locations to always include the whole line
// That is unlikely to be annoying now that I think about it.
// So maybe we just always do that? Then we always have the complete information
// and the actual token we want to focus on is just the one we have?
// @Update(nb): We actually do this now for a bunch of places, but not all.
// Error reporting in this case is still not great, since it doesn't properly mark the
// faulty variable.
create_equivalence_constraint(checker, arg.var, function_param, arg.node);
if !types_compatible(checker, arg.var, function_param) {
if all_args_match {
arg_node = arg.node;
}
fun_param := h2tv(checker, function_param);
mismatch : Type_Mismatch_Data;
mismatch.lhs = arg;
mismatch.rhs = .{ function_param, fun_param.source_node };
array_add(*mismatches, mismatch);
all_args_match = false;
} else {
overload_found = all_args_match;
}
}
if overload_found {
if function.return_var > 0 {
return_var := h2tv(checker, function.return_var);
constrained_var := h2tv(checker, type_var);
constrained_var.type = return_var.type;
constrained_var.typename = return_var.typename;
print("%\n", constrained_var.typename);
}
}
}
if !overload_found {
no_matching_overload_found(checker, node, find_result, arg_node);
}
for mismatch : mismatches {
type_mismatch(checker, mismatch.lhs.node, mismatch.rhs.node, mismatch.rhs.var, mismatch.lhs.var);
}
}
}
check_node :: (checker : *Semantic_Checker, node : *AST_Node) -> Type_Variable_Handle {
@@ -1486,7 +1478,7 @@ check_node :: (checker : *Semantic_Checker, node : *AST_Node) -> Type_Variable_H
type_variable.type = .Unresolved_Expression;
type_variable.source_node = node;
node.type_variable = handle;
create_call_constraint(checker, node, handle);
return handle;
@@ -1610,11 +1602,7 @@ union_terms :: (checker : *Semantic_Checker, lhs_handle : Type_Variable_Handle,
} else {
type_mismatch(checker, lhs_var.source_node.parent, rhs_var.source_node.parent, rhs_handle, lhs_handle);
}
return;
}
if lhs_handle != rhs_handle {
} else if lhs_handle != rhs_handle {
lhs := h2tv(checker, lhs_handle);
lhs.uf_parent = rhs_handle;
}