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

@@ -153,7 +153,8 @@ emit_function :: (state : *Codegen_State, node : *AST_Node, indentation : int, e
if function_variable.return_var { if function_variable.return_var {
return_variable := h2tv(state.type_variables, function_variable.return_var); return_variable := h2tv(state.type_variables, function_variable.return_var);
print_to_builder(*state.builder, "% ", type_to_string(return_variable)); print_to_builder(*state.builder, "% ", type_to_string(return_variable));
print("shiet: %\n", return_variable.*);
} else { } else {
append(*state.builder, "void "); append(*state.builder, "void ");
} }

View File

@@ -284,9 +284,6 @@ Use of undeclard symbol '%'.
record_error(checker, message, node.source_location, false); 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) { no_matching_overload_found :: (checker : *Semantic_Checker, call : *AST_Node, overloads : *Defined_Symbol, arg_node : *AST_Node = null) {
builder : String_Builder; builder : String_Builder;
init_string_builder(*builder,, temp); 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) // foo :: (f : float) {} (file_path:line_num)
func_location := func_var.source_node.source_location; func_location := func_var.source_node.source_location;
indent(*builder, 2); 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, print_to_builder(*builder, "% (%:%)\n", print_from_source_location(func_location), checker.path,
func_location.main_token.line); 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"); print_to_builder(*builder, "got:\n");
indent(*builder, 2); 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); 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."); 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; handle := find_result.type_variable;
if node.foreign_declaration { if node.foreign_declaration {
return; return;
@@ -1309,12 +1297,6 @@ create_call_constraint :: (checker : *Semantic_Checker, node : *AST_Node, type_v
return; 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; overload_found := false;
arg_node : *AST_Node = null; arg_node : *AST_Node = null;
@@ -1346,6 +1328,14 @@ create_call_constraint :: (checker : *Semantic_Checker, node : *AST_Node, type_v
return; return;
} }
Type_Mismatch_Data :: struct {
lhs : Result;
rhs : Result;
}
mismatches : [..]Type_Mismatch_Data;
mismatches.allocator = temp;
for *func : find_result.functions { for *func : find_result.functions {
if overload_found { if overload_found {
break; break;
@@ -1357,13 +1347,6 @@ create_call_constraint :: (checker : *Semantic_Checker, node : *AST_Node, type_v
continue; 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 { if node.children.count == 0 && function.child_count == 0 {
overload_found = true; overload_found = true;
break; break;
@@ -1374,31 +1357,40 @@ create_call_constraint :: (checker : *Semantic_Checker, node : *AST_Node, type_v
for arg : arg_vars { for arg : arg_vars {
function_param := function.children[it_index]; 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 !types_compatible(checker, arg.var, function_param) {
if all_args_match { if all_args_match {
arg_node = arg.node; 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; all_args_match = false;
} else { } else {
overload_found = all_args_match; 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 { if !overload_found {
no_matching_overload_found(checker, node, find_result, arg_node); 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 { 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.type = .Unresolved_Expression;
type_variable.source_node = node; type_variable.source_node = node;
node.type_variable = handle; node.type_variable = handle;
create_call_constraint(checker, node, handle); create_call_constraint(checker, node, handle);
return handle; return handle;
@@ -1610,11 +1602,7 @@ union_terms :: (checker : *Semantic_Checker, lhs_handle : Type_Variable_Handle,
} else { } else {
type_mismatch(checker, lhs_var.source_node.parent, rhs_var.source_node.parent, rhs_handle, lhs_handle); type_mismatch(checker, lhs_var.source_node.parent, rhs_var.source_node.parent, rhs_handle, lhs_handle);
} }
} else if lhs_handle != rhs_handle {
return;
}
if lhs_handle != rhs_handle {
lhs := h2tv(checker, lhs_handle); lhs := h2tv(checker, lhs_handle);
lhs.uf_parent = rhs_handle; lhs.uf_parent = rhs_handle;
} }

View File

@@ -4,7 +4,9 @@ camera :: constant_buffer {
} }
vertex main :: (pos : float4 @position) -> float4 @position { vertex main :: (pos : float4 @position) -> float4 @position {
return mul(camera.projection, mul(camera.view, pos)); mv : float4 = mul(camera.view, pos);
mvp : float4 = mul(camera.projection, mv);
return mvp;
} }
pixel main :: () -> float4 @target { pixel main :: () -> float4 @target {

View File

@@ -1,16 +1,4 @@
test/unknown_overload.shd:6,0: error: Procedure call did not match any of the possible overloads for 'foo' test/unknown_overload.shd:6,4: error: Type mismatch. Expected float3 got float
 found:
foo(v, v);
^^^
 While matching argument 1 in function call.
 foo(v, v);
^
 Possible overloads:
 foo :: (v1 : float3, v2 : float3) { (test/unknown_overload.shd:1)
 foo :: (v1 : float2, v2 : float2, v3 : float2) { (test/unknown_overload.shd:2)
test/unknown_overload.shd:6,4: error: Type mismatch. Expected float3 got float
 found:  found:
foo(v, v); foo(v, v);
^ ^
@@ -30,4 +18,16 @@
got: got:
v : float = 2.0 v : float = 2.0
test/unknown_overload.shd:6,0: error: Procedure call did not match any of the possible overloads for 'foo'
 found:
foo(v, v);
^^^
 While matching argument 1 in function call.
 foo(v, v);
^
 Possible overloads:
 foo :: (v1 : float3, v2 : float3) { (test/unknown_overload.shd:1)
 foo :: (v1 : float2, v2 : float2, v3 : float2) { (test/unknown_overload.shd:2)
 

View File

@@ -6,6 +6,6 @@
float float
got: got:
res : float2 = float2(2.0, 2.0) res : float2 = float2(2.0, 2.0);
 

View File

@@ -1,4 +1,14 @@
test/wrong_type_for_function.shd:11,17: error: Procedure call did not match any of the possible overloads for 'float4' test/wrong_type_for_function.shd:11,24: error: Type mismatch. Expected float got float2
 found:
color : float4 = float4(y, 1.0, 1.0, 1.0);
^
expected:
float
got:
y : float2 = foo()
test/wrong_type_for_function.shd:11,17: error: Procedure call did not match any of the possible overloads for 'float4'
 found:  found:
color : float4 = float4(y, 1.0, 1.0, 1.0); color : float4 = float4(y, 1.0, 1.0, 1.0);
^^^^^^ ^^^^^^
@@ -9,14 +19,4 @@
 Possible overloads:  Possible overloads:
 foreign float4 :: (float, float, float, float) -> float4; (test/wrong_type_for_function.shd:79)  foreign float4 :: (float, float, float, float) -> float4; (test/wrong_type_for_function.shd:79)
test/wrong_type_for_function.shd:11,24: error: Type mismatch. Expected float got float2
 found:
color : float4 = float4(y, 1.0, 1.0, 1.0);
^
expected:
float
got:
y : float2 = foo()