diff --git a/Codegen.jai b/Codegen.jai index e215b70..d164997 100644 --- a/Codegen.jai +++ b/Codegen.jai @@ -151,10 +151,9 @@ emit_function :: (state : *Codegen_State, node : *AST_Node, indentation : int, e indent(state, indentation); - if function_variable.return_var { - return_variable := h2tv(state.type_variables, function_variable.return_var); + if function_variable.return_type_variable { + return_variable := h2tv(state.type_variables, function_variable.return_type_variable); print_to_builder(*state.builder, "% ", type_to_string(return_variable)); - print("shiet: %\n", return_variable.*); } else { append(*state.builder, "void "); } @@ -319,6 +318,57 @@ emit_node :: (state : *Codegen_State, node : *AST_Node, indentation : int) { } } +emit_field_list :: (state : *Codegen_State, field_list : *AST_Node, indentation : int) { + for child : field_list.children { + emit_node(state, child, 1); + + if it_index < field_list.children.count { + append(*state.builder, ";\n"); + } + } +} + +emit_struct :: (state : *Codegen_State, node : *AST_Node, indentation : int) { + print_to_builder(*state.builder, "struct %", node.name); + + current_scope := state.current_scope; + state.current_scope = h2tv(state.type_variables, node.type_variable).scope; + + field_list := node.children[0]; + + if field_list.children.count > 0 { + append(*state.builder, "\n{\n"); + } else { + append(*state.builder, " {"); + } + + emit_field_list(state, field_list, indentation); + + append(*state.builder, "}\n\n"); + state.current_scope = current_scope; +} + +emit_cbuffer :: (state : *Codegen_State, node : *AST_Node, indentation : int) { + variable := h2tv(state.type_variables, node.type_variable); + print_to_builder(*state.builder, "cbuffer % : register(b%)", variable.name, variable.buffer_index); + + current_scope := state.current_scope; + state.current_scope = h2tv(state.type_variables, node.type_variable).scope; + + field_list := node.children[0]; + + if field_list.children.count > 0 { + append(*state.builder, "\n{\n"); + } else { + append(*state.builder, " {"); + } + + emit_field_list(state, field_list, indentation); + + append(*state.builder, "}\n\n"); + state.current_scope = current_scope; +} + emit_declaration :: (state : *Codegen_State, node : *AST_Node) { if node.kind == { case .Function; { @@ -327,31 +377,11 @@ emit_declaration :: (state : *Codegen_State, node : *AST_Node) { case .Properties; { emit_properties(state, node, 0); } + case .CBuffer; { + emit_cbuffer(state, node, 0); + } case .Struct; { - print_to_builder(*state.builder, "struct %", node.name); - - current_scope := state.current_scope; - state.current_scope = h2tv(state.type_variables, node.type_variable).scope; - - field_list := node.children[0]; - - if field_list.children.count > 0 { - append(*state.builder, "\n{\n"); - } else { - append(*state.builder, " {"); - } - - - for child : field_list.children { - emit_node(state, child, 1); - - if it_index < field_list.children.count { - append(*state.builder, ";\n"); - } - } - - append(*state.builder, "}\n\n"); - state.current_scope = current_scope; + emit_struct(state, node, 0); } } } diff --git a/Semantic_Analysis.jai b/Semantic_Analysis.jai index ab6d203..cb91b13 100644 --- a/Semantic_Analysis.jai +++ b/Semantic_Analysis.jai @@ -8,6 +8,7 @@ // [x] Improve error reporting on mismatched overloads when types don't match, but arity does // [ ] Improve error reporting for type mismatches in general. It seems like the expect node is no always correct. +#load "static_array.jai"; #import "Hash_Table"; VERTEX_MAIN_FUNCTION_PREFIX :: "vertex"; @@ -61,13 +62,13 @@ Type_Variable :: struct { name : string; //@Note(niels) For functions - return_var : Type_Variable_Handle; + return_type_variable : Type_Variable_Handle; //@Note(niels) The scope this variable creates (function, struct, global) scope : Scope_Handle; //@Note(niels): For struct members - field_parent : *AST_Node; + struct_field_parent : *AST_Node; typename : string; @@ -170,6 +171,11 @@ Semantic_Check_Result :: struct { messages : [..]Compiler_Message; had_error : bool; + vertex_entry_point : *AST_Node; + pixel_entry_point : *AST_Node; + + constant_buffers : Static_Array(Type_Variable_Handle, 16); + scope_stack : Scope_Stack; type_variables : [..]Type_Variable; } @@ -187,9 +193,6 @@ Semantic_Checker :: struct { current_scope : Scope_Handle; - vertex_entry_point : *AST_Node; - pixel_entry_point : *AST_Node; - // type_variables : [..]Type_Variable; constraints : [..]Type_Constraint; @@ -701,7 +704,6 @@ new_type_variable :: (checker : *Semantic_Checker) -> *Type_Variable, Type_Varia return h2tv(checker, handle), handle; } - add_child :: (variable : *Type_Variable, child : Type_Variable_Handle) { assert(variable.child_count < Type_Variable.MAX_TYPE_VARIABLE_CHILDREN); variable.children[variable.child_count] = child; @@ -718,6 +720,8 @@ add_child :: (checker : *Semantic_Checker, handle : Type_Variable_Handle, child init_semantic_checker :: (checker : *Semantic_Checker, root : *AST_Node, path : string) { checker.program_root = root; checker.path = path; + + // @Incomplete(niels): Use other allocator and/or add static array with convenience functions array_reserve(*checker.result.type_variables, 2048); array_reserve(*checker.result.scope_stack.stack, 256); @@ -791,14 +795,14 @@ proper_type_to_string :: (builder : *String_Builder, checker : *Semantic_Checker append(builder, ")"); - if var.return_var > 0 { + if var.return_type_variable > 0 { append(builder, " -> ", ); - return_var := h2tv(checker, var.return_var); + return_var := h2tv(checker, var.return_type_variable); if is_proper(return_var) { proper_type_to_string(builder, checker, return_var); } else { append(builder, "[["); - print_type_variable(builder, checker, var.return_var); + print_type_variable(builder, checker, var.return_type_variable); append(builder, "]]", ); } } else { @@ -936,6 +940,7 @@ declare_cbuffer :: (checker : *Semantic_Checker, node : *AST_Node) -> Type_Varia var.type = .CBuffer; current_custom_buffer_index += 1; var.buffer_index = current_custom_buffer_index; + array_add(*checker.result.constant_buffers, type_var); return type_var; } @@ -980,11 +985,11 @@ declare_function :: (checker : *Semantic_Checker, node : *AST_Node, builtin : bo name_to_check := get_actual_function_name(node); if node.vertex_entry_point { - checker.vertex_entry_point = node; + checker.result.vertex_entry_point = node; } if node.pixel_entry_point { - checker.pixel_entry_point = node; + checker.result.pixel_entry_point = node; } find_result := find_symbol(checker, name_to_check, checker.current_scope); @@ -1079,7 +1084,7 @@ declare_function :: (checker : *Semantic_Checker, node : *AST_Node, builtin : bo if builtin && node.token.ident_value.count > 0 { return_var, return_handle := new_type_variable(checker); return_var.type = get_type_from_identifier(checker, checker.current_scope, node, *return_var.typename); - h2tv(checker, handle).return_var = return_handle; + h2tv(checker, handle).return_type_variable= return_handle; } if !builtin { @@ -1128,8 +1133,8 @@ create_function_constraint :: (checker : *Semantic_Checker, node : *AST_Node) { if statement.kind == .Return { result_var := check_node(checker, statement); if result_var > 0 { - variable.return_var = result_var; - constraint.function.return_variable = variable.return_var; + variable.return_type_variable= result_var; + constraint.function.return_variable = variable.return_type_variable; } } else { result_var := check_node(checker, statement); @@ -1142,7 +1147,7 @@ create_function_constraint :: (checker : *Semantic_Checker, node : *AST_Node) { } } - if node.token.ident_value.count > 0 && !variable.return_var { + if node.token.ident_value.count > 0 && !variable.return_type_variable{ not_all_control_paths_return_value(checker, node); } @@ -1184,7 +1189,7 @@ create_equivalence_constraint :: (checker : *Semantic_Checker, lhs : Type_Variab return cast(Type_Constraint_Handle)checker.constraints.count; } -create_variable :: (checker : *Semantic_Checker, node : *AST_Node, field_parent : *AST_Node = null) -> Type_Variable_Handle { +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; // x.d = 5; @@ -1192,7 +1197,7 @@ create_variable :: (checker : *Semantic_Checker, node : *AST_Node, field_parent if find_result { node.type_variable = find_result.type_variable; variable := h2tv(checker, find_result.type_variable); - variable.field_parent = field_parent; + variable.struct_field_parent = struct_field_parent; if get_scope(checker, checker.current_scope).kind == .Struct { variable.scope = checker.current_scope; @@ -1204,10 +1209,6 @@ create_variable :: (checker : *Semantic_Checker, node : *AST_Node, field_parent return 0; } else { lookup_name : string = variable.typename; - // if variable.typename == "properties" { - // lookup_name = variable.name; - // } - print("Lookup: %\n", lookup_name); struct_symbol := find_symbol(checker, lookup_name, checker.current_scope); type_variable := h2tv(checker, struct_symbol.type_variable); @@ -1368,18 +1369,18 @@ create_call_constraint :: (checker : *Semantic_Checker, node : *AST_Node, type_v array_add(*mismatches, mismatch); all_args_match = false; + overload_found = false; } else { overload_found = all_args_match; } } if overload_found { - if function.return_var > 0 { - return_var := h2tv(checker, function.return_var); + 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; constrained_var.typename = return_var.typename; - print("%\n", constrained_var.typename); } } } @@ -1436,7 +1437,7 @@ check_node :: (checker : *Semantic_Checker, node : *AST_Node) -> Type_Variable_H proper_variable, rhs_handle := new_type_variable(checker); proper_variable.type = h2tv(checker, lhs_var).type; proper_variable.source_node = h2tv(checker, lhs_var).source_node; - proper_variable.field_parent = h2tv(checker, lhs_var).field_parent; + proper_variable.struct_field_parent = h2tv(checker, lhs_var).struct_field_parent; create_equivalence_constraint(checker, handle, rhs_handle, node); } @@ -1817,8 +1818,8 @@ pretty_print_function :: (checker : *Semantic_Checker, builder : *String_Builder } } - if function.return_var > 0 { - print_to_builder(builder, ") -> %\n", type_to_string(h2tv(checker, function.return_var))); + if function.return_type_variable> 0 { + print_to_builder(builder, ") -> %\n", type_to_string(h2tv(checker, function.return_type_variable))); } else { append(builder, ")\n"); } @@ -2015,8 +2016,8 @@ print_type_variable :: (builder : *String_Builder, variable : Type_Variable, che case .Function; #through; case .Struct; #through; case .Field; { - if variable.field_parent { - print_to_builder(builder, "%.", variable.field_parent.name); + if variable.struct_field_parent { + print_to_builder(builder, "%.", variable.struct_field_parent.name); } print_to_builder(builder, "%", node.name); @@ -2041,10 +2042,10 @@ print_type_variable :: (builder : *String_Builder, variable : Type_Variable, che print_from_source_location(builder, source_location); } case .Call; { - if variable.return_var { + if variable.return_type_variable{ assert(false); print_to_builder(builder, "%", variable.typename); - print_type_variable(builder, checker, variable.return_var); + print_type_variable(builder, checker, variable.return_type_variable); } print_to_builder(builder, "%(", node.name); diff --git a/module.jai b/module.jai index ed632e2..1da089f 100644 --- a/module.jai +++ b/module.jai @@ -111,9 +111,19 @@ Properties :: struct { buffer_index : u32; } +Constant_Buffer :: struct { + register : int; + + name : string; + + fields : Property_Field; +} + Shader_Variant_Collection :: struct { properties : Properties; + cbuffers : [..]Constant_Buffer; + variants : [..]Shader_Variant; } @@ -334,10 +344,10 @@ compile_file :: (compiler : *Shader_Compiler, path : string) -> Compilation_Resu variant : Shader_Variant; variant.text = codegen_result.result_text; - if checker.vertex_entry_point { - variant.vertex_entry_point.name = checker.vertex_entry_point.name; + if checker.result.vertex_entry_point { + variant.vertex_entry_point.name = checker.result.vertex_entry_point.name; - type_variable := h2tv(*checker, checker.vertex_entry_point.type_variable); + type_variable := h2tv(*checker, checker.result.vertex_entry_point.type_variable); assert(type_variable.type == .Function); node := type_variable.source_node; @@ -354,6 +364,8 @@ compile_file :: (compiler : *Shader_Compiler, path : string) -> Compilation_Resu } } + + find_result := find_symbol(*check_result.scope_stack, "properties", xx 1); if find_result { property_variable := h2tv(check_result.type_variables, find_result.type_variable); @@ -368,13 +380,13 @@ compile_file :: (compiler : *Shader_Compiler, path : string) -> Compilation_Resu result.collection.properties.buffer_index = property_variable.buffer_index; } - if checker.pixel_entry_point { - variant.pixel_entry_point.name = checker.pixel_entry_point.name; + if checker.result.pixel_entry_point { + variant.pixel_entry_point.name = checker.result.pixel_entry_point.name; - type_variable := h2tv(*checker, checker.pixel_entry_point.type_variable); + type_variable := h2tv(*checker, checker.result.pixel_entry_point.type_variable); assert(type_variable.type == .Function); - field := type_variable_to_field(*checker, type_variable.return_var); + field := type_variable_to_field(*checker, type_variable.return_type_variable); for hint : type_variable.source_node.hint_tokens { field_hint : Field_Hint; diff --git a/static_array.jai b/static_array.jai new file mode 100644 index 0000000..9a96f32 --- /dev/null +++ b/static_array.jai @@ -0,0 +1,29 @@ +Static_Array :: struct ($T : Type, $N : s64) { + array : [N] T; + + capacity : s64 = N; + count : s64; +} + +// operator [] :: (array : Static_Array($T, $N), index : int) -> T { +// assert(index < array.count); +// return array.array[index]; +// } + +// operator []= :: (array : *Static_Array($T, $N), index : int, value : T) { +// assert(index < array.count); +// array.array[index] = value; +// } + +operator *[] :: (array : *Static_Array($T, $N), index : int) -> *T { + assert(index < array.count); + return *(array.array[index]); +} + +array_add :: (array : *Static_Array($T, $N), item : T) { + assert(array.count + 1 < array.capacity); + + print("%\n", array[array.count]); + array[array.count] = item; + array.count += 1; +} diff --git a/test/semant/unknown_overload.golden b/test/semant/unknown_overload.golden index 299b9fb..fb7f709 100644 --- a/test/semant/unknown_overload.golden +++ b/test/semant/unknown_overload.golden @@ -1,4 +1,16 @@ -test/unknown_overload.shd:6,4: error: Type mismatch. Expected float3 got float +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  found: foo(v, v); ^ @@ -18,16 +30,4 @@ 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_type_for_function.golden b/test/semant/wrong_type_for_function.golden index a42219b..d14646f 100644 --- a/test/semant/wrong_type_for_function.golden +++ b/test/semant/wrong_type_for_function.golden @@ -1,14 +1,4 @@ -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' +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); ^^^^^^ @@ -19,4 +9,14 @@  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