diff --git a/Codegen.jai b/Codegen.jai index bea238f..e215b70 100644 --- a/Codegen.jai +++ b/Codegen.jai @@ -153,7 +153,8 @@ emit_function :: (state : *Codegen_State, node : *AST_Node, indentation : int, e if 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 { append(*state.builder, "void "); } diff --git a/Semantic_Analysis.jai b/Semantic_Analysis.jai index 6944b72..ab6d203 100644 --- a/Semantic_Analysis.jai +++ b/Semantic_Analysis.jai @@ -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; } diff --git a/test/constant_buffer.shd b/test/constant_buffer.shd index 1e9b414..20b2f0a 100644 --- a/test/constant_buffer.shd +++ b/test/constant_buffer.shd @@ -4,7 +4,9 @@ camera :: constant_buffer { } 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 { diff --git a/test/semant/unknown_overload.golden b/test/semant/unknown_overload.golden index fb7f709..299b9fb 100644 --- a/test/semant/unknown_overload.golden +++ b/test/semant/unknown_overload.golden @@ -1,16 +1,4 @@ -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) - -test/unknown_overload.shd:6,4: error: Type mismatch. Expected float3 got float +test/unknown_overload.shd:6,4: error: Type mismatch. Expected float3 got float  found: foo(v, v); ^ @@ -30,4 +18,16 @@ got: 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) +  \ No newline at end of file diff --git a/test/semant/wrong_multiply.golden b/test/semant/wrong_multiply.golden index a2e935f..3b17997 100644 --- a/test/semant/wrong_multiply.golden +++ b/test/semant/wrong_multiply.golden @@ -6,6 +6,6 @@ float got: - res : float2 = float2(2.0, 2.0) + res : float2 = float2(2.0, 2.0);  \ No newline at end of file diff --git a/test/semant/wrong_type_for_function.golden b/test/semant/wrong_type_for_function.golden index d14646f..a42219b 100644 --- a/test/semant/wrong_type_for_function.golden +++ b/test/semant/wrong_type_for_function.golden @@ -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: color : float4 = float4(y, 1.0, 1.0, 1.0); ^^^^^^ @@ -9,14 +19,4 @@  Possible overloads:  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() -  \ No newline at end of file