From 6b6c7bce62eb14e7d697606e994203ea99d96fad Mon Sep 17 00:00:00 2001 From: Niels Bross Date: Thu, 14 Aug 2025 14:04:54 +0200 Subject: [PATCH] Fixed a bunch of semant back and forth but now it looks like I broke some parameter checking in functions. --- Semantic_Analysis.jai | 109 +++++++++++++++++------------- Test.jai | 144 ++++++++++++++++++++++++++++++++++++++- module.jai | 153 ++---------------------------------------- 3 files changed, 208 insertions(+), 198 deletions(-) diff --git a/Semantic_Analysis.jai b/Semantic_Analysis.jai index 619f7f3..533e129 100644 --- a/Semantic_Analysis.jai +++ b/Semantic_Analysis.jai @@ -467,7 +467,7 @@ Attempting to access a field on a primitive type '%'. init_string_builder(*builder,, temp); variable := from_handle(checker, handle); - print_to_builder(*builder, "Attempting to access a field on a primitive type '%'.\n", proper_type_to_string(checker, variable)); + print_to_builder(*builder, "Attempting to access a field on a primitive type '%'.\n", proper_type_to_string(checker.result.type_variables, variable)); indent(*builder, 1); cyan(*builder); @@ -528,7 +528,7 @@ if_condition_has_to_be_boolean_type :: (checker : *Semantic_Checker, usage_site usage_child := usage_site.children[0]; usage_loc := usage_child.source_location; - print_to_builder(*builder, "% has type %\n", print_from_source_location(*usage_loc), proper_type_to_string(checker, var)); + print_to_builder(*builder, "% has type %\n", print_from_source_location(*usage_loc), proper_type_to_string(checker.result.type_variables, var)); message := builder_to_string(*builder,, temp); record_error(checker, message, usage_site.source_location, false); @@ -570,7 +570,7 @@ type_mismatch :: (checker : *Semantic_Checker, usage_site : *AST_Node, expect_no indent(*builder, 1); print_to_builder(*builder, "expected:\n"); indent(*builder, 2); - proper_type_to_string(*builder, checker, expect_var); + proper_type_to_string(*builder, checker.result.type_variables, expect_var); append(*builder, "\n"); // indent(*builder, 2); @@ -692,8 +692,8 @@ get_scope :: (checker : *Semantic_Checker, handle : Scope_Handle) -> *Scope { return get_scope(*checker.result.scope_stack, handle); } -add_symbol_to_scope :: (checker : *Semantic_Checker, scope_handle : Scope_Handle, name : string, symbol : Defined_Symbol) -> *Defined_Symbol { - scope := get_scope(checker, scope_handle); +add_symbol_to_scope :: (state : Checker_State, scope_stack : *Scope_Stack, scope_handle : Scope_Handle, name : string, symbol : Defined_Symbol) -> *Defined_Symbol { + scope := get_scope(scope_stack.*, scope_handle); scope.longest_key_length = max(scope.longest_key_length, name.count); symbol_to_add : Defined_Symbol; @@ -702,7 +702,7 @@ add_symbol_to_scope :: (checker : *Semantic_Checker, scope_handle : Scope_Handle symbol_to_add.source_node = symbol.source_node; symbol_to_add.functions = symbol.functions; - if checker.state == .Adding_Builtins { + if state == .Adding_Builtins { symbol_to_add.builtin = true; } @@ -787,7 +787,7 @@ from_handle :: (checker : *Semantic_Checker, handle : Type_Variable_Handle) -> * return from_handle(checker.result.type_variables, handle); } -proper_type_to_string :: (builder : *String_Builder, checker : *Semantic_Checker, var : Type_Variable) { +proper_type_to_string :: (builder : *String_Builder, variables : []Type_Variable, var : Type_Variable) { if var.type == { case .Int; #through; case .Half; #through; @@ -806,7 +806,7 @@ proper_type_to_string :: (builder : *String_Builder, checker : *Semantic_Checker if child.kind == .FieldList { for field : child.children { var := field.type_variable; - print_type_variable(builder, checker, var); + print_type_variable(builder, variables, var); if it_index != child.children.count - 1 { append(builder, ", "); @@ -819,12 +819,12 @@ proper_type_to_string :: (builder : *String_Builder, checker : *Semantic_Checker if var.return_type_variable > 0 { append(builder, " -> ", ); - return_var := from_handle(checker, var.return_type_variable); + return_var := from_handle(variables, var.return_type_variable); if is_proper(return_var) { - proper_type_to_string(builder, checker, return_var); + proper_type_to_string(builder, variables, return_var); } else { append(builder, "[["); - print_type_variable(builder, checker, var.return_type_variable); + print_type_variable(builder, variables, var.return_type_variable); append(builder, "]]", ); } } else { @@ -837,7 +837,7 @@ proper_type_to_string :: (builder : *String_Builder, checker : *Semantic_Checker } } -proper_type_to_string :: (checker : *Semantic_Checker, var : Type_Variable, allocator := context.allocator) -> string { +proper_type_to_string :: (variables : []Type_Variable, var : Type_Variable, allocator := context.allocator) -> string { if var.type == { case .Int; #through; case .Half; #through; @@ -849,7 +849,7 @@ proper_type_to_string :: (checker : *Semantic_Checker, var : Type_Variable, allo builder : String_Builder; init_string_builder(*builder,, allocator); - proper_type_to_string(*builder, checker, var); + proper_type_to_string(*builder, variables, var); return builder_to_string(*builder,, allocator); } case .Struct; { @@ -915,7 +915,7 @@ declare_struct :: (checker : *Semantic_Checker, node : *AST_Node, name : string) symbol.name = name; symbol.source_node = node; symbol.type_variable = handle; - add_symbol_to_scope(checker, checker.current_scope, name, symbol); + add_symbol_to_scope(checker.state, *checker.result.scope_stack, checker.current_scope, name, symbol); } else { symbol_redeclaration(checker, node, find_result); return 0; @@ -1024,7 +1024,7 @@ declare_function :: (checker : *Semantic_Checker, node : *AST_Node, builtin : bo array_reserve(*symbol.functions, 32); array_add(*symbol.functions, function); - add_symbol_to_scope(checker, checker.current_scope, name_to_check, symbol); + add_symbol_to_scope(checker.state, *checker.result.scope_stack, checker.current_scope, name_to_check, symbol); } else { //@Note(niels): This is some ugly code, but it's probably fine for now. field_list := node.children[0]; @@ -1261,7 +1261,7 @@ create_field :: (checker : *Semantic_Checker, node : *AST_Node) -> Type_Variable symbol.name = node.name; symbol.source_node = node; symbol.type_variable = handle; - add_symbol_to_scope(checker, checker.current_scope, node.name, symbol); + add_symbol_to_scope(checker.state, *checker.result.scope_stack, checker.current_scope, node.name, symbol); } else { symbol_redeclaration(checker, node, find_result); return 0; @@ -1828,8 +1828,8 @@ type_to_string :: (type_variable : Type_Variable) -> string { #scope_export -print_key :: (checker : *Semantic_Checker, builder : *String_Builder, name : string) { - scope := get_current_scope(checker); +print_key :: (scope_stack : *Scope_Stack, current_scope : Scope_Handle, builder : *String_Builder, name : string) { + scope := get_scope(scope_stack, current_scope); target_length := scope.longest_key_length + 1; missing_padding := target_length - name.count; str := tprint("[%]", name); @@ -1841,15 +1841,15 @@ print_key :: (checker : *Semantic_Checker, builder : *String_Builder, name : str append(builder, ": "); } -pretty_print_function :: (checker : *Semantic_Checker, builder : *String_Builder, name : string, function : Type_Variable, indentation : int) { +pretty_print_function :: (scope_stack : *Scope_Stack, current_scope : Scope_Handle, variables : []Type_Variable, builder : *String_Builder, name : string, function : Type_Variable, indentation : int) { indent(builder, indentation); - print_key(checker, builder, name); + print_key(scope_stack, current_scope, builder, name); append(builder, "("); for child : function.source_node.children { if child.kind == .FieldList { for field : child.children { - tv := from_handle(checker, field.type_variable); + tv := from_handle(variables, field.type_variable); if tv.type != .Function { if tv.builtin { print_to_builder(builder, "%", tv.name); @@ -1857,7 +1857,7 @@ pretty_print_function :: (checker : *Semantic_Checker, builder : *String_Builder print_to_builder(builder, "% : %", tv.name, type_to_string(tv)); } } else { - pretty_print_function(checker, builder, "", tv, 0); + pretty_print_function(scope_stack, current_scope, variables, builder, "", tv, 0); } if it_index < child.children.count - 1 { @@ -1868,20 +1868,20 @@ pretty_print_function :: (checker : *Semantic_Checker, builder : *String_Builder } if function.return_type_variable> 0 { - print_to_builder(builder, ") -> %\n", type_to_string(from_handle(checker, function.return_type_variable))); + print_to_builder(builder, ") -> %\n", type_to_string(from_handle(variables, function.return_type_variable))); } else { append(builder, ")\n"); } } -pretty_print_struct :: (checker : *Semantic_Checker, builder : *String_Builder, name : string, struct_type : Type_Variable, indentation : int) { +pretty_print_struct :: (scope_stack : *Scope_Stack, current_scope : Scope_Handle, variables : []Type_Variable, builder : *String_Builder, name : string, struct_type : Type_Variable, indentation : int) { indent(builder, indentation); - print_key(checker, builder, name); + print_key(scope_stack, current_scope, builder, name); append(builder, "{"); for 0..struct_type.children.count - 1 { child_handle := struct_type.children[it]; - child := from_handle(checker, child_handle); + child := from_handle(variables, child_handle); print_to_builder(builder, child.name); append(builder, " : "); print_to_builder(builder, type_to_string(child)); @@ -1894,7 +1894,7 @@ pretty_print_struct :: (checker : *Semantic_Checker, builder : *String_Builder, append(builder, "}\n"); } -pretty_print_scope :: (checker : *Semantic_Checker, scope : *Scope, builder : *String_Builder, indentation : int = 0) { +pretty_print_scope :: (current_scope : Scope_Handle, scope_stack : Scope_Stack, variables : []Type_Variable, scope : *Scope, builder : *String_Builder, indentation : int = 0) { if scope.builtin { return; } @@ -1919,51 +1919,51 @@ pretty_print_scope :: (checker : *Semantic_Checker, scope : *Scope, builder : *S if value.functions.count > 0 { for func : value.functions { - type_variable := from_handle(checker, func.type_variable); + type_variable := from_handle(variables, func.type_variable); if type_variable.type == { case .Function; { - pretty_print_function(checker, builder, key, type_variable, 1); + pretty_print_function(*scope_stack, current_scope, variables, builder, key, type_variable, 1); } case .CBuffer; #through; case .Properties; #through; case .Struct; { if type_variable.typename.count > 0 && type_variable.kind != .Declaration { indent(builder, indentation + 1); - print_key(checker, builder, key); - print_type_variable(builder, type_variable, checker); + print_key(*scope_stack, current_scope, builder, key); + print_type_variable(builder, variables, type_variable); append(builder, "\n"); // print_to_builder(builder, "%\n", type_variable.typename); } else { - pretty_print_struct(checker, builder, key, type_variable, 1); + pretty_print_struct(*scope_stack, current_scope, variables, builder, key, type_variable, 1); } } case; { indent(builder, indentation + 1); - print_key(checker, builder, key); + print_key(*scope_stack, current_scope, builder, key); print_to_builder(builder, "%\n", type_to_string(type_variable)); } } } } else { - type_variable := from_handle(checker, value.type_variable); + type_variable := from_handle(variables, value.type_variable); if type_variable.type == { case .Function; { - pretty_print_function(checker, builder, key, type_variable, 1); + pretty_print_function(*scope_stack, current_scope, variables, builder, key, type_variable, 1); } case .CBuffer; #through; case .Properties; #through; case .Struct; { if type_variable.typename.count > 0 && type_variable.kind != .Declaration { indent(builder, indentation + 1); - print_key(checker, builder, key); + print_key(*scope_stack, current_scope, builder, key); print_to_builder(builder, "%\n", type_variable.typename); } else { - pretty_print_struct(checker, builder, key, type_variable, 1); + pretty_print_struct(*scope_stack, current_scope, variables, builder, key, type_variable, 1); } } case; { indent(builder, indentation + 1); - print_key(checker, builder, key); + print_key(*scope_stack, current_scope, builder, key); print_to_builder(builder, "%\n", type_to_string(type_variable)); } } @@ -1972,8 +1972,8 @@ pretty_print_scope :: (checker : *Semantic_Checker, scope : *Scope, builder : *S } for child : scope.children { - child_scope := *checker.result.scope_stack.stack[child - 1]; - pretty_print_scope(checker, child_scope, builder, indentation + 1); + child_scope := *scope_stack.stack[child - 1]; + pretty_print_scope(current_scope, *scope_stack, variables, child_scope, builder, indentation + 1); } if scope.table.count > 0 { @@ -1982,7 +1982,7 @@ pretty_print_scope :: (checker : *Semantic_Checker, scope : *Scope, builder : *S append(builder, "]\n"); } -print_type_variable :: (builder : *String_Builder, variable : Type_Variable, checker : *Semantic_Checker) { +print_type_variable :: (builder : *String_Builder, variables : []Type_Variable, variable : Type_Variable) { if variable.builtin { if variable.type != .Function || variable.type != .Struct { print_to_builder(builder, "%", type_to_string(variable)); @@ -2036,7 +2036,7 @@ print_type_variable :: (builder : *String_Builder, variable : Type_Variable, che if variable.return_type_variable{ assert(false); print_to_builder(builder, "%", variable.typename); - print_type_variable(builder, checker, variable.return_type_variable); + print_type_variable(builder, variables, variable.return_type_variable); } print_to_builder(builder, "%(", node.name); @@ -2045,7 +2045,7 @@ print_type_variable :: (builder : *String_Builder, variable : Type_Variable, che for child : node.children { if child.kind == .ArgList { for arg : child.children { - print_type_variable(builder, checker, arg.type_variable); + print_type_variable(builder, variables, arg.type_variable); if it_index < child.children.count - 1 { append(builder, ", "); @@ -2064,20 +2064,35 @@ print_type_variable :: (builder : *String_Builder, variable : Type_Variable, che } } -print_type_variable :: (builder : *String_Builder, checker : *Semantic_Checker, handle : Type_Variable_Handle) { - variable := from_handle(checker, handle); - print_type_variable(builder, variable, checker); +print_type_variable :: (builder : *String_Builder, variables : []Type_Variable, handle : Type_Variable_Handle) { + variable := from_handle(variables, handle); + print_type_variable(builder, variables, variable); } pretty_print_symbol_table :: (checker : *Semantic_Checker, allocator : Allocator) -> string { builder : String_Builder; init_string_builder(*builder,, allocator); - pretty_print_scope(checker, *checker.result.scope_stack.stack[0], *builder); + pretty_print_scope(xx checker.current_scope, checker.result.scope_stack, checker.result.type_variables, *checker.result.scope_stack.stack[0], *builder); return builder_to_string(*builder,, allocator); } +pretty_print_symbol_table :: (result : *Compile_Result, allocator : Allocator) -> string { + builder : String_Builder; + init_string_builder(*builder,, allocator); + + for *file : result.files { + current_scope := cast(Scope_Handle)0; + check_result := file.semantic_check_result; + pretty_print_scope(current_scope, check_result.scope_stack, check_result.type_variables, *check_result.scope_stack.stack[0], *builder); + + } + + + return builder_to_string(*builder,, allocator); +} + #scope_module #import "ncore"; diff --git a/Test.jai b/Test.jai index c143b54..e4a317d 100644 --- a/Test.jai +++ b/Test.jai @@ -169,7 +169,7 @@ run_parser_test :: (file_path : string, output_type : Output_Type = 0) -> Result result := lex(*lexer, *temp); if result.had_error { - result_data.type = .Passed; + result_data.type = .Passed; //@Incomplete: Huh? return result_data, null; } @@ -408,10 +408,10 @@ run_codegen_test :: (path : string, output_type : Output_Type = 0) -> Result, Co return result, codegen_result; } -run_compile_test :: (path : string, output_type : Output_Type = 0) -> Result, Compilation_Result { +run_compile_test :: (path : string, output_type : Output_Type = 0) -> Result, Compile_Result { compiler : Shader_Compiler; result : Result; - compilation_result := compile_file(*compiler, path); + compilation_result := compile_file(*compiler, .[path]); print("\n"); if compilation_result.had_error { @@ -422,6 +422,102 @@ run_compile_test :: (path : string, output_type : Output_Type = 0) -> Result, Co return result, compilation_result; } +run_lexer_test :: (file_path : string, result : *Compile_Result, output_type : Output_Type = 0) -> Result { + result_data : Result; + result_data.path = file_path; + result_data.stage = .Lexer; + + result_text : string; + + add_file(result, file_path); + lex(result); + if result.had_error { + result_data.type = .Failed; + result_text = report_messages(result.messages); + } else { + result_text = pretty_print_tokens(result.files[0].tokens.tokens, *temp); + } + + if output_type & .StdOut { + result_data.info_text = result_text; + result_data.type = .StdOut; + return result_data; + } + + golden_path := get_golden_path(file_path, .Lexer); + do_golden_comparison(golden_path, result_text, *result_data, output_type); + return result_data; +} + +run_parser_test :: (file_path : string, result : *Compile_Result, output_type : Output_Type = 0) -> Result { + result_data : Result; + result_data.path = file_path; + + add_file(result, file_path); + + lex(result); + if result.had_error { + result_data.type = .Passed; + return result_data; + } + + result_data = run_parser_test(result, output_type); + + return result_data; +} + +run_parser_test :: (result : *Compile_Result, output_type : Output_Type = 0) -> Result { + parse(result); + result_data : Result; + result_data.path = result.files[0].file.path; + result_text : string; + + if result.had_error { + result_data.type = .Failed; + result_text = report_messages(result.messages,, temp); + } else { + result_text = pretty_print_ast(result.files[0].ast_root, *temp); + } + + if output_type & .StdOut { + result_data.info_text = result_text; + result_data.type = .StdOut; + return result_data; + } + + golden_path := get_golden_path(result.files[0].file.path, .Parser); + do_golden_comparison(golden_path, result_text, *result_data, output_type); + return result_data; +} + +run_semantic_analysis_test :: (file_path : string, result : *Compile_Result, output_type : Output_Type = 0) -> Result { + add_file(result, file_path); + + result_data : Result; + + result_data.path = file_path; + result_data.stage = .Semantic_Analysis; + result_text : string; + check(result); + + if result.had_error { + result_data.type = .Failed; + result_text = report_messages(result.messages); + } else { + result_text = pretty_print_symbol_table(result, temp); + } + + if output_type & .StdOut { + result_data.info_text = result_text; + result_data.type = .StdOut; + return result_data; + } + + golden_path := get_golden_path(file_path, .Semantic_Analysis); + do_golden_comparison(golden_path, result_text, *result_data, output_type); + return result_data; +} + make_test_case :: (path : string, stage_flags : Stage_Flags, allocator := context.allocator) -> Test_Case { test_case : Test_Case; test_case.path = copy_string(path,, allocator); @@ -431,6 +527,48 @@ make_test_case :: (path : string, stage_flags : Stage_Flags, allocator := contex return test_case; } +run_test_new :: (file_path : string, stage_flags : Stage_Flags, results : *[..]Result, output_type : Output_Type = 0) { + compile_result : Compile_Result; + result : Result; + if stage_flags & .Lexer { + result = run_lexer_test(file_path, *compile_result, output_type); + record_result(results, result); + } + + if stage_flags & .Parser { + if stage_flags & .Lexer && result.type == .Passed || result.type == .Golden_Output { + result = run_parser_test(*compile_result, output_type); + } else { + result = run_parser_test(file_path, output_type); + } + record_result(results, result); + } + + if stage_flags & .Semantic_Analysis { + if stage_flags & .Parser && (result.type == .Passed || result.type == .Golden_Output) { + result = run_semantic_analysis_test(file_path, *compile_result, output_type); + } else { + result = run_semantic_analysis_test(file_path, *compile_result, output_type); + } + record_result(results, result); + } + + // if stage_flags & .Codegen { + // if stage_flags & .Semantic_Analysis && (result.type == .Passed || result.type == .Golden_Output) { + // result = run_codegen_test(file_path, *compile_result, output_type); + // } else if compile_result.ast_root { + // result = run_codegen_test(file_path, *compile_result, output_type); + // } else { + // result = run_codegen_test(file_path, *compile_result, output_type); + // } + // record_result(results, result); + // } + + // if stage_flags & .Compile { + // result = run_compile_test(file_path, output_type); + // } +} + run_test :: (file_path : string, stage_flags : Stage_Flags, results : *[..]Result, output_type : Output_Type = 0) { lexer : Lexer; result : Result; diff --git a/module.jai b/module.jai index 59c70a5..d1117d2 100644 --- a/module.jai +++ b/module.jai @@ -215,13 +215,13 @@ from_files :: (paths : []string) -> Compile_Result { return result; } -Compilation_Result :: struct { - messages : [..]Compiler_Message; +// Compilation_Result :: struct { +// messages : [..]Compiler_Message; - had_error : bool; +// had_error : bool; - collection : Shader_Variant_Collection; -} +// collection : Shader_Variant_Collection; +// } pretty_print_field :: (field : *Field) -> string { builder : String_Builder; @@ -492,146 +492,3 @@ compile_file :: (compiler : *Shader_Compiler, paths : []string) -> Compile_Resul return result; } - -compile_file :: (compiler : *Shader_Compiler, path : string) -> Compilation_Result { - result : Compilation_Result; - - lexer : Lexer; - - init_lexer_from_file(*lexer, path); - if lexer.result.had_error { - copy_messages(lexer.result.messages, *result.messages); - result.had_error = true; - return result; - } - - lex_result := lex(*lexer,, *temp); - if lex_result.had_error { - copy_messages(lex_result.messages, *result.messages); - result.had_error = true; - return result; - } - - parse_state : Parse_State; - init_parse_state(*parse_state, lex_result.tokens, lexer.path); - - parse_result := parse(*parse_state); - if parse_result.had_error { - copy_messages(parse_result.messages, *result.messages); - result.had_error = true; - return result; - } - - checker : Semantic_Checker; - init_semantic_checker(*checker, parse_result.root, path); - - check_result := check(*checker); - if check_result.had_error { - copy_messages(check_result.messages, *result.messages); - result.had_error = true; - return result; - } - - state : Codegen_State; - init_codegen_state(*state, parse_result.root, check_result, .HLSL); - - result_text : string; - - codegen_result := codegen(*state); - if codegen_result.had_error { - copy_messages(codegen_result.messages, *result.messages); - result.had_error = true; - - return result; - } - - // @Incomplete(nb): Assumes only a single variant for now - - variant : Shader_Variant; - variant.text = codegen_result.result_text; - - if checker.result.vertex_entry_point { - variant.vertex_entry_point.name = checker.result.vertex_entry_point.name; - - type_variable := from_handle(*checker, checker.result.vertex_entry_point.type_variable); - assert(type_variable.type == .Function); - - node := type_variable.source_node; - if node.children.count > 0 { - if node.children[0].kind == .FieldList { - field_list := node.children[0]; - for child : field_list.children { - tv := from_handle(*checker, child.type_variable); - field := type_variable_to_field(*checker, tv); - array_add(*variant.vertex_entry_point.input, field); - } - } - } - } - - for buffer_variable : to_array(*check_result.constant_buffers) { - variable := from_handle(check_result.type_variables, buffer_variable); - - cb := array_add(*result.collection.cbuffers); - - for i : 0..variable.children.count - 1 { - child := variable.children[i]; - field : Property_Field; - field.base_field = type_variable_to_field(*checker, from_handle(*checker, child));; - array_add(*cb.fields, field); - } - - cb.buffer_index = variable.resource_index; - } - - find_result := find_symbol(*check_result.scope_stack, check_result.property_name, xx 1); - if find_result { - property_variable := from_handle(check_result.type_variables, find_result.type_variable); - - for i : 0..property_variable.children.count - 1 { - child := property_variable.children[i]; - field := type_variable_to_field(*checker, from_handle(*checker, child)); - prop_field : Property_Field; - prop_field.base_field = field; - array_add(*result.collection.properties.fields, prop_field); - } - result.collection.properties.buffer_index = property_variable.resource_index; - } - - if checker.result.pixel_entry_point { - variant.pixel_entry_point.name = checker.result.pixel_entry_point.name; - - type_variable := from_handle(*checker, checker.result.pixel_entry_point.type_variable); - assert(type_variable.type == .Function); - - field := type_variable_to_field(*checker, type_variable.return_type_variable); - for hint : type_variable.source_node.hint_tokens { - field_hint : Field_Hint; - - if hint.ident_value == "position" { - // @Incomplete(nb): Should be a lookup table somewhere - field_hint.kind = .Position; - } else if starts_with(hint.ident_value, "target") { - // @Incomplete(nb): Should be a lookup table somewhere - index_str : string; - index_str.data = *hint.ident_value.data[7]; - index_str.count = 1; - - result, ok, remainder := string_to_int(index_str); - if ok { - field_hint.target_index = result; - } - field_hint.kind = .Target; - } else { - // @Incomplete(nb): custo hints - } - array_add(*field.hints, field_hint); - } - - variant.pixel_entry_point.return_value = field; - } - - array_add(*result.collection.variants, variant); - - return result; -}