From f13508262b5fb4a041991d93f062df9ad49a6a29 Mon Sep 17 00:00:00 2001 From: Niels Bross Date: Sun, 29 Dec 2024 23:39:57 +0100 Subject: [PATCH] Remove dumbass type constraint crap. --- Parsing.jai | 3 +- Semantic_Analysis.jai | 382 ++++-------------------------- Test.jai | 4 - check.bat | 3 + first.jai | 10 + test/semant/wrong_multiply.golden | 2 +- test/wrong_multiply.shd | 2 +- 7 files changed, 65 insertions(+), 341 deletions(-) create mode 100644 check.bat diff --git a/Parsing.jai b/Parsing.jai index 0aa57d5..20c75cb 100644 --- a/Parsing.jai +++ b/Parsing.jai @@ -463,8 +463,9 @@ array_access :: (parse_state : *Parse_State, left : *AST_Node) -> *AST_Node { add_child(node, expression(parse_state)); return node; } - + source_location.end = parse_state.previous; + left.source_location = source_location; return left; } diff --git a/Semantic_Analysis.jai b/Semantic_Analysis.jai index 31bd7fd..44e78b9 100644 --- a/Semantic_Analysis.jai +++ b/Semantic_Analysis.jai @@ -77,52 +77,10 @@ Type_Variable :: struct { //@Note(niels): For constant buffers resource_index : u32; - uf_parent : Type_Variable_Handle; - source_node : *AST_Node; } Type_Variable_Handle :: #type, distinct u32; -Type_Constraint_Handle :: #type, distinct u32; - -Type_Constraint_Kind :: enum { - Int_Literal; // [[I]] = int - Float_Literal; // [[F]] = float - Equivalence; // [[X]] = int/float - Equality; // E1 == E2: [[E1]] = [[E2]] && [[E1 == E2]] = bool - Function_Decl; // X(X1, ..., Xn) { return E; }: [[X]] = ([[X1]], ..., [[Xn]]) -> [[E]] - Function_Call; // E(E1, ..., En): [[E]] = ([[E1]], ..., [[En]]) -> [[E(E1, ..., En)]] -} - -Type_Constraint :: struct { - kind : Type_Constraint_Kind; - - union { - literal : struct { - type_variable : Type_Variable_Handle; - union { - i : int; - f : float; - } - } - - equivalence : struct { - lhs : Type_Variable_Handle; - rhs : Type_Variable_Handle; - } - - function : struct { - symbol_variable : Type_Variable_Handle; - return_variable : Type_Variable_Handle; - arguments : [16]Type_Variable_Handle; - argument_count : int; - } - } - - usage_site : *AST_Node; - - binary_operator : Token; -} Scope_Stack :: struct { allocator : Allocator; @@ -199,7 +157,6 @@ Semantic_Checker :: struct { current_scope : Scope_Handle; // type_variables : [..]Type_Variable; - constraints : [..]Type_Constraint; current_buffer_index : u32 = 0; current_sampler_index : u32 = 0; @@ -708,7 +665,6 @@ add_symbol_to_scope :: (checker : *Semantic_Checker, scope_handle : Scope_Handle new_type_variable :: (checker : *Semantic_Checker) -> *Type_Variable, Type_Variable_Handle { variable : Type_Variable; handle := cast(Type_Variable_Handle)checker.result.type_variables.count + 1; - variable.uf_parent = handle; array_add(*checker.result.type_variables, variable); return h2tv(checker, handle), handle; @@ -1103,7 +1059,7 @@ declare_function :: (checker : *Semantic_Checker, node : *AST_Node, builtin : bo return handle; } -create_function_constraint :: (checker : *Semantic_Checker, node : *AST_Node) { +create_function :: (checker : *Semantic_Checker, node : *AST_Node) { name_to_check := get_actual_function_name(node); find_result := find_symbol(checker, name_to_check, checker.current_scope); @@ -1123,27 +1079,13 @@ create_function_constraint :: (checker : *Semantic_Checker, node : *AST_Node) { previous_scope := use_scope(checker, variable.scope); - constraint : Type_Constraint; - constraint.kind = .Function_Decl; - constraint.function.symbol_variable = function.type_variable; - - for i : 0..variable.children.count - 1 { - arg_var := variable.children[i]; - - if arg_var > 0 { - constraint.function.arguments[constraint.function.argument_count] = arg_var; - constraint.function.argument_count += 1; - } - } - for child : node.children { if child.kind == .Block { for statement : child.children { if statement.kind == .Return { result_var := check_node(checker, statement); if result_var > 0 { - variable.return_type_variable= result_var; - constraint.function.return_variable = variable.return_type_variable; + variable.return_type_variable = result_var; } } else { result_var := check_node(checker, statement); @@ -1160,44 +1102,10 @@ create_function_constraint :: (checker : *Semantic_Checker, node : *AST_Node) { not_all_control_paths_return_value(checker, node); } - array_add(*checker.constraints, constraint); - use_scope(checker, previous_scope); } } -create_literal_constraint :: (checker : *Semantic_Checker, value : int, type_variable : Type_Variable_Handle) { - constraint : Type_Constraint; - constraint.kind = .Int_Literal; - constraint.literal.i = value; - constraint.literal.type_variable = type_variable; - - array_add(*checker.constraints, constraint); -} - -create_literal_constraint :: (checker : *Semantic_Checker, value : float, type_variable : Type_Variable_Handle) -> Type_Constraint_Handle { - constraint : Type_Constraint; - constraint.kind = .Float_Literal; - constraint.literal.f = value; - constraint.literal.type_variable = type_variable; - - array_add(*checker.constraints, constraint); - - return cast(Type_Constraint_Handle)checker.constraints.count; -} - -create_equivalence_constraint :: (checker : *Semantic_Checker, lhs : Type_Variable_Handle, rhs : Type_Variable_Handle, usage_site : *AST_Node = null) -> Type_Constraint_Handle { - constraint : Type_Constraint; - constraint.kind = .Equivalence; - constraint.equivalence.lhs = lhs; - constraint.equivalence.rhs = rhs; - constraint.usage_site = usage_site; - - array_add(*checker.constraints, constraint); - - return cast(Type_Constraint_Handle)checker.constraints.count; -} - create_variable :: (checker : *Semantic_Checker, node : *AST_Node, struct_field_parent : *AST_Node = null) -> Type_Variable_Handle { find_result := find_symbol(checker, node.name, checker.current_scope); // x : int; @@ -1317,18 +1225,30 @@ create_field :: (checker : *Semantic_Checker, node : *AST_Node) -> Type_Variable for child : node.children { rhs = check_node(checker, child); } - create_equivalence_constraint(checker, handle, rhs, node); + + if handle == 0 || rhs == 0 { + return handle; + } + + l := h2tv(checker, handle); + r := h2tv(checker, rhs); + assert(l.type != .Unresolved_Expression && r.type != .Unresolved_Expression); + + if !types_compatible(checker, handle, rhs) { + type_mismatch(checker, l.source_node, r.source_node, rhs, handle); + return 0; + } } return handle; } -create_call_constraint :: (checker : *Semantic_Checker, node : *AST_Node, type_var : Type_Variable_Handle) { +check_call :: (checker : *Semantic_Checker, node : *AST_Node, type_var : Type_Variable_Handle) -> error : bool { find_result := find_symbol(checker, node.name, checker.current_scope); if !find_result { function_undeclared(checker, node); - return; + return true; } overload_found := false; @@ -1359,7 +1279,7 @@ create_call_constraint :: (checker : *Semantic_Checker, node : *AST_Node, type_v } if arg_vars.count != arg_count { - return; + return true; } Type_Mismatch_Data :: struct { @@ -1383,6 +1303,9 @@ create_call_constraint :: (checker : *Semantic_Checker, node : *AST_Node, type_v if node.children.count == 0 && function.children.count == 0 { overload_found = true; + } + + if overload_found && function.return_type_variable == 0 { break; } @@ -1409,7 +1332,7 @@ create_call_constraint :: (checker : *Semantic_Checker, node : *AST_Node, type_v } if overload_found { - if function.return_type_variable> 0 { + if function.return_type_variable > 0 { return_var := h2tv(checker, function.return_type_variable); constrained_var := h2tv(checker, type_var); constrained_var.type = return_var.type; @@ -1424,13 +1347,17 @@ create_call_constraint :: (checker : *Semantic_Checker, node : *AST_Node, type_v for mismatch : mismatches { type_mismatch(checker, mismatch.lhs.node, mismatch.rhs.node, mismatch.rhs.var, mismatch.lhs.var); } - } + + return true; + } + + return false; } check_node :: (checker : *Semantic_Checker, node : *AST_Node) -> Type_Variable_Handle { if node.kind == { case .Function; { - create_function_constraint(checker, node); + create_function(checker, node); return 0; } case. Field; { @@ -1466,19 +1393,17 @@ check_node :: (checker : *Semantic_Checker, node : *AST_Node) -> Type_Variable_H case .TOKEN_MINUS; #through; case .TOKEN_STAR; #through; case .TOKEN_SLASH; { - create_equivalence_constraint(checker, rhs_var, lhs_var, node); - - proper_variable, rhs_handle := new_type_variable(checker); - lhs_type_var := h2tv(checker, lhs_var); - proper_variable.type = lhs_type_var.type; - proper_variable.typename = lhs_type_var.typename; - proper_variable.source_node = h2tv(checker, lhs_var).source_node; - proper_variable.struct_field_parent = h2tv(checker, lhs_var).struct_field_parent; - - create_equivalence_constraint(checker, handle, rhs_handle, node); + if !types_compatible(checker, lhs_var, rhs_var, true) { + type_mismatch(checker, node, node.children[1], lhs_var, rhs_var); + return 0; + } } case .TOKEN_ASSIGN; { - create_equivalence_constraint(checker, lhs_var, rhs_var, node); + + if !types_compatible(checker, lhs_var, rhs_var, true) { + type_mismatch(checker, node.parent, node.children[1], lhs_var, rhs_var); + return 0; + } } } return handle; @@ -1494,7 +1419,6 @@ check_node :: (checker : *Semantic_Checker, node : *AST_Node) -> Type_Variable_H type_variable.type = .Int; type_variable.source_node = node; node.type_variable = handle; - type_constraint := create_literal_constraint(checker, node.integer_value, handle); return handle; } @@ -1503,7 +1427,6 @@ check_node :: (checker : *Semantic_Checker, node : *AST_Node) -> Type_Variable_H type_variable.type = .Float; type_variable.source_node = node; node.type_variable = handle; - type_constraint := create_literal_constraint(checker, node.float_value, handle); return handle; } @@ -1516,7 +1439,9 @@ check_node :: (checker : *Semantic_Checker, node : *AST_Node) -> Type_Variable_H type_variable.source_node = node; node.type_variable = handle; - create_call_constraint(checker, node, handle); + if check_call(checker, node, handle) { + return 0; + } return handle; } @@ -1555,16 +1480,16 @@ traverse :: (checker : *Semantic_Checker) { traverse(checker, checker.program_root); } -find :: (checker : *Semantic_Checker, root_handle : Type_Variable_Handle) -> Type_Variable_Handle { - assert(root_handle > 0); - root := h2tv(checker, root_handle); +// find :: (checker : *Semantic_Checker, root_handle : Type_Variable_Handle) -> Type_Variable_Handle { +// assert(root_handle > 0); +// root := h2tv(checker, root_handle); - if root.uf_parent != root_handle { - root.uf_parent = find(checker, root.uf_parent); - } +// // if root.uf_parent != root_handle { +// // root.uf_parent = find(checker, root.uf_parent); +// // } - return root.uf_parent; -} +// return root.uf_parent; +// } Unification_Result :: enum { Unification_Success; @@ -1653,78 +1578,6 @@ types_compatible :: (checker : *Semantic_Checker, lhs : Type_Variable_Handle, rh return false; } -union_terms :: (checker : *Semantic_Checker, lhs_handle : Type_Variable_Handle, rhs_handle : Type_Variable_Handle, usage_site : *AST_Node) { - - if !types_compatible(checker, lhs_handle, rhs_handle) { - lhs_var := h2tv(checker, lhs_handle); - rhs_var := h2tv(checker, rhs_handle); - - if usage_site { - type_mismatch(checker, usage_site, rhs_var.source_node.parent, rhs_handle, lhs_handle); - } else { - type_mismatch(checker, lhs_var.source_node.parent, rhs_var.source_node.parent, rhs_handle, lhs_handle); - } - } else if lhs_handle != rhs_handle { - lhs := h2tv(checker, lhs_handle); - lhs.uf_parent = rhs_handle; - } -} - -unify :: (checker : *Semantic_Checker, lhs_handle : Type_Variable_Handle, rhs_handle : Type_Variable_Handle, usage_site : *AST_Node = null) -> Unification_Result { - rep_lhs := find(checker, lhs_handle); - rep_rhs := find(checker, rhs_handle); - - if rep_lhs != rep_rhs { - lhs := h2tv(checker, rep_lhs); - rhs := h2tv(checker, rep_rhs); - if !is_proper(lhs) && !is_proper(rhs) { - union_terms(checker, rep_lhs, rep_rhs, usage_site); - } else if !is_proper(lhs) && is_proper(rhs) { - union_terms(checker, rep_lhs, rep_rhs, usage_site); - } else if is_proper(lhs) && !is_proper(rhs) { - union_terms(checker, rep_rhs, rep_lhs, usage_site); - } else if is_proper(lhs) && is_proper(rhs) { - union_terms(checker, rep_lhs, rep_rhs, usage_site); - - //@Incomplete(niels): Evaluate sub-terms for functions. - } else { - return .Unification_Failure; - } - } - return .Unification_Success; -} - -union_find :: (checker : *Semantic_Checker) -> bool { - for constraint : checker.constraints { - if constraint.kind == { - case .Int_Literal; { - - } - case .Float_Literal; { - - } - case .Equivalence; { - if !constraint.equivalence.lhs || !constraint.equivalence.rhs { - return false; - } - - handle_lhs := find(checker, constraint.equivalence.lhs); - handle_rhs := find(checker, constraint.equivalence.rhs); - - unification_result := unify(checker, handle_lhs, handle_rhs, constraint.usage_site); - if unification_result == .Unification_Failure { - return false; - } - } - case .Function_Decl; { - - } - } - } - - return true; -} - // HLSL_BUILTIN :: #run -> string { // T := #load "hlsl_builtin.jai"; @@ -1796,24 +1649,6 @@ add_hlsl_builtins :: (checker : *Semantic_Checker) { type_check :: (checker : *Semantic_Checker, root : *AST_Node) { traverse(checker, root); - - // if checker.result.had_error { - // //@Incomplete(niels): handle error... - // return checker.result; - // } - uf_result := union_find(checker); - - if !uf_result { - //@Incomplete(niels): handle error... - // return result; - } - - for *type_variable : checker.result.type_variables { - if type_variable.type == .Unresolved_Variable { - rep := h2tv(checker, type_variable.uf_parent); - type_variable.type = rep.type; - } - } } check :: (checker : *Semantic_Checker, root : *AST_Node) -> Semantic_Check_Result { @@ -1821,7 +1656,6 @@ check :: (checker : *Semantic_Checker, root : *AST_Node) -> Semantic_Check_Resul checker.current_sampler_index = 0; checker.current_texture_index = 0; array_reserve(*checker.result.messages, 16); - array_reserve(*checker.constraints, 1024); add_hlsl_builtins(checker); type_check(checker, root); @@ -2019,64 +1853,6 @@ pretty_print_scope :: (checker : *Semantic_Checker, scope : *Scope, builder : *S append(builder, "]\n"); } -pretty_print_constraint :: (checker : *Semantic_Checker, constraint : Type_Constraint, builder : *String_Builder) { - if constraint.kind == { - case .Int_Literal; { - print_to_builder(builder, "[[%]] = int\n", constraint.literal.i); - } - case .Float_Literal; { - print_to_builder(builder, "[[%]] = float\n", constraint.literal.f); - } - case .Equivalence; { - lhs_var := h2tv(checker, constraint.equivalence.lhs); - rhs_var := h2tv(checker, constraint.equivalence.rhs); - - append(builder, "[["); - print_type_variable(builder, lhs_var, checker); - append(builder, "]] = "); - if rhs_var.source_node { - append(builder, "[["); - } - - print_type_variable(builder, rhs_var, checker); - if rhs_var.source_node { - append(builder, "]]"); - } - append(builder, "\n"); - } - case .Function_Decl; { - sym := h2tv(checker, constraint.function.symbol_variable); - print_to_builder(builder, "[[%]] =", sym.name); - append(builder, " ("); - if constraint.function.argument_count > 0 { - for i : 0..constraint.function.argument_count - 1 { - arg := h2tv(checker, constraint.function.arguments[i]); - print_to_builder(builder, "[[%]]", arg.name); - - if i < constraint.function.argument_count - 1 { - append(builder, ", "); - } - } - } - append(builder, ")"); - - if constraint.function.return_variable > 0 { - return_var := h2tv(checker, constraint.function.return_variable); - - append(builder, " -> "); - append(builder, "[["); - - print_type_variable(builder, return_var, checker); - - append(builder, "]]", ); - append(builder, "\n"); - } else { - append(builder, " -> unit\n"); - } - } - } -} - print_type_variable :: (builder : *String_Builder, variable : Type_Variable, checker : *Semantic_Checker) { if variable.builtin { if variable.type != .Function || variable.type != .Struct { @@ -2173,68 +1949,6 @@ pretty_print_symbol_table :: (checker : *Semantic_Checker, allocator : Allocator return builder_to_string(*builder,, allocator); } -pretty_print_type_variable :: (checker : *Semantic_Checker, type_variable : *Type_Variable, builder : *String_Builder) { - rep := type_variable.uf_parent; - if type_variable.name.count > 0 { - append(builder, "[["); - print_type_variable(builder, type_variable, checker); - append(builder, "]] = "); - rep_var := h2tv(checker, rep); - if is_proper(type_variable) { - print_to_builder(builder, proper_type_to_string(checker, type_variable, temp)); - } else if type_variable.type == .Struct || type_variable.type == .Properties || - type_variable.type == .CBuffer { - if type_variable.kind == .Declaration { - append(builder, "{"); - - for 0..type_variable.children.count - 1 { - child_handle := type_variable.children[it]; - child := h2tv(checker, child_handle); - print_to_builder(builder, child.name); - append(builder, " : "); - print_to_builder(builder, type_to_string(child)); - - if it < type_variable.children.count - 1 { - append(builder, ", "); - } - } - - append(builder, "}"); - } else if type_variable.typename.count > 0 { - print_to_builder(builder, "%", type_variable.typename); - } - } else { - print_from_source_location(builder, rep_var.source_node.source_location); - } - append(builder, "\n"); - } -} - -pretty_print_type_variables :: (checker : *Semantic_Checker, allocator : Allocator) -> string { - builder : String_Builder; - - init_string_builder(*builder,, allocator); - - for *type_variable : checker.result.type_variables { - if type_variable.builtin continue; - - pretty_print_type_variable(checker, type_variable, *builder); - } - - return builder_to_string(*builder,, allocator); -} - -pretty_print_type_constraints :: (checker : *Semantic_Checker, allocator : Allocator) -> string { - builder : String_Builder; - init_string_builder(*builder,, allocator); - - for *constraint : checker.constraints { - pretty_print_constraint(checker, constraint, *builder); - } - - return builder_to_string(*builder,, allocator); -} - #scope_module #import "ncore"; diff --git a/Test.jai b/Test.jai index 82ba0f3..c708b30 100644 --- a/Test.jai +++ b/Test.jai @@ -308,10 +308,6 @@ run_semantic_analysis_test :: (file_path : string, root : *AST_Node, output_type result_text = report_messages(checker.result.messages); } else { result_text = pretty_print_symbol_table(*checker, temp); - constraints := pretty_print_type_constraints(*checker, temp); - type_vars := pretty_print_type_variables(*checker, temp); - // print("Constraints\n%\n", constraints); - // print("Solution\n%\n", type_vars); } if output_type & .StdOut { diff --git a/check.bat b/check.bat new file mode 100644 index 0000000..1e12322 --- /dev/null +++ b/check.bat @@ -0,0 +1,3 @@ +@echo off + +jai first.jai -natvis - check diff --git a/first.jai b/first.jai index aa25295..b4abb2f 100644 --- a/first.jai +++ b/first.jai @@ -16,6 +16,16 @@ build :: () { options.write_added_strings = true; + args := options.compile_time_command_line; + + for arg : args { + if arg == { + case "check"; { + options.output_type = .NO_OUTPUT; + } + } + } + new_path: [..] string; array_add(*new_path, ..options.import_path); array_add(*new_path, "modules"); diff --git a/test/semant/wrong_multiply.golden b/test/semant/wrong_multiply.golden index 3b17997..a2e935f 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/wrong_multiply.shd b/test/wrong_multiply.shd index 87cd93f..820290f 100644 --- a/test/wrong_multiply.shd +++ b/test/wrong_multiply.shd @@ -2,5 +2,5 @@ vertex main :: (pos : float4 @position) -> float4 @position { res : float2 = float2(2.0, 2.0); foo : float = 1.0; result : float4 = float4(1.0, foo * res, 0.0, 1.0); - return result; + return float4(1,1,1,1); }