From d08529a3ebfc72a58ff4a0e591480280d6f97dfa Mon Sep 17 00:00:00 2001 From: Niels Bross Date: Sat, 4 Jan 2025 23:12:54 +0100 Subject: [PATCH 01/17] Simplification of API. --- Codegen.jai | 16 ++++++++++++++++ Lexing.jai | 4 +++- Parsing.jai | 4 ++++ Semantic_Analysis.jai | 21 +++++++++++++++++++++ module.jai | 12 ++++++++---- 5 files changed, 52 insertions(+), 5 deletions(-) diff --git a/Codegen.jai b/Codegen.jai index 7f252e9..cfd569d 100644 --- a/Codegen.jai +++ b/Codegen.jai @@ -504,6 +504,22 @@ emit_declaration :: (state : *Codegen_State, node : *AST_Node) { } } +codegen :: (result : *Compile_Result) { + if result.had_error { + return; + } + + for *file : result.files { + state : Codegen_State; + init_codegen_state(*state, file.ast_root, file.semantic_check_result, .HLSL); + + //@Incomplete(nb): just call the codegen function for now with old result struct + codegen_result := codegen(*state); + + file.codegen_result_text = copy_string(codegen_result.result_text); + } +} + codegen :: (state : *Codegen_State) -> Codegen_Result { found_function : bool = false; // found_struct : bool = false; diff --git a/Lexing.jai b/Lexing.jai index 3451623..ab77cf9 100644 --- a/Lexing.jai +++ b/Lexing.jai @@ -506,7 +506,7 @@ lex :: (result : *Compile_Result) { return; } - for file : result.files { + for *file : result.files { lexer : Lexer; init_lexer_from_string(*lexer, file.file.source); token : *Token = scan_next_token(*lexer); @@ -514,6 +514,8 @@ lex :: (result : *Compile_Result) { token = scan_next_token(*lexer); } + array_copy(*file.tokens.tokens, lexer.result.tokens); + // @Incomplete(nb): Temporary until we figure out a good way of passing this stuff around copy_messages(lexer.result.messages, *result.messages); } diff --git a/Parsing.jai b/Parsing.jai index 20c75cb..30b8b89 100644 --- a/Parsing.jai +++ b/Parsing.jai @@ -1061,6 +1061,10 @@ declaration :: (parse_state : *Parse_State) -> *AST_Node { } parse :: (result : *Compile_Result) { + if result.had_error { + return; + } + for *file : result.files { parse_state : Parse_State; init_parse_state(*parse_state, file.tokens.tokens, file.file.path); diff --git a/Semantic_Analysis.jai b/Semantic_Analysis.jai index 78d49d6..be635bc 100644 --- a/Semantic_Analysis.jai +++ b/Semantic_Analysis.jai @@ -1651,6 +1651,27 @@ type_check :: (checker : *Semantic_Checker, root : *AST_Node) { traverse(checker, root); } +check :: (result : *Compile_Result) { + if result.had_error { + return; + } + + for *file : result.files { + checker : Semantic_Checker; + + checker.current_buffer_index = 0; + checker.current_sampler_index = 0; + checker.current_texture_index = 0; + array_reserve(*checker.result.messages, 16); + add_hlsl_builtins(*checker); + + type_check(*checker, file.ast_root); + + file.semantic_check_result = checker.result; + copy_messages(checker.result.messages, *result.messages); + } +} + check :: (checker : *Semantic_Checker, root : *AST_Node) -> Semantic_Check_Result { checker.current_buffer_index = 0; checker.current_sampler_index = 0; diff --git a/module.jai b/module.jai index 647ff40..b65bfd8 100644 --- a/module.jai +++ b/module.jai @@ -145,7 +145,11 @@ Compiled_File :: struct { file : Input_File; tokens : Token_Stream; ast_root : *AST_Node; - ast_nodes : [..]AST_Node; + ast_nodes : [..]AST_Node; + + codegen_result_text : string; + + semantic_check_result : Semantic_Check_Result; } Compile_Result :: struct { @@ -368,9 +372,9 @@ compile_file :: (compiler : *Shader_Compiler, paths : []string) -> Compile_Resul } lex(*result); - // parse(*result); - // check(*result); - // codegen(*result); + parse(*result); + check(*result); + codegen(*result); return result; } From d65c6359dbacc7d3b8941dbdf9665179f149fbf1 Mon Sep 17 00:00:00 2001 From: Niels Bross Date: Sun, 5 Jan 2025 22:38:08 +0100 Subject: [PATCH 02/17] Fixed some sem check init. --- Semantic_Analysis.jai | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Semantic_Analysis.jai b/Semantic_Analysis.jai index be635bc..b631e29 100644 --- a/Semantic_Analysis.jai +++ b/Semantic_Analysis.jai @@ -684,6 +684,12 @@ add_child :: (checker : *Semantic_Checker, handle : Type_Variable_Handle, child } init_semantic_checker :: (checker : *Semantic_Checker, root : *AST_Node, path : string) { + checker.current_buffer_index = 0; + checker.current_sampler_index = 0; + checker.current_texture_index = 0; + + array_reserve(*checker.result.messages, 16); + checker.program_root = root; checker.path = path; @@ -1663,6 +1669,9 @@ check :: (result : *Compile_Result) { checker.current_sampler_index = 0; checker.current_texture_index = 0; array_reserve(*checker.result.messages, 16); + + init_semantic_checker(*checker, file.ast_root, file.file.path); + add_hlsl_builtins(*checker); type_check(*checker, file.ast_root); From 1adb289c10dca8d00e3670a5c730d5173e12b6e7 Mon Sep 17 00:00:00 2001 From: Niels Bross Date: Mon, 6 Jan 2025 22:17:44 +0100 Subject: [PATCH 03/17] Add error propagation to lexer. --- Lexing.jai | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Lexing.jai b/Lexing.jai index ab77cf9..7b6a310 100644 --- a/Lexing.jai +++ b/Lexing.jai @@ -509,12 +509,14 @@ lex :: (result : *Compile_Result) { for *file : result.files { lexer : Lexer; init_lexer_from_string(*lexer, file.file.source); + lexer.path = file.file.path; token : *Token = scan_next_token(*lexer); while token && token.kind != .TOKEN_EOF { token = scan_next_token(*lexer); } array_copy(*file.tokens.tokens, lexer.result.tokens); + result.had_error |= lexer.result.had_error; // @Incomplete(nb): Temporary until we figure out a good way of passing this stuff around copy_messages(lexer.result.messages, *result.messages); From 4053400152af2705d789709fcc16249fb66fcf0f Mon Sep 17 00:00:00 2001 From: Niels Bross Date: Wed, 8 Jan 2025 22:37:48 +0100 Subject: [PATCH 04/17] Added unary expressions to semcheck and codegen. --- AST.jai | 4 ++ Codegen.jai | 5 +- Semantic_Analysis.jai | 14 ++++ test/codegen/unary.golden | 10 +++ test/codegen_all.suite | 1 + test/compile_all.suite | 1 + test/lex/float_suffix.golden | 2 +- test/lex/unary.golden | 64 +++++++++++++++++++ test/lex_all.suite | 1 + .../parse/field_without_type_specifier.golden | 2 +- test/parse/unary.golden | 8 +++ test/parse_all.suite | 1 + test/semant/functions_with_same_name.golden | 4 +- test/semant/redeclared_variable.golden | 4 +- .../struct_access_primitive_type.golden | 2 +- test/semant/type_as_variable_name.golden | 2 +- test/semant/unary.golden | 10 +++ test/semant/undeclared_function.golden | 2 +- test/semant/undeclared_symbol.golden | 2 +- test/semant/unknown_overload.golden | 10 +-- test/semant/wrong_argument_count.golden | 8 +-- test/semant/wrong_multiply.golden | 2 +- test/semant/wrong_type_for_function.golden | 6 +- test/semant_all.suite | 1 + test/unary.ink | 7 ++ 25 files changed, 149 insertions(+), 24 deletions(-) create mode 100644 test/codegen/unary.golden create mode 100644 test/lex/unary.golden create mode 100644 test/parse/unary.golden create mode 100644 test/semant/unary.golden create mode 100644 test/unary.ink diff --git a/AST.jai b/AST.jai index 2f16603..57993a4 100644 --- a/AST.jai +++ b/AST.jai @@ -211,7 +211,11 @@ pretty_print_binary :: (node : *AST_Node, indentation : int, builder : *String_B } pretty_print_unary :: (node : *AST_Node, indentation : int, builder : *String_Builder) { + indent(builder, indentation); + op := node.token; + print_to_builder(builder, op_to_string(op)); + pretty_print_children(node, 0, builder, flags = 0); } print_return_node :: (node : *AST_Node, indentation : int, builder : *String_Builder) { diff --git a/Codegen.jai b/Codegen.jai index cfd569d..8fe0512 100644 --- a/Codegen.jai +++ b/Codegen.jai @@ -420,7 +420,10 @@ emit_node :: (state : *Codegen_State, node : *AST_Node, indentation : int) { } } case .Unary; { - assert(false, "Not implemented yet: unary"); + indent(*state.builder, indentation); + + emit_operator(state, node.token.kind); + emit_node(state, node.children[0], 0); } case .Expression_Statement; { emit_node(state, node.children[0], indentation); diff --git a/Semantic_Analysis.jai b/Semantic_Analysis.jai index b631e29..6beebca 100644 --- a/Semantic_Analysis.jai +++ b/Semantic_Analysis.jai @@ -330,6 +330,7 @@ no_matching_overload_found :: (checker : *Semantic_Checker, call : *AST_Node, ov record_error(checker, message, locations, false); } + not_all_control_paths_return_value :: (checker : *Semantic_Checker, node : *AST_Node) { builder : String_Builder; init_string_builder(*builder,, temp); @@ -1374,6 +1375,19 @@ check_node :: (checker : *Semantic_Checker, node : *AST_Node) -> Type_Variable_H field_var := create_field(checker, node); return field_var; } + case .Unary; { + var := check_node(checker, node.children[0]); + variable, handle := new_type_variable(checker); + type := from_handle(checker, var); + variable.type = type.type; + variable.typename = type.typename; + variable.scope = type.scope; + variable.source_node = node; + node.type_variable = handle; + add_child(variable, var); + + return handle; + } case .Binary; { lhs_var := check_node(checker, node.children[0]); if lhs_var == 0 { diff --git a/test/codegen/unary.golden b/test/codegen/unary.golden new file mode 100644 index 0000000..9c73d21 --- /dev/null +++ b/test/codegen/unary.golden @@ -0,0 +1,10 @@ +float4 vs_vs_main(float3 position : POSITION) : SV_POSITION +{ + return float4(position.x, position.y, position.z, 1.0f); +} + +float4 ps_ps_main(float4 position : SV_POSITION) : SV_TARGET +{ + return float4(0.5f, -1, 0, 1); +} + diff --git a/test/codegen_all.suite b/test/codegen_all.suite index c1d2088..87c48e9 100644 --- a/test/codegen_all.suite +++ b/test/codegen_all.suite @@ -17,4 +17,5 @@ test/passthrough.ink codegen test/property_rename.ink codegen test/simple_struct_access.ink codegen test/struct_within_struct.ink codegen +test/unary.ink codegen test/use_builtin_functions.ink codegen diff --git a/test/compile_all.suite b/test/compile_all.suite index d2e4495..b17e326 100644 --- a/test/compile_all.suite +++ b/test/compile_all.suite @@ -17,4 +17,5 @@ test/pass_and_access_struct_fields_in_functions.ink compile test/passthrough.ink compile test/simple_struct_access.ink compile test/struct_within_struct.ink compile +test/unary.ink compile test/use_builtin_functions.ink compile \ No newline at end of file diff --git a/test/lex/float_suffix.golden b/test/lex/float_suffix.golden index de8d3af..94acbd1 100644 --- a/test/lex/float_suffix.golden +++ b/test/lex/float_suffix.golden @@ -1,4 +1,4 @@ -test/float_suffix.inx:2,12: error: We don't use 'f' suffixes for floating point values. +test/float_suffix.ink:2,12: error: We don't use 'f' suffixes for floating point values.  x : float = 2.0f ^^^^  \ No newline at end of file diff --git a/test/lex/unary.golden b/test/lex/unary.golden new file mode 100644 index 0000000..51d8753 --- /dev/null +++ b/test/lex/unary.golden @@ -0,0 +1,64 @@ +{kind = TOKEN_VERTEX; ; index = 0 ; length = 6 line = 1 ; column = 0 ; value ='vertex'; } +{kind = TOKEN_IDENTIFIER; ; index = 7 ; length = 7 line = 1 ; column = 7 ; value ='vs_main'; } +{kind = TOKEN_DOUBLECOLON; ; index = 15 ; length = 2 line = 1 ; column = 15 ; value ='::'; } +{kind = TOKEN_LEFTPAREN; ; index = 18 ; length = 1 line = 1 ; column = 18 ; value ='('; } +{kind = TOKEN_IDENTIFIER; ; index = 19 ; length = 8 line = 1 ; column = 19 ; value ='position'; } +{kind = TOKEN_COLON; ; index = 28 ; length = 1 line = 1 ; column = 28 ; value =':'; } +{kind = TOKEN_IDENTIFIER; ; index = 30 ; length = 6 line = 1 ; column = 30 ; value ='float3'; } +{kind = TOKEN_AT; ; index = 37 ; length = 1 line = 1 ; column = 37 ; value ='@'; } +{kind = TOKEN_IDENTIFIER; ; index = 38 ; length = 8 line = 1 ; column = 38 ; value ='position'; } +{kind = TOKEN_RIGHTPAREN; ; index = 46 ; length = 1 line = 1 ; column = 46 ; value =')'; } +{kind = TOKEN_ARROW; ; index = 48 ; length = 2 line = 1 ; column = 48 ; value ='->'; } +{kind = TOKEN_IDENTIFIER; ; index = 51 ; length = 6 line = 1 ; column = 51 ; value ='float4'; } +{kind = TOKEN_AT; ; index = 58 ; length = 1 line = 1 ; column = 58 ; value ='@'; } +{kind = TOKEN_IDENTIFIER; ; index = 59 ; length = 8 line = 1 ; column = 59 ; value ='position'; } +{kind = TOKEN_LEFTBRACE; ; index = 68 ; length = 1 line = 1 ; column = 68 ; value ='{'; } +{kind = TOKEN_RETURN; ; index = 75 ; length = 6 line = 2 ; column = 3 ; value ='return'; } +{kind = TOKEN_IDENTIFIER; ; index = 82 ; length = 6 line = 2 ; column = 10 ; value ='float4'; } +{kind = TOKEN_LEFTPAREN; ; index = 88 ; length = 1 line = 2 ; column = 16 ; value ='('; } +{kind = TOKEN_IDENTIFIER; ; index = 89 ; length = 8 line = 2 ; column = 17 ; value ='position'; } +{kind = TOKEN_DOT; ; index = 97 ; length = 1 line = 2 ; column = 25 ; value ='.'; } +{kind = TOKEN_IDENTIFIER; ; index = 98 ; length = 1 line = 2 ; column = 26 ; value ='x'; } +{kind = TOKEN_COMMA; ; index = 99 ; length = 1 line = 2 ; column = 27 ; value =','; } +{kind = TOKEN_IDENTIFIER; ; index = 101 ; length = 8 line = 2 ; column = 29 ; value ='position'; } +{kind = TOKEN_DOT; ; index = 109 ; length = 1 line = 2 ; column = 37 ; value ='.'; } +{kind = TOKEN_IDENTIFIER; ; index = 110 ; length = 1 line = 2 ; column = 38 ; value ='y'; } +{kind = TOKEN_COMMA; ; index = 111 ; length = 1 line = 2 ; column = 39 ; value =','; } +{kind = TOKEN_IDENTIFIER; ; index = 113 ; length = 8 line = 2 ; column = 41 ; value ='position'; } +{kind = TOKEN_DOT; ; index = 121 ; length = 1 line = 2 ; column = 49 ; value ='.'; } +{kind = TOKEN_IDENTIFIER; ; index = 122 ; length = 1 line = 2 ; column = 50 ; value ='z'; } +{kind = TOKEN_COMMA; ; index = 123 ; length = 1 line = 2 ; column = 51 ; value =','; } +{kind = TOKEN_FLOATLITERAL; ; index = 125 ; length = 3 line = 2 ; column = 53 ; value ='1'; } +{kind = TOKEN_RIGHTPAREN; ; index = 128 ; length = 1 line = 2 ; column = 56 ; value =')'; } +{kind = TOKEN_SEMICOLON; ; index = 129 ; length = 1 line = 2 ; column = 57 ; value =';'; } +{kind = TOKEN_RIGHTBRACE; ; index = 132 ; length = 1 line = 3 ; column = 0 ; value ='}'; } +{kind = TOKEN_PIXEL; ; index = 137 ; length = 5 line = 5 ; column = 0 ; value ='pixel'; } +{kind = TOKEN_IDENTIFIER; ; index = 143 ; length = 7 line = 5 ; column = 6 ; value ='ps_main'; } +{kind = TOKEN_DOUBLECOLON; ; index = 151 ; length = 2 line = 5 ; column = 14 ; value ='::'; } +{kind = TOKEN_LEFTPAREN; ; index = 154 ; length = 1 line = 5 ; column = 17 ; value ='('; } +{kind = TOKEN_IDENTIFIER; ; index = 155 ; length = 8 line = 5 ; column = 18 ; value ='position'; } +{kind = TOKEN_COLON; ; index = 164 ; length = 1 line = 5 ; column = 27 ; value =':'; } +{kind = TOKEN_IDENTIFIER; ; index = 166 ; length = 6 line = 5 ; column = 29 ; value ='float4'; } +{kind = TOKEN_AT; ; index = 173 ; length = 1 line = 5 ; column = 36 ; value ='@'; } +{kind = TOKEN_IDENTIFIER; ; index = 174 ; length = 11 line = 5 ; column = 37 ; value ='outposition'; } +{kind = TOKEN_RIGHTPAREN; ; index = 185 ; length = 1 line = 5 ; column = 48 ; value =')'; } +{kind = TOKEN_ARROW; ; index = 187 ; length = 2 line = 5 ; column = 50 ; value ='->'; } +{kind = TOKEN_IDENTIFIER; ; index = 190 ; length = 6 line = 5 ; column = 53 ; value ='float4'; } +{kind = TOKEN_AT; ; index = 197 ; length = 1 line = 5 ; column = 60 ; value ='@'; } +{kind = TOKEN_IDENTIFIER; ; index = 198 ; length = 6 line = 5 ; column = 61 ; value ='target'; } +{kind = TOKEN_LEFTBRACE; ; index = 205 ; length = 1 line = 5 ; column = 68 ; value ='{'; } +{kind = TOKEN_RETURN; ; index = 211 ; length = 6 line = 6 ; column = 2 ; value ='return'; } +{kind = TOKEN_IDENTIFIER; ; index = 218 ; length = 6 line = 6 ; column = 9 ; value ='float4'; } +{kind = TOKEN_LEFTPAREN; ; index = 224 ; length = 1 line = 6 ; column = 15 ; value ='('; } +{kind = TOKEN_FLOATLITERAL; ; index = 225 ; length = 3 line = 6 ; column = 16 ; value ='0.5'; } +{kind = TOKEN_COMMA; ; index = 228 ; length = 1 line = 6 ; column = 19 ; value =','; } +{kind = TOKEN_MINUS; ; index = 230 ; length = 1 line = 6 ; column = 21 ; value ='-'; } +{kind = TOKEN_INTLITERAL; ; index = 231 ; length = 1 line = 6 ; column = 22 ; value ='1'; } +{kind = TOKEN_COMMA; ; index = 232 ; length = 1 line = 6 ; column = 23 ; value =','; } +{kind = TOKEN_INTLITERAL; ; index = 234 ; length = 1 line = 6 ; column = 25 ; value ='0'; } +{kind = TOKEN_COMMA; ; index = 235 ; length = 1 line = 6 ; column = 26 ; value =','; } +{kind = TOKEN_INTLITERAL; ; index = 237 ; length = 1 line = 6 ; column = 28 ; value ='1'; } +{kind = TOKEN_RIGHTPAREN; ; index = 238 ; length = 1 line = 6 ; column = 29 ; value =')'; } +{kind = TOKEN_SEMICOLON; ; index = 239 ; length = 1 line = 6 ; column = 30 ; value =';'; } +{kind = TOKEN_RIGHTBRACE; ; index = 242 ; length = 1 line = 7 ; column = 0 ; value ='}'; } +{kind = TOKEN_EOF; ; index = 243 ; length = 0 line = 7 ; column = 1 ; value =''; } diff --git a/test/lex_all.suite b/test/lex_all.suite index 03f71bb..852a8f3 100644 --- a/test/lex_all.suite +++ b/test/lex_all.suite @@ -24,6 +24,7 @@ test/simple_struct_access.ink lex test/struct_access_primitive_type.ink lex test/struct_within_struct.ink lex test/type_as_variable_name.ink lex +test/unary.ink lex test/undeclared_function.ink lex test/undeclared_symbol.ink lex test/unknown_overload.ink lex diff --git a/test/parse/field_without_type_specifier.golden b/test/parse/field_without_type_specifier.golden index 81d11ba..77cd077 100644 --- a/test/parse/field_without_type_specifier.golden +++ b/test/parse/field_without_type_specifier.golden @@ -1,4 +1,4 @@ -test/field_without_type_specifier.inx:2,0: error: Expected type specifier after field name. +test/field_without_type_specifier.ink:2,0: error: Expected type specifier after field name. x := 5.0; ^  \ No newline at end of file diff --git a/test/parse/unary.golden b/test/parse/unary.golden new file mode 100644 index 0000000..e246f2a --- /dev/null +++ b/test/parse/unary.golden @@ -0,0 +1,8 @@ +(program + (fun vertex vs_vs_main -> float4 (@position) + [(:= position float3 (@position))] + (return (float4 position.x position.y position.z 1))) + + (fun pixel ps_ps_main -> float4 (@target) + [(:= position float4 (@outposition))] + (return (float4 0.5 -1 0 1)))) \ No newline at end of file diff --git a/test/parse_all.suite b/test/parse_all.suite index 21b2e0f..14ae4ac 100644 --- a/test/parse_all.suite +++ b/test/parse_all.suite @@ -24,6 +24,7 @@ test/simple_struct_access.ink parse test/struct_access_primitive_type.ink parse test/struct_within_struct.ink parse test/type_as_variable_name.ink parse +test/unary.ink parse test/undeclared_function.ink parse test/undeclared_symbol.ink parse test/unknown_overload.ink parse diff --git a/test/semant/functions_with_same_name.golden b/test/semant/functions_with_same_name.golden index 9b9d09c..fcfc0cf 100644 --- a/test/semant/functions_with_same_name.golden +++ b/test/semant/functions_with_same_name.golden @@ -1,8 +1,8 @@ -test/functions_with_same_name.inx:2,0: error: Redeclaration of 'foo' +test/functions_with_same_name.ink:2,0: error: Redeclaration of 'foo'  foo :: () { ^^^ -test/functions_with_same_name.inx:1,0: info: Here is the first declaration of 'foo' +test/functions_with_same_name.ink:1,0: info: Here is the first declaration of 'foo'  foo :: () { ^^^  \ No newline at end of file diff --git a/test/semant/redeclared_variable.golden b/test/semant/redeclared_variable.golden index 72fd8d9..e1aca71 100644 --- a/test/semant/redeclared_variable.golden +++ b/test/semant/redeclared_variable.golden @@ -1,8 +1,8 @@ -test/redeclared_variable.inx:3,0: error: Redeclaration of 'x' +test/redeclared_variable.ink:3,0: error: Redeclaration of 'x'  x : float = 5.0 ^ -test/redeclared_variable.inx:2,0: info: Here is the first declaration of 'x' +test/redeclared_variable.ink:2,0: info: Here is the first declaration of 'x'  x : float = 1.0 ^  \ No newline at end of file diff --git a/test/semant/struct_access_primitive_type.golden b/test/semant/struct_access_primitive_type.golden index a77f4f9..abffb44 100644 --- a/test/semant/struct_access_primitive_type.golden +++ b/test/semant/struct_access_primitive_type.golden @@ -1,4 +1,4 @@ -test/struct_access_primitive_type.inx:3,0: error: Attempting to access a field on a primitive type 'int'. +test/struct_access_primitive_type.ink:3,0: error: Attempting to access a field on a primitive type 'int'. x.d = 4; ^ declaration: diff --git a/test/semant/type_as_variable_name.golden b/test/semant/type_as_variable_name.golden index bdb0bbc..59e7901 100644 --- a/test/semant/type_as_variable_name.golden +++ b/test/semant/type_as_variable_name.golden @@ -1,4 +1,4 @@ -test/type_as_variable_name.inx:2,0: error: Invalid variable name 'int' +test/type_as_variable_name.ink:2,0: error: Invalid variable name 'int'  int : float = 4.0 ^^^  \ No newline at end of file diff --git a/test/semant/unary.golden b/test/semant/unary.golden new file mode 100644 index 0000000..75a59f9 --- /dev/null +++ b/test/semant/unary.golden @@ -0,0 +1,10 @@ +scope (global) [ + [pixel__ps_ps_main] : (position : float4) -> float4 + [vertex__vs_vs_main] : (position : float3) -> float4 + scope (vertex__vs_vs_main) [ + [position] : float3 + ] + scope (pixel__ps_ps_main) [ + [position] : float4 + ] +] diff --git a/test/semant/undeclared_function.golden b/test/semant/undeclared_function.golden index ae521d4..296d548 100644 --- a/test/semant/undeclared_function.golden +++ b/test/semant/undeclared_function.golden @@ -1,4 +1,4 @@ -test/undeclared_function.inx:2,0: error: Attempt to call undeclared function 'foo'. +test/undeclared_function.ink:2,0: error: Attempt to call undeclared function 'foo'.  foo(); ^^^ diff --git a/test/semant/undeclared_symbol.golden b/test/semant/undeclared_symbol.golden index a9d7aa0..14ef641 100644 --- a/test/semant/undeclared_symbol.golden +++ b/test/semant/undeclared_symbol.golden @@ -1,4 +1,4 @@ -test/undeclared_symbol.inx:2,10: error: Use of undeclared symbol 'f' +test/undeclared_symbol.ink:2,10: error: Use of undeclared symbol 'f'  b : int = f; ^  \ No newline at end of file diff --git a/test/semant/unknown_overload.golden b/test/semant/unknown_overload.golden index 1c6273e..a317a2b 100644 --- a/test/semant/unknown_overload.golden +++ b/test/semant/unknown_overload.golden @@ -1,4 +1,4 @@ -test/unknown_overload.inx:6,0: error: Procedure call did not match any of the possible overloads for 'foo' +test/unknown_overload.ink:6,0: error: Procedure call did not match any of the possible overloads for 'foo'  found: foo(v, v); ^^^ @@ -7,10 +7,10 @@  foo(v, v); ^  Possible overloads: - foo :: (v1 : float3, v2 : float3) { (test/unknown_overload.inx:1) - foo :: (v1 : float2, v2 : float2, v3 : float2) { (test/unknown_overload.inx:2) + foo :: (v1 : float3, v2 : float3) { (test/unknown_overload.ink:1) + foo :: (v1 : float2, v2 : float2, v3 : float2) { (test/unknown_overload.ink:2) -test/unknown_overload.inx:6,4: error: Type mismatch. Expected float3 got float +test/unknown_overload.ink:6,4: error: Type mismatch. Expected float3 got float  found: foo(v, v); ^ @@ -20,7 +20,7 @@ got: v : float = 2.0 -test/unknown_overload.inx:6,7: error: Type mismatch. Expected float3 got float +test/unknown_overload.ink:6,7: error: Type mismatch. Expected float3 got float  found: foo(v, v); ^ diff --git a/test/semant/wrong_argument_count.golden b/test/semant/wrong_argument_count.golden index a81118d..562a3c4 100644 --- a/test/semant/wrong_argument_count.golden +++ b/test/semant/wrong_argument_count.golden @@ -1,15 +1,15 @@ -test/wrong_argument_count.inx:5,19: error: Use of undeclared symbol 'w' +test/wrong_argument_count.ink:5,19: error: Use of undeclared symbol 'w'  return x * y * z * w; ^ -test/wrong_argument_count.inx:9,0: error: Procedure call did not match any of the possible overloads for 'foo' +test/wrong_argument_count.ink:9,0: error: Procedure call did not match any of the possible overloads for 'foo'  found: foo(2.0, 3.0); ^^^  Possible overloads: - foo :: (x : float, y : float, z : float) -> float { (test/wrong_argument_count.inx:1) + foo :: (x : float, y : float, z : float) -> float { (test/wrong_argument_count.ink:1)  Not enough arguments: Wanted 3, got 2. - foo :: (x : float, y : float, z : float, w : float) -> float { (test/wrong_argument_count.inx:4) + foo :: (x : float, y : float, z : float, w : float) -> float { (test/wrong_argument_count.ink:4)  Not enough arguments: Wanted 4, got 2. diff --git a/test/semant/wrong_multiply.golden b/test/semant/wrong_multiply.golden index f2c948b..c92670d 100644 --- a/test/semant/wrong_multiply.golden +++ b/test/semant/wrong_multiply.golden @@ -1,4 +1,4 @@ -test/wrong_multiply.inx:4,34: error: Type mismatch. Expected float got float2 +test/wrong_multiply.ink:4,34: error: Type mismatch. Expected float got float2  found: result : float4 = float4(1.0, foo * res, 0.0, 1.0); ^ diff --git a/test/semant/wrong_type_for_function.golden b/test/semant/wrong_type_for_function.golden index e0c8330..7f42213 100644 --- a/test/semant/wrong_type_for_function.golden +++ b/test/semant/wrong_type_for_function.golden @@ -1,4 +1,4 @@ -test/wrong_type_for_function.inx:11,17: error: Procedure call did not match any of the possible overloads for 'float4' +test/wrong_type_for_function.ink: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); ^^^^^^ @@ -7,9 +7,9 @@  color : float4 = float4(y, 1.0, 1.0, 1.0); ^  Possible overloads: - foreign float4 :: (float, float, float, float) -> float4; (test/wrong_type_for_function.inx:78) + foreign float4 :: (float, float, float, float) -> float4; (test/wrong_type_for_function.ink:78) -test/wrong_type_for_function.inx:11,24: error: Type mismatch. Expected float got float2 +test/wrong_type_for_function.ink:11,24: error: Type mismatch. Expected float got float2  found: color : float4 = float4(y, 1.0, 1.0, 1.0); ^ diff --git a/test/semant_all.suite b/test/semant_all.suite index 21f11dd..38a7c88 100644 --- a/test/semant_all.suite +++ b/test/semant_all.suite @@ -21,6 +21,7 @@ test/simple_struct_access.ink semant test/struct_access_primitive_type.ink semant test/struct_within_struct.ink semant test/type_as_variable_name.ink semant +test/unary.ink semant test/undeclared_function.ink semant test/undeclared_symbol.ink semant test/unknown_overload.ink semant diff --git a/test/unary.ink b/test/unary.ink new file mode 100644 index 0000000..74c8857 --- /dev/null +++ b/test/unary.ink @@ -0,0 +1,7 @@ +vertex vs_main :: (position : float3 @position) -> float4 @position { + return float4(position.x, position.y, position.z, 1.0); +} + +pixel ps_main :: (position : float4 @outposition) -> float4 @target { + return float4(0.5, -1, 0, 1); +} \ No newline at end of file From 8bd766281e8ff06aec17ee24e3eec45fa52ef87c Mon Sep 17 00:00:00 2001 From: Niels Bross Date: Wed, 8 Jan 2025 22:38:01 +0100 Subject: [PATCH 05/17] Added shader output data to compiled_file API --- module.jai | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 113 insertions(+), 4 deletions(-) diff --git a/module.jai b/module.jai index b65bfd8..226ca2d 100644 --- a/module.jai +++ b/module.jai @@ -150,6 +150,23 @@ Compiled_File :: struct { codegen_result_text : string; semantic_check_result : Semantic_Check_Result; + + vertex_entry_point : struct { + name : string; + + input : [..]Field; + } + + pixel_entry_point : struct { + name : string; + + return_value : Field; + } + + properties : Properties; + + max_constant_buffers :: 16; + cbuffers : Static_Array(Constant_Buffer, max_constant_buffers); } Compile_Result :: struct { @@ -286,7 +303,7 @@ type_variable_to_field :: (checker : *Semantic_Checker, variable : Type_Variable return type_variable_to_field(checker, from_handle(checker, variable)); } -type_variable_to_field :: (checker : *Semantic_Checker, variable : *Type_Variable) -> Field { +type_variable_to_field :: (type_variables : []Type_Variable, scope_stack : Scope_Stack, variable : *Type_Variable) -> Field { field : Field; field.name = variable.name; @@ -319,14 +336,14 @@ type_variable_to_field :: (checker : *Semantic_Checker, variable : *Type_Variabl case .Struct; { type.kind = Field_Kind.Struct; - find_result := find_symbol(checker, variable.typename, xx 1); + find_result := find_symbol(scope_stack, variable.typename, xx 1); assert(find_result != null, "Internal compiler error\n"); - type_var := from_handle(checker, find_result.type_variable); + type_var := from_handle(type_variables, find_result.type_variable); for i : 0..type_var.children.count - 1 { child := type_var.children[i]; - child_field := type_variable_to_field(checker, from_handle(checker, child)); + child_field := type_variable_to_field(type_variables, scope_stack, child); array_add(*type.children, child_field); } @@ -364,6 +381,14 @@ type_variable_to_field :: (checker : *Semantic_Checker, variable : *Type_Variabl return field; } +type_variable_to_field :: (type_variables : []Type_Variable, scope_stack : Scope_Stack, variable : Type_Variable_Handle) -> Field { + return type_variable_to_field(type_variables, scope_stack, from_handle(type_variables, variable)); +} + +type_variable_to_field :: (checker : *Semantic_Checker, variable : *Type_Variable) -> Field { + return type_variable_to_field(checker.result.type_variables, checker.result.scope_stack, variable); +} + compile_file :: (compiler : *Shader_Compiler, paths : []string) -> Compile_Result { result : Compile_Result; @@ -376,6 +401,90 @@ compile_file :: (compiler : *Shader_Compiler, paths : []string) -> Compile_Resul check(*result); codegen(*result); + for *file : result.files { + check_result := file.semantic_check_result; + if check_result.vertex_entry_point { + file.vertex_entry_point.name = check_result.vertex_entry_point.name; + + type_variable := from_handle(check_result.type_variables, check_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(check_result.type_variables, child.type_variable); + field := type_variable_to_field(check_result.type_variables, check_result.scope_stack, tv); + array_add(*file.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(*file.cbuffers); + + for i : 0..variable.children.count - 1 { + child := variable.children[i]; + field : Property_Field; + field.base_field = type_variable_to_field(check_result.type_variables, check_result.scope_stack, from_handle(check_result.type_variables, 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(check_result.type_variables, check_result.scope_stack, from_handle(check_result.type_variables, child)); + prop_field : Property_Field; + prop_field.base_field = field; + array_add(*file.properties.fields, prop_field); + } + file.properties.buffer_index = property_variable.resource_index; + } + + if check_result.pixel_entry_point { + file.pixel_entry_point.name = check_result.pixel_entry_point.name; + + type_variable := from_handle(check_result.type_variables, check_result.pixel_entry_point.type_variable); + assert(type_variable.type == .Function); + + field := type_variable_to_field(check_result.type_variables, check_result.scope_stack, 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): custom hints + } + array_add(*field.hints, field_hint); + } + + file.pixel_entry_point.return_value = field; + } + } + return result; } From ec31046d302452f18f43bfd68f19b6d417a1cee1 Mon Sep 17 00:00:00 2001 From: Niels Bross Date: Fri, 10 Jan 2025 22:44:15 +0100 Subject: [PATCH 06/17] Added inferred types and missing length function. --- Parsing.jai | 12 +- Semantic_Analysis.jai | 18 ++- Test.jai | 1 + hlsl_builtin.shd => hlsl_builtin.ink | 4 + module.jai | 4 + test/codegen/inferred_types.golden | 24 ++++ test/codegen_all.suite | 1 + test/compile_all.suite | 1 + test/inferred_types.ink | 17 +++ test/lex/inferred_types.golden | 105 ++++++++++++++++++ test/lex_all.suite | 1 + .../parse/field_without_type_specifier.golden | 8 +- test/parse/inferred_types.golden | 18 +++ test/parse_all.suite | 1 + test/semant/inferred_types.golden | 15 +++ test/semant_all.suite | 1 + 16 files changed, 218 insertions(+), 13 deletions(-) rename hlsl_builtin.shd => hlsl_builtin.ink (98%) create mode 100644 test/codegen/inferred_types.golden create mode 100644 test/inferred_types.ink create mode 100644 test/lex/inferred_types.golden create mode 100644 test/parse/inferred_types.golden create mode 100644 test/semant/inferred_types.golden diff --git a/Parsing.jai b/Parsing.jai index 30b8b89..d8b799f 100644 --- a/Parsing.jai +++ b/Parsing.jai @@ -264,7 +264,7 @@ error_node :: (parse_state : *Parse_State, message : string) -> *AST_Node { advance_to_sync_point :: (parse_state : *Parse_State) { while true { if parse_state.current.kind == .TOKEN_SEMICOLON || parse_state.current.kind == .TOKEN_RIGHTBRACE || - parse_state.current.kind == .TOKEN_LEFTBRACE{ + parse_state.current.kind == .TOKEN_LEFTBRACE { break; } advance(parse_state); @@ -644,8 +644,12 @@ field_declaration :: (parse_state : *Parse_State, identifier_token : *Token) -> advance(parse_state); node.array_field = true; } else { - missing_type_specifier(parse_state, identifier_token, "Expected type specifier after field name."); - return node; + if !check(parse_state, .TOKEN_ASSIGN) { + internal_error_message(*parse_state.result.messages, "Unimplemented error message.", parse_state.path); + return node; + } + // missing_type_specifier(parse_state, identifier_token, "Expected type specifier after field name."); + } if check(parse_state, .TOKEN_AT) { @@ -1088,6 +1092,8 @@ parse :: (result : *Compile_Result) { file.ast_root = parse_state.result.root; file.ast_nodes = parse_state.result.nodes; copy_messages(parse_state.result.messages, *result.messages); + + result.had_error |= parse_state.result.had_error; } } diff --git a/Semantic_Analysis.jai b/Semantic_Analysis.jai index 6beebca..144a33e 100644 --- a/Semantic_Analysis.jai +++ b/Semantic_Analysis.jai @@ -1241,9 +1241,14 @@ create_field :: (checker : *Semantic_Checker, node : *AST_Node) -> Type_Variable r := from_handle(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; + if l.type == .Unresolved_Variable { + l.type = r.type; + l.typename = r.typename; + } else { + if !types_compatible(checker, handle, rhs) { + type_mismatch(checker, l.source_node, r.source_node, rhs, handle); + return 0; + } } } @@ -1419,7 +1424,6 @@ check_node :: (checker : *Semantic_Checker, node : *AST_Node) -> Type_Variable_H } } case .TOKEN_ASSIGN; { - if !types_compatible(checker, lhs_var, rhs_var, true) { type_mismatch(checker, node.parent, node.children[1], lhs_var, rhs_var); return 0; @@ -1614,7 +1618,7 @@ add_hlsl_builtins :: (checker : *Semantic_Checker) { append(*sb, "/"); } - append(*sb, "hlsl_builtin.shd"); + append(*sb, "hlsl_builtin.ink"); path := builder_to_string(*sb); @@ -1685,12 +1689,14 @@ check :: (result : *Compile_Result) { array_reserve(*checker.result.messages, 16); init_semantic_checker(*checker, file.ast_root, file.file.path); - + + // @Performance: Should have this built in stuff done earlier and only once add_hlsl_builtins(*checker); type_check(*checker, file.ast_root); file.semantic_check_result = checker.result; + result.had_error |= checker.result.had_error; copy_messages(checker.result.messages, *result.messages); } } diff --git a/Test.jai b/Test.jai index a32e3ad..67e4f8a 100644 --- a/Test.jai +++ b/Test.jai @@ -2,6 +2,7 @@ //~ nbr: General improvements // // [x] Print out all failed tests in a list at the end +// [ ] Use new compiler API with Compile_Result and Compiled_File instead // [ ] Use unix (posix? bash? ascii?) color codes for errors // [ ] Print golden file as green and new output as red diff --git a/hlsl_builtin.shd b/hlsl_builtin.ink similarity index 98% rename from hlsl_builtin.shd rename to hlsl_builtin.ink index c8ac743..54dbfcc 100644 --- a/hlsl_builtin.shd +++ b/hlsl_builtin.ink @@ -83,6 +83,10 @@ int4x4 :: struct { #foreign distance :: (float3, float3) -> float; #foreign distance :: (float4, float4) -> float; +#foreign length :: (float2) -> float; +#foreign length :: (float3) -> float; +#foreign length :: (float4) -> float; + #foreign dot :: (float2, float2) -> float; #foreign dot :: (float3, float3) -> float; #foreign dot :: (float4, float4) -> float; diff --git a/module.jai b/module.jai index 226ca2d..2d4ae7c 100644 --- a/module.jai +++ b/module.jai @@ -401,6 +401,10 @@ compile_file :: (compiler : *Shader_Compiler, paths : []string) -> Compile_Resul check(*result); codegen(*result); + if result.had_error { + return result; + } + for *file : result.files { check_result := file.semantic_check_result; if check_result.vertex_entry_point { diff --git a/test/codegen/inferred_types.golden b/test/codegen/inferred_types.golden new file mode 100644 index 0000000..825439c --- /dev/null +++ b/test/codegen/inferred_types.golden @@ -0,0 +1,24 @@ +float bar(); +float foo(); + +float bar() +{ + return 5.0f; +} + +float foo() +{ + return bar(); +} + +float4 vs_main(float3 pos : POSITION) : SV_POSITION +{ + float f = 2.0f; + int i = 10; + f = foo(); + float2 v2 = float2(2, 2); + float3 v3 = float3(2, 2, 3); + float4 v4 = float4(4, 5, 6, 7); + return float4(1, 1, 1, 1); +} + diff --git a/test/codegen_all.suite b/test/codegen_all.suite index 87c48e9..c939b7c 100644 --- a/test/codegen_all.suite +++ b/test/codegen_all.suite @@ -9,6 +9,7 @@ test/field_assignment.ink codegen test/function_call.ink codegen test/function_call_out_of_order_declaration.ink codegen test/function_call_return.ink codegen +test/inferred_types.ink codegen test/meta_block.ink codegen test/multiple_functions.ink codegen test/multiple_semicolons_everywhere.ink codegen diff --git a/test/compile_all.suite b/test/compile_all.suite index b17e326..58b17f2 100644 --- a/test/compile_all.suite +++ b/test/compile_all.suite @@ -10,6 +10,7 @@ test/function_call.ink compile test/function_call_out_of_order_declaration.ink compile test/function_call_return.ink compile test/functions_with_same_name.ink compile +test/inferred_types.ink compile test/meta_block.ink compile test/multiple_functions.ink compile test/multiple_semicolons_everywhere.ink compile diff --git a/test/inferred_types.ink b/test/inferred_types.ink new file mode 100644 index 0000000..30f8ded --- /dev/null +++ b/test/inferred_types.ink @@ -0,0 +1,17 @@ +bar :: () -> float { + return 5.0; +} + +foo :: () -> float { + return bar(); +} + +vertex main :: (pos : float3 @position) -> float4 @position { + f := 2.0; + i := 10; + f = foo(); + v2 := float2(2, 2); + v3 := float3(2, 2, 3); + v4 := float4(4, 5, 6, 7); + return float4(1, 1, 1, 1); +} \ No newline at end of file diff --git a/test/lex/inferred_types.golden b/test/lex/inferred_types.golden new file mode 100644 index 0000000..146cb73 --- /dev/null +++ b/test/lex/inferred_types.golden @@ -0,0 +1,105 @@ +{kind = TOKEN_IDENTIFIER; ; index = 0 ; length = 3 line = 1 ; column = 0 ; value ='bar'; } +{kind = TOKEN_DOUBLECOLON; ; index = 4 ; length = 2 line = 1 ; column = 4 ; value ='::'; } +{kind = TOKEN_LEFTPAREN; ; index = 7 ; length = 1 line = 1 ; column = 7 ; value ='('; } +{kind = TOKEN_RIGHTPAREN; ; index = 8 ; length = 1 line = 1 ; column = 8 ; value =')'; } +{kind = TOKEN_ARROW; ; index = 10 ; length = 2 line = 1 ; column = 10 ; value ='->'; } +{kind = TOKEN_IDENTIFIER; ; index = 13 ; length = 5 line = 1 ; column = 13 ; value ='float'; } +{kind = TOKEN_LEFTBRACE; ; index = 19 ; length = 1 line = 1 ; column = 19 ; value ='{'; } +{kind = TOKEN_RETURN; ; index = 23 ; length = 6 line = 2 ; column = 0 ; value ='return'; } +{kind = TOKEN_FLOATLITERAL; ; index = 30 ; length = 3 line = 2 ; column = 7 ; value ='5'; } +{kind = TOKEN_SEMICOLON; ; index = 33 ; length = 1 line = 2 ; column = 10 ; value =';'; } +{kind = TOKEN_RIGHTBRACE; ; index = 36 ; length = 1 line = 3 ; column = 0 ; value ='}'; } +{kind = TOKEN_IDENTIFIER; ; index = 41 ; length = 3 line = 5 ; column = 0 ; value ='foo'; } +{kind = TOKEN_DOUBLECOLON; ; index = 45 ; length = 2 line = 5 ; column = 4 ; value ='::'; } +{kind = TOKEN_LEFTPAREN; ; index = 48 ; length = 1 line = 5 ; column = 7 ; value ='('; } +{kind = TOKEN_RIGHTPAREN; ; index = 49 ; length = 1 line = 5 ; column = 8 ; value =')'; } +{kind = TOKEN_ARROW; ; index = 51 ; length = 2 line = 5 ; column = 10 ; value ='->'; } +{kind = TOKEN_IDENTIFIER; ; index = 54 ; length = 5 line = 5 ; column = 13 ; value ='float'; } +{kind = TOKEN_LEFTBRACE; ; index = 60 ; length = 1 line = 5 ; column = 19 ; value ='{'; } +{kind = TOKEN_RETURN; ; index = 64 ; length = 6 line = 6 ; column = 0 ; value ='return'; } +{kind = TOKEN_IDENTIFIER; ; index = 71 ; length = 3 line = 6 ; column = 7 ; value ='bar'; } +{kind = TOKEN_LEFTPAREN; ; index = 74 ; length = 1 line = 6 ; column = 10 ; value ='('; } +{kind = TOKEN_RIGHTPAREN; ; index = 75 ; length = 1 line = 6 ; column = 11 ; value =')'; } +{kind = TOKEN_SEMICOLON; ; index = 76 ; length = 1 line = 6 ; column = 12 ; value =';'; } +{kind = TOKEN_RIGHTBRACE; ; index = 79 ; length = 1 line = 7 ; column = 0 ; value ='}'; } +{kind = TOKEN_VERTEX; ; index = 84 ; length = 6 line = 9 ; column = 0 ; value ='vertex'; } +{kind = TOKEN_IDENTIFIER; ; index = 91 ; length = 4 line = 9 ; column = 7 ; value ='main'; } +{kind = TOKEN_DOUBLECOLON; ; index = 96 ; length = 2 line = 9 ; column = 12 ; value ='::'; } +{kind = TOKEN_LEFTPAREN; ; index = 99 ; length = 1 line = 9 ; column = 15 ; value ='('; } +{kind = TOKEN_IDENTIFIER; ; index = 100 ; length = 3 line = 9 ; column = 16 ; value ='pos'; } +{kind = TOKEN_COLON; ; index = 104 ; length = 1 line = 9 ; column = 20 ; value =':'; } +{kind = TOKEN_IDENTIFIER; ; index = 106 ; length = 6 line = 9 ; column = 22 ; value ='float3'; } +{kind = TOKEN_AT; ; index = 113 ; length = 1 line = 9 ; column = 29 ; value ='@'; } +{kind = TOKEN_IDENTIFIER; ; index = 114 ; length = 8 line = 9 ; column = 30 ; value ='position'; } +{kind = TOKEN_RIGHTPAREN; ; index = 122 ; length = 1 line = 9 ; column = 38 ; value =')'; } +{kind = TOKEN_ARROW; ; index = 124 ; length = 2 line = 9 ; column = 40 ; value ='->'; } +{kind = TOKEN_IDENTIFIER; ; index = 127 ; length = 6 line = 9 ; column = 43 ; value ='float4'; } +{kind = TOKEN_AT; ; index = 134 ; length = 1 line = 9 ; column = 50 ; value ='@'; } +{kind = TOKEN_IDENTIFIER; ; index = 135 ; length = 8 line = 9 ; column = 51 ; value ='position'; } +{kind = TOKEN_LEFTBRACE; ; index = 144 ; length = 1 line = 9 ; column = 60 ; value ='{'; } +{kind = TOKEN_IDENTIFIER; ; index = 151 ; length = 1 line = 10 ; column = 3 ; value ='f'; } +{kind = TOKEN_COLON; ; index = 153 ; length = 1 line = 10 ; column = 5 ; value =':'; } +{kind = TOKEN_ASSIGN; ; index = 154 ; length = 1 line = 10 ; column = 6 ; value ='='; } +{kind = TOKEN_FLOATLITERAL; ; index = 156 ; length = 3 line = 10 ; column = 8 ; value ='2'; } +{kind = TOKEN_SEMICOLON; ; index = 159 ; length = 1 line = 10 ; column = 11 ; value =';'; } +{kind = TOKEN_IDENTIFIER; ; index = 166 ; length = 1 line = 11 ; column = 3 ; value ='i'; } +{kind = TOKEN_COLON; ; index = 168 ; length = 1 line = 11 ; column = 5 ; value =':'; } +{kind = TOKEN_ASSIGN; ; index = 169 ; length = 1 line = 11 ; column = 6 ; value ='='; } +{kind = TOKEN_INTLITERAL; ; index = 171 ; length = 2 line = 11 ; column = 8 ; value ='10'; } +{kind = TOKEN_SEMICOLON; ; index = 173 ; length = 1 line = 11 ; column = 10 ; value =';'; } +{kind = TOKEN_IDENTIFIER; ; index = 180 ; length = 1 line = 12 ; column = 3 ; value ='f'; } +{kind = TOKEN_ASSIGN; ; index = 182 ; length = 1 line = 12 ; column = 5 ; value ='='; } +{kind = TOKEN_IDENTIFIER; ; index = 184 ; length = 3 line = 12 ; column = 7 ; value ='foo'; } +{kind = TOKEN_LEFTPAREN; ; index = 187 ; length = 1 line = 12 ; column = 10 ; value ='('; } +{kind = TOKEN_RIGHTPAREN; ; index = 188 ; length = 1 line = 12 ; column = 11 ; value =')'; } +{kind = TOKEN_SEMICOLON; ; index = 189 ; length = 1 line = 12 ; column = 12 ; value =';'; } +{kind = TOKEN_IDENTIFIER; ; index = 196 ; length = 2 line = 13 ; column = 3 ; value ='v2'; } +{kind = TOKEN_COLON; ; index = 199 ; length = 1 line = 13 ; column = 6 ; value =':'; } +{kind = TOKEN_ASSIGN; ; index = 200 ; length = 1 line = 13 ; column = 7 ; value ='='; } +{kind = TOKEN_IDENTIFIER; ; index = 202 ; length = 6 line = 13 ; column = 9 ; value ='float2'; } +{kind = TOKEN_LEFTPAREN; ; index = 208 ; length = 1 line = 13 ; column = 15 ; value ='('; } +{kind = TOKEN_INTLITERAL; ; index = 209 ; length = 1 line = 13 ; column = 16 ; value ='2'; } +{kind = TOKEN_COMMA; ; index = 210 ; length = 1 line = 13 ; column = 17 ; value =','; } +{kind = TOKEN_INTLITERAL; ; index = 212 ; length = 1 line = 13 ; column = 19 ; value ='2'; } +{kind = TOKEN_RIGHTPAREN; ; index = 213 ; length = 1 line = 13 ; column = 20 ; value =')'; } +{kind = TOKEN_SEMICOLON; ; index = 214 ; length = 1 line = 13 ; column = 21 ; value =';'; } +{kind = TOKEN_IDENTIFIER; ; index = 221 ; length = 2 line = 14 ; column = 3 ; value ='v3'; } +{kind = TOKEN_COLON; ; index = 224 ; length = 1 line = 14 ; column = 6 ; value =':'; } +{kind = TOKEN_ASSIGN; ; index = 225 ; length = 1 line = 14 ; column = 7 ; value ='='; } +{kind = TOKEN_IDENTIFIER; ; index = 227 ; length = 6 line = 14 ; column = 9 ; value ='float3'; } +{kind = TOKEN_LEFTPAREN; ; index = 233 ; length = 1 line = 14 ; column = 15 ; value ='('; } +{kind = TOKEN_INTLITERAL; ; index = 234 ; length = 1 line = 14 ; column = 16 ; value ='2'; } +{kind = TOKEN_COMMA; ; index = 235 ; length = 1 line = 14 ; column = 17 ; value =','; } +{kind = TOKEN_INTLITERAL; ; index = 237 ; length = 1 line = 14 ; column = 19 ; value ='2'; } +{kind = TOKEN_COMMA; ; index = 238 ; length = 1 line = 14 ; column = 20 ; value =','; } +{kind = TOKEN_INTLITERAL; ; index = 240 ; length = 1 line = 14 ; column = 22 ; value ='3'; } +{kind = TOKEN_RIGHTPAREN; ; index = 241 ; length = 1 line = 14 ; column = 23 ; value =')'; } +{kind = TOKEN_SEMICOLON; ; index = 242 ; length = 1 line = 14 ; column = 24 ; value =';'; } +{kind = TOKEN_IDENTIFIER; ; index = 249 ; length = 2 line = 15 ; column = 3 ; value ='v4'; } +{kind = TOKEN_COLON; ; index = 252 ; length = 1 line = 15 ; column = 6 ; value =':'; } +{kind = TOKEN_ASSIGN; ; index = 253 ; length = 1 line = 15 ; column = 7 ; value ='='; } +{kind = TOKEN_IDENTIFIER; ; index = 255 ; length = 6 line = 15 ; column = 9 ; value ='float4'; } +{kind = TOKEN_LEFTPAREN; ; index = 261 ; length = 1 line = 15 ; column = 15 ; value ='('; } +{kind = TOKEN_INTLITERAL; ; index = 262 ; length = 1 line = 15 ; column = 16 ; value ='4'; } +{kind = TOKEN_COMMA; ; index = 263 ; length = 1 line = 15 ; column = 17 ; value =','; } +{kind = TOKEN_INTLITERAL; ; index = 265 ; length = 1 line = 15 ; column = 19 ; value ='5'; } +{kind = TOKEN_COMMA; ; index = 266 ; length = 1 line = 15 ; column = 20 ; value =','; } +{kind = TOKEN_INTLITERAL; ; index = 268 ; length = 1 line = 15 ; column = 22 ; value ='6'; } +{kind = TOKEN_COMMA; ; index = 269 ; length = 1 line = 15 ; column = 23 ; value =','; } +{kind = TOKEN_INTLITERAL; ; index = 271 ; length = 1 line = 15 ; column = 25 ; value ='7'; } +{kind = TOKEN_RIGHTPAREN; ; index = 272 ; length = 1 line = 15 ; column = 26 ; value =')'; } +{kind = TOKEN_SEMICOLON; ; index = 273 ; length = 1 line = 15 ; column = 27 ; value =';'; } +{kind = TOKEN_RETURN; ; index = 280 ; length = 6 line = 16 ; column = 3 ; value ='return'; } +{kind = TOKEN_IDENTIFIER; ; index = 287 ; length = 6 line = 16 ; column = 10 ; value ='float4'; } +{kind = TOKEN_LEFTPAREN; ; index = 293 ; length = 1 line = 16 ; column = 16 ; value ='('; } +{kind = TOKEN_INTLITERAL; ; index = 294 ; length = 1 line = 16 ; column = 17 ; value ='1'; } +{kind = TOKEN_COMMA; ; index = 295 ; length = 1 line = 16 ; column = 18 ; value =','; } +{kind = TOKEN_INTLITERAL; ; index = 297 ; length = 1 line = 16 ; column = 20 ; value ='1'; } +{kind = TOKEN_COMMA; ; index = 298 ; length = 1 line = 16 ; column = 21 ; value =','; } +{kind = TOKEN_INTLITERAL; ; index = 300 ; length = 1 line = 16 ; column = 23 ; value ='1'; } +{kind = TOKEN_COMMA; ; index = 301 ; length = 1 line = 16 ; column = 24 ; value =','; } +{kind = TOKEN_INTLITERAL; ; index = 303 ; length = 1 line = 16 ; column = 26 ; value ='1'; } +{kind = TOKEN_RIGHTPAREN; ; index = 304 ; length = 1 line = 16 ; column = 27 ; value =')'; } +{kind = TOKEN_SEMICOLON; ; index = 305 ; length = 1 line = 16 ; column = 28 ; value =';'; } +{kind = TOKEN_RIGHTBRACE; ; index = 308 ; length = 1 line = 17 ; column = 0 ; value ='}'; } +{kind = TOKEN_EOF; ; index = 309 ; length = 0 line = 17 ; column = 1 ; value =''; } diff --git a/test/lex_all.suite b/test/lex_all.suite index 852a8f3..699b02d 100644 --- a/test/lex_all.suite +++ b/test/lex_all.suite @@ -13,6 +13,7 @@ test/function_call_out_of_order_declaration.ink lex test/function_call_return.ink lex test/functions_with_same_name.ink lex test/function_with_int_return.ink lex +test/inferred_types.ink lex test/meta_block.ink lex test/multiple_functions.ink lex test/multiple_semicolons_everywhere.ink lex diff --git a/test/parse/field_without_type_specifier.golden b/test/parse/field_without_type_specifier.golden index 77cd077..f8800b3 100644 --- a/test/parse/field_without_type_specifier.golden +++ b/test/parse/field_without_type_specifier.golden @@ -1,4 +1,4 @@ -test/field_without_type_specifier.ink:2,0: error: Expected type specifier after field name. - x := 5.0; - ^ - \ No newline at end of file +(program + (fun vertex vs_main + [] + (:= x 5))) \ No newline at end of file diff --git a/test/parse/inferred_types.golden b/test/parse/inferred_types.golden new file mode 100644 index 0000000..530b95d --- /dev/null +++ b/test/parse/inferred_types.golden @@ -0,0 +1,18 @@ +(program + (fun bar -> float + [] + (return 5)) + + (fun foo -> float + [] + (return (bar))) + + (fun vertex vs_main -> float4 (@position) + [(:= pos float3 (@position))] + (:= f 2) + (:= i 10) + (= f (foo)) + (:= v2 (float2 2 2)) + (:= v3 (float3 2 2 3)) + (:= v4 (float4 4 5 6 7)) + (return (float4 1 1 1 1)))) \ No newline at end of file diff --git a/test/parse_all.suite b/test/parse_all.suite index 14ae4ac..9c9584c 100644 --- a/test/parse_all.suite +++ b/test/parse_all.suite @@ -13,6 +13,7 @@ test/function_call_out_of_order_declaration.ink parse test/function_call_return.ink parse test/functions_with_same_name.ink parse test/function_with_int_return.ink parse +test/inferred_types.ink parse test/meta_block.ink parse test/multiple_functions.ink parse test/multiple_semicolons_everywhere.ink parse diff --git a/test/semant/inferred_types.golden b/test/semant/inferred_types.golden new file mode 100644 index 0000000..40c9c9d --- /dev/null +++ b/test/semant/inferred_types.golden @@ -0,0 +1,15 @@ +scope (global) [ + [foo] : () -> float + [vertex__vs_main] : (pos : float3) -> float4 + [bar] : () -> float + scope (bar) [] + scope (foo) [] + scope (vertex__vs_main) [ + [v2] : float2 + [i] : int + [v4] : float4 + [pos] : float3 + [v3] : float3 + [f] : float + ] +] diff --git a/test/semant_all.suite b/test/semant_all.suite index 38a7c88..7773b41 100644 --- a/test/semant_all.suite +++ b/test/semant_all.suite @@ -11,6 +11,7 @@ test/function_call_out_of_order_declaration.ink semant test/function_call_return.ink semant test/functions_with_same_name.ink semant test/function_with_int_return.ink semant +test/inferred_types.ink semant test/multiple_functions.ink semant test/multiple_semicolons_everywhere.ink semant test/pass_and_access_struct_fields_in_functions.ink semant From 85b23f90e5a953fd8726d748cef89585175dffbb Mon Sep 17 00:00:00 2001 From: Niels Bross Date: Sun, 12 Jan 2025 22:15:02 +0100 Subject: [PATCH 07/17] Function overload check cleanup. Added if statement to parsing. --- AST.jai | 12 ++ Parsing.jai | 28 ++- Semantic_Analysis.jai | 3 +- hlsl_builtin.ink | 21 +++ test/codegen/custom_hint.golden | 17 ++ test/colorful_circle.ink | 39 +++++ test/custom_hint.ink | 12 ++ test/lex/colorful_circle.golden | 297 ++++++++++++++++++++++++++++++++ test/lex/custom_hint.golden | 81 +++++++++ test/parse/custom_hint.golden | 12 ++ test/semant/custom_hint.golden | 15 ++ test/simple_if.ink | 6 + 12 files changed, 540 insertions(+), 3 deletions(-) create mode 100644 test/codegen/custom_hint.golden create mode 100644 test/colorful_circle.ink create mode 100644 test/custom_hint.ink create mode 100644 test/lex/colorful_circle.golden create mode 100644 test/lex/custom_hint.golden create mode 100644 test/parse/custom_hint.golden create mode 100644 test/semant/custom_hint.golden create mode 100644 test/simple_if.ink diff --git a/AST.jai b/AST.jai index 57993a4..016883c 100644 --- a/AST.jai +++ b/AST.jai @@ -20,6 +20,7 @@ AST_Kind :: enum { // Operator; Call; Struct; + If; CBuffer; FieldList; ArgList; @@ -226,6 +227,14 @@ print_return_node :: (node : *AST_Node, indentation : int, builder : *String_Bui append(builder, ")"); } +pretty_print_if :: (node : *AST_Node, indentation : int, builder : *String_Builder) { + append(builder, "(if "); + + pretty_print_children(node, 0, builder); + + append(builder, ")"); +} + print_expression_statement :: (node : *AST_Node, indentation : int, builder : *String_Builder) { indent(builder, indentation); @@ -239,6 +248,9 @@ pretty_print_node :: (node : *AST_Node, indentation : int, builder : *String_Bui case .Return; { print_return_node(node, indentation, builder); } + case .If; { + pretty_print_if(node, indentation, builder); + } case .Struct; case .ArgList; { pretty_print_arglist(node, indentation + 2, builder); diff --git a/Parsing.jai b/Parsing.jai index d8b799f..e047496 100644 --- a/Parsing.jai +++ b/Parsing.jai @@ -112,7 +112,7 @@ parse_rules :: #run -> [(cast(int)Token_Kind.TOKEN_ERROR) + 1]Parse_Rule { rules[Token_Kind.TOKEN_ELSE] = .{null, null, .PREC_NONE}; rules[Token_Kind.TOKEN_FALSE] = .{null, null, .PREC_NONE}; rules[Token_Kind.TOKEN_FOR] = .{null, null, .PREC_NONE}; - rules[Token_Kind.TOKEN_IF] = .{null, null, .PREC_NONE}; + rules[Token_Kind.TOKEN_IF] = .{if_, null, .PREC_NONE}; rules[Token_Kind.TOKEN_LOGICALOR] = .{null, binary, .PREC_OR}; rules[Token_Kind.TOKEN_LOGICALAND] = .{null, binary, .PREC_AND}; rules[Token_Kind.TOKEN_RETURN] = .{null, null, .PREC_NONE}; @@ -264,7 +264,7 @@ error_node :: (parse_state : *Parse_State, message : string) -> *AST_Node { advance_to_sync_point :: (parse_state : *Parse_State) { while true { if parse_state.current.kind == .TOKEN_SEMICOLON || parse_state.current.kind == .TOKEN_RIGHTBRACE || - parse_state.current.kind == .TOKEN_LEFTBRACE { + parse_state.current.kind == .TOKEN_LEFTBRACE || parse_state.current.kind == .TOKEN_EOF { break; } advance(parse_state); @@ -387,6 +387,10 @@ precedence :: (parse_state : *Parse_State, precedence : Precedence) -> *AST_Node return left; } +if_ :: (parse_state : *Parse_State, left : *AST_Node) -> *AST_Node { + return error_node(parse_state, "If not yet implemented."); +} + named_variable :: (parse_state : *Parse_State, left : *AST_Node) -> *AST_Node { if check(parse_state, .TOKEN_LEFTPAREN) { return call(parse_state, left); @@ -415,6 +419,8 @@ binary :: (parse_state : *Parse_State, left : *AST_Node) -> *AST_Node { if op.kind == { case .TOKEN_PLUS; #through; + case .TOKEN_PLUSEQUALS; #through; + case .TOKEN_MINUSEQUALS; #through; case .TOKEN_MINUS; #through; case .TOKEN_STAR; #through; case .TOKEN_SLASH; #through; @@ -753,6 +759,24 @@ statement :: (parse_state : *Parse_State) -> *AST_Node { } source_location.end = parse_state.previous; node.source_location = source_location; + return node; + } else if match(parse_state, .TOKEN_IF) { + node := make_node(parse_state, .If); + + source_location : Source_Range; + source_location.begin = parse_state.previous; + + if_expression := expression(parse_state); + // consume(parse_state, .TOKEN_LEFTBRACE, "Expect '{' after if-condition."); + + if_body := block(parse_state); + if if_body.children.count > 0 { + add_child(node, if_body); + } + + source_location.end = parse_state.previous; + node.source_location = source_location; + return node; } else { return expression_statement(parse_state); diff --git a/Semantic_Analysis.jai b/Semantic_Analysis.jai index 144a33e..cc2ec5c 100644 --- a/Semantic_Analysis.jai +++ b/Semantic_Analysis.jai @@ -1309,7 +1309,8 @@ check_call :: (checker : *Semantic_Checker, node : *AST_Node, type_var : Type_Va function := from_handle(checker, func.type_variable); - if arg_count != function.children.count { + field_list := function.source_node.children[0]; + if arg_count != field_list.children.count { continue; } diff --git a/hlsl_builtin.ink b/hlsl_builtin.ink index 54dbfcc..e77b01b 100644 --- a/hlsl_builtin.ink +++ b/hlsl_builtin.ink @@ -74,8 +74,24 @@ int4x4 :: struct { //~ nbr: Constructors #foreign float2 :: (float, float) -> float2; +#foreign float2 :: (float2) -> float2; +#foreign float2 :: (float) -> float2; + #foreign float3 :: (float, float, float) -> float3; +#foreign float3 :: (float3) -> float3; +#foreign float3 :: (float2, float) -> float3; +#foreign float3 :: (float, float2) -> float3; +#foreign float3 :: (float) -> float3; + #foreign float4 :: (float, float, float, float) -> float4; +#foreign float4 :: (float4) -> float4; +#foreign float4 :: (float2, float2) -> float4; +#foreign float4 :: (float2, float, float) -> float4; +#foreign float4 :: (float, float2, float) -> float4; +#foreign float4 :: (float, float, float2) -> float4; +#foreign float4 :: (float3, float) -> float4; +#foreign float4 :: (float, float3) -> float4; +#foreign float4 :: (float) -> float4; //~ nbr: Vectors #foreign cross :: (float3, float3) -> float3; @@ -264,3 +280,8 @@ int4x4 :: struct { #foreign atan2 :: (float4x4, float4x4) -> float4x4; #foreign sample :: (Texture2D, Sampler, float2) -> float4; + +#foreign lerp :: (float, float, float) -> float; +#foreign lerp :: (float2, float2, float) -> float2; +#foreign lerp :: (float3, float3, float) -> float3; +#foreign lerp :: (float4, float4, float) -> float4; diff --git a/test/codegen/custom_hint.golden b/test/codegen/custom_hint.golden new file mode 100644 index 0000000..0373787 --- /dev/null +++ b/test/codegen/custom_hint.golden @@ -0,0 +1,17 @@ +cbuffer __PROPERTIES : register(b0) +{ + float __PROPERTIES__time; +} + + +float4 vs_main(float3 pos : POSITION) : SV_POSITION +{ + return float4(pos.x, pos.y, pos.z, 1.0f); +} + +float4 ps_main(float4 pos : SV_POSITION) : SV_TARGET +{ + float t = __PROPERTIES__time; + return float4(1, 1, 1, 1); +} + diff --git a/test/colorful_circle.ink b/test/colorful_circle.ink new file mode 100644 index 0000000..9ef9063 --- /dev/null +++ b/test/colorful_circle.ink @@ -0,0 +1,39 @@ +prop :: properties { + time : float @time; + resolution : float2 @resolution; +} + +vertex main :: (pos : float3 @position) -> float4 @position { + return float4(pos, 1.0); +} + +pixel main :: (pos : float4 @outposition) -> float4 @target { + p := float2(2.0 * pos.x - prop.resolution.x, 2.0 * pos.y - prop.resolution.y) / prop.resolution.y; + tau := 3.1415926535 * 2.0; + a := atan(p.x, p.y); + r := length(p) * 0.75; + + uv := float2(a / tau, r); + + x_col := (uv.x - (p.time / 3.0)) * 3.0; + x_col = mod(x_col, 3.0); + hor_colour := float3(0.25, 0.25, 0.25); + + if x_col < 1.0 { + horColour.r += 1.0 - xCol; + horColour.g += xCol; + } else if x_col < 2.0 { + xCol -= 1.0; + horColour.g += 1.0 - xCol; + horColour.b += xCol; + } else { + x_col -= 2.0; + hor_colour.b += 1.0 - x_col; + hor_colour.r += x_col; + } + + uv = (2.0 * uv) - 1.0; + beam_width = (0.7+0.5*cos(uv.x*10.0*tau*0.15*clamp(floor(5.0 + 10.0*cos(iTime)), 0.0, 10.0))) * abs(1.0 / (30.0 * uv.y)); + hor_beam = float3(beam_width); + result := float4(((hor_beam) * hor_colour), 1.0); +} diff --git a/test/custom_hint.ink b/test/custom_hint.ink new file mode 100644 index 0000000..69772be --- /dev/null +++ b/test/custom_hint.ink @@ -0,0 +1,12 @@ +p :: properties { + time : float @time; +} + +vertex main :: (pos : float3 @position) -> float4 @position { + return float4(pos.x, pos.y, pos.z, 1.0); +} + +pixel main :: (pos : float4 @outposition) -> float4 @target { + t := p.time; + return float4(1, 1, 1, 1); +} diff --git a/test/lex/colorful_circle.golden b/test/lex/colorful_circle.golden new file mode 100644 index 0000000..222b72a --- /dev/null +++ b/test/lex/colorful_circle.golden @@ -0,0 +1,297 @@ +{kind = TOKEN_IDENTIFIER; ; index = 0 ; length = 4 line = 1 ; column = 0 ; value ='prop'; } +{kind = TOKEN_DOUBLECOLON; ; index = 5 ; length = 2 line = 1 ; column = 5 ; value ='::'; } +{kind = TOKEN_PROPERTIES; ; index = 8 ; length = 10 line = 1 ; column = 8 ; value ='properties'; } +{kind = TOKEN_LEFTBRACE; ; index = 19 ; length = 1 line = 1 ; column = 19 ; value ='{'; } +{kind = TOKEN_IDENTIFIER; ; index = 23 ; length = 4 line = 2 ; column = 0 ; value ='time'; } +{kind = TOKEN_COLON; ; index = 28 ; length = 1 line = 2 ; column = 5 ; value =':'; } +{kind = TOKEN_IDENTIFIER; ; index = 30 ; length = 5 line = 2 ; column = 7 ; value ='float'; } +{kind = TOKEN_AT; ; index = 36 ; length = 1 line = 2 ; column = 13 ; value ='@'; } +{kind = TOKEN_IDENTIFIER; ; index = 37 ; length = 4 line = 2 ; column = 14 ; value ='time'; } +{kind = TOKEN_SEMICOLON; ; index = 41 ; length = 1 line = 2 ; column = 18 ; value =';'; } +{kind = TOKEN_IDENTIFIER; ; index = 45 ; length = 10 line = 3 ; column = 0 ; value ='resolution'; } +{kind = TOKEN_COLON; ; index = 56 ; length = 1 line = 3 ; column = 11 ; value =':'; } +{kind = TOKEN_IDENTIFIER; ; index = 58 ; length = 6 line = 3 ; column = 13 ; value ='float2'; } +{kind = TOKEN_AT; ; index = 65 ; length = 1 line = 3 ; column = 20 ; value ='@'; } +{kind = TOKEN_IDENTIFIER; ; index = 66 ; length = 10 line = 3 ; column = 21 ; value ='resolution'; } +{kind = TOKEN_SEMICOLON; ; index = 76 ; length = 1 line = 3 ; column = 31 ; value =';'; } +{kind = TOKEN_RIGHTBRACE; ; index = 79 ; length = 1 line = 4 ; column = 0 ; value ='}'; } +{kind = TOKEN_VERTEX; ; index = 84 ; length = 6 line = 6 ; column = 0 ; value ='vertex'; } +{kind = TOKEN_IDENTIFIER; ; index = 91 ; length = 4 line = 6 ; column = 7 ; value ='main'; } +{kind = TOKEN_DOUBLECOLON; ; index = 96 ; length = 2 line = 6 ; column = 12 ; value ='::'; } +{kind = TOKEN_LEFTPAREN; ; index = 99 ; length = 1 line = 6 ; column = 15 ; value ='('; } +{kind = TOKEN_IDENTIFIER; ; index = 100 ; length = 3 line = 6 ; column = 16 ; value ='pos'; } +{kind = TOKEN_COLON; ; index = 104 ; length = 1 line = 6 ; column = 20 ; value =':'; } +{kind = TOKEN_IDENTIFIER; ; index = 106 ; length = 6 line = 6 ; column = 22 ; value ='float3'; } +{kind = TOKEN_AT; ; index = 113 ; length = 1 line = 6 ; column = 29 ; value ='@'; } +{kind = TOKEN_IDENTIFIER; ; index = 114 ; length = 8 line = 6 ; column = 30 ; value ='position'; } +{kind = TOKEN_RIGHTPAREN; ; index = 122 ; length = 1 line = 6 ; column = 38 ; value =')'; } +{kind = TOKEN_ARROW; ; index = 124 ; length = 2 line = 6 ; column = 40 ; value ='->'; } +{kind = TOKEN_IDENTIFIER; ; index = 127 ; length = 6 line = 6 ; column = 43 ; value ='float4'; } +{kind = TOKEN_AT; ; index = 134 ; length = 1 line = 6 ; column = 50 ; value ='@'; } +{kind = TOKEN_IDENTIFIER; ; index = 135 ; length = 8 line = 6 ; column = 51 ; value ='position'; } +{kind = TOKEN_LEFTBRACE; ; index = 144 ; length = 1 line = 6 ; column = 60 ; value ='{'; } +{kind = TOKEN_RETURN; ; index = 148 ; length = 6 line = 7 ; column = 0 ; value ='return'; } +{kind = TOKEN_IDENTIFIER; ; index = 155 ; length = 6 line = 7 ; column = 7 ; value ='float4'; } +{kind = TOKEN_LEFTPAREN; ; index = 161 ; length = 1 line = 7 ; column = 13 ; value ='('; } +{kind = TOKEN_IDENTIFIER; ; index = 162 ; length = 3 line = 7 ; column = 14 ; value ='pos'; } +{kind = TOKEN_COMMA; ; index = 165 ; length = 1 line = 7 ; column = 17 ; value =','; } +{kind = TOKEN_FLOATLITERAL; ; index = 167 ; length = 3 line = 7 ; column = 19 ; value ='1'; } +{kind = TOKEN_RIGHTPAREN; ; index = 170 ; length = 1 line = 7 ; column = 22 ; value =')'; } +{kind = TOKEN_SEMICOLON; ; index = 171 ; length = 1 line = 7 ; column = 23 ; value =';'; } +{kind = TOKEN_RIGHTBRACE; ; index = 174 ; length = 1 line = 8 ; column = 0 ; value ='}'; } +{kind = TOKEN_PIXEL; ; index = 179 ; length = 5 line = 10 ; column = 0 ; value ='pixel'; } +{kind = TOKEN_IDENTIFIER; ; index = 185 ; length = 4 line = 10 ; column = 6 ; value ='main'; } +{kind = TOKEN_DOUBLECOLON; ; index = 190 ; length = 2 line = 10 ; column = 11 ; value ='::'; } +{kind = TOKEN_LEFTPAREN; ; index = 193 ; length = 1 line = 10 ; column = 14 ; value ='('; } +{kind = TOKEN_IDENTIFIER; ; index = 194 ; length = 3 line = 10 ; column = 15 ; value ='pos'; } +{kind = TOKEN_COLON; ; index = 198 ; length = 1 line = 10 ; column = 19 ; value =':'; } +{kind = TOKEN_IDENTIFIER; ; index = 200 ; length = 6 line = 10 ; column = 21 ; value ='float4'; } +{kind = TOKEN_AT; ; index = 207 ; length = 1 line = 10 ; column = 28 ; value ='@'; } +{kind = TOKEN_IDENTIFIER; ; index = 208 ; length = 11 line = 10 ; column = 29 ; value ='outposition'; } +{kind = TOKEN_RIGHTPAREN; ; index = 219 ; length = 1 line = 10 ; column = 40 ; value =')'; } +{kind = TOKEN_ARROW; ; index = 221 ; length = 2 line = 10 ; column = 42 ; value ='->'; } +{kind = TOKEN_IDENTIFIER; ; index = 224 ; length = 6 line = 10 ; column = 45 ; value ='float4'; } +{kind = TOKEN_AT; ; index = 231 ; length = 1 line = 10 ; column = 52 ; value ='@'; } +{kind = TOKEN_IDENTIFIER; ; index = 232 ; length = 6 line = 10 ; column = 53 ; value ='target'; } +{kind = TOKEN_LEFTBRACE; ; index = 239 ; length = 1 line = 10 ; column = 60 ; value ='{'; } +{kind = TOKEN_IDENTIFIER; ; index = 243 ; length = 1 line = 11 ; column = 0 ; value ='p'; } +{kind = TOKEN_COLON; ; index = 245 ; length = 1 line = 11 ; column = 2 ; value =':'; } +{kind = TOKEN_ASSIGN; ; index = 246 ; length = 1 line = 11 ; column = 3 ; value ='='; } +{kind = TOKEN_IDENTIFIER; ; index = 248 ; length = 6 line = 11 ; column = 5 ; value ='float2'; } +{kind = TOKEN_LEFTPAREN; ; index = 254 ; length = 1 line = 11 ; column = 11 ; value ='('; } +{kind = TOKEN_FLOATLITERAL; ; index = 255 ; length = 3 line = 11 ; column = 12 ; value ='2'; } +{kind = TOKEN_STAR; ; index = 259 ; length = 1 line = 11 ; column = 16 ; value ='*'; } +{kind = TOKEN_IDENTIFIER; ; index = 261 ; length = 3 line = 11 ; column = 18 ; value ='pos'; } +{kind = TOKEN_DOT; ; index = 264 ; length = 1 line = 11 ; column = 21 ; value ='.'; } +{kind = TOKEN_IDENTIFIER; ; index = 265 ; length = 1 line = 11 ; column = 22 ; value ='x'; } +{kind = TOKEN_MINUS; ; index = 267 ; length = 1 line = 11 ; column = 24 ; value ='-'; } +{kind = TOKEN_IDENTIFIER; ; index = 269 ; length = 4 line = 11 ; column = 26 ; value ='prop'; } +{kind = TOKEN_DOT; ; index = 273 ; length = 1 line = 11 ; column = 30 ; value ='.'; } +{kind = TOKEN_IDENTIFIER; ; index = 274 ; length = 10 line = 11 ; column = 31 ; value ='resolution'; } +{kind = TOKEN_DOT; ; index = 284 ; length = 1 line = 11 ; column = 41 ; value ='.'; } +{kind = TOKEN_IDENTIFIER; ; index = 285 ; length = 1 line = 11 ; column = 42 ; value ='x'; } +{kind = TOKEN_COMMA; ; index = 286 ; length = 1 line = 11 ; column = 43 ; value =','; } +{kind = TOKEN_FLOATLITERAL; ; index = 288 ; length = 3 line = 11 ; column = 45 ; value ='2'; } +{kind = TOKEN_STAR; ; index = 292 ; length = 1 line = 11 ; column = 49 ; value ='*'; } +{kind = TOKEN_IDENTIFIER; ; index = 294 ; length = 3 line = 11 ; column = 51 ; value ='pos'; } +{kind = TOKEN_DOT; ; index = 297 ; length = 1 line = 11 ; column = 54 ; value ='.'; } +{kind = TOKEN_IDENTIFIER; ; index = 298 ; length = 1 line = 11 ; column = 55 ; value ='y'; } +{kind = TOKEN_MINUS; ; index = 300 ; length = 1 line = 11 ; column = 57 ; value ='-'; } +{kind = TOKEN_IDENTIFIER; ; index = 302 ; length = 4 line = 11 ; column = 59 ; value ='prop'; } +{kind = TOKEN_DOT; ; index = 306 ; length = 1 line = 11 ; column = 63 ; value ='.'; } +{kind = TOKEN_IDENTIFIER; ; index = 307 ; length = 10 line = 11 ; column = 64 ; value ='resolution'; } +{kind = TOKEN_DOT; ; index = 317 ; length = 1 line = 11 ; column = 74 ; value ='.'; } +{kind = TOKEN_IDENTIFIER; ; index = 318 ; length = 1 line = 11 ; column = 75 ; value ='y'; } +{kind = TOKEN_RIGHTPAREN; ; index = 319 ; length = 1 line = 11 ; column = 76 ; value =')'; } +{kind = TOKEN_SLASH; ; index = 321 ; length = 1 line = 11 ; column = 78 ; value ='/'; } +{kind = TOKEN_IDENTIFIER; ; index = 323 ; length = 4 line = 11 ; column = 80 ; value ='prop'; } +{kind = TOKEN_DOT; ; index = 327 ; length = 1 line = 11 ; column = 84 ; value ='.'; } +{kind = TOKEN_IDENTIFIER; ; index = 328 ; length = 10 line = 11 ; column = 85 ; value ='resolution'; } +{kind = TOKEN_DOT; ; index = 338 ; length = 1 line = 11 ; column = 95 ; value ='.'; } +{kind = TOKEN_IDENTIFIER; ; index = 339 ; length = 1 line = 11 ; column = 96 ; value ='y'; } +{kind = TOKEN_SEMICOLON; ; index = 340 ; length = 1 line = 11 ; column = 97 ; value =';'; } +{kind = TOKEN_IDENTIFIER; ; index = 344 ; length = 3 line = 12 ; column = 0 ; value ='tau'; } +{kind = TOKEN_COLON; ; index = 348 ; length = 1 line = 12 ; column = 4 ; value =':'; } +{kind = TOKEN_ASSIGN; ; index = 349 ; length = 1 line = 12 ; column = 5 ; value ='='; } +{kind = TOKEN_FLOATLITERAL; ; index = 351 ; length = 12 line = 12 ; column = 7 ; value ='3.141593'; } +{kind = TOKEN_STAR; ; index = 364 ; length = 1 line = 12 ; column = 20 ; value ='*'; } +{kind = TOKEN_FLOATLITERAL; ; index = 366 ; length = 3 line = 12 ; column = 22 ; value ='2'; } +{kind = TOKEN_SEMICOLON; ; index = 369 ; length = 1 line = 12 ; column = 25 ; value =';'; } +{kind = TOKEN_IDENTIFIER; ; index = 373 ; length = 1 line = 13 ; column = 0 ; value ='a'; } +{kind = TOKEN_COLON; ; index = 375 ; length = 1 line = 13 ; column = 2 ; value =':'; } +{kind = TOKEN_ASSIGN; ; index = 376 ; length = 1 line = 13 ; column = 3 ; value ='='; } +{kind = TOKEN_IDENTIFIER; ; index = 378 ; length = 4 line = 13 ; column = 5 ; value ='atan'; } +{kind = TOKEN_LEFTPAREN; ; index = 382 ; length = 1 line = 13 ; column = 9 ; value ='('; } +{kind = TOKEN_IDENTIFIER; ; index = 383 ; length = 1 line = 13 ; column = 10 ; value ='p'; } +{kind = TOKEN_DOT; ; index = 384 ; length = 1 line = 13 ; column = 11 ; value ='.'; } +{kind = TOKEN_IDENTIFIER; ; index = 385 ; length = 1 line = 13 ; column = 12 ; value ='x'; } +{kind = TOKEN_COMMA; ; index = 386 ; length = 1 line = 13 ; column = 13 ; value =','; } +{kind = TOKEN_IDENTIFIER; ; index = 388 ; length = 1 line = 13 ; column = 15 ; value ='p'; } +{kind = TOKEN_DOT; ; index = 389 ; length = 1 line = 13 ; column = 16 ; value ='.'; } +{kind = TOKEN_IDENTIFIER; ; index = 390 ; length = 1 line = 13 ; column = 17 ; value ='y'; } +{kind = TOKEN_RIGHTPAREN; ; index = 391 ; length = 1 line = 13 ; column = 18 ; value =')'; } +{kind = TOKEN_SEMICOLON; ; index = 392 ; length = 1 line = 13 ; column = 19 ; value =';'; } +{kind = TOKEN_IDENTIFIER; ; index = 396 ; length = 1 line = 14 ; column = 0 ; value ='r'; } +{kind = TOKEN_COLON; ; index = 398 ; length = 1 line = 14 ; column = 2 ; value =':'; } +{kind = TOKEN_ASSIGN; ; index = 399 ; length = 1 line = 14 ; column = 3 ; value ='='; } +{kind = TOKEN_IDENTIFIER; ; index = 401 ; length = 6 line = 14 ; column = 5 ; value ='length'; } +{kind = TOKEN_LEFTPAREN; ; index = 407 ; length = 1 line = 14 ; column = 11 ; value ='('; } +{kind = TOKEN_IDENTIFIER; ; index = 408 ; length = 1 line = 14 ; column = 12 ; value ='p'; } +{kind = TOKEN_RIGHTPAREN; ; index = 409 ; length = 1 line = 14 ; column = 13 ; value =')'; } +{kind = TOKEN_STAR; ; index = 411 ; length = 1 line = 14 ; column = 15 ; value ='*'; } +{kind = TOKEN_FLOATLITERAL; ; index = 413 ; length = 4 line = 14 ; column = 17 ; value ='0.75'; } +{kind = TOKEN_SEMICOLON; ; index = 417 ; length = 1 line = 14 ; column = 21 ; value =';'; } +{kind = TOKEN_IDENTIFIER; ; index = 423 ; length = 2 line = 16 ; column = 0 ; value ='uv'; } +{kind = TOKEN_COLON; ; index = 426 ; length = 1 line = 16 ; column = 3 ; value =':'; } +{kind = TOKEN_ASSIGN; ; index = 427 ; length = 1 line = 16 ; column = 4 ; value ='='; } +{kind = TOKEN_IDENTIFIER; ; index = 429 ; length = 6 line = 16 ; column = 6 ; value ='float2'; } +{kind = TOKEN_LEFTPAREN; ; index = 435 ; length = 1 line = 16 ; column = 12 ; value ='('; } +{kind = TOKEN_IDENTIFIER; ; index = 436 ; length = 1 line = 16 ; column = 13 ; value ='a'; } +{kind = TOKEN_SLASH; ; index = 438 ; length = 1 line = 16 ; column = 15 ; value ='/'; } +{kind = TOKEN_IDENTIFIER; ; index = 440 ; length = 3 line = 16 ; column = 17 ; value ='tau'; } +{kind = TOKEN_COMMA; ; index = 443 ; length = 1 line = 16 ; column = 20 ; value =','; } +{kind = TOKEN_IDENTIFIER; ; index = 445 ; length = 1 line = 16 ; column = 22 ; value ='r'; } +{kind = TOKEN_RIGHTPAREN; ; index = 446 ; length = 1 line = 16 ; column = 23 ; value =')'; } +{kind = TOKEN_SEMICOLON; ; index = 447 ; length = 1 line = 16 ; column = 24 ; value =';'; } +{kind = TOKEN_IDENTIFIER; ; index = 453 ; length = 5 line = 18 ; column = 0 ; value ='x_col'; } +{kind = TOKEN_COLON; ; index = 459 ; length = 1 line = 18 ; column = 6 ; value =':'; } +{kind = TOKEN_ASSIGN; ; index = 460 ; length = 1 line = 18 ; column = 7 ; value ='='; } +{kind = TOKEN_LEFTPAREN; ; index = 462 ; length = 1 line = 18 ; column = 9 ; value ='('; } +{kind = TOKEN_IDENTIFIER; ; index = 463 ; length = 2 line = 18 ; column = 10 ; value ='uv'; } +{kind = TOKEN_DOT; ; index = 465 ; length = 1 line = 18 ; column = 12 ; value ='.'; } +{kind = TOKEN_IDENTIFIER; ; index = 466 ; length = 1 line = 18 ; column = 13 ; value ='x'; } +{kind = TOKEN_MINUS; ; index = 468 ; length = 1 line = 18 ; column = 15 ; value ='-'; } +{kind = TOKEN_LEFTPAREN; ; index = 470 ; length = 1 line = 18 ; column = 17 ; value ='('; } +{kind = TOKEN_IDENTIFIER; ; index = 471 ; length = 1 line = 18 ; column = 18 ; value ='p'; } +{kind = TOKEN_DOT; ; index = 472 ; length = 1 line = 18 ; column = 19 ; value ='.'; } +{kind = TOKEN_IDENTIFIER; ; index = 473 ; length = 4 line = 18 ; column = 20 ; value ='time'; } +{kind = TOKEN_SLASH; ; index = 478 ; length = 1 line = 18 ; column = 25 ; value ='/'; } +{kind = TOKEN_FLOATLITERAL; ; index = 480 ; length = 3 line = 18 ; column = 27 ; value ='3'; } +{kind = TOKEN_RIGHTPAREN; ; index = 483 ; length = 1 line = 18 ; column = 30 ; value =')'; } +{kind = TOKEN_RIGHTPAREN; ; index = 484 ; length = 1 line = 18 ; column = 31 ; value =')'; } +{kind = TOKEN_STAR; ; index = 486 ; length = 1 line = 18 ; column = 33 ; value ='*'; } +{kind = TOKEN_FLOATLITERAL; ; index = 488 ; length = 3 line = 18 ; column = 35 ; value ='3'; } +{kind = TOKEN_SEMICOLON; ; index = 491 ; length = 1 line = 18 ; column = 38 ; value =';'; } +{kind = TOKEN_IDENTIFIER; ; index = 495 ; length = 5 line = 19 ; column = 0 ; value ='x_col'; } +{kind = TOKEN_ASSIGN; ; index = 501 ; length = 1 line = 19 ; column = 6 ; value ='='; } +{kind = TOKEN_IDENTIFIER; ; index = 503 ; length = 3 line = 19 ; column = 8 ; value ='mod'; } +{kind = TOKEN_LEFTPAREN; ; index = 506 ; length = 1 line = 19 ; column = 11 ; value ='('; } +{kind = TOKEN_IDENTIFIER; ; index = 507 ; length = 5 line = 19 ; column = 12 ; value ='x_col'; } +{kind = TOKEN_COMMA; ; index = 512 ; length = 1 line = 19 ; column = 17 ; value =','; } +{kind = TOKEN_FLOATLITERAL; ; index = 514 ; length = 3 line = 19 ; column = 19 ; value ='3'; } +{kind = TOKEN_RIGHTPAREN; ; index = 517 ; length = 1 line = 19 ; column = 22 ; value =')'; } +{kind = TOKEN_SEMICOLON; ; index = 518 ; length = 1 line = 19 ; column = 23 ; value =';'; } +{kind = TOKEN_IDENTIFIER; ; index = 522 ; length = 10 line = 20 ; column = 0 ; value ='hor_colour'; } +{kind = TOKEN_COLON; ; index = 533 ; length = 1 line = 20 ; column = 11 ; value =':'; } +{kind = TOKEN_ASSIGN; ; index = 534 ; length = 1 line = 20 ; column = 12 ; value ='='; } +{kind = TOKEN_IDENTIFIER; ; index = 536 ; length = 6 line = 20 ; column = 14 ; value ='float3'; } +{kind = TOKEN_LEFTPAREN; ; index = 542 ; length = 1 line = 20 ; column = 20 ; value ='('; } +{kind = TOKEN_FLOATLITERAL; ; index = 543 ; length = 4 line = 20 ; column = 21 ; value ='0.25'; } +{kind = TOKEN_COMMA; ; index = 547 ; length = 1 line = 20 ; column = 25 ; value =','; } +{kind = TOKEN_FLOATLITERAL; ; index = 549 ; length = 4 line = 20 ; column = 27 ; value ='0.25'; } +{kind = TOKEN_COMMA; ; index = 553 ; length = 1 line = 20 ; column = 31 ; value =','; } +{kind = TOKEN_FLOATLITERAL; ; index = 555 ; length = 4 line = 20 ; column = 33 ; value ='0.25'; } +{kind = TOKEN_RIGHTPAREN; ; index = 559 ; length = 1 line = 20 ; column = 37 ; value =')'; } +{kind = TOKEN_SEMICOLON; ; index = 560 ; length = 1 line = 20 ; column = 38 ; value =';'; } +{kind = TOKEN_IF; ; index = 567 ; length = 2 line = 22 ; column = 0 ; value ='if'; } +{kind = TOKEN_IDENTIFIER; ; index = 570 ; length = 5 line = 22 ; column = 3 ; value ='x_col'; } +{kind = TOKEN_LESS; ; index = 576 ; length = 1 line = 22 ; column = 9 ; value ='<'; } +{kind = TOKEN_FLOATLITERAL; ; index = 578 ; length = 3 line = 22 ; column = 11 ; value ='1'; } +{kind = TOKEN_LEFTBRACE; ; index = 582 ; length = 1 line = 22 ; column = 15 ; value ='{'; } +{kind = TOKEN_RIGHTBRACE; ; index = 587 ; length = 1 line = 24 ; column = 0 ; value ='}'; } +{kind = TOKEN_ELSE; ; index = 589 ; length = 4 line = 24 ; column = 2 ; value ='else'; } +{kind = TOKEN_IF; ; index = 594 ; length = 2 line = 24 ; column = 7 ; value ='if'; } +{kind = TOKEN_IDENTIFIER; ; index = 597 ; length = 5 line = 24 ; column = 10 ; value ='x_col'; } +{kind = TOKEN_LESS; ; index = 603 ; length = 1 line = 24 ; column = 16 ; value ='<'; } +{kind = TOKEN_FLOATLITERAL; ; index = 605 ; length = 3 line = 24 ; column = 18 ; value ='2'; } +{kind = TOKEN_LEFTBRACE; ; index = 609 ; length = 1 line = 24 ; column = 22 ; value ='{'; } +{kind = TOKEN_RIGHTBRACE; ; index = 615 ; length = 1 line = 26 ; column = 0 ; value ='}'; } +{kind = TOKEN_ELSE; ; index = 617 ; length = 4 line = 26 ; column = 2 ; value ='else'; } +{kind = TOKEN_LEFTBRACE; ; index = 622 ; length = 1 line = 26 ; column = 7 ; value ='{'; } +{kind = TOKEN_IDENTIFIER; ; index = 626 ; length = 5 line = 27 ; column = 0 ; value ='x_col'; } +{kind = TOKEN_MINUSEQUALS; ; index = 632 ; length = 2 line = 27 ; column = 6 ; value ='-='; } +{kind = TOKEN_FLOATLITERAL; ; index = 635 ; length = 3 line = 27 ; column = 9 ; value ='2'; } +{kind = TOKEN_SEMICOLON; ; index = 638 ; length = 1 line = 27 ; column = 12 ; value =';'; } +{kind = TOKEN_IDENTIFIER; ; index = 642 ; length = 10 line = 28 ; column = 0 ; value ='hor_colour'; } +{kind = TOKEN_DOT; ; index = 652 ; length = 1 line = 28 ; column = 10 ; value ='.'; } +{kind = TOKEN_IDENTIFIER; ; index = 653 ; length = 1 line = 28 ; column = 11 ; value ='b'; } +{kind = TOKEN_PLUSEQUALS; ; index = 655 ; length = 2 line = 28 ; column = 13 ; value ='+='; } +{kind = TOKEN_FLOATLITERAL; ; index = 658 ; length = 3 line = 28 ; column = 16 ; value ='1'; } +{kind = TOKEN_MINUS; ; index = 662 ; length = 1 line = 28 ; column = 20 ; value ='-'; } +{kind = TOKEN_IDENTIFIER; ; index = 664 ; length = 5 line = 28 ; column = 22 ; value ='x_col'; } +{kind = TOKEN_SEMICOLON; ; index = 669 ; length = 1 line = 28 ; column = 27 ; value =';'; } +{kind = TOKEN_IDENTIFIER; ; index = 673 ; length = 10 line = 29 ; column = 0 ; value ='hor_colour'; } +{kind = TOKEN_DOT; ; index = 683 ; length = 1 line = 29 ; column = 10 ; value ='.'; } +{kind = TOKEN_IDENTIFIER; ; index = 684 ; length = 1 line = 29 ; column = 11 ; value ='r'; } +{kind = TOKEN_PLUSEQUALS; ; index = 686 ; length = 2 line = 29 ; column = 13 ; value ='+='; } +{kind = TOKEN_IDENTIFIER; ; index = 689 ; length = 5 line = 29 ; column = 16 ; value ='x_col'; } +{kind = TOKEN_SEMICOLON; ; index = 694 ; length = 1 line = 29 ; column = 21 ; value =';'; } +{kind = TOKEN_RIGHTBRACE; ; index = 697 ; length = 1 line = 30 ; column = 0 ; value ='}'; } +{kind = TOKEN_IDENTIFIER; ; index = 702 ; length = 2 line = 32 ; column = 0 ; value ='uv'; } +{kind = TOKEN_ASSIGN; ; index = 705 ; length = 1 line = 32 ; column = 3 ; value ='='; } +{kind = TOKEN_LEFTPAREN; ; index = 707 ; length = 1 line = 32 ; column = 5 ; value ='('; } +{kind = TOKEN_FLOATLITERAL; ; index = 708 ; length = 3 line = 32 ; column = 6 ; value ='2'; } +{kind = TOKEN_STAR; ; index = 712 ; length = 1 line = 32 ; column = 10 ; value ='*'; } +{kind = TOKEN_IDENTIFIER; ; index = 714 ; length = 2 line = 32 ; column = 12 ; value ='uv'; } +{kind = TOKEN_RIGHTPAREN; ; index = 716 ; length = 1 line = 32 ; column = 14 ; value =')'; } +{kind = TOKEN_MINUS; ; index = 718 ; length = 1 line = 32 ; column = 16 ; value ='-'; } +{kind = TOKEN_FLOATLITERAL; ; index = 720 ; length = 3 line = 32 ; column = 18 ; value ='1'; } +{kind = TOKEN_SEMICOLON; ; index = 723 ; length = 1 line = 32 ; column = 21 ; value =';'; } +{kind = TOKEN_IDENTIFIER; ; index = 726 ; length = 10 line = 33 ; column = 0 ; value ='beam_width'; } +{kind = TOKEN_ASSIGN; ; index = 737 ; length = 1 line = 33 ; column = 11 ; value ='='; } +{kind = TOKEN_LEFTPAREN; ; index = 739 ; length = 1 line = 33 ; column = 13 ; value ='('; } +{kind = TOKEN_FLOATLITERAL; ; index = 740 ; length = 3 line = 33 ; column = 14 ; value ='0.7'; } +{kind = TOKEN_PLUS; ; index = 743 ; length = 1 line = 33 ; column = 17 ; value ='+'; } +{kind = TOKEN_FLOATLITERAL; ; index = 744 ; length = 3 line = 33 ; column = 18 ; value ='0.5'; } +{kind = TOKEN_STAR; ; index = 747 ; length = 1 line = 33 ; column = 21 ; value ='*'; } +{kind = TOKEN_IDENTIFIER; ; index = 748 ; length = 3 line = 33 ; column = 22 ; value ='cos'; } +{kind = TOKEN_LEFTPAREN; ; index = 751 ; length = 1 line = 33 ; column = 25 ; value ='('; } +{kind = TOKEN_IDENTIFIER; ; index = 752 ; length = 2 line = 33 ; column = 26 ; value ='uv'; } +{kind = TOKEN_DOT; ; index = 754 ; length = 1 line = 33 ; column = 28 ; value ='.'; } +{kind = TOKEN_IDENTIFIER; ; index = 755 ; length = 1 line = 33 ; column = 29 ; value ='x'; } +{kind = TOKEN_STAR; ; index = 756 ; length = 1 line = 33 ; column = 30 ; value ='*'; } +{kind = TOKEN_FLOATLITERAL; ; index = 757 ; length = 4 line = 33 ; column = 31 ; value ='10'; } +{kind = TOKEN_STAR; ; index = 761 ; length = 1 line = 33 ; column = 35 ; value ='*'; } +{kind = TOKEN_IDENTIFIER; ; index = 762 ; length = 3 line = 33 ; column = 36 ; value ='tau'; } +{kind = TOKEN_STAR; ; index = 765 ; length = 1 line = 33 ; column = 39 ; value ='*'; } +{kind = TOKEN_FLOATLITERAL; ; index = 766 ; length = 4 line = 33 ; column = 40 ; value ='0.15'; } +{kind = TOKEN_STAR; ; index = 770 ; length = 1 line = 33 ; column = 44 ; value ='*'; } +{kind = TOKEN_IDENTIFIER; ; index = 771 ; length = 5 line = 33 ; column = 45 ; value ='clamp'; } +{kind = TOKEN_LEFTPAREN; ; index = 776 ; length = 1 line = 33 ; column = 50 ; value ='('; } +{kind = TOKEN_IDENTIFIER; ; index = 777 ; length = 5 line = 33 ; column = 51 ; value ='floor'; } +{kind = TOKEN_LEFTPAREN; ; index = 782 ; length = 1 line = 33 ; column = 56 ; value ='('; } +{kind = TOKEN_FLOATLITERAL; ; index = 783 ; length = 3 line = 33 ; column = 57 ; value ='5'; } +{kind = TOKEN_PLUS; ; index = 787 ; length = 1 line = 33 ; column = 61 ; value ='+'; } +{kind = TOKEN_FLOATLITERAL; ; index = 789 ; length = 4 line = 33 ; column = 63 ; value ='10'; } +{kind = TOKEN_STAR; ; index = 793 ; length = 1 line = 33 ; column = 67 ; value ='*'; } +{kind = TOKEN_IDENTIFIER; ; index = 794 ; length = 3 line = 33 ; column = 68 ; value ='cos'; } +{kind = TOKEN_LEFTPAREN; ; index = 797 ; length = 1 line = 33 ; column = 71 ; value ='('; } +{kind = TOKEN_IDENTIFIER; ; index = 798 ; length = 5 line = 33 ; column = 72 ; value ='iTime'; } +{kind = TOKEN_RIGHTPAREN; ; index = 803 ; length = 1 line = 33 ; column = 77 ; value =')'; } +{kind = TOKEN_RIGHTPAREN; ; index = 804 ; length = 1 line = 33 ; column = 78 ; value =')'; } +{kind = TOKEN_COMMA; ; index = 805 ; length = 1 line = 33 ; column = 79 ; value =','; } +{kind = TOKEN_FLOATLITERAL; ; index = 807 ; length = 3 line = 33 ; column = 81 ; value ='0'; } +{kind = TOKEN_COMMA; ; index = 810 ; length = 1 line = 33 ; column = 84 ; value =','; } +{kind = TOKEN_FLOATLITERAL; ; index = 812 ; length = 4 line = 33 ; column = 86 ; value ='10'; } +{kind = TOKEN_RIGHTPAREN; ; index = 816 ; length = 1 line = 33 ; column = 90 ; value =')'; } +{kind = TOKEN_RIGHTPAREN; ; index = 817 ; length = 1 line = 33 ; column = 91 ; value =')'; } +{kind = TOKEN_RIGHTPAREN; ; index = 818 ; length = 1 line = 33 ; column = 92 ; value =')'; } +{kind = TOKEN_STAR; ; index = 820 ; length = 1 line = 33 ; column = 94 ; value ='*'; } +{kind = TOKEN_IDENTIFIER; ; index = 822 ; length = 3 line = 33 ; column = 96 ; value ='abs'; } +{kind = TOKEN_LEFTPAREN; ; index = 825 ; length = 1 line = 33 ; column = 99 ; value ='('; } +{kind = TOKEN_FLOATLITERAL; ; index = 826 ; length = 3 line = 33 ; column = 100 ; value ='1'; } +{kind = TOKEN_SLASH; ; index = 830 ; length = 1 line = 33 ; column = 104 ; value ='/'; } +{kind = TOKEN_LEFTPAREN; ; index = 832 ; length = 1 line = 33 ; column = 106 ; value ='('; } +{kind = TOKEN_FLOATLITERAL; ; index = 833 ; length = 4 line = 33 ; column = 107 ; value ='30'; } +{kind = TOKEN_STAR; ; index = 838 ; length = 1 line = 33 ; column = 112 ; value ='*'; } +{kind = TOKEN_IDENTIFIER; ; index = 840 ; length = 2 line = 33 ; column = 114 ; value ='uv'; } +{kind = TOKEN_DOT; ; index = 842 ; length = 1 line = 33 ; column = 116 ; value ='.'; } +{kind = TOKEN_IDENTIFIER; ; index = 843 ; length = 1 line = 33 ; column = 117 ; value ='y'; } +{kind = TOKEN_RIGHTPAREN; ; index = 844 ; length = 1 line = 33 ; column = 118 ; value =')'; } +{kind = TOKEN_RIGHTPAREN; ; index = 845 ; length = 1 line = 33 ; column = 119 ; value =')'; } +{kind = TOKEN_SEMICOLON; ; index = 846 ; length = 1 line = 33 ; column = 120 ; value =';'; } +{kind = TOKEN_IDENTIFIER; ; index = 849 ; length = 8 line = 34 ; column = 0 ; value ='hor_beam'; } +{kind = TOKEN_ASSIGN; ; index = 858 ; length = 1 line = 34 ; column = 9 ; value ='='; } +{kind = TOKEN_IDENTIFIER; ; index = 860 ; length = 6 line = 34 ; column = 11 ; value ='float3'; } +{kind = TOKEN_LEFTPAREN; ; index = 866 ; length = 1 line = 34 ; column = 17 ; value ='('; } +{kind = TOKEN_IDENTIFIER; ; index = 867 ; length = 10 line = 34 ; column = 18 ; value ='beam_width'; } +{kind = TOKEN_RIGHTPAREN; ; index = 877 ; length = 1 line = 34 ; column = 28 ; value =')'; } +{kind = TOKEN_SEMICOLON; ; index = 878 ; length = 1 line = 34 ; column = 29 ; value =';'; } +{kind = TOKEN_IDENTIFIER; ; index = 881 ; length = 6 line = 35 ; column = 0 ; value ='result'; } +{kind = TOKEN_COLON; ; index = 888 ; length = 1 line = 35 ; column = 7 ; value =':'; } +{kind = TOKEN_ASSIGN; ; index = 889 ; length = 1 line = 35 ; column = 8 ; value ='='; } +{kind = TOKEN_IDENTIFIER; ; index = 891 ; length = 6 line = 35 ; column = 10 ; value ='float4'; } +{kind = TOKEN_LEFTPAREN; ; index = 897 ; length = 1 line = 35 ; column = 16 ; value ='('; } +{kind = TOKEN_LEFTPAREN; ; index = 898 ; length = 1 line = 35 ; column = 17 ; value ='('; } +{kind = TOKEN_LEFTPAREN; ; index = 899 ; length = 1 line = 35 ; column = 18 ; value ='('; } +{kind = TOKEN_IDENTIFIER; ; index = 900 ; length = 8 line = 35 ; column = 19 ; value ='hor_beam'; } +{kind = TOKEN_RIGHTPAREN; ; index = 908 ; length = 1 line = 35 ; column = 27 ; value =')'; } +{kind = TOKEN_STAR; ; index = 910 ; length = 1 line = 35 ; column = 29 ; value ='*'; } +{kind = TOKEN_IDENTIFIER; ; index = 912 ; length = 10 line = 35 ; column = 31 ; value ='hor_colour'; } +{kind = TOKEN_RIGHTPAREN; ; index = 922 ; length = 1 line = 35 ; column = 41 ; value =')'; } +{kind = TOKEN_COMMA; ; index = 923 ; length = 1 line = 35 ; column = 42 ; value =','; } +{kind = TOKEN_FLOATLITERAL; ; index = 925 ; length = 3 line = 35 ; column = 44 ; value ='1'; } +{kind = TOKEN_RIGHTPAREN; ; index = 928 ; length = 1 line = 35 ; column = 47 ; value =')'; } +{kind = TOKEN_SEMICOLON; ; index = 929 ; length = 1 line = 35 ; column = 48 ; value =';'; } +{kind = TOKEN_RIGHTBRACE; ; index = 932 ; length = 1 line = 36 ; column = 0 ; value ='}'; } +{kind = TOKEN_EOF; ; index = 935 ; length = 0 line = 37 ; column = 0 ; value =''; } diff --git a/test/lex/custom_hint.golden b/test/lex/custom_hint.golden new file mode 100644 index 0000000..3e224eb --- /dev/null +++ b/test/lex/custom_hint.golden @@ -0,0 +1,81 @@ +{kind = TOKEN_IDENTIFIER; ; index = 0 ; length = 1 line = 1 ; column = 0 ; value ='p'; } +{kind = TOKEN_DOUBLECOLON; ; index = 2 ; length = 2 line = 1 ; column = 2 ; value ='::'; } +{kind = TOKEN_PROPERTIES; ; index = 5 ; length = 10 line = 1 ; column = 5 ; value ='properties'; } +{kind = TOKEN_LEFTBRACE; ; index = 16 ; length = 1 line = 1 ; column = 16 ; value ='{'; } +{kind = TOKEN_IDENTIFIER; ; index = 20 ; length = 4 line = 2 ; column = 0 ; value ='time'; } +{kind = TOKEN_COLON; ; index = 25 ; length = 1 line = 2 ; column = 5 ; value =':'; } +{kind = TOKEN_IDENTIFIER; ; index = 27 ; length = 5 line = 2 ; column = 7 ; value ='float'; } +{kind = TOKEN_AT; ; index = 33 ; length = 1 line = 2 ; column = 13 ; value ='@'; } +{kind = TOKEN_IDENTIFIER; ; index = 34 ; length = 4 line = 2 ; column = 14 ; value ='time'; } +{kind = TOKEN_SEMICOLON; ; index = 38 ; length = 1 line = 2 ; column = 18 ; value =';'; } +{kind = TOKEN_RIGHTBRACE; ; index = 41 ; length = 1 line = 3 ; column = 0 ; value ='}'; } +{kind = TOKEN_VERTEX; ; index = 46 ; length = 6 line = 5 ; column = 0 ; value ='vertex'; } +{kind = TOKEN_IDENTIFIER; ; index = 53 ; length = 4 line = 5 ; column = 7 ; value ='main'; } +{kind = TOKEN_DOUBLECOLON; ; index = 58 ; length = 2 line = 5 ; column = 12 ; value ='::'; } +{kind = TOKEN_LEFTPAREN; ; index = 61 ; length = 1 line = 5 ; column = 15 ; value ='('; } +{kind = TOKEN_IDENTIFIER; ; index = 62 ; length = 3 line = 5 ; column = 16 ; value ='pos'; } +{kind = TOKEN_COLON; ; index = 66 ; length = 1 line = 5 ; column = 20 ; value =':'; } +{kind = TOKEN_IDENTIFIER; ; index = 68 ; length = 6 line = 5 ; column = 22 ; value ='float3'; } +{kind = TOKEN_AT; ; index = 75 ; length = 1 line = 5 ; column = 29 ; value ='@'; } +{kind = TOKEN_IDENTIFIER; ; index = 76 ; length = 8 line = 5 ; column = 30 ; value ='position'; } +{kind = TOKEN_RIGHTPAREN; ; index = 84 ; length = 1 line = 5 ; column = 38 ; value =')'; } +{kind = TOKEN_ARROW; ; index = 86 ; length = 2 line = 5 ; column = 40 ; value ='->'; } +{kind = TOKEN_IDENTIFIER; ; index = 89 ; length = 6 line = 5 ; column = 43 ; value ='float4'; } +{kind = TOKEN_AT; ; index = 96 ; length = 1 line = 5 ; column = 50 ; value ='@'; } +{kind = TOKEN_IDENTIFIER; ; index = 97 ; length = 8 line = 5 ; column = 51 ; value ='position'; } +{kind = TOKEN_LEFTBRACE; ; index = 106 ; length = 1 line = 5 ; column = 60 ; value ='{'; } +{kind = TOKEN_RETURN; ; index = 110 ; length = 6 line = 6 ; column = 0 ; value ='return'; } +{kind = TOKEN_IDENTIFIER; ; index = 117 ; length = 6 line = 6 ; column = 7 ; value ='float4'; } +{kind = TOKEN_LEFTPAREN; ; index = 123 ; length = 1 line = 6 ; column = 13 ; value ='('; } +{kind = TOKEN_IDENTIFIER; ; index = 124 ; length = 3 line = 6 ; column = 14 ; value ='pos'; } +{kind = TOKEN_DOT; ; index = 127 ; length = 1 line = 6 ; column = 17 ; value ='.'; } +{kind = TOKEN_IDENTIFIER; ; index = 128 ; length = 1 line = 6 ; column = 18 ; value ='x'; } +{kind = TOKEN_COMMA; ; index = 129 ; length = 1 line = 6 ; column = 19 ; value =','; } +{kind = TOKEN_IDENTIFIER; ; index = 131 ; length = 3 line = 6 ; column = 21 ; value ='pos'; } +{kind = TOKEN_DOT; ; index = 134 ; length = 1 line = 6 ; column = 24 ; value ='.'; } +{kind = TOKEN_IDENTIFIER; ; index = 135 ; length = 1 line = 6 ; column = 25 ; value ='y'; } +{kind = TOKEN_COMMA; ; index = 136 ; length = 1 line = 6 ; column = 26 ; value =','; } +{kind = TOKEN_IDENTIFIER; ; index = 138 ; length = 3 line = 6 ; column = 28 ; value ='pos'; } +{kind = TOKEN_DOT; ; index = 141 ; length = 1 line = 6 ; column = 31 ; value ='.'; } +{kind = TOKEN_IDENTIFIER; ; index = 142 ; length = 1 line = 6 ; column = 32 ; value ='z'; } +{kind = TOKEN_COMMA; ; index = 143 ; length = 1 line = 6 ; column = 33 ; value =','; } +{kind = TOKEN_FLOATLITERAL; ; index = 145 ; length = 3 line = 6 ; column = 35 ; value ='1'; } +{kind = TOKEN_RIGHTPAREN; ; index = 148 ; length = 1 line = 6 ; column = 38 ; value =')'; } +{kind = TOKEN_SEMICOLON; ; index = 149 ; length = 1 line = 6 ; column = 39 ; value =';'; } +{kind = TOKEN_RIGHTBRACE; ; index = 152 ; length = 1 line = 7 ; column = 0 ; value ='}'; } +{kind = TOKEN_PIXEL; ; index = 157 ; length = 5 line = 9 ; column = 0 ; value ='pixel'; } +{kind = TOKEN_IDENTIFIER; ; index = 163 ; length = 4 line = 9 ; column = 6 ; value ='main'; } +{kind = TOKEN_DOUBLECOLON; ; index = 168 ; length = 2 line = 9 ; column = 11 ; value ='::'; } +{kind = TOKEN_LEFTPAREN; ; index = 171 ; length = 1 line = 9 ; column = 14 ; value ='('; } +{kind = TOKEN_IDENTIFIER; ; index = 172 ; length = 3 line = 9 ; column = 15 ; value ='pos'; } +{kind = TOKEN_COLON; ; index = 176 ; length = 1 line = 9 ; column = 19 ; value =':'; } +{kind = TOKEN_IDENTIFIER; ; index = 178 ; length = 6 line = 9 ; column = 21 ; value ='float4'; } +{kind = TOKEN_AT; ; index = 185 ; length = 1 line = 9 ; column = 28 ; value ='@'; } +{kind = TOKEN_IDENTIFIER; ; index = 186 ; length = 11 line = 9 ; column = 29 ; value ='outposition'; } +{kind = TOKEN_RIGHTPAREN; ; index = 197 ; length = 1 line = 9 ; column = 40 ; value =')'; } +{kind = TOKEN_ARROW; ; index = 199 ; length = 2 line = 9 ; column = 42 ; value ='->'; } +{kind = TOKEN_IDENTIFIER; ; index = 202 ; length = 6 line = 9 ; column = 45 ; value ='float4'; } +{kind = TOKEN_AT; ; index = 209 ; length = 1 line = 9 ; column = 52 ; value ='@'; } +{kind = TOKEN_IDENTIFIER; ; index = 210 ; length = 6 line = 9 ; column = 53 ; value ='target'; } +{kind = TOKEN_LEFTBRACE; ; index = 217 ; length = 1 line = 9 ; column = 60 ; value ='{'; } +{kind = TOKEN_IDENTIFIER; ; index = 221 ; length = 1 line = 10 ; column = 0 ; value ='t'; } +{kind = TOKEN_COLON; ; index = 223 ; length = 1 line = 10 ; column = 2 ; value =':'; } +{kind = TOKEN_ASSIGN; ; index = 224 ; length = 1 line = 10 ; column = 3 ; value ='='; } +{kind = TOKEN_IDENTIFIER; ; index = 226 ; length = 1 line = 10 ; column = 5 ; value ='p'; } +{kind = TOKEN_DOT; ; index = 227 ; length = 1 line = 10 ; column = 6 ; value ='.'; } +{kind = TOKEN_IDENTIFIER; ; index = 228 ; length = 4 line = 10 ; column = 7 ; value ='time'; } +{kind = TOKEN_SEMICOLON; ; index = 232 ; length = 1 line = 10 ; column = 11 ; value =';'; } +{kind = TOKEN_RETURN; ; index = 236 ; length = 6 line = 11 ; column = 0 ; value ='return'; } +{kind = TOKEN_IDENTIFIER; ; index = 243 ; length = 6 line = 11 ; column = 7 ; value ='float4'; } +{kind = TOKEN_LEFTPAREN; ; index = 249 ; length = 1 line = 11 ; column = 13 ; value ='('; } +{kind = TOKEN_INTLITERAL; ; index = 250 ; length = 1 line = 11 ; column = 14 ; value ='1'; } +{kind = TOKEN_COMMA; ; index = 251 ; length = 1 line = 11 ; column = 15 ; value =','; } +{kind = TOKEN_INTLITERAL; ; index = 253 ; length = 1 line = 11 ; column = 17 ; value ='1'; } +{kind = TOKEN_COMMA; ; index = 254 ; length = 1 line = 11 ; column = 18 ; value =','; } +{kind = TOKEN_INTLITERAL; ; index = 256 ; length = 1 line = 11 ; column = 20 ; value ='1'; } +{kind = TOKEN_COMMA; ; index = 257 ; length = 1 line = 11 ; column = 21 ; value =','; } +{kind = TOKEN_INTLITERAL; ; index = 259 ; length = 1 line = 11 ; column = 23 ; value ='1'; } +{kind = TOKEN_RIGHTPAREN; ; index = 260 ; length = 1 line = 11 ; column = 24 ; value =')'; } +{kind = TOKEN_SEMICOLON; ; index = 261 ; length = 1 line = 11 ; column = 25 ; value =';'; } +{kind = TOKEN_RIGHTBRACE; ; index = 264 ; length = 1 line = 12 ; column = 0 ; value ='}'; } +{kind = TOKEN_EOF; ; index = 267 ; length = 0 line = 13 ; column = 0 ; value =''; } diff --git a/test/parse/custom_hint.golden b/test/parse/custom_hint.golden new file mode 100644 index 0000000..cb0ee66 --- /dev/null +++ b/test/parse/custom_hint.golden @@ -0,0 +1,12 @@ +(program + (properties p + [(:= time float (@time))]) + + (fun vertex vs_main -> float4 (@position) + [(:= pos float3 (@position))] + (return (float4 pos.x pos.y pos.z 1))) + + (fun pixel ps_main -> float4 (@target) + [(:= pos float4 (@outposition))] + (:= t p.time) + (return (float4 1 1 1 1)))) \ No newline at end of file diff --git a/test/semant/custom_hint.golden b/test/semant/custom_hint.golden new file mode 100644 index 0000000..d5c60c6 --- /dev/null +++ b/test/semant/custom_hint.golden @@ -0,0 +1,15 @@ +scope (global) [ + [pixel__ps_main] : (pos : float4) -> float4 + [vertex__vs_main] : (pos : float3) -> float4 + [p] : {time : float} + scope (p) [ + [time] : float + ] + scope (vertex__vs_main) [ + [pos] : float3 + ] + scope (pixel__ps_main) [ + [t] : float + [pos] : float4 + ] +] diff --git a/test/simple_if.ink b/test/simple_if.ink new file mode 100644 index 0000000..65e2a67 --- /dev/null +++ b/test/simple_if.ink @@ -0,0 +1,6 @@ +vertex main :: (pos : float3 @position) -> float4 @position { + if 0 > 100 { + return float4(pos, 1.0); + } + return float4(0.0); +} From 4b927b6be90dd859d0aa5c4e52c35c6555affea7 Mon Sep 17 00:00:00 2001 From: Niels Bross Date: Mon, 13 Jan 2025 09:14:36 +0100 Subject: [PATCH 08/17] Add else parsing. Still a few bugs with output. --- AST.jai | 12 ++++++++- Parsing.jai | 18 +++++++++---- test/lex/simple_if_else.golden | 46 ++++++++++++++++++++++++++++++++++ test/simple_if_else.ink | 8 ++++++ 4 files changed, 78 insertions(+), 6 deletions(-) create mode 100644 test/lex/simple_if_else.golden create mode 100644 test/simple_if_else.ink diff --git a/AST.jai b/AST.jai index 016883c..ad0bc2f 100644 --- a/AST.jai +++ b/AST.jai @@ -228,9 +228,19 @@ print_return_node :: (node : *AST_Node, indentation : int, builder : *String_Bui } pretty_print_if :: (node : *AST_Node, indentation : int, builder : *String_Builder) { +indent(builder, indentation); append(builder, "(if "); - pretty_print_children(node, 0, builder); + body := node.children[0]; + pretty_print_node(body, 0, builder); + + if node.children.count == 2 { + append(builder, "\n"); + indent(builder, indentation); + append(builder, "(else "); + pretty_print_node(node.children[1], 0, builder); + append(builder, ")"); + } append(builder, ")"); } diff --git a/Parsing.jai b/Parsing.jai index e047496..2909f7e 100644 --- a/Parsing.jai +++ b/Parsing.jai @@ -112,7 +112,7 @@ parse_rules :: #run -> [(cast(int)Token_Kind.TOKEN_ERROR) + 1]Parse_Rule { rules[Token_Kind.TOKEN_ELSE] = .{null, null, .PREC_NONE}; rules[Token_Kind.TOKEN_FALSE] = .{null, null, .PREC_NONE}; rules[Token_Kind.TOKEN_FOR] = .{null, null, .PREC_NONE}; - rules[Token_Kind.TOKEN_IF] = .{if_, null, .PREC_NONE}; + rules[Token_Kind.TOKEN_IF] = .{null, null, .PREC_NONE}; rules[Token_Kind.TOKEN_LOGICALOR] = .{null, binary, .PREC_OR}; rules[Token_Kind.TOKEN_LOGICALAND] = .{null, binary, .PREC_AND}; rules[Token_Kind.TOKEN_RETURN] = .{null, null, .PREC_NONE}; @@ -387,10 +387,6 @@ precedence :: (parse_state : *Parse_State, precedence : Precedence) -> *AST_Node return left; } -if_ :: (parse_state : *Parse_State, left : *AST_Node) -> *AST_Node { - return error_node(parse_state, "If not yet implemented."); -} - named_variable :: (parse_state : *Parse_State, left : *AST_Node) -> *AST_Node { if check(parse_state, .TOKEN_LEFTPAREN) { return call(parse_state, left); @@ -774,6 +770,11 @@ statement :: (parse_state : *Parse_State) -> *AST_Node { add_child(node, if_body); } + if match(parse_state, .TOKEN_ELSE) { + else_node := else_statement(parse_state); + add_child(node, else_node); + } + source_location.end = parse_state.previous; node.source_location = source_location; @@ -785,6 +786,13 @@ statement :: (parse_state : *Parse_State) -> *AST_Node { return error_node(parse_state, "Couldn't parse statement."); } +else_statement :: (parse_state : *Parse_State) -> *AST_Node { + if check(parse_state, .TOKEN_IF) { + return statement(parse_state); + } + return block(parse_state); +} + block :: (parse_state : *Parse_State) -> *AST_Node { node : *AST_Node = make_node(parse_state, .Block); array_reserve(*node.children, 1024); diff --git a/test/lex/simple_if_else.golden b/test/lex/simple_if_else.golden new file mode 100644 index 0000000..2b0cc59 --- /dev/null +++ b/test/lex/simple_if_else.golden @@ -0,0 +1,46 @@ +{kind = TOKEN_VERTEX; ; index = 0 ; length = 6 line = 1 ; column = 0 ; value ='vertex'; } +{kind = TOKEN_IDENTIFIER; ; index = 7 ; length = 4 line = 1 ; column = 7 ; value ='main'; } +{kind = TOKEN_DOUBLECOLON; ; index = 12 ; length = 2 line = 1 ; column = 12 ; value ='::'; } +{kind = TOKEN_LEFTPAREN; ; index = 15 ; length = 1 line = 1 ; column = 15 ; value ='('; } +{kind = TOKEN_IDENTIFIER; ; index = 16 ; length = 3 line = 1 ; column = 16 ; value ='pos'; } +{kind = TOKEN_COLON; ; index = 20 ; length = 1 line = 1 ; column = 20 ; value =':'; } +{kind = TOKEN_IDENTIFIER; ; index = 22 ; length = 6 line = 1 ; column = 22 ; value ='float3'; } +{kind = TOKEN_AT; ; index = 29 ; length = 1 line = 1 ; column = 29 ; value ='@'; } +{kind = TOKEN_IDENTIFIER; ; index = 30 ; length = 8 line = 1 ; column = 30 ; value ='position'; } +{kind = TOKEN_RIGHTPAREN; ; index = 38 ; length = 1 line = 1 ; column = 38 ; value =')'; } +{kind = TOKEN_ARROW; ; index = 40 ; length = 2 line = 1 ; column = 40 ; value ='->'; } +{kind = TOKEN_IDENTIFIER; ; index = 43 ; length = 6 line = 1 ; column = 43 ; value ='float4'; } +{kind = TOKEN_AT; ; index = 50 ; length = 1 line = 1 ; column = 50 ; value ='@'; } +{kind = TOKEN_IDENTIFIER; ; index = 51 ; length = 8 line = 1 ; column = 51 ; value ='position'; } +{kind = TOKEN_LEFTBRACE; ; index = 60 ; length = 1 line = 1 ; column = 60 ; value ='{'; } +{kind = TOKEN_IF; ; index = 64 ; length = 2 line = 2 ; column = 0 ; value ='if'; } +{kind = TOKEN_INTLITERAL; ; index = 67 ; length = 1 line = 2 ; column = 3 ; value ='0'; } +{kind = TOKEN_GREATER; ; index = 69 ; length = 1 line = 2 ; column = 5 ; value ='>'; } +{kind = TOKEN_INTLITERAL; ; index = 71 ; length = 3 line = 2 ; column = 7 ; value ='100'; } +{kind = TOKEN_LEFTBRACE; ; index = 75 ; length = 1 line = 2 ; column = 11 ; value ='{'; } +{kind = TOKEN_RETURN; ; index = 80 ; length = 6 line = 3 ; column = 0 ; value ='return'; } +{kind = TOKEN_IDENTIFIER; ; index = 87 ; length = 6 line = 3 ; column = 7 ; value ='float4'; } +{kind = TOKEN_LEFTPAREN; ; index = 93 ; length = 1 line = 3 ; column = 13 ; value ='('; } +{kind = TOKEN_IDENTIFIER; ; index = 94 ; length = 3 line = 3 ; column = 14 ; value ='pos'; } +{kind = TOKEN_COMMA; ; index = 97 ; length = 1 line = 3 ; column = 17 ; value =','; } +{kind = TOKEN_FLOATLITERAL; ; index = 99 ; length = 3 line = 3 ; column = 19 ; value ='1'; } +{kind = TOKEN_RIGHTPAREN; ; index = 102 ; length = 1 line = 3 ; column = 22 ; value =')'; } +{kind = TOKEN_SEMICOLON; ; index = 103 ; length = 1 line = 3 ; column = 23 ; value =';'; } +{kind = TOKEN_RIGHTBRACE; ; index = 107 ; length = 1 line = 4 ; column = 0 ; value ='}'; } +{kind = TOKEN_ELSE; ; index = 109 ; length = 4 line = 4 ; column = 2 ; value ='else'; } +{kind = TOKEN_LEFTBRACE; ; index = 114 ; length = 1 line = 4 ; column = 7 ; value ='{'; } +{kind = TOKEN_RETURN; ; index = 119 ; length = 6 line = 5 ; column = 0 ; value ='return'; } +{kind = TOKEN_IDENTIFIER; ; index = 126 ; length = 6 line = 5 ; column = 7 ; value ='float4'; } +{kind = TOKEN_LEFTPAREN; ; index = 132 ; length = 1 line = 5 ; column = 13 ; value ='('; } +{kind = TOKEN_FLOATLITERAL; ; index = 133 ; length = 3 line = 5 ; column = 14 ; value ='1'; } +{kind = TOKEN_RIGHTPAREN; ; index = 136 ; length = 1 line = 5 ; column = 17 ; value =')'; } +{kind = TOKEN_SEMICOLON; ; index = 137 ; length = 1 line = 5 ; column = 18 ; value =';'; } +{kind = TOKEN_RIGHTBRACE; ; index = 141 ; length = 1 line = 6 ; column = 0 ; value ='}'; } +{kind = TOKEN_RETURN; ; index = 145 ; length = 6 line = 7 ; column = 0 ; value ='return'; } +{kind = TOKEN_IDENTIFIER; ; index = 152 ; length = 6 line = 7 ; column = 7 ; value ='float4'; } +{kind = TOKEN_LEFTPAREN; ; index = 158 ; length = 1 line = 7 ; column = 13 ; value ='('; } +{kind = TOKEN_FLOATLITERAL; ; index = 159 ; length = 3 line = 7 ; column = 14 ; value ='0'; } +{kind = TOKEN_RIGHTPAREN; ; index = 162 ; length = 1 line = 7 ; column = 17 ; value =')'; } +{kind = TOKEN_SEMICOLON; ; index = 163 ; length = 1 line = 7 ; column = 18 ; value =';'; } +{kind = TOKEN_RIGHTBRACE; ; index = 166 ; length = 1 line = 8 ; column = 0 ; value ='}'; } +{kind = TOKEN_EOF; ; index = 169 ; length = 0 line = 9 ; column = 0 ; value =''; } diff --git a/test/simple_if_else.ink b/test/simple_if_else.ink new file mode 100644 index 0000000..b80447e --- /dev/null +++ b/test/simple_if_else.ink @@ -0,0 +1,8 @@ +vertex main :: (pos : float3 @position) -> float4 @position { + if 0 > 100 { + return float4(pos, 1.0); + } else { + return float4(1.0); + } + return float4(0.0); +} From aaeda22fa3ec1e4e0094377893c00e0cfd85deba Mon Sep 17 00:00:00 2001 From: Niels Bross Date: Mon, 13 Jan 2025 16:33:03 +0100 Subject: [PATCH 09/17] Added broken check for bool if cond. Also added some wonky if/else pretty printing for AST. --- AST.jai | 29 +++++++------- Parsing.jai | 1 + Semantic_Analysis.jai | 50 ++++++++++++++++++++++++ module.jai | 2 +- test/float_if_cond.ink | 6 +++ test/lex/simple_else_if.golden | 65 +++++++++++++++++++++++++++++++ test/parse/simple_else_if.golden | 9 +++++ test/semant/simple_else_if.golden | 6 +++ test/simple_else_if.ink | 11 ++++++ 9 files changed, 165 insertions(+), 14 deletions(-) create mode 100644 test/float_if_cond.ink create mode 100644 test/lex/simple_else_if.golden create mode 100644 test/parse/simple_else_if.golden create mode 100644 test/semant/simple_else_if.golden create mode 100644 test/simple_else_if.ink diff --git a/AST.jai b/AST.jai index ad0bc2f..3f5cc42 100644 --- a/AST.jai +++ b/AST.jai @@ -146,12 +146,13 @@ pretty_print_children :: (parent : *AST_Node, indentation : int, builder : *Stri children := parent.children; for child : children { - if it_index > 0 { - indent(builder, indentation); - } + // if it_index > 0 { + // indent(builder, indentation); + // } if !child continue; - pretty_print_node(child, 0, builder); + + pretty_print_node(child, indentation, builder); if it_index != children.count - 1 { if flags & .Separator { @@ -220,6 +221,7 @@ pretty_print_unary :: (node : *AST_Node, indentation : int, builder : *String_Bu } print_return_node :: (node : *AST_Node, indentation : int, builder : *String_Builder) { + indent(builder, indentation); append(builder, "(return "); pretty_print_children(node, 0, builder); @@ -228,18 +230,19 @@ print_return_node :: (node : *AST_Node, indentation : int, builder : *String_Bui } pretty_print_if :: (node : *AST_Node, indentation : int, builder : *String_Builder) { -indent(builder, indentation); + indent(builder, indentation); append(builder, "(if "); - body := node.children[0]; - pretty_print_node(body, 0, builder); + condition := node.children[0]; + pretty_print_node(condition, 0, builder); + append(builder, "\n"); - if node.children.count == 2 { + body := node.children[1]; + pretty_print_node(body, indentation + 1, builder); + + if node.children.count == 3 { append(builder, "\n"); - indent(builder, indentation); - append(builder, "(else "); - pretty_print_node(node.children[1], 0, builder); - append(builder, ")"); + pretty_print_node(node.children[2], indentation + 1, builder); } append(builder, ")"); @@ -259,7 +262,7 @@ pretty_print_node :: (node : *AST_Node, indentation : int, builder : *String_Bui print_return_node(node, indentation, builder); } case .If; { - pretty_print_if(node, indentation, builder); + pretty_print_if(node, indentation + 2, builder); } case .Struct; case .ArgList; { diff --git a/Parsing.jai b/Parsing.jai index 2909f7e..c4ec21c 100644 --- a/Parsing.jai +++ b/Parsing.jai @@ -763,6 +763,7 @@ statement :: (parse_state : *Parse_State) -> *AST_Node { source_location.begin = parse_state.previous; if_expression := expression(parse_state); + add_child(node, if_expression); // consume(parse_state, .TOKEN_LEFTBRACE, "Expect '{' after if-condition."); if_body := block(parse_state); diff --git a/Semantic_Analysis.jai b/Semantic_Analysis.jai index cc2ec5c..ea72bd9 100644 --- a/Semantic_Analysis.jai +++ b/Semantic_Analysis.jai @@ -23,6 +23,8 @@ Semantic_Type :: enum { Texture2D :: 4; Sampler :: 5; + Bool :: 6; + Max_Builtin :: Sampler + 1; Unit; @@ -488,6 +490,33 @@ Attempting to access a field on a primitive type '%'. message := builder_to_string(*builder,, temp); record_error(checker, message, node.source_location, false); + + white(*builder); +} + +if_condition_has_to_be_boolean_type :: (checker : *Semantic_Checker, usage_site : *AST_Node, handle : Type_Variable_Handle) { + /* + Type of expression in if condition has to be bool. + if x > 100 { + ^^^^^^^ + */ + + builder : String_Builder; + init_string_builder(*builder,, temp); + + variable := from_handle(checker, handle); + append(*builder, "Type of expression in if condition has to be bool.\n"); + + indent(*builder, 1); + cyan(*builder); + + print_to_builder(*builder, "%\n", print_from_source_location(usage_site.source_location)); + indent(*builder, 1); + + message := builder_to_string(*builder,, temp); + record_error(checker, message, usage_site.source_location, false); + + white(*builder); } type_mismatch :: (checker : *Semantic_Checker, usage_site : *AST_Node, expect_node : *AST_Node, expect : Type_Variable_Handle, got : Type_Variable_Handle) { @@ -1430,12 +1459,33 @@ check_node :: (checker : *Semantic_Checker, node : *AST_Node) -> Type_Variable_H return 0; } } + case .TOKEN_GREATER; #through; + case .TOKEN_GREATEREQUALS; #through; + case .TOKEN_LESS; #through; + case .TOKEN_LESSEQUALS; #through; + case .TOKEN_LOGICALOR; #through; + case .TOKEN_ISEQUAL; #through; + case .TOKEN_ISNOTEQUAL; #through; + case .TOKEN_LOGICALAND; { + variable.type = .Bool; + variable.typename = Typenames[variable.type]; + } } return handle; } case .Return; { return check_node(checker, node.children[0]); } + case .If; { + cond_var := check_node(checker, node.children[0]); + + if cond_var > 0 { + cond := from_handle(checker, cond_var); + if cond.type != .Bool { + if_condition_has_to_be_boolean_type(checker, node, cond_var); + } + } + } case .Variable; { return create_variable(checker, node); } diff --git a/module.jai b/module.jai index 2d4ae7c..6df2b3f 100644 --- a/module.jai +++ b/module.jai @@ -371,7 +371,7 @@ type_variable_to_field :: (type_variables : []Type_Variable, scope_stack : Scope } field_hint.kind = .Target; } else { - // @Incomplete(nb): custo hints + field_hint.custom_hint_name = copy_string(hint.ident_value); } array_add(*field.hints, field_hint); } diff --git a/test/float_if_cond.ink b/test/float_if_cond.ink new file mode 100644 index 0000000..9ec6373 --- /dev/null +++ b/test/float_if_cond.ink @@ -0,0 +1,6 @@ +vertex main :: (pos : float3 @position) -> float4 @position { + if 1.0 { + return float4(pos, 1.0); + } + return float4(0.0); +} diff --git a/test/lex/simple_else_if.golden b/test/lex/simple_else_if.golden new file mode 100644 index 0000000..111002d --- /dev/null +++ b/test/lex/simple_else_if.golden @@ -0,0 +1,65 @@ +{kind = TOKEN_VERTEX; ; index = 0 ; length = 6 line = 1 ; column = 0 ; value ='vertex'; } +{kind = TOKEN_IDENTIFIER; ; index = 7 ; length = 4 line = 1 ; column = 7 ; value ='main'; } +{kind = TOKEN_DOUBLECOLON; ; index = 12 ; length = 2 line = 1 ; column = 12 ; value ='::'; } +{kind = TOKEN_LEFTPAREN; ; index = 15 ; length = 1 line = 1 ; column = 15 ; value ='('; } +{kind = TOKEN_IDENTIFIER; ; index = 16 ; length = 3 line = 1 ; column = 16 ; value ='pos'; } +{kind = TOKEN_COLON; ; index = 20 ; length = 1 line = 1 ; column = 20 ; value =':'; } +{kind = TOKEN_IDENTIFIER; ; index = 22 ; length = 6 line = 1 ; column = 22 ; value ='float3'; } +{kind = TOKEN_AT; ; index = 29 ; length = 1 line = 1 ; column = 29 ; value ='@'; } +{kind = TOKEN_IDENTIFIER; ; index = 30 ; length = 8 line = 1 ; column = 30 ; value ='position'; } +{kind = TOKEN_RIGHTPAREN; ; index = 38 ; length = 1 line = 1 ; column = 38 ; value =')'; } +{kind = TOKEN_ARROW; ; index = 40 ; length = 2 line = 1 ; column = 40 ; value ='->'; } +{kind = TOKEN_IDENTIFIER; ; index = 43 ; length = 6 line = 1 ; column = 43 ; value ='float4'; } +{kind = TOKEN_AT; ; index = 50 ; length = 1 line = 1 ; column = 50 ; value ='@'; } +{kind = TOKEN_IDENTIFIER; ; index = 51 ; length = 8 line = 1 ; column = 51 ; value ='position'; } +{kind = TOKEN_LEFTBRACE; ; index = 60 ; length = 1 line = 1 ; column = 60 ; value ='{'; } +{kind = TOKEN_IF; ; index = 64 ; length = 2 line = 2 ; column = 0 ; value ='if'; } +{kind = TOKEN_IDENTIFIER; ; index = 67 ; length = 3 line = 2 ; column = 3 ; value ='pos'; } +{kind = TOKEN_DOT; ; index = 70 ; length = 1 line = 2 ; column = 6 ; value ='.'; } +{kind = TOKEN_IDENTIFIER; ; index = 71 ; length = 1 line = 2 ; column = 7 ; value ='x'; } +{kind = TOKEN_GREATER; ; index = 73 ; length = 1 line = 2 ; column = 9 ; value ='>'; } +{kind = TOKEN_INTLITERAL; ; index = 75 ; length = 3 line = 2 ; column = 11 ; value ='100'; } +{kind = TOKEN_LEFTBRACE; ; index = 79 ; length = 1 line = 2 ; column = 15 ; value ='{'; } +{kind = TOKEN_RETURN; ; index = 84 ; length = 6 line = 3 ; column = 0 ; value ='return'; } +{kind = TOKEN_IDENTIFIER; ; index = 91 ; length = 6 line = 3 ; column = 7 ; value ='float4'; } +{kind = TOKEN_LEFTPAREN; ; index = 97 ; length = 1 line = 3 ; column = 13 ; value ='('; } +{kind = TOKEN_IDENTIFIER; ; index = 98 ; length = 3 line = 3 ; column = 14 ; value ='pos'; } +{kind = TOKEN_COMMA; ; index = 101 ; length = 1 line = 3 ; column = 17 ; value =','; } +{kind = TOKEN_FLOATLITERAL; ; index = 103 ; length = 3 line = 3 ; column = 19 ; value ='1'; } +{kind = TOKEN_RIGHTPAREN; ; index = 106 ; length = 1 line = 3 ; column = 22 ; value =')'; } +{kind = TOKEN_SEMICOLON; ; index = 107 ; length = 1 line = 3 ; column = 23 ; value =';'; } +{kind = TOKEN_RIGHTBRACE; ; index = 111 ; length = 1 line = 4 ; column = 0 ; value ='}'; } +{kind = TOKEN_ELSE; ; index = 113 ; length = 4 line = 4 ; column = 2 ; value ='else'; } +{kind = TOKEN_IF; ; index = 118 ; length = 2 line = 4 ; column = 7 ; value ='if'; } +{kind = TOKEN_IDENTIFIER; ; index = 121 ; length = 3 line = 4 ; column = 10 ; value ='pos'; } +{kind = TOKEN_DOT; ; index = 124 ; length = 1 line = 4 ; column = 13 ; value ='.'; } +{kind = TOKEN_IDENTIFIER; ; index = 125 ; length = 1 line = 4 ; column = 14 ; value ='x'; } +{kind = TOKEN_GREATER; ; index = 127 ; length = 1 line = 4 ; column = 16 ; value ='>'; } +{kind = TOKEN_INTLITERAL; ; index = 129 ; length = 2 line = 4 ; column = 18 ; value ='50'; } +{kind = TOKEN_LEFTBRACE; ; index = 132 ; length = 1 line = 4 ; column = 21 ; value ='{'; } +{kind = TOKEN_RETURN; ; index = 137 ; length = 6 line = 5 ; column = 0 ; value ='return'; } +{kind = TOKEN_IDENTIFIER; ; index = 144 ; length = 6 line = 5 ; column = 7 ; value ='float4'; } +{kind = TOKEN_LEFTPAREN; ; index = 150 ; length = 1 line = 5 ; column = 13 ; value ='('; } +{kind = TOKEN_IDENTIFIER; ; index = 151 ; length = 3 line = 5 ; column = 14 ; value ='pos'; } +{kind = TOKEN_COMMA; ; index = 154 ; length = 1 line = 5 ; column = 17 ; value =','; } +{kind = TOKEN_FLOATLITERAL; ; index = 156 ; length = 3 line = 5 ; column = 19 ; value ='1'; } +{kind = TOKEN_RIGHTPAREN; ; index = 159 ; length = 1 line = 5 ; column = 22 ; value =')'; } +{kind = TOKEN_SEMICOLON; ; index = 160 ; length = 1 line = 5 ; column = 23 ; value =';'; } +{kind = TOKEN_RIGHTBRACE; ; index = 164 ; length = 1 line = 6 ; column = 0 ; value ='}'; } +{kind = TOKEN_ELSE; ; index = 166 ; length = 4 line = 6 ; column = 2 ; value ='else'; } +{kind = TOKEN_LEFTBRACE; ; index = 171 ; length = 1 line = 6 ; column = 7 ; value ='{'; } +{kind = TOKEN_RETURN; ; index = 176 ; length = 6 line = 7 ; column = 0 ; value ='return'; } +{kind = TOKEN_IDENTIFIER; ; index = 183 ; length = 6 line = 7 ; column = 7 ; value ='float4'; } +{kind = TOKEN_LEFTPAREN; ; index = 189 ; length = 1 line = 7 ; column = 13 ; value ='('; } +{kind = TOKEN_FLOATLITERAL; ; index = 190 ; length = 3 line = 7 ; column = 14 ; value ='1'; } +{kind = TOKEN_RIGHTPAREN; ; index = 193 ; length = 1 line = 7 ; column = 17 ; value =')'; } +{kind = TOKEN_SEMICOLON; ; index = 194 ; length = 1 line = 7 ; column = 18 ; value =';'; } +{kind = TOKEN_RIGHTBRACE; ; index = 198 ; length = 1 line = 8 ; column = 0 ; value ='}'; } +{kind = TOKEN_RETURN; ; index = 202 ; length = 6 line = 9 ; column = 0 ; value ='return'; } +{kind = TOKEN_IDENTIFIER; ; index = 209 ; length = 6 line = 9 ; column = 7 ; value ='float4'; } +{kind = TOKEN_LEFTPAREN; ; index = 215 ; length = 1 line = 9 ; column = 13 ; value ='('; } +{kind = TOKEN_FLOATLITERAL; ; index = 216 ; length = 3 line = 9 ; column = 14 ; value ='0'; } +{kind = TOKEN_RIGHTPAREN; ; index = 219 ; length = 1 line = 9 ; column = 17 ; value =')'; } +{kind = TOKEN_SEMICOLON; ; index = 220 ; length = 1 line = 9 ; column = 18 ; value =';'; } +{kind = TOKEN_RIGHTBRACE; ; index = 223 ; length = 1 line = 10 ; column = 0 ; value ='}'; } +{kind = TOKEN_EOF; ; index = 228 ; length = 0 line = 12 ; column = 0 ; value =''; } diff --git a/test/parse/simple_else_if.golden b/test/parse/simple_else_if.golden new file mode 100644 index 0000000..fd3b76b --- /dev/null +++ b/test/parse/simple_else_if.golden @@ -0,0 +1,9 @@ +(program + (fun vertex vs_main -> float4 (@position) + [(:= pos float3 (@position))] + (if (> pos.x 100) + (return (float4 pos 1)) + (if (> pos.x 50) + (return (float4 pos 1)) + (return (float4 1)))) + (return (float4 0)))) \ No newline at end of file diff --git a/test/semant/simple_else_if.golden b/test/semant/simple_else_if.golden new file mode 100644 index 0000000..7d9b85d --- /dev/null +++ b/test/semant/simple_else_if.golden @@ -0,0 +1,6 @@ +scope (global) [ + [vertex__vs_main] : (pos : float3) -> float4 + scope (vertex__vs_main) [ + [pos] : float3 + ] +] diff --git a/test/simple_else_if.ink b/test/simple_else_if.ink new file mode 100644 index 0000000..5a0e776 --- /dev/null +++ b/test/simple_else_if.ink @@ -0,0 +1,11 @@ +vertex main :: (pos : float3 @position) -> float4 @position { + if pos.x > 100 { + return float4(pos, 1.0); + } else if pos.x > 50 { + return float4(pos, 1.0); + } else { + return float4(1.0); + } + return float4(0.0); +} + From bc69a39570c6e0629a18362f3d261cabf735b147 Mon Sep 17 00:00:00 2001 From: Niels Bross Date: Tue, 14 Jan 2025 09:38:05 +0100 Subject: [PATCH 10/17] Attempt to improved error log. --- Parsing.jai | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/Parsing.jai b/Parsing.jai index 2909f7e..296e63a 100644 --- a/Parsing.jai +++ b/Parsing.jai @@ -182,7 +182,33 @@ generate_source_location_from_token :: (state : *Parse_State, token : Token) -> } unexpected_token :: (state : *Parse_State, token : Token, message : string) { - record_error(state, token, message); + /* + +*/ + builder : String_Builder; + init_string_builder(*builder,, temp); + + print_to_builder(*builder, "%\n", message); + + location : Source_Range; + location.begin = token; + location.begin.source = location.begin.source - location.begin.column; + location.begin.column = 0; + + location.main_token = token; + + advance(state); + location.end = state.current; + + indent(*builder, 1); + cyan(*builder); + print_to_builder(*builder, "%\n", print_from_source_location(location)); + + indent(*builder, 1); + print_token_pointer(*builder, token); + + final_message := builder_to_string(*builder); + record_error(state, token, final_message, false); } expected_expression :: (state : *Parse_State, token : Token, message : string) { @@ -350,8 +376,9 @@ consume :: (parse_state : *Parse_State, kind : Token_Kind, message : string) { return; } + token := parse_state.previous; advance(parse_state); - unexpected_token(parse_state, parse_state.current, message); + unexpected_token(parse_state, token, message); consume(parse_state, kind, message); } From a72a9ff50de905b1fe7b8c94c168b9d8b82e7084 Mon Sep 17 00:00:00 2001 From: Niels Bross Date: Wed, 15 Jan 2025 07:15:31 +0100 Subject: [PATCH 11/17] More print improvements. --- AST.jai | 52 ++++++++++++++++++++++++++++++++++++++++------------ Parsing.jai | 10 ++++++---- 2 files changed, 46 insertions(+), 16 deletions(-) diff --git a/AST.jai b/AST.jai index 3f5cc42..2bb3040 100644 --- a/AST.jai +++ b/AST.jai @@ -105,6 +105,7 @@ pretty_print_fieldlist :: (node : *AST_Node, indentation : int, builder : *Strin } pretty_print_field :: (node : *AST_Node, indentation : int, builder : *String_Builder) { + indent(builder, indentation); print_to_builder(builder, tprint("(:= %", node.name)); if node.kind != .Unnamed_Field && node.token.ident_value.count > 0 { @@ -127,7 +128,7 @@ pretty_print_field :: (node : *AST_Node, indentation : int, builder : *String_Bu if !node.array_field && node.children.count > 0 { append(builder, " "); - pretty_print_children(node, indentation, builder); + pretty_print_node(node.children[0], indentation, builder); } append(builder, ")"); @@ -139,6 +140,15 @@ Children_Print_Flags :: enum_flags { Space :: 1 << 2; } +pretty_print_block :: (node : *AST_Node, indentation : int, builder : *String_Builder) { + for child : node.children { + pretty_print_node(child, indentation, builder); + if it_index != node.children.count - 1 { + append(builder, "\n"); + } + } +} + pretty_print_children :: (parent : *AST_Node, indentation : int, builder : *String_Builder, flags : Children_Print_Flags = .Separator) { if !parent { return; @@ -152,7 +162,8 @@ pretty_print_children :: (parent : *AST_Node, indentation : int, builder : *Stri if !child continue; - pretty_print_node(child, indentation, builder); + ind := ifx it_index > 0 indentation else 0; + pretty_print_node(child, ind, builder); if it_index != children.count - 1 { if flags & .Separator { @@ -208,7 +219,9 @@ pretty_print_binary :: (node : *AST_Node, indentation : int, builder : *String_B print_to_builder(builder, op_to_string(op)); append(builder, " "); - pretty_print_children(node, 0, builder, flags = 0); + pretty_print_node(node.children[0], 0, builder); + append(builder, " "); + pretty_print_node(node.children[1], 0, builder); append(builder, ")"); } @@ -217,14 +230,14 @@ pretty_print_unary :: (node : *AST_Node, indentation : int, builder : *String_Bu op := node.token; print_to_builder(builder, op_to_string(op)); - pretty_print_children(node, 0, builder, flags = 0); + pretty_print_node(node.children[0], 0, builder); } print_return_node :: (node : *AST_Node, indentation : int, builder : *String_Builder) { indent(builder, indentation); append(builder, "(return "); - pretty_print_children(node, 0, builder); + pretty_print_children(node, indentation, builder); append(builder, ")"); } @@ -238,11 +251,11 @@ pretty_print_if :: (node : *AST_Node, indentation : int, builder : *String_Build append(builder, "\n"); body := node.children[1]; - pretty_print_node(body, indentation + 1, builder); + pretty_print_node(body, indentation, builder); if node.children.count == 3 { append(builder, "\n"); - pretty_print_node(node.children[2], indentation + 1, builder); + pretty_print_node(node.children[2], indentation, builder); } append(builder, ")"); @@ -252,7 +265,7 @@ print_expression_statement :: (node : *AST_Node, indentation : int, builder : *S indent(builder, indentation); if node.children[0] { - pretty_print_node(node.children[0], indentation, builder); + pretty_print_node(node.children[0], 0, builder); } } @@ -262,7 +275,7 @@ pretty_print_node :: (node : *AST_Node, indentation : int, builder : *String_Bui print_return_node(node, indentation, builder); } case .If; { - pretty_print_if(node, indentation + 2, builder); + pretty_print_if(node, indentation + 4, builder); } case .Struct; case .ArgList; { @@ -278,7 +291,7 @@ pretty_print_node :: (node : *AST_Node, indentation : int, builder : *String_Bui pretty_print_field(node, indentation, builder); } case .Block; { - pretty_print_children(node, indentation + 2, builder, flags = .NewLine); + pretty_print_block(node, indentation, builder); } case .Binary; { pretty_print_binary(node, indentation, builder); @@ -369,12 +382,27 @@ pretty_print_declaration :: (declaration : *AST_Node, indentation : int, builder print_to_builder(builder, " (@%)", hint.string_value); } } - } if declaration.children.count > 0 { print_to_builder(builder, "\n"); - pretty_print_children(declaration, indentation + 1, builder, flags = .NewLine); + if declaration.kind == .Function { + field_list := declaration.children[0]; + pretty_print_fieldlist(field_list, indentation + 1, builder); + append(builder, "\n"); + + if declaration.children.count > 1 { + body := declaration.children[1]; + pretty_print_node(body, indentation + 1, builder); + } + } else if declaration.kind == .Struct { + pretty_print_node(declaration.children[0], indentation + 1, builder); + } else { + pretty_print_node(declaration.children[0], indentation + 1, builder); + } + + // print_to_builder(builder, "\n"); + // pretty_print_children(declaration, indentation + 1, builder, flags = .NewLine); } append(builder, ")"); diff --git a/Parsing.jai b/Parsing.jai index 69b046b..710041d 100644 --- a/Parsing.jai +++ b/Parsing.jai @@ -188,17 +188,19 @@ unexpected_token :: (state : *Parse_State, token : Token, message : string) { builder : String_Builder; init_string_builder(*builder,, temp); - print_to_builder(*builder, "%\n", message); + print_to_builder(*builder, "%\n\n", message); location : Source_Range; location.begin = token; - location.begin.source = location.begin.source - location.begin.column; + location.begin.index -= location.begin.column; + location.begin.source -= location.begin.column; + location.begin.length += location.begin.column; location.begin.column = 0; location.main_token = token; + location.end = token; - advance(state); - location.end = state.current; + // advance(state); indent(*builder, 1); cyan(*builder); From b4d119230bed03a7a097e2293822474d35409a9c Mon Sep 17 00:00:00 2001 From: Niels Bross Date: Wed, 15 Jan 2025 21:32:18 +0100 Subject: [PATCH 12/17] Proper pretty printing and error handling on non-cool if condition. --- AST.jai | 178 ++++++++++++++++++------------- Parsing.jai | 4 +- Semantic_Analysis.jai | 17 ++- test/codegen_all.suite | 3 + test/compile_all.suite | 3 + test/lex/non_bool_cond.golden | 35 ++++++ test/lex/simple_if.golden | 37 +++++++ test/lex_all.suite | 4 + test/non_bool_cond.ink | 6 ++ test/parse/non_bool_cond.golden | 6 ++ test/parse/simple_else_if.golden | 14 +-- test/parse/simple_if.golden | 6 ++ test/parse/simple_if_else.golden | 7 ++ test/parse_all.suite | 4 + test/semant/non_bool_cond.golden | 6 ++ test/semant_all.suite | 4 + 16 files changed, 249 insertions(+), 85 deletions(-) create mode 100644 test/lex/non_bool_cond.golden create mode 100644 test/lex/simple_if.golden create mode 100644 test/non_bool_cond.ink create mode 100644 test/parse/non_bool_cond.golden create mode 100644 test/parse/simple_if.golden create mode 100644 test/parse/simple_if_else.golden create mode 100644 test/semant/non_bool_cond.golden diff --git a/AST.jai b/AST.jai index 2bb3040..8abc868 100644 --- a/AST.jai +++ b/AST.jai @@ -72,22 +72,25 @@ AST_Node :: struct { pixel_entry_point : bool; } - // =========================================================== // Pretty printing -pretty_print_call :: (node : *AST_Node, indentation : int, builder : *String_Builder) { - indent(builder, indentation); +pretty_print_call :: (node : *AST_Node, indentation : int, builder : *String_Builder, skip_indent := false) { + if !skip_indent { + indent(builder, indentation); + } append(builder, "("); append(builder, node.name); if node.children.count > 0 { append(builder, " "); - pretty_print_children(node.children[0], indentation, builder, flags = 0); + pretty_print_children(node.children[0], indentation, builder, flags = 0, skip_indent = true); } append(builder, ")"); } -pretty_print_arglist :: (node : *AST_Node, indentation : int, builder : *String_Builder) { - indent(builder, indentation); +pretty_print_arglist :: (node : *AST_Node, indentation : int, builder : *String_Builder, skip_indent := false) { + if !skip_indent { + indent(builder, indentation); + } append(builder, "["); pretty_print_children(node, indentation + 1, builder, flags = .NewLine); @@ -95,8 +98,10 @@ pretty_print_arglist :: (node : *AST_Node, indentation : int, builder : *String_ append(builder, "]"); } -pretty_print_fieldlist :: (node : *AST_Node, indentation : int, builder : *String_Builder) { - indent(builder, indentation); +pretty_print_fieldlist :: (node : *AST_Node, indentation : int, builder : *String_Builder, skip_indent := false) { + if !skip_indent { + indent(builder, indentation); + } append(builder, "["); pretty_print_children(node, indentation + 1, builder, flags = .NewLine); @@ -104,14 +109,16 @@ pretty_print_fieldlist :: (node : *AST_Node, indentation : int, builder : *Strin append(builder, "]"); } -pretty_print_field :: (node : *AST_Node, indentation : int, builder : *String_Builder) { - indent(builder, indentation); +pretty_print_field :: (node : *AST_Node, indentation : int, builder : *String_Builder, skip_indent := false) { + if !skip_indent { + indent(builder, indentation); + } print_to_builder(builder, tprint("(:= %", node.name)); if node.kind != .Unnamed_Field && node.token.ident_value.count > 0 { if node.array_field { append(builder, " ["); - pretty_print_node(node.children[0], 0, builder); + pretty_print_node(node.children[0], indentation, builder, true); append(builder, "]."); print_to_builder(builder, "%", node.token.ident_value); } else { @@ -128,28 +135,24 @@ pretty_print_field :: (node : *AST_Node, indentation : int, builder : *String_Bu if !node.array_field && node.children.count > 0 { append(builder, " "); - pretty_print_node(node.children[0], indentation, builder); + pretty_print_node(node.children[0], indentation, builder, true); } append(builder, ")"); } Children_Print_Flags :: enum_flags { - NewLine :: 1 << 0; - Separator :: 1 << 1; - Space :: 1 << 2; + NewLine :: 1 << 0; + Separator :: 1 << 1; + Space :: 1 << 2; + Dont_Skip_Indent_On_First :: 1 << 3; } -pretty_print_block :: (node : *AST_Node, indentation : int, builder : *String_Builder) { - for child : node.children { - pretty_print_node(child, indentation, builder); - if it_index != node.children.count - 1 { - append(builder, "\n"); - } - } +pretty_print_block :: (node : *AST_Node, indentation : int, builder : *String_Builder, skip_indent := false) { + pretty_print_children(node, indentation, builder, flags = .NewLine | .Dont_Skip_Indent_On_First); } -pretty_print_children :: (parent : *AST_Node, indentation : int, builder : *String_Builder, flags : Children_Print_Flags = .Separator) { +pretty_print_children :: (parent : *AST_Node, indentation : int, builder : *String_Builder, flags : Children_Print_Flags = .Separator, skip_indent := false) { if !parent { return; } @@ -162,7 +165,20 @@ pretty_print_children :: (parent : *AST_Node, indentation : int, builder : *Stri if !child continue; - ind := ifx it_index > 0 indentation else 0; + + ind := indentation; + if flags & .Dont_Skip_Indent_On_First { + ind = indentation; + } else { + if it_index == 0 { + ind = 0; + } + } + + if skip_indent{ + ind = 0; + } + // skip := ifx it_index > 0 then false else true; pretty_print_node(child, ind, builder); if it_index != children.count - 1 { @@ -211,8 +227,10 @@ op_to_string :: (oper : Token) -> string { return ""; } -pretty_print_binary :: (node : *AST_Node, indentation : int, builder : *String_Builder) { - indent(builder, indentation); +pretty_print_binary :: (node : *AST_Node, indentation : int, builder : *String_Builder, skip_indent := false) { + if !skip_indent { + indent(builder, indentation); + } append(builder, "("); op := node.token; @@ -225,16 +243,20 @@ pretty_print_binary :: (node : *AST_Node, indentation : int, builder : *String_B append(builder, ")"); } -pretty_print_unary :: (node : *AST_Node, indentation : int, builder : *String_Builder) { - indent(builder, indentation); +pretty_print_unary :: (node : *AST_Node, indentation : int, builder : *String_Builder, skip_indent := false) { + if !skip_indent { + indent(builder, indentation); + } op := node.token; print_to_builder(builder, op_to_string(op)); pretty_print_node(node.children[0], 0, builder); } -print_return_node :: (node : *AST_Node, indentation : int, builder : *String_Builder) { - indent(builder, indentation); +print_return_node :: (node : *AST_Node, indentation : int, builder : *String_Builder, skip_indent := false) { + if !skip_indent { + indent(builder, indentation); + } append(builder, "(return "); pretty_print_children(node, indentation, builder); @@ -242,8 +264,10 @@ print_return_node :: (node : *AST_Node, indentation : int, builder : *String_Bui append(builder, ")"); } -pretty_print_if :: (node : *AST_Node, indentation : int, builder : *String_Builder) { - indent(builder, indentation); +pretty_print_if :: (node : *AST_Node, indentation : int, builder : *String_Builder, skip_indent := false) { + if !skip_indent { + indent(builder, indentation); + } append(builder, "(if "); condition := node.children[0]; @@ -251,83 +275,87 @@ pretty_print_if :: (node : *AST_Node, indentation : int, builder : *String_Build append(builder, "\n"); body := node.children[1]; - pretty_print_node(body, indentation, builder); + pretty_print_node(body, indentation + 4, builder); if node.children.count == 3 { append(builder, "\n"); - pretty_print_node(node.children[2], indentation, builder); + pretty_print_node(node.children[2], indentation + 4, builder); } append(builder, ")"); } -print_expression_statement :: (node : *AST_Node, indentation : int, builder : *String_Builder) { - indent(builder, indentation); +print_expression_statement :: (node : *AST_Node, indentation : int, builder : *String_Builder, skip_indent := false) { + if !skip_indent { + indent(builder, indentation); + } if node.children[0] { pretty_print_node(node.children[0], 0, builder); } } -pretty_print_node :: (node : *AST_Node, indentation : int, builder : *String_Builder) { +pretty_print_node :: (node : *AST_Node, indentation : int, builder : *String_Builder, skip_indent := false) { if node.kind == { case .Return; { - print_return_node(node, indentation, builder); + print_return_node(node, indentation, builder, skip_indent); } case .If; { - pretty_print_if(node, indentation + 4, builder); + pretty_print_if(node, indentation, builder, skip_indent); } case .Struct; case .ArgList; { - pretty_print_arglist(node, indentation + 2, builder); + pretty_print_arglist(node, indentation + 2, builder, skip_indent); } case .FieldList; { - pretty_print_fieldlist(node, indentation + 2, builder); + pretty_print_fieldlist(node, indentation + 2, builder, skip_indent); } case .Field; { - pretty_print_field(node, indentation, builder); + pretty_print_field(node, indentation, builder, skip_indent); } case .Unnamed_Field; { - pretty_print_field(node, indentation, builder); + pretty_print_field(node, indentation, builder, skip_indent); } case .Block; { - pretty_print_block(node, indentation, builder); + pretty_print_block(node, indentation, builder, skip_indent); } case .Binary; { - pretty_print_binary(node, indentation, builder); + pretty_print_binary(node, indentation, builder, skip_indent); } case .Unary; { - pretty_print_unary(node, indentation, builder); + pretty_print_unary(node, indentation, builder, skip_indent); } case .Variable; { - pretty_print_variable(node, indentation, builder); + pretty_print_variable(node, indentation, builder, skip_indent); } case .Expression_Statement; { - print_expression_statement(node, indentation, builder); + print_expression_statement(node, indentation, builder, skip_indent); } case .Integer; { - print_to_builder(builder, "%", node.integer_value); + print_to_builder(builder, "%", node.integer_value, skip_indent); } case .Float; { - print_to_builder(builder, "%", node.float_value); + print_to_builder(builder, "%", node.float_value, skip_indent); } case .Call; { - pretty_print_call(node, indentation, builder); + pretty_print_call(node, indentation, builder, skip_indent); } case .Error; { - print_to_builder(builder, "(error \"%\")", node.name); + print_to_builder(builder, "(error \"%\")", node.name, skip_indent); } } } -pretty_print_variable :: (node : *AST_Node, indentation : int, builder : *String_Builder) { - indent(builder, indentation); +pretty_print_variable :: (node : *AST_Node, indentation : int, builder : *String_Builder, skip_indent := false) { + if !skip_indent { + indent(builder, indentation); + } print_to_builder(builder, "%", node.name); for child : node.children { if child.kind == .Variable { append(builder, "."); - pretty_print_variable(child, indentation, builder); + pretty_print_variable(child, indentation, builder, skip_indent = true); } else if child.kind == .Unary { append(builder, "["); pretty_print_node(child.children[0], 0, builder); @@ -336,8 +364,10 @@ pretty_print_variable :: (node : *AST_Node, indentation : int, builder : *String } } -pretty_print_declaration :: (declaration : *AST_Node, indentation : int, builder : *String_Builder) { - indent(builder, indentation); +pretty_print_declaration :: (declaration : *AST_Node, indentation : int, builder : *String_Builder, skip_indent := false) { + if !skip_indent { + indent(builder, indentation); + } append(builder, "("); if declaration.foreign_declaration { @@ -385,24 +415,24 @@ pretty_print_declaration :: (declaration : *AST_Node, indentation : int, builder } if declaration.children.count > 0 { - print_to_builder(builder, "\n"); - if declaration.kind == .Function { - field_list := declaration.children[0]; - pretty_print_fieldlist(field_list, indentation + 1, builder); - append(builder, "\n"); - - if declaration.children.count > 1 { - body := declaration.children[1]; - pretty_print_node(body, indentation + 1, builder); - } - } else if declaration.kind == .Struct { - pretty_print_node(declaration.children[0], indentation + 1, builder); - } else { - pretty_print_node(declaration.children[0], indentation + 1, builder); - } - // print_to_builder(builder, "\n"); - // pretty_print_children(declaration, indentation + 1, builder, flags = .NewLine); + // if declaration.kind == .Function { + // field_list := declaration.children[0]; + // pretty_print_fieldlist(field_list, indentation + 1, builder); + // append(builder, "\n"); + + // if declaration.children.count > 1 { + // body := declaration.children[1]; + // pretty_print_node(body, indentation + 1, builder, true); + // } + // } else if declaration.kind == .Struct { + // pretty_print_node(declaration.children[0], indentation + 1, builder); + // } else { + // pretty_print_node(declaration.children[0], indentation + 1, builder); + // } + + print_to_builder(builder, "\n"); + pretty_print_children(declaration, indentation + 1, builder, flags = .NewLine); } append(builder, ")"); diff --git a/Parsing.jai b/Parsing.jai index 710041d..b2503bb 100644 --- a/Parsing.jai +++ b/Parsing.jai @@ -794,6 +794,7 @@ statement :: (parse_state : *Parse_State) -> *AST_Node { if_expression := expression(parse_state); add_child(node, if_expression); // consume(parse_state, .TOKEN_LEFTBRACE, "Expect '{' after if-condition."); + source_location.end = parse_state.previous; if_body := block(parse_state); if if_body.children.count > 0 { @@ -804,8 +805,7 @@ statement :: (parse_state : *Parse_State) -> *AST_Node { else_node := else_statement(parse_state); add_child(node, else_node); } - - source_location.end = parse_state.previous; + node.source_location = source_location; return node; diff --git a/Semantic_Analysis.jai b/Semantic_Analysis.jai index ea72bd9..61625e3 100644 --- a/Semantic_Analysis.jai +++ b/Semantic_Analysis.jai @@ -52,6 +52,7 @@ Typenames :: string.[ "double" , "Texture2D", "Sampler" , + "bool" , ]; Type_Variable :: struct { @@ -497,8 +498,10 @@ Attempting to access a field on a primitive type '%'. if_condition_has_to_be_boolean_type :: (checker : *Semantic_Checker, usage_site : *AST_Node, handle : Type_Variable_Handle) { /* Type of expression in if condition has to be bool. - if x > 100 { + if 100.0 ^^^^^^^ + + 100.0 has type float */ builder : String_Builder; @@ -510,9 +513,19 @@ if_condition_has_to_be_boolean_type :: (checker : *Semantic_Checker, usage_site indent(*builder, 1); cyan(*builder); - print_to_builder(*builder, "%\n", print_from_source_location(usage_site.source_location)); + location := usage_site.source_location; + + print_to_builder(*builder, "%\n", print_from_source_location(location)); indent(*builder, 1); + print_token_pointer(*builder, usage_site.children[0].source_location.begin); + append(*builder, "\n"); + + indent(*builder, 1); + + var := from_handle(checker, handle); + print_to_builder(*builder, "% has type %\n", print_from_source_location(*usage_site.children[0].source_location), proper_type_to_string(checker, var)); + message := builder_to_string(*builder,, temp); record_error(checker, message, usage_site.source_location, false); diff --git a/test/codegen_all.suite b/test/codegen_all.suite index c939b7c..1dd698b 100644 --- a/test/codegen_all.suite +++ b/test/codegen_all.suite @@ -16,6 +16,9 @@ test/multiple_semicolons_everywhere.ink codegen test/pass_and_access_struct_fields_in_functions.ink codegen test/passthrough.ink codegen test/property_rename.ink codegen +test/simple_else_if.ink codegen +test/simple_if_else.ink codegen +test/simple_if.ink codegen test/simple_struct_access.ink codegen test/struct_within_struct.ink codegen test/unary.ink codegen diff --git a/test/compile_all.suite b/test/compile_all.suite index 58b17f2..7f12ef6 100644 --- a/test/compile_all.suite +++ b/test/compile_all.suite @@ -16,6 +16,9 @@ test/multiple_functions.ink compile test/multiple_semicolons_everywhere.ink compile test/pass_and_access_struct_fields_in_functions.ink compile test/passthrough.ink compile +test/simple_else_if.ink compile +test/simple_if_else.ink compile +test/simple_if.ink compile test/simple_struct_access.ink compile test/struct_within_struct.ink compile test/unary.ink compile diff --git a/test/lex/non_bool_cond.golden b/test/lex/non_bool_cond.golden new file mode 100644 index 0000000..38f1583 --- /dev/null +++ b/test/lex/non_bool_cond.golden @@ -0,0 +1,35 @@ +{kind = TOKEN_VERTEX; ; index = 0 ; length = 6 line = 1 ; column = 0 ; value ='vertex'; } +{kind = TOKEN_IDENTIFIER; ; index = 7 ; length = 4 line = 1 ; column = 7 ; value ='main'; } +{kind = TOKEN_DOUBLECOLON; ; index = 12 ; length = 2 line = 1 ; column = 12 ; value ='::'; } +{kind = TOKEN_LEFTPAREN; ; index = 15 ; length = 1 line = 1 ; column = 15 ; value ='('; } +{kind = TOKEN_IDENTIFIER; ; index = 16 ; length = 3 line = 1 ; column = 16 ; value ='pos'; } +{kind = TOKEN_COLON; ; index = 20 ; length = 1 line = 1 ; column = 20 ; value =':'; } +{kind = TOKEN_IDENTIFIER; ; index = 22 ; length = 6 line = 1 ; column = 22 ; value ='float3'; } +{kind = TOKEN_AT; ; index = 29 ; length = 1 line = 1 ; column = 29 ; value ='@'; } +{kind = TOKEN_IDENTIFIER; ; index = 30 ; length = 8 line = 1 ; column = 30 ; value ='position'; } +{kind = TOKEN_RIGHTPAREN; ; index = 38 ; length = 1 line = 1 ; column = 38 ; value =')'; } +{kind = TOKEN_ARROW; ; index = 40 ; length = 2 line = 1 ; column = 40 ; value ='->'; } +{kind = TOKEN_IDENTIFIER; ; index = 43 ; length = 6 line = 1 ; column = 43 ; value ='float4'; } +{kind = TOKEN_AT; ; index = 50 ; length = 1 line = 1 ; column = 50 ; value ='@'; } +{kind = TOKEN_IDENTIFIER; ; index = 51 ; length = 8 line = 1 ; column = 51 ; value ='position'; } +{kind = TOKEN_LEFTBRACE; ; index = 60 ; length = 1 line = 1 ; column = 60 ; value ='{'; } +{kind = TOKEN_IF; ; index = 64 ; length = 2 line = 2 ; column = 0 ; value ='if'; } +{kind = TOKEN_FLOATLITERAL; ; index = 67 ; length = 3 line = 2 ; column = 3 ; value ='1'; } +{kind = TOKEN_LEFTBRACE; ; index = 71 ; length = 1 line = 2 ; column = 7 ; value ='{'; } +{kind = TOKEN_RETURN; ; index = 76 ; length = 6 line = 3 ; column = 0 ; value ='return'; } +{kind = TOKEN_IDENTIFIER; ; index = 83 ; length = 6 line = 3 ; column = 7 ; value ='float4'; } +{kind = TOKEN_LEFTPAREN; ; index = 89 ; length = 1 line = 3 ; column = 13 ; value ='('; } +{kind = TOKEN_IDENTIFIER; ; index = 90 ; length = 3 line = 3 ; column = 14 ; value ='pos'; } +{kind = TOKEN_COMMA; ; index = 93 ; length = 1 line = 3 ; column = 17 ; value =','; } +{kind = TOKEN_FLOATLITERAL; ; index = 95 ; length = 3 line = 3 ; column = 19 ; value ='1'; } +{kind = TOKEN_RIGHTPAREN; ; index = 98 ; length = 1 line = 3 ; column = 22 ; value =')'; } +{kind = TOKEN_SEMICOLON; ; index = 99 ; length = 1 line = 3 ; column = 23 ; value =';'; } +{kind = TOKEN_RIGHTBRACE; ; index = 103 ; length = 1 line = 4 ; column = 0 ; value ='}'; } +{kind = TOKEN_RETURN; ; index = 107 ; length = 6 line = 5 ; column = 0 ; value ='return'; } +{kind = TOKEN_IDENTIFIER; ; index = 114 ; length = 6 line = 5 ; column = 7 ; value ='float4'; } +{kind = TOKEN_LEFTPAREN; ; index = 120 ; length = 1 line = 5 ; column = 13 ; value ='('; } +{kind = TOKEN_FLOATLITERAL; ; index = 121 ; length = 3 line = 5 ; column = 14 ; value ='0'; } +{kind = TOKEN_RIGHTPAREN; ; index = 124 ; length = 1 line = 5 ; column = 17 ; value =')'; } +{kind = TOKEN_SEMICOLON; ; index = 125 ; length = 1 line = 5 ; column = 18 ; value =';'; } +{kind = TOKEN_RIGHTBRACE; ; index = 128 ; length = 1 line = 6 ; column = 0 ; value ='}'; } +{kind = TOKEN_EOF; ; index = 131 ; length = 0 line = 7 ; column = 0 ; value =''; } diff --git a/test/lex/simple_if.golden b/test/lex/simple_if.golden new file mode 100644 index 0000000..9808533 --- /dev/null +++ b/test/lex/simple_if.golden @@ -0,0 +1,37 @@ +{kind = TOKEN_VERTEX; ; index = 0 ; length = 6 line = 1 ; column = 0 ; value ='vertex'; } +{kind = TOKEN_IDENTIFIER; ; index = 7 ; length = 4 line = 1 ; column = 7 ; value ='main'; } +{kind = TOKEN_DOUBLECOLON; ; index = 12 ; length = 2 line = 1 ; column = 12 ; value ='::'; } +{kind = TOKEN_LEFTPAREN; ; index = 15 ; length = 1 line = 1 ; column = 15 ; value ='('; } +{kind = TOKEN_IDENTIFIER; ; index = 16 ; length = 3 line = 1 ; column = 16 ; value ='pos'; } +{kind = TOKEN_COLON; ; index = 20 ; length = 1 line = 1 ; column = 20 ; value =':'; } +{kind = TOKEN_IDENTIFIER; ; index = 22 ; length = 6 line = 1 ; column = 22 ; value ='float3'; } +{kind = TOKEN_AT; ; index = 29 ; length = 1 line = 1 ; column = 29 ; value ='@'; } +{kind = TOKEN_IDENTIFIER; ; index = 30 ; length = 8 line = 1 ; column = 30 ; value ='position'; } +{kind = TOKEN_RIGHTPAREN; ; index = 38 ; length = 1 line = 1 ; column = 38 ; value =')'; } +{kind = TOKEN_ARROW; ; index = 40 ; length = 2 line = 1 ; column = 40 ; value ='->'; } +{kind = TOKEN_IDENTIFIER; ; index = 43 ; length = 6 line = 1 ; column = 43 ; value ='float4'; } +{kind = TOKEN_AT; ; index = 50 ; length = 1 line = 1 ; column = 50 ; value ='@'; } +{kind = TOKEN_IDENTIFIER; ; index = 51 ; length = 8 line = 1 ; column = 51 ; value ='position'; } +{kind = TOKEN_LEFTBRACE; ; index = 60 ; length = 1 line = 1 ; column = 60 ; value ='{'; } +{kind = TOKEN_IF; ; index = 64 ; length = 2 line = 2 ; column = 0 ; value ='if'; } +{kind = TOKEN_INTLITERAL; ; index = 67 ; length = 1 line = 2 ; column = 3 ; value ='0'; } +{kind = TOKEN_GREATER; ; index = 69 ; length = 1 line = 2 ; column = 5 ; value ='>'; } +{kind = TOKEN_INTLITERAL; ; index = 71 ; length = 3 line = 2 ; column = 7 ; value ='100'; } +{kind = TOKEN_LEFTBRACE; ; index = 75 ; length = 1 line = 2 ; column = 11 ; value ='{'; } +{kind = TOKEN_RETURN; ; index = 80 ; length = 6 line = 3 ; column = 0 ; value ='return'; } +{kind = TOKEN_IDENTIFIER; ; index = 87 ; length = 6 line = 3 ; column = 7 ; value ='float4'; } +{kind = TOKEN_LEFTPAREN; ; index = 93 ; length = 1 line = 3 ; column = 13 ; value ='('; } +{kind = TOKEN_IDENTIFIER; ; index = 94 ; length = 3 line = 3 ; column = 14 ; value ='pos'; } +{kind = TOKEN_COMMA; ; index = 97 ; length = 1 line = 3 ; column = 17 ; value =','; } +{kind = TOKEN_FLOATLITERAL; ; index = 99 ; length = 3 line = 3 ; column = 19 ; value ='1'; } +{kind = TOKEN_RIGHTPAREN; ; index = 102 ; length = 1 line = 3 ; column = 22 ; value =')'; } +{kind = TOKEN_SEMICOLON; ; index = 103 ; length = 1 line = 3 ; column = 23 ; value =';'; } +{kind = TOKEN_RIGHTBRACE; ; index = 107 ; length = 1 line = 4 ; column = 0 ; value ='}'; } +{kind = TOKEN_RETURN; ; index = 111 ; length = 6 line = 5 ; column = 0 ; value ='return'; } +{kind = TOKEN_IDENTIFIER; ; index = 118 ; length = 6 line = 5 ; column = 7 ; value ='float4'; } +{kind = TOKEN_LEFTPAREN; ; index = 124 ; length = 1 line = 5 ; column = 13 ; value ='('; } +{kind = TOKEN_FLOATLITERAL; ; index = 125 ; length = 3 line = 5 ; column = 14 ; value ='0'; } +{kind = TOKEN_RIGHTPAREN; ; index = 128 ; length = 1 line = 5 ; column = 17 ; value =')'; } +{kind = TOKEN_SEMICOLON; ; index = 129 ; length = 1 line = 5 ; column = 18 ; value =';'; } +{kind = TOKEN_RIGHTBRACE; ; index = 132 ; length = 1 line = 6 ; column = 0 ; value ='}'; } +{kind = TOKEN_EOF; ; index = 135 ; length = 0 line = 7 ; column = 0 ; value =''; } diff --git a/test/lex_all.suite b/test/lex_all.suite index 699b02d..b4e73d5 100644 --- a/test/lex_all.suite +++ b/test/lex_all.suite @@ -17,10 +17,14 @@ test/inferred_types.ink lex test/meta_block.ink lex test/multiple_functions.ink lex test/multiple_semicolons_everywhere.ink lex +test/non_bool_cond.ink lex test/pass_and_access_struct_fields_in_functions.ink lex test/passthrough.ink lex test/property_rename.ink lex test/redeclared_variable.ink lex +test/simple_else_if.ink lex +test/simple_if_else.ink lex +test/simple_if.ink lex test/simple_struct_access.ink lex test/struct_access_primitive_type.ink lex test/struct_within_struct.ink lex diff --git a/test/non_bool_cond.ink b/test/non_bool_cond.ink new file mode 100644 index 0000000..9ec6373 --- /dev/null +++ b/test/non_bool_cond.ink @@ -0,0 +1,6 @@ +vertex main :: (pos : float3 @position) -> float4 @position { + if 1.0 { + return float4(pos, 1.0); + } + return float4(0.0); +} diff --git a/test/parse/non_bool_cond.golden b/test/parse/non_bool_cond.golden new file mode 100644 index 0000000..19b9cad --- /dev/null +++ b/test/parse/non_bool_cond.golden @@ -0,0 +1,6 @@ +(program + (fun vertex vs_main -> float4 (@position) + [(:= pos float3 (@position))] + (if 1 + (return (float4 pos 1))) + (return (float4 0)))) \ No newline at end of file diff --git a/test/parse/simple_else_if.golden b/test/parse/simple_else_if.golden index fd3b76b..111f8a9 100644 --- a/test/parse/simple_else_if.golden +++ b/test/parse/simple_else_if.golden @@ -1,9 +1,9 @@ (program (fun vertex vs_main -> float4 (@position) - [(:= pos float3 (@position))] - (if (> pos.x 100) - (return (float4 pos 1)) - (if (> pos.x 50) - (return (float4 pos 1)) - (return (float4 1)))) - (return (float4 0)))) \ No newline at end of file + [(:= pos float3 (@position))] + (if (> pos.x 100) + (return (float4 pos 1)) + (if (> pos.x 50) + (return (float4 pos 1)) + (return (float4 1)))) + (return (float4 0)))) \ No newline at end of file diff --git a/test/parse/simple_if.golden b/test/parse/simple_if.golden new file mode 100644 index 0000000..3473f24 --- /dev/null +++ b/test/parse/simple_if.golden @@ -0,0 +1,6 @@ +(program + (fun vertex vs_main -> float4 (@position) + [(:= pos float3 (@position))] + (if (> 0 100) + (return (float4 pos 1))) + (return (float4 0)))) \ No newline at end of file diff --git a/test/parse/simple_if_else.golden b/test/parse/simple_if_else.golden new file mode 100644 index 0000000..ab5dcdf --- /dev/null +++ b/test/parse/simple_if_else.golden @@ -0,0 +1,7 @@ +(program + (fun vertex vs_main -> float4 (@position) + [(:= pos float3 (@position))] + (if (> 0 100) + (return (float4 pos 1)) + (return (float4 1))) + (return (float4 0)))) \ No newline at end of file diff --git a/test/parse_all.suite b/test/parse_all.suite index 9c9584c..30b4b93 100644 --- a/test/parse_all.suite +++ b/test/parse_all.suite @@ -17,10 +17,14 @@ test/inferred_types.ink parse test/meta_block.ink parse test/multiple_functions.ink parse test/multiple_semicolons_everywhere.ink parse +test/non_bool_cond.ink parse test/pass_and_access_struct_fields_in_functions.ink parse test/passthrough.ink parse test/property_rename.ink parse test/redeclared_variable.ink parse +test/simple_else_if.ink parse +test/simple_if_else.ink parse +test/simple_if.ink parse test/simple_struct_access.ink parse test/struct_access_primitive_type.ink parse test/struct_within_struct.ink parse diff --git a/test/semant/non_bool_cond.golden b/test/semant/non_bool_cond.golden new file mode 100644 index 0000000..87b2739 --- /dev/null +++ b/test/semant/non_bool_cond.golden @@ -0,0 +1,6 @@ +test/non_bool_cond.ink:0,0: error: Type of expression in if condition has to be bool. + if 1.0 + ^^^ + 1.0 has type float + + \ No newline at end of file diff --git a/test/semant_all.suite b/test/semant_all.suite index 7773b41..0108363 100644 --- a/test/semant_all.suite +++ b/test/semant_all.suite @@ -14,10 +14,14 @@ test/function_with_int_return.ink semant test/inferred_types.ink semant test/multiple_functions.ink semant test/multiple_semicolons_everywhere.ink semant +test/non_bool_cond.ink semant test/pass_and_access_struct_fields_in_functions.ink semant test/passthrough.ink semant test/property_rename.ink semant test/redeclared_variable.ink semant +test/simple_else_if.ink semant +test/simple_if_else.ink semant +test/simple_if.ink semant test/simple_struct_access.ink semant test/struct_access_primitive_type.ink semant test/struct_within_struct.ink semant From 45ea54cf9396b72fa2c36a4ee6613decca4195df Mon Sep 17 00:00:00 2001 From: Niels Bross Date: Sat, 18 Jan 2025 22:22:16 +0100 Subject: [PATCH 13/17] Fixed some error handling for invalid if statements. Started if codegen. --- AST.jai | 7 +- Codegen.jai | 20 ++++++ Parsing.jai | 81 +++++++++++++++++++--- Semantic_Analysis.jai | 6 +- test/else_if_after_else.ink | 10 +++ test/if_cond_assign.ink | 6 ++ test/if_if_if.ink | 6 ++ test/lex/else_if_after_else.golden | 39 +++++++++++ test/lex/float_if_cond.golden | 35 ++++++++++ test/lex/if_cond_assign.golden | 37 ++++++++++ test/lex/if_if_if.golden | 39 +++++++++++ test/lex_all.suite | 4 ++ test/parse/else_if_after_else.golden | 4 ++ test/parse/float_if_cond.golden | 6 ++ test/parse/if_cond_assign.golden | 6 ++ test/parse/if_if_if.golden | 4 ++ test/parse_all.suite | 4 ++ test/semant/float_if_cond.golden | 6 ++ test/semant/if_cond_assign.golden | 6 ++ test/semant/simple_if.golden | 6 ++ test/semant/simple_if_else.golden | 6 ++ test/semant/wrong_type_for_function.golden | 15 +++- test/semant_all.suite | 2 + 23 files changed, 344 insertions(+), 11 deletions(-) create mode 100644 test/else_if_after_else.ink create mode 100644 test/if_cond_assign.ink create mode 100644 test/if_if_if.ink create mode 100644 test/lex/else_if_after_else.golden create mode 100644 test/lex/float_if_cond.golden create mode 100644 test/lex/if_cond_assign.golden create mode 100644 test/lex/if_if_if.golden create mode 100644 test/parse/else_if_after_else.golden create mode 100644 test/parse/float_if_cond.golden create mode 100644 test/parse/if_cond_assign.golden create mode 100644 test/parse/if_if_if.golden create mode 100644 test/semant/float_if_cond.golden create mode 100644 test/semant/if_cond_assign.golden create mode 100644 test/semant/simple_if.golden create mode 100644 test/semant/simple_if_else.golden diff --git a/AST.jai b/AST.jai index 8abc868..f38c9dc 100644 --- a/AST.jai +++ b/AST.jai @@ -149,7 +149,12 @@ Children_Print_Flags :: enum_flags { } pretty_print_block :: (node : *AST_Node, indentation : int, builder : *String_Builder, skip_indent := false) { - pretty_print_children(node, indentation, builder, flags = .NewLine | .Dont_Skip_Indent_On_First); + if node.children.count == 0 { + indent(builder, indentation); + append(builder, "()"); + } else { + pretty_print_children(node, indentation, builder, flags = .NewLine | .Dont_Skip_Indent_On_First); + } } pretty_print_children :: (parent : *AST_Node, indentation : int, builder : *String_Builder, flags : Children_Print_Flags = .Separator, skip_indent := false) { diff --git a/Codegen.jai b/Codegen.jai index 8fe0512..e03eaea 100644 --- a/Codegen.jai +++ b/Codegen.jai @@ -374,6 +374,7 @@ emit_node :: (state : *Codegen_State, node : *AST_Node, indentation : int) { emit_field(state, node, indentation); } case .Block; { + assert(false, "Not implemented yet: block"); } case .Variable; { @@ -436,9 +437,28 @@ emit_node :: (state : *Codegen_State, node : *AST_Node, indentation : int) { append(*state.builder, "return "); emit_node(state, node.children[0], 0); } + case .If; { + indent(*state.builder, indentation); + append(*state.builder, "if "); + + cond := node.children[0]; + emit_node(state, cond, 0); + + body := node.children[1]; + emit_block(state, body, 0); + + if node.children.count == 2 { + emit_else(state, node.children[2]); + } + } } } +emit_else :: (state : *Codegen_State, node : *AST_Node) { + append(*state.builder, "else "); + emit_node(state, node.children[0], 0); +} + emit_field_list :: (state : *Codegen_State, field_list : *AST_Node, indentation : int) { for child : field_list.children { emit_node(state, child, 1); diff --git a/Parsing.jai b/Parsing.jai index b2503bb..aae0c36 100644 --- a/Parsing.jai +++ b/Parsing.jai @@ -213,6 +213,50 @@ unexpected_token :: (state : *Parse_State, token : Token, message : string) { record_error(state, token, final_message, false); } +else_if_without_if :: (state : *Parse_State) { + builder : String_Builder; + init_string_builder(*builder,, temp); + + append(*builder, "'else if' without 'if'\n"); + + token := state.previous; + + location : Source_Range = generate_source_location_from_token(state, token); + + indent(*builder, 1); + cyan(*builder); + print_to_builder(*builder, "%\n", print_from_source_location(location)); + + indent(*builder, 1); + print_token_pointer(*builder, token); + white(*builder); + + final_message := builder_to_string(*builder); + record_error(state, token, final_message, false); +} + +else_without_if :: (state : *Parse_State) { + builder : String_Builder; + init_string_builder(*builder,, temp); + + append(*builder, "'else' without 'if'\n"); + + token := state.previous; + + location : Source_Range = generate_source_location_from_token(state, token); + + indent(*builder, 1); + cyan(*builder); + print_to_builder(*builder, "%\n", print_from_source_location(location)); + + indent(*builder, 1); + print_token_pointer(*builder, token); + white(*builder); + + final_message := builder_to_string(*builder); + record_error(state, token, final_message, false); +} + expected_expression :: (state : *Parse_State, token : Token, message : string) { builder : String_Builder; init_string_builder(*builder,, temp); @@ -395,7 +439,10 @@ precedence :: (parse_state : *Parse_State, precedence : Precedence) -> *AST_Node prefix_rule := get_rule(parse_state.previous.kind).prefix; if prefix_rule == null { - expected_expression(parse_state, parse_state.current, "Expected expression."); + tok_s : string; + tok_s.data = parse_state.previous.source; + tok_s.count = parse_state.previous.length; + expected_expression(parse_state, parse_state.previous, tprint("Expected expression after '%'.", tok_s)); // @Incomplete: Add error node here? return error_node(parse_state, "Expected expression."); } @@ -405,7 +452,11 @@ precedence :: (parse_state : *Parse_State, precedence : Precedence) -> *AST_Node while precedence <= get_rule(parse_state.current.kind).precedence { advance(parse_state); if parse_state.current.kind == .TOKEN_EOF { - expected_expression(parse_state, parse_state.current, "Reached end of file. Expected expression."); + tok_s : string; + tok_s.data = parse_state.previous.source; + tok_s.count = parse_state.previous.length; + expected_expression(parse_state, parse_state.current, tprint("Reached end of file. Expected expression after '%'.", tok_s)); + // expected_expression(parse_state, parse_state.current, "Reached end of file. Expected expression."); // @Incomplete: Add error node here? return null; } @@ -791,15 +842,12 @@ statement :: (parse_state : *Parse_State) -> *AST_Node { source_location : Source_Range; source_location.begin = parse_state.previous; - if_expression := expression(parse_state); - add_child(node, if_expression); - // consume(parse_state, .TOKEN_LEFTBRACE, "Expect '{' after if-condition."); + if_cond := expression(parse_state); + add_child(node, if_cond); source_location.end = parse_state.previous; if_body := block(parse_state); - if if_body.children.count > 0 { - add_child(node, if_body); - } + add_child(node, if_body); if match(parse_state, .TOKEN_ELSE) { else_node := else_statement(parse_state); @@ -809,6 +857,23 @@ statement :: (parse_state : *Parse_State) -> *AST_Node { node.source_location = source_location; return node; + } else if match(parse_state, .TOKEN_ELSE) { + if check(parse_state, .TOKEN_IF) { + else_if_without_if(parse_state); + advance_to_sync_point(parse_state); + if check(parse_state, .TOKEN_LEFTBRACE) { + return block(parse_state); + } + return error_node(parse_state, "'else if' without 'if'."); + } else { + else_without_if(parse_state); + advance_to_sync_point(parse_state); + if check(parse_state, .TOKEN_LEFTBRACE) { + return block(parse_state); + } + + return error_node(parse_state, "'else' without 'if'."); + } } else { return expression_statement(parse_state); } diff --git a/Semantic_Analysis.jai b/Semantic_Analysis.jai index 61625e3..14e3f16 100644 --- a/Semantic_Analysis.jai +++ b/Semantic_Analysis.jai @@ -524,7 +524,11 @@ if_condition_has_to_be_boolean_type :: (checker : *Semantic_Checker, usage_site indent(*builder, 1); var := from_handle(checker, handle); - print_to_builder(*builder, "% has type %\n", print_from_source_location(*usage_site.children[0].source_location), proper_type_to_string(checker, var)); + + 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)); message := builder_to_string(*builder,, temp); record_error(checker, message, usage_site.source_location, false); diff --git a/test/else_if_after_else.ink b/test/else_if_after_else.ink new file mode 100644 index 0000000..be4360d --- /dev/null +++ b/test/else_if_after_else.ink @@ -0,0 +1,10 @@ +vertex main :: (pos : float3 @position) -> float4 @position { + if 0 > 100 { + + } else { + + } else if 0 > 200 { + + } + return float4(0.0); +} diff --git a/test/if_cond_assign.ink b/test/if_cond_assign.ink new file mode 100644 index 0000000..7baa0fa --- /dev/null +++ b/test/if_cond_assign.ink @@ -0,0 +1,6 @@ +vertex main :: (pos : float3 @position) -> float4 @position { + if 0 = 100 { + return float4(pos, 1.0); + } + return float4(0.0); +} diff --git a/test/if_if_if.ink b/test/if_if_if.ink new file mode 100644 index 0000000..71e196e --- /dev/null +++ b/test/if_if_if.ink @@ -0,0 +1,6 @@ +vertex main :: (pos : float3 @position) -> float4 @position { + if if if 0 > 100 { + return float4(pos, 1.0); + } + return float4(0.0); +} diff --git a/test/lex/else_if_after_else.golden b/test/lex/else_if_after_else.golden new file mode 100644 index 0000000..8e04b09 --- /dev/null +++ b/test/lex/else_if_after_else.golden @@ -0,0 +1,39 @@ +{kind = TOKEN_VERTEX; ; index = 0 ; length = 6 line = 1 ; column = 0 ; value ='vertex'; } +{kind = TOKEN_IDENTIFIER; ; index = 7 ; length = 4 line = 1 ; column = 7 ; value ='main'; } +{kind = TOKEN_DOUBLECOLON; ; index = 12 ; length = 2 line = 1 ; column = 12 ; value ='::'; } +{kind = TOKEN_LEFTPAREN; ; index = 15 ; length = 1 line = 1 ; column = 15 ; value ='('; } +{kind = TOKEN_IDENTIFIER; ; index = 16 ; length = 3 line = 1 ; column = 16 ; value ='pos'; } +{kind = TOKEN_COLON; ; index = 20 ; length = 1 line = 1 ; column = 20 ; value =':'; } +{kind = TOKEN_IDENTIFIER; ; index = 22 ; length = 6 line = 1 ; column = 22 ; value ='float3'; } +{kind = TOKEN_AT; ; index = 29 ; length = 1 line = 1 ; column = 29 ; value ='@'; } +{kind = TOKEN_IDENTIFIER; ; index = 30 ; length = 8 line = 1 ; column = 30 ; value ='position'; } +{kind = TOKEN_RIGHTPAREN; ; index = 38 ; length = 1 line = 1 ; column = 38 ; value =')'; } +{kind = TOKEN_ARROW; ; index = 40 ; length = 2 line = 1 ; column = 40 ; value ='->'; } +{kind = TOKEN_IDENTIFIER; ; index = 43 ; length = 6 line = 1 ; column = 43 ; value ='float4'; } +{kind = TOKEN_AT; ; index = 50 ; length = 1 line = 1 ; column = 50 ; value ='@'; } +{kind = TOKEN_IDENTIFIER; ; index = 51 ; length = 8 line = 1 ; column = 51 ; value ='position'; } +{kind = TOKEN_LEFTBRACE; ; index = 60 ; length = 1 line = 1 ; column = 60 ; value ='{'; } +{kind = TOKEN_IF; ; index = 64 ; length = 2 line = 2 ; column = 0 ; value ='if'; } +{kind = TOKEN_INTLITERAL; ; index = 67 ; length = 1 line = 2 ; column = 3 ; value ='0'; } +{kind = TOKEN_GREATER; ; index = 69 ; length = 1 line = 2 ; column = 5 ; value ='>'; } +{kind = TOKEN_INTLITERAL; ; index = 71 ; length = 3 line = 2 ; column = 7 ; value ='100'; } +{kind = TOKEN_LEFTBRACE; ; index = 75 ; length = 1 line = 2 ; column = 11 ; value ='{'; } +{kind = TOKEN_RIGHTBRACE; ; index = 83 ; length = 1 line = 4 ; column = 0 ; value ='}'; } +{kind = TOKEN_ELSE; ; index = 85 ; length = 4 line = 4 ; column = 2 ; value ='else'; } +{kind = TOKEN_LEFTBRACE; ; index = 90 ; length = 1 line = 4 ; column = 7 ; value ='{'; } +{kind = TOKEN_RIGHTBRACE; ; index = 99 ; length = 1 line = 6 ; column = 4 ; value ='}'; } +{kind = TOKEN_ELSE; ; index = 101 ; length = 4 line = 6 ; column = 6 ; value ='else'; } +{kind = TOKEN_IF; ; index = 106 ; length = 2 line = 6 ; column = 11 ; value ='if'; } +{kind = TOKEN_INTLITERAL; ; index = 109 ; length = 1 line = 6 ; column = 14 ; value ='0'; } +{kind = TOKEN_GREATER; ; index = 111 ; length = 1 line = 6 ; column = 16 ; value ='>'; } +{kind = TOKEN_INTLITERAL; ; index = 113 ; length = 3 line = 6 ; column = 18 ; value ='200'; } +{kind = TOKEN_LEFTBRACE; ; index = 117 ; length = 1 line = 6 ; column = 22 ; value ='{'; } +{kind = TOKEN_RIGHTBRACE; ; index = 123 ; length = 1 line = 8 ; column = 0 ; value ='}'; } +{kind = TOKEN_RETURN; ; index = 127 ; length = 6 line = 9 ; column = 0 ; value ='return'; } +{kind = TOKEN_IDENTIFIER; ; index = 134 ; length = 6 line = 9 ; column = 7 ; value ='float4'; } +{kind = TOKEN_LEFTPAREN; ; index = 140 ; length = 1 line = 9 ; column = 13 ; value ='('; } +{kind = TOKEN_FLOATLITERAL; ; index = 141 ; length = 3 line = 9 ; column = 14 ; value ='0'; } +{kind = TOKEN_RIGHTPAREN; ; index = 144 ; length = 1 line = 9 ; column = 17 ; value =')'; } +{kind = TOKEN_SEMICOLON; ; index = 145 ; length = 1 line = 9 ; column = 18 ; value =';'; } +{kind = TOKEN_RIGHTBRACE; ; index = 148 ; length = 1 line = 10 ; column = 0 ; value ='}'; } +{kind = TOKEN_EOF; ; index = 151 ; length = 0 line = 11 ; column = 0 ; value =''; } diff --git a/test/lex/float_if_cond.golden b/test/lex/float_if_cond.golden new file mode 100644 index 0000000..38f1583 --- /dev/null +++ b/test/lex/float_if_cond.golden @@ -0,0 +1,35 @@ +{kind = TOKEN_VERTEX; ; index = 0 ; length = 6 line = 1 ; column = 0 ; value ='vertex'; } +{kind = TOKEN_IDENTIFIER; ; index = 7 ; length = 4 line = 1 ; column = 7 ; value ='main'; } +{kind = TOKEN_DOUBLECOLON; ; index = 12 ; length = 2 line = 1 ; column = 12 ; value ='::'; } +{kind = TOKEN_LEFTPAREN; ; index = 15 ; length = 1 line = 1 ; column = 15 ; value ='('; } +{kind = TOKEN_IDENTIFIER; ; index = 16 ; length = 3 line = 1 ; column = 16 ; value ='pos'; } +{kind = TOKEN_COLON; ; index = 20 ; length = 1 line = 1 ; column = 20 ; value =':'; } +{kind = TOKEN_IDENTIFIER; ; index = 22 ; length = 6 line = 1 ; column = 22 ; value ='float3'; } +{kind = TOKEN_AT; ; index = 29 ; length = 1 line = 1 ; column = 29 ; value ='@'; } +{kind = TOKEN_IDENTIFIER; ; index = 30 ; length = 8 line = 1 ; column = 30 ; value ='position'; } +{kind = TOKEN_RIGHTPAREN; ; index = 38 ; length = 1 line = 1 ; column = 38 ; value =')'; } +{kind = TOKEN_ARROW; ; index = 40 ; length = 2 line = 1 ; column = 40 ; value ='->'; } +{kind = TOKEN_IDENTIFIER; ; index = 43 ; length = 6 line = 1 ; column = 43 ; value ='float4'; } +{kind = TOKEN_AT; ; index = 50 ; length = 1 line = 1 ; column = 50 ; value ='@'; } +{kind = TOKEN_IDENTIFIER; ; index = 51 ; length = 8 line = 1 ; column = 51 ; value ='position'; } +{kind = TOKEN_LEFTBRACE; ; index = 60 ; length = 1 line = 1 ; column = 60 ; value ='{'; } +{kind = TOKEN_IF; ; index = 64 ; length = 2 line = 2 ; column = 0 ; value ='if'; } +{kind = TOKEN_FLOATLITERAL; ; index = 67 ; length = 3 line = 2 ; column = 3 ; value ='1'; } +{kind = TOKEN_LEFTBRACE; ; index = 71 ; length = 1 line = 2 ; column = 7 ; value ='{'; } +{kind = TOKEN_RETURN; ; index = 76 ; length = 6 line = 3 ; column = 0 ; value ='return'; } +{kind = TOKEN_IDENTIFIER; ; index = 83 ; length = 6 line = 3 ; column = 7 ; value ='float4'; } +{kind = TOKEN_LEFTPAREN; ; index = 89 ; length = 1 line = 3 ; column = 13 ; value ='('; } +{kind = TOKEN_IDENTIFIER; ; index = 90 ; length = 3 line = 3 ; column = 14 ; value ='pos'; } +{kind = TOKEN_COMMA; ; index = 93 ; length = 1 line = 3 ; column = 17 ; value =','; } +{kind = TOKEN_FLOATLITERAL; ; index = 95 ; length = 3 line = 3 ; column = 19 ; value ='1'; } +{kind = TOKEN_RIGHTPAREN; ; index = 98 ; length = 1 line = 3 ; column = 22 ; value =')'; } +{kind = TOKEN_SEMICOLON; ; index = 99 ; length = 1 line = 3 ; column = 23 ; value =';'; } +{kind = TOKEN_RIGHTBRACE; ; index = 103 ; length = 1 line = 4 ; column = 0 ; value ='}'; } +{kind = TOKEN_RETURN; ; index = 107 ; length = 6 line = 5 ; column = 0 ; value ='return'; } +{kind = TOKEN_IDENTIFIER; ; index = 114 ; length = 6 line = 5 ; column = 7 ; value ='float4'; } +{kind = TOKEN_LEFTPAREN; ; index = 120 ; length = 1 line = 5 ; column = 13 ; value ='('; } +{kind = TOKEN_FLOATLITERAL; ; index = 121 ; length = 3 line = 5 ; column = 14 ; value ='0'; } +{kind = TOKEN_RIGHTPAREN; ; index = 124 ; length = 1 line = 5 ; column = 17 ; value =')'; } +{kind = TOKEN_SEMICOLON; ; index = 125 ; length = 1 line = 5 ; column = 18 ; value =';'; } +{kind = TOKEN_RIGHTBRACE; ; index = 128 ; length = 1 line = 6 ; column = 0 ; value ='}'; } +{kind = TOKEN_EOF; ; index = 131 ; length = 0 line = 7 ; column = 0 ; value =''; } diff --git a/test/lex/if_cond_assign.golden b/test/lex/if_cond_assign.golden new file mode 100644 index 0000000..be22abf --- /dev/null +++ b/test/lex/if_cond_assign.golden @@ -0,0 +1,37 @@ +{kind = TOKEN_VERTEX; ; index = 0 ; length = 6 line = 1 ; column = 0 ; value ='vertex'; } +{kind = TOKEN_IDENTIFIER; ; index = 7 ; length = 4 line = 1 ; column = 7 ; value ='main'; } +{kind = TOKEN_DOUBLECOLON; ; index = 12 ; length = 2 line = 1 ; column = 12 ; value ='::'; } +{kind = TOKEN_LEFTPAREN; ; index = 15 ; length = 1 line = 1 ; column = 15 ; value ='('; } +{kind = TOKEN_IDENTIFIER; ; index = 16 ; length = 3 line = 1 ; column = 16 ; value ='pos'; } +{kind = TOKEN_COLON; ; index = 20 ; length = 1 line = 1 ; column = 20 ; value =':'; } +{kind = TOKEN_IDENTIFIER; ; index = 22 ; length = 6 line = 1 ; column = 22 ; value ='float3'; } +{kind = TOKEN_AT; ; index = 29 ; length = 1 line = 1 ; column = 29 ; value ='@'; } +{kind = TOKEN_IDENTIFIER; ; index = 30 ; length = 8 line = 1 ; column = 30 ; value ='position'; } +{kind = TOKEN_RIGHTPAREN; ; index = 38 ; length = 1 line = 1 ; column = 38 ; value =')'; } +{kind = TOKEN_ARROW; ; index = 40 ; length = 2 line = 1 ; column = 40 ; value ='->'; } +{kind = TOKEN_IDENTIFIER; ; index = 43 ; length = 6 line = 1 ; column = 43 ; value ='float4'; } +{kind = TOKEN_AT; ; index = 50 ; length = 1 line = 1 ; column = 50 ; value ='@'; } +{kind = TOKEN_IDENTIFIER; ; index = 51 ; length = 8 line = 1 ; column = 51 ; value ='position'; } +{kind = TOKEN_LEFTBRACE; ; index = 60 ; length = 1 line = 1 ; column = 60 ; value ='{'; } +{kind = TOKEN_IF; ; index = 64 ; length = 2 line = 2 ; column = 0 ; value ='if'; } +{kind = TOKEN_INTLITERAL; ; index = 67 ; length = 1 line = 2 ; column = 3 ; value ='0'; } +{kind = TOKEN_ASSIGN; ; index = 69 ; length = 1 line = 2 ; column = 5 ; value ='='; } +{kind = TOKEN_INTLITERAL; ; index = 71 ; length = 3 line = 2 ; column = 7 ; value ='100'; } +{kind = TOKEN_LEFTBRACE; ; index = 75 ; length = 1 line = 2 ; column = 11 ; value ='{'; } +{kind = TOKEN_RETURN; ; index = 80 ; length = 6 line = 3 ; column = 0 ; value ='return'; } +{kind = TOKEN_IDENTIFIER; ; index = 87 ; length = 6 line = 3 ; column = 7 ; value ='float4'; } +{kind = TOKEN_LEFTPAREN; ; index = 93 ; length = 1 line = 3 ; column = 13 ; value ='('; } +{kind = TOKEN_IDENTIFIER; ; index = 94 ; length = 3 line = 3 ; column = 14 ; value ='pos'; } +{kind = TOKEN_COMMA; ; index = 97 ; length = 1 line = 3 ; column = 17 ; value =','; } +{kind = TOKEN_FLOATLITERAL; ; index = 99 ; length = 3 line = 3 ; column = 19 ; value ='1'; } +{kind = TOKEN_RIGHTPAREN; ; index = 102 ; length = 1 line = 3 ; column = 22 ; value =')'; } +{kind = TOKEN_SEMICOLON; ; index = 103 ; length = 1 line = 3 ; column = 23 ; value =';'; } +{kind = TOKEN_RIGHTBRACE; ; index = 107 ; length = 1 line = 4 ; column = 0 ; value ='}'; } +{kind = TOKEN_RETURN; ; index = 111 ; length = 6 line = 5 ; column = 0 ; value ='return'; } +{kind = TOKEN_IDENTIFIER; ; index = 118 ; length = 6 line = 5 ; column = 7 ; value ='float4'; } +{kind = TOKEN_LEFTPAREN; ; index = 124 ; length = 1 line = 5 ; column = 13 ; value ='('; } +{kind = TOKEN_FLOATLITERAL; ; index = 125 ; length = 3 line = 5 ; column = 14 ; value ='0'; } +{kind = TOKEN_RIGHTPAREN; ; index = 128 ; length = 1 line = 5 ; column = 17 ; value =')'; } +{kind = TOKEN_SEMICOLON; ; index = 129 ; length = 1 line = 5 ; column = 18 ; value =';'; } +{kind = TOKEN_RIGHTBRACE; ; index = 132 ; length = 1 line = 6 ; column = 0 ; value ='}'; } +{kind = TOKEN_EOF; ; index = 135 ; length = 0 line = 7 ; column = 0 ; value =''; } diff --git a/test/lex/if_if_if.golden b/test/lex/if_if_if.golden new file mode 100644 index 0000000..476a91c --- /dev/null +++ b/test/lex/if_if_if.golden @@ -0,0 +1,39 @@ +{kind = TOKEN_VERTEX; ; index = 0 ; length = 6 line = 1 ; column = 0 ; value ='vertex'; } +{kind = TOKEN_IDENTIFIER; ; index = 7 ; length = 4 line = 1 ; column = 7 ; value ='main'; } +{kind = TOKEN_DOUBLECOLON; ; index = 12 ; length = 2 line = 1 ; column = 12 ; value ='::'; } +{kind = TOKEN_LEFTPAREN; ; index = 15 ; length = 1 line = 1 ; column = 15 ; value ='('; } +{kind = TOKEN_IDENTIFIER; ; index = 16 ; length = 3 line = 1 ; column = 16 ; value ='pos'; } +{kind = TOKEN_COLON; ; index = 20 ; length = 1 line = 1 ; column = 20 ; value =':'; } +{kind = TOKEN_IDENTIFIER; ; index = 22 ; length = 6 line = 1 ; column = 22 ; value ='float3'; } +{kind = TOKEN_AT; ; index = 29 ; length = 1 line = 1 ; column = 29 ; value ='@'; } +{kind = TOKEN_IDENTIFIER; ; index = 30 ; length = 8 line = 1 ; column = 30 ; value ='position'; } +{kind = TOKEN_RIGHTPAREN; ; index = 38 ; length = 1 line = 1 ; column = 38 ; value =')'; } +{kind = TOKEN_ARROW; ; index = 40 ; length = 2 line = 1 ; column = 40 ; value ='->'; } +{kind = TOKEN_IDENTIFIER; ; index = 43 ; length = 6 line = 1 ; column = 43 ; value ='float4'; } +{kind = TOKEN_AT; ; index = 50 ; length = 1 line = 1 ; column = 50 ; value ='@'; } +{kind = TOKEN_IDENTIFIER; ; index = 51 ; length = 8 line = 1 ; column = 51 ; value ='position'; } +{kind = TOKEN_LEFTBRACE; ; index = 60 ; length = 1 line = 1 ; column = 60 ; value ='{'; } +{kind = TOKEN_IF; ; index = 64 ; length = 2 line = 2 ; column = 0 ; value ='if'; } +{kind = TOKEN_IF; ; index = 67 ; length = 2 line = 2 ; column = 3 ; value ='if'; } +{kind = TOKEN_IF; ; index = 70 ; length = 2 line = 2 ; column = 6 ; value ='if'; } +{kind = TOKEN_INTLITERAL; ; index = 73 ; length = 1 line = 2 ; column = 9 ; value ='0'; } +{kind = TOKEN_GREATER; ; index = 75 ; length = 1 line = 2 ; column = 11 ; value ='>'; } +{kind = TOKEN_INTLITERAL; ; index = 77 ; length = 3 line = 2 ; column = 13 ; value ='100'; } +{kind = TOKEN_LEFTBRACE; ; index = 81 ; length = 1 line = 2 ; column = 17 ; value ='{'; } +{kind = TOKEN_RETURN; ; index = 86 ; length = 6 line = 3 ; column = 0 ; value ='return'; } +{kind = TOKEN_IDENTIFIER; ; index = 93 ; length = 6 line = 3 ; column = 7 ; value ='float4'; } +{kind = TOKEN_LEFTPAREN; ; index = 99 ; length = 1 line = 3 ; column = 13 ; value ='('; } +{kind = TOKEN_IDENTIFIER; ; index = 100 ; length = 3 line = 3 ; column = 14 ; value ='pos'; } +{kind = TOKEN_COMMA; ; index = 103 ; length = 1 line = 3 ; column = 17 ; value =','; } +{kind = TOKEN_FLOATLITERAL; ; index = 105 ; length = 3 line = 3 ; column = 19 ; value ='1'; } +{kind = TOKEN_RIGHTPAREN; ; index = 108 ; length = 1 line = 3 ; column = 22 ; value =')'; } +{kind = TOKEN_SEMICOLON; ; index = 109 ; length = 1 line = 3 ; column = 23 ; value =';'; } +{kind = TOKEN_RIGHTBRACE; ; index = 113 ; length = 1 line = 4 ; column = 0 ; value ='}'; } +{kind = TOKEN_RETURN; ; index = 117 ; length = 6 line = 5 ; column = 0 ; value ='return'; } +{kind = TOKEN_IDENTIFIER; ; index = 124 ; length = 6 line = 5 ; column = 7 ; value ='float4'; } +{kind = TOKEN_LEFTPAREN; ; index = 130 ; length = 1 line = 5 ; column = 13 ; value ='('; } +{kind = TOKEN_FLOATLITERAL; ; index = 131 ; length = 3 line = 5 ; column = 14 ; value ='0'; } +{kind = TOKEN_RIGHTPAREN; ; index = 134 ; length = 1 line = 5 ; column = 17 ; value =')'; } +{kind = TOKEN_SEMICOLON; ; index = 135 ; length = 1 line = 5 ; column = 18 ; value =';'; } +{kind = TOKEN_RIGHTBRACE; ; index = 138 ; length = 1 line = 6 ; column = 0 ; value ='}'; } +{kind = TOKEN_EOF; ; index = 141 ; length = 0 line = 7 ; column = 0 ; value =''; } diff --git a/test/lex_all.suite b/test/lex_all.suite index b4e73d5..26a696d 100644 --- a/test/lex_all.suite +++ b/test/lex_all.suite @@ -2,17 +2,21 @@ test/assign_arithmetic_expression.ink lex test/basic_property_and_return_value.ink lex test/complicated_computation.ink lex test/constant_buffer.ink lex +test/else_if_after_else.ink lex test/empty_struct.ink lex test/empty_vertex_main.ink lex test/empty_vertex_main_with_position_parameter.ink lex test/field_assignment.ink lex test/field_without_type_specifier.ink lex test/float_suffix.ink lex +test/float_if_cond.ink lex test/function_call.ink lex test/function_call_out_of_order_declaration.ink lex test/function_call_return.ink lex test/functions_with_same_name.ink lex test/function_with_int_return.ink lex +test/if_cond_assign.ink lex +test/if_if_if.ink lex test/inferred_types.ink lex test/meta_block.ink lex test/multiple_functions.ink lex diff --git a/test/parse/else_if_after_else.golden b/test/parse/else_if_after_else.golden new file mode 100644 index 0000000..e7796d4 --- /dev/null +++ b/test/parse/else_if_after_else.golden @@ -0,0 +1,4 @@ +test/else_if_after_else.ink:6,6: error: 'else if' without 'if' +  } else if 0 > 200 { + ^^^^ + \ No newline at end of file diff --git a/test/parse/float_if_cond.golden b/test/parse/float_if_cond.golden new file mode 100644 index 0000000..19b9cad --- /dev/null +++ b/test/parse/float_if_cond.golden @@ -0,0 +1,6 @@ +(program + (fun vertex vs_main -> float4 (@position) + [(:= pos float3 (@position))] + (if 1 + (return (float4 pos 1))) + (return (float4 0)))) \ No newline at end of file diff --git a/test/parse/if_cond_assign.golden b/test/parse/if_cond_assign.golden new file mode 100644 index 0000000..508188f --- /dev/null +++ b/test/parse/if_cond_assign.golden @@ -0,0 +1,6 @@ +(program + (fun vertex vs_main -> float4 (@position) + [(:= pos float3 (@position))] + (if (= 0 100) + (return (float4 pos 1))) + (return (float4 0)))) \ No newline at end of file diff --git a/test/parse/if_if_if.golden b/test/parse/if_if_if.golden new file mode 100644 index 0000000..c63be74 --- /dev/null +++ b/test/parse/if_if_if.golden @@ -0,0 +1,4 @@ +test/if_if_if.ink:2,3: error: Expected expression after 'if'. + if if if 0 > 100 { + ^^ + \ No newline at end of file diff --git a/test/parse_all.suite b/test/parse_all.suite index 30b4b93..f43cd0e 100644 --- a/test/parse_all.suite +++ b/test/parse_all.suite @@ -2,17 +2,21 @@ test/assign_arithmetic_expression.ink parse test/basic_property_and_return_value.ink parse test/complicated_computation.ink parse test/constant_buffer.ink parse +test/else_if_after_else.ink parse test/empty_struct.ink parse test/empty_vertex_main.ink parse test/empty_vertex_main_with_position_parameter.ink parse test/field_assignment.ink parse test/field_without_type_specifier.ink parse +test/float_if_cond.ink parse test/float_suffix.ink parse test/function_call.ink parse test/function_call_out_of_order_declaration.ink parse test/function_call_return.ink parse test/functions_with_same_name.ink parse test/function_with_int_return.ink parse +test/if_cond_assign.ink parse +test/if_if_if.ink parse test/inferred_types.ink parse test/meta_block.ink parse test/multiple_functions.ink parse diff --git a/test/semant/float_if_cond.golden b/test/semant/float_if_cond.golden new file mode 100644 index 0000000..3cdaf2b --- /dev/null +++ b/test/semant/float_if_cond.golden @@ -0,0 +1,6 @@ +test/float_if_cond.ink:0,0: error: Type of expression in if condition has to be bool. + if 1.0 + ^^^ + 1.0 has type float + + \ No newline at end of file diff --git a/test/semant/if_cond_assign.golden b/test/semant/if_cond_assign.golden new file mode 100644 index 0000000..2fa9f46 --- /dev/null +++ b/test/semant/if_cond_assign.golden @@ -0,0 +1,6 @@ +test/if_cond_assign.ink:0,0: error: Type of expression in if condition has to be bool. + if 0 = 100 + ^^^^^^ + if 0 = 100 { has type int + + \ No newline at end of file diff --git a/test/semant/simple_if.golden b/test/semant/simple_if.golden new file mode 100644 index 0000000..7d9b85d --- /dev/null +++ b/test/semant/simple_if.golden @@ -0,0 +1,6 @@ +scope (global) [ + [vertex__vs_main] : (pos : float3) -> float4 + scope (vertex__vs_main) [ + [pos] : float3 + ] +] diff --git a/test/semant/simple_if_else.golden b/test/semant/simple_if_else.golden new file mode 100644 index 0000000..7d9b85d --- /dev/null +++ b/test/semant/simple_if_else.golden @@ -0,0 +1,6 @@ +scope (global) [ + [vertex__vs_main] : (pos : float3) -> float4 + scope (vertex__vs_main) [ + [pos] : float3 + ] +] diff --git a/test/semant/wrong_type_for_function.golden b/test/semant/wrong_type_for_function.golden index 7f42213..f9d22c8 100644 --- a/test/semant/wrong_type_for_function.golden +++ b/test/semant/wrong_type_for_function.golden @@ -7,7 +7,20 @@  color : float4 = float4(y, 1.0, 1.0, 1.0); ^  Possible overloads: - foreign float4 :: (float, float, float, float) -> float4; (test/wrong_type_for_function.ink:78) + foreign float4 :: (float, float, float, float) -> float4; (test/wrong_type_for_function.ink:86) + foreign float4 :: (float4) -> float4; (test/wrong_type_for_function.ink:87) + foreign float4 :: (float2, float2) -> float4; (test/wrong_type_for_function.ink:88) + foreign float4 :: (float2, float, float) -> float4; (test/wrong_type_for_function.ink:89) + foreign float4 :: (float, float2, float) -> float4; (test/wrong_type_for_function.ink:90) + foreign float4 :: (float, float2, float) -> float4; (test/wrong_type_for_function.ink:90) + foreign float4 :: (float, float, float2) -> float4; (test/wrong_type_for_function.ink:91) + foreign float4 :: (float, float, float2) -> float4; (test/wrong_type_for_function.ink:91) + foreign float4 :: (float3, float) -> float4; (test/wrong_type_for_function.ink:92) + foreign float4 :: (float3, float) -> float4; (test/wrong_type_for_function.ink:92) + foreign float4 :: (float, float3) -> float4; (test/wrong_type_for_function.ink:93) + foreign float4 :: (float, float3) -> float4; (test/wrong_type_for_function.ink:93) + foreign float4 :: (float) -> float4; (test/wrong_type_for_function.ink:94) + foreign float4 :: (float) -> float4; (test/wrong_type_for_function.ink:94) test/wrong_type_for_function.ink:11,24: error: Type mismatch. Expected float got float2  found: diff --git a/test/semant_all.suite b/test/semant_all.suite index 0108363..d0bd7b9 100644 --- a/test/semant_all.suite +++ b/test/semant_all.suite @@ -1,3 +1,4 @@ + test/assign_arithmetic_expression.ink semant test/basic_property_and_return_value.ink semant test/complicated_computation.ink semant @@ -11,6 +12,7 @@ test/function_call_out_of_order_declaration.ink semant test/function_call_return.ink semant test/functions_with_same_name.ink semant test/function_with_int_return.ink semant +test/if_cond_assign.ink semant test/inferred_types.ink semant test/multiple_functions.ink semant test/multiple_semicolons_everywhere.ink semant From 42c5baa8464bfc79ff3c21bb2e23b948bb0c1de3 Mon Sep 17 00:00:00 2001 From: Niels Bross Date: Mon, 20 Jan 2025 22:20:47 +0100 Subject: [PATCH 14/17] if else if else if if else if else --- Codegen.jai | 74 +++++++++++++++++++++++++----- Semantic_Analysis.jai | 6 +++ test/codegen/nested_if.golden | 18 ++++++++ test/codegen/simple_else_if.golden | 17 +++++++ test/codegen/simple_if.golden | 10 ++++ test/codegen/simple_if_else.golden | 13 ++++++ test/codegen_all.suite | 1 + test/lex/nested_if.golden | 64 ++++++++++++++++++++++++++ test/lex_all.suite | 1 + test/nested_if.ink | 11 +++++ test/parse/nested_if.golden | 9 ++++ test/parse_all.suite | 1 + test/semant/nested_if.golden | 6 +++ test/semant_all.suite | 1 + 14 files changed, 220 insertions(+), 12 deletions(-) create mode 100644 test/codegen/nested_if.golden create mode 100644 test/codegen/simple_else_if.golden create mode 100644 test/codegen/simple_if.golden create mode 100644 test/codegen/simple_if_else.golden create mode 100644 test/lex/nested_if.golden create mode 100644 test/nested_if.ink create mode 100644 test/parse/nested_if.golden create mode 100644 test/semant/nested_if.golden diff --git a/Codegen.jai b/Codegen.jai index e03eaea..5a980a7 100644 --- a/Codegen.jai +++ b/Codegen.jai @@ -37,6 +37,25 @@ Codegen_Result :: struct { result_text : string; // @Incomplete(nb): Result for now, should likely be far more sophisticated. } +Reserved_HLSL_Words :: string.[ + "texture", + "sampler", + "matrix", + "line", + "precise", + "shared", + "triangle", + "triangleadj", +]; + +Reserved_MLSL_Words :: string.[ + "" +]; + +Reserved_GLSL_Words :: string.[ + "" +]; + init_codegen_state :: (state : *Codegen_State, root : *AST_Node, checker_result : Semantic_Check_Result, output_language : Output_Language) { state.root = root; state.scope_stack = checker_result.scope_stack; @@ -50,7 +69,7 @@ indent :: (state : *Codegen_State, indentation : int) { for 1..indentation append(*state.builder, " "); } -dx11_type_to_string :: (type_variable : Type_Variable) -> string { +hlsl_type_to_string :: (type_variable : Type_Variable) -> string { if type_variable.type == { case .Invalid; return "{{invalid}}"; @@ -92,7 +111,7 @@ emit_field :: (state : *Codegen_State, node : *AST_Node, indentation : int) { indent(state, indentation); - print_to_builder(*state.builder, "% ", dx11_type_to_string(field)); + print_to_builder(*state.builder, "% ", hlsl_type_to_string(field)); if field.struct_field_parent { parent_tv := from_handle(state.type_variables, field.struct_field_parent.type_variable); @@ -111,13 +130,19 @@ emit_field :: (state : *Codegen_State, node : *AST_Node, indentation : int) { print_to_builder(*state.builder, " : register(t%)", field.resource_index); } - for i :0..node.children.count - 1 { - child := node.children[i]; + if node.children.count == 1 { + child := node.children[0]; print_to_builder(*state.builder, " = "); emit_node(state, child, 0); + } + if node.parent.kind == .Block { + append(*state.builder, ";"); + } + + for i :0..field.children.count - 1 { child := from_handle(state.type_variables, field.children[i]); emit_node(state, child.source_node, 0); @@ -140,7 +165,7 @@ emit_block :: (state : *Codegen_State, node : *AST_Node, indentation : int) { emit_node(state, statement, indentation); if it_index < node.children.count { - append(*state.builder, ";\n"); + append(*state.builder, "\n"); } } } @@ -256,7 +281,7 @@ emit_function :: (state : *Codegen_State, node : *AST_Node, indentation : int, e if function_variable.return_type_variable { return_variable := from_handle(state.type_variables, function_variable.return_type_variable); - print_to_builder(*state.builder, "% ", dx11_type_to_string(return_variable)); + print_to_builder(*state.builder, "% ", hlsl_type_to_string(return_variable)); } else { append(*state.builder, "void "); } @@ -428,6 +453,7 @@ emit_node :: (state : *Codegen_State, node : *AST_Node, indentation : int) { } case .Expression_Statement; { emit_node(state, node.children[0], indentation); + append(*state.builder, ";"); } case .Call; { emit_call(state, node, indentation); @@ -436,27 +462,51 @@ emit_node :: (state : *Codegen_State, node : *AST_Node, indentation : int) { indent(*state.builder, indentation); append(*state.builder, "return "); emit_node(state, node.children[0], 0); + append(*state.builder, ";"); } case .If; { - indent(*state.builder, indentation); + if node.parent.kind != .If { + indent(*state.builder, indentation); + } + append(*state.builder, "if "); cond := node.children[0]; emit_node(state, cond, 0); body := node.children[1]; - emit_block(state, body, 0); + append(*state.builder, "\n"); + indent(*state.builder, indentation); + append(*state.builder, "{\n"); - if node.children.count == 2 { - emit_else(state, node.children[2]); + emit_block(state, body, indentation + 1); + + indent(*state.builder, indentation); + append(*state.builder, "}\n"); + + if node.children.count == 3 { + emit_else(state, node.children[2], indentation); } } } } -emit_else :: (state : *Codegen_State, node : *AST_Node) { +emit_else :: (state : *Codegen_State, node : *AST_Node, indentation : int) { + indent(*state.builder, indentation); append(*state.builder, "else "); - emit_node(state, node.children[0], 0); + + if node.kind == .If { + emit_node(state, node, indentation); + } else if node.kind == .Block { + append(*state.builder, "\n"); + indent(*state.builder, indentation); + append(*state.builder, "{\n"); + + emit_block(state, node, indentation + 1); + + indent(*state.builder, indentation); + append(*state.builder, "}"); + } } emit_field_list :: (state : *Codegen_State, field_list : *AST_Node, indentation : int) { diff --git a/Semantic_Analysis.jai b/Semantic_Analysis.jai index 14e3f16..b515ae5 100644 --- a/Semantic_Analysis.jai +++ b/Semantic_Analysis.jai @@ -1502,6 +1502,12 @@ check_node :: (checker : *Semantic_Checker, node : *AST_Node) -> Type_Variable_H if_condition_has_to_be_boolean_type(checker, node, cond_var); } } + + body_var := check_block(checker, node.children[1]); + + if node.children.count == 3 { + else_var := check_node(checker, node.children[2]); + } } case .Variable; { return create_variable(checker, node); diff --git a/test/codegen/nested_if.golden b/test/codegen/nested_if.golden new file mode 100644 index 0000000..828f34e --- /dev/null +++ b/test/codegen/nested_if.golden @@ -0,0 +1,18 @@ +float4 vs_main(float3 pos : POSITION) : SV_POSITION +{ + if (pos.x > 100) + { + if (pos.x > 50) + { + return float4(pos, 1.0f); + } + else + { + return float4(1.0f); + } + return float4(pos, 1.0f); + } + + return float4(0.0f); +} + diff --git a/test/codegen/simple_else_if.golden b/test/codegen/simple_else_if.golden new file mode 100644 index 0000000..c9197f6 --- /dev/null +++ b/test/codegen/simple_else_if.golden @@ -0,0 +1,17 @@ +float4 vs_main(float3 pos : POSITION) : SV_POSITION +{ + if (pos.x > 100) + { + return float4(pos, 1.0f); + } + else if (pos.x > 50) + { + return float4(pos, 1.0f); + } + else + { + return float4(1.0f); + } + return float4(0.0f); +} + diff --git a/test/codegen/simple_if.golden b/test/codegen/simple_if.golden new file mode 100644 index 0000000..05588f3 --- /dev/null +++ b/test/codegen/simple_if.golden @@ -0,0 +1,10 @@ +float4 vs_main(float3 pos : POSITION) : SV_POSITION +{ + if (0 > 100) + { + return float4(pos, 1.0f); + } + + return float4(0.0f); +} + diff --git a/test/codegen/simple_if_else.golden b/test/codegen/simple_if_else.golden new file mode 100644 index 0000000..a59b39f --- /dev/null +++ b/test/codegen/simple_if_else.golden @@ -0,0 +1,13 @@ +float4 vs_main(float3 pos : POSITION) : SV_POSITION +{ + if (0 > 100) + { + return float4(pos, 1.0f); + } + else + { + return float4(1.0f); + } + return float4(0.0f); +} + diff --git a/test/codegen_all.suite b/test/codegen_all.suite index 1dd698b..3108a84 100644 --- a/test/codegen_all.suite +++ b/test/codegen_all.suite @@ -13,6 +13,7 @@ test/inferred_types.ink codegen test/meta_block.ink codegen test/multiple_functions.ink codegen test/multiple_semicolons_everywhere.ink codegen +test/nested_if.ink codegen test/pass_and_access_struct_fields_in_functions.ink codegen test/passthrough.ink codegen test/property_rename.ink codegen diff --git a/test/lex/nested_if.golden b/test/lex/nested_if.golden new file mode 100644 index 0000000..8a8e101 --- /dev/null +++ b/test/lex/nested_if.golden @@ -0,0 +1,64 @@ +{kind = TOKEN_VERTEX; ; index = 0 ; length = 6 line = 1 ; column = 0 ; value ='vertex'; } +{kind = TOKEN_IDENTIFIER; ; index = 7 ; length = 4 line = 1 ; column = 7 ; value ='main'; } +{kind = TOKEN_DOUBLECOLON; ; index = 12 ; length = 2 line = 1 ; column = 12 ; value ='::'; } +{kind = TOKEN_LEFTPAREN; ; index = 15 ; length = 1 line = 1 ; column = 15 ; value ='('; } +{kind = TOKEN_IDENTIFIER; ; index = 16 ; length = 3 line = 1 ; column = 16 ; value ='pos'; } +{kind = TOKEN_COLON; ; index = 20 ; length = 1 line = 1 ; column = 20 ; value =':'; } +{kind = TOKEN_IDENTIFIER; ; index = 22 ; length = 6 line = 1 ; column = 22 ; value ='float3'; } +{kind = TOKEN_AT; ; index = 29 ; length = 1 line = 1 ; column = 29 ; value ='@'; } +{kind = TOKEN_IDENTIFIER; ; index = 30 ; length = 8 line = 1 ; column = 30 ; value ='position'; } +{kind = TOKEN_RIGHTPAREN; ; index = 38 ; length = 1 line = 1 ; column = 38 ; value =')'; } +{kind = TOKEN_ARROW; ; index = 40 ; length = 2 line = 1 ; column = 40 ; value ='->'; } +{kind = TOKEN_IDENTIFIER; ; index = 43 ; length = 6 line = 1 ; column = 43 ; value ='float4'; } +{kind = TOKEN_AT; ; index = 50 ; length = 1 line = 1 ; column = 50 ; value ='@'; } +{kind = TOKEN_IDENTIFIER; ; index = 51 ; length = 8 line = 1 ; column = 51 ; value ='position'; } +{kind = TOKEN_LEFTBRACE; ; index = 60 ; length = 1 line = 1 ; column = 60 ; value ='{'; } +{kind = TOKEN_IF; ; index = 64 ; length = 2 line = 2 ; column = 0 ; value ='if'; } +{kind = TOKEN_IDENTIFIER; ; index = 67 ; length = 3 line = 2 ; column = 3 ; value ='pos'; } +{kind = TOKEN_DOT; ; index = 70 ; length = 1 line = 2 ; column = 6 ; value ='.'; } +{kind = TOKEN_IDENTIFIER; ; index = 71 ; length = 1 line = 2 ; column = 7 ; value ='x'; } +{kind = TOKEN_GREATER; ; index = 73 ; length = 1 line = 2 ; column = 9 ; value ='>'; } +{kind = TOKEN_INTLITERAL; ; index = 75 ; length = 3 line = 2 ; column = 11 ; value ='100'; } +{kind = TOKEN_LEFTBRACE; ; index = 79 ; length = 1 line = 2 ; column = 15 ; value ='{'; } +{kind = TOKEN_IF; ; index = 84 ; length = 2 line = 3 ; column = 0 ; value ='if'; } +{kind = TOKEN_IDENTIFIER; ; index = 87 ; length = 3 line = 3 ; column = 3 ; value ='pos'; } +{kind = TOKEN_DOT; ; index = 90 ; length = 1 line = 3 ; column = 6 ; value ='.'; } +{kind = TOKEN_IDENTIFIER; ; index = 91 ; length = 1 line = 3 ; column = 7 ; value ='x'; } +{kind = TOKEN_GREATER; ; index = 93 ; length = 1 line = 3 ; column = 9 ; value ='>'; } +{kind = TOKEN_INTLITERAL; ; index = 95 ; length = 2 line = 3 ; column = 11 ; value ='50'; } +{kind = TOKEN_LEFTBRACE; ; index = 98 ; length = 1 line = 3 ; column = 14 ; value ='{'; } +{kind = TOKEN_RETURN; ; index = 104 ; length = 6 line = 4 ; column = 0 ; value ='return'; } +{kind = TOKEN_IDENTIFIER; ; index = 111 ; length = 6 line = 4 ; column = 7 ; value ='float4'; } +{kind = TOKEN_LEFTPAREN; ; index = 117 ; length = 1 line = 4 ; column = 13 ; value ='('; } +{kind = TOKEN_IDENTIFIER; ; index = 118 ; length = 3 line = 4 ; column = 14 ; value ='pos'; } +{kind = TOKEN_COMMA; ; index = 121 ; length = 1 line = 4 ; column = 17 ; value =','; } +{kind = TOKEN_FLOATLITERAL; ; index = 123 ; length = 3 line = 4 ; column = 19 ; value ='1'; } +{kind = TOKEN_RIGHTPAREN; ; index = 126 ; length = 1 line = 4 ; column = 22 ; value =')'; } +{kind = TOKEN_SEMICOLON; ; index = 127 ; length = 1 line = 4 ; column = 23 ; value =';'; } +{kind = TOKEN_RIGHTBRACE; ; index = 132 ; length = 1 line = 5 ; column = 0 ; value ='}'; } +{kind = TOKEN_ELSE; ; index = 134 ; length = 4 line = 5 ; column = 2 ; value ='else'; } +{kind = TOKEN_LEFTBRACE; ; index = 139 ; length = 1 line = 5 ; column = 7 ; value ='{'; } +{kind = TOKEN_RETURN; ; index = 145 ; length = 6 line = 6 ; column = 0 ; value ='return'; } +{kind = TOKEN_IDENTIFIER; ; index = 152 ; length = 6 line = 6 ; column = 7 ; value ='float4'; } +{kind = TOKEN_LEFTPAREN; ; index = 158 ; length = 1 line = 6 ; column = 13 ; value ='('; } +{kind = TOKEN_FLOATLITERAL; ; index = 159 ; length = 3 line = 6 ; column = 14 ; value ='1'; } +{kind = TOKEN_RIGHTPAREN; ; index = 162 ; length = 1 line = 6 ; column = 17 ; value =')'; } +{kind = TOKEN_SEMICOLON; ; index = 163 ; length = 1 line = 6 ; column = 18 ; value =';'; } +{kind = TOKEN_RIGHTBRACE; ; index = 168 ; length = 1 line = 7 ; column = 0 ; value ='}'; } +{kind = TOKEN_RETURN; ; index = 173 ; length = 6 line = 8 ; column = 0 ; value ='return'; } +{kind = TOKEN_IDENTIFIER; ; index = 180 ; length = 6 line = 8 ; column = 7 ; value ='float4'; } +{kind = TOKEN_LEFTPAREN; ; index = 186 ; length = 1 line = 8 ; column = 13 ; value ='('; } +{kind = TOKEN_IDENTIFIER; ; index = 187 ; length = 3 line = 8 ; column = 14 ; value ='pos'; } +{kind = TOKEN_COMMA; ; index = 190 ; length = 1 line = 8 ; column = 17 ; value =','; } +{kind = TOKEN_FLOATLITERAL; ; index = 192 ; length = 3 line = 8 ; column = 19 ; value ='1'; } +{kind = TOKEN_RIGHTPAREN; ; index = 195 ; length = 1 line = 8 ; column = 22 ; value =')'; } +{kind = TOKEN_SEMICOLON; ; index = 196 ; length = 1 line = 8 ; column = 23 ; value =';'; } +{kind = TOKEN_RIGHTBRACE; ; index = 200 ; length = 1 line = 9 ; column = 0 ; value ='}'; } +{kind = TOKEN_RETURN; ; index = 205 ; length = 6 line = 10 ; column = 0 ; value ='return'; } +{kind = TOKEN_IDENTIFIER; ; index = 212 ; length = 6 line = 10 ; column = 7 ; value ='float4'; } +{kind = TOKEN_LEFTPAREN; ; index = 218 ; length = 1 line = 10 ; column = 13 ; value ='('; } +{kind = TOKEN_FLOATLITERAL; ; index = 219 ; length = 3 line = 10 ; column = 14 ; value ='0'; } +{kind = TOKEN_RIGHTPAREN; ; index = 222 ; length = 1 line = 10 ; column = 17 ; value =')'; } +{kind = TOKEN_SEMICOLON; ; index = 223 ; length = 1 line = 10 ; column = 18 ; value =';'; } +{kind = TOKEN_RIGHTBRACE; ; index = 226 ; length = 1 line = 11 ; column = 0 ; value ='}'; } +{kind = TOKEN_EOF; ; index = 229 ; length = 0 line = 12 ; column = 0 ; value =''; } diff --git a/test/lex_all.suite b/test/lex_all.suite index 26a696d..613e14d 100644 --- a/test/lex_all.suite +++ b/test/lex_all.suite @@ -21,6 +21,7 @@ test/inferred_types.ink lex test/meta_block.ink lex test/multiple_functions.ink lex test/multiple_semicolons_everywhere.ink lex +test/nested_if.ink lex test/non_bool_cond.ink lex test/pass_and_access_struct_fields_in_functions.ink lex test/passthrough.ink lex diff --git a/test/nested_if.ink b/test/nested_if.ink new file mode 100644 index 0000000..6ab592b --- /dev/null +++ b/test/nested_if.ink @@ -0,0 +1,11 @@ +vertex main :: (pos : float3 @position) -> float4 @position { + if pos.x > 100 { + if pos.x > 50 { + return float4(pos, 1.0); + } else { + return float4(1.0); + } + return float4(pos, 1.0); + } + return float4(0.0); +} diff --git a/test/parse/nested_if.golden b/test/parse/nested_if.golden new file mode 100644 index 0000000..80608cf --- /dev/null +++ b/test/parse/nested_if.golden @@ -0,0 +1,9 @@ +(program + (fun vertex vs_main -> float4 (@position) + [(:= pos float3 (@position))] + (if (> pos.x 100) + (if (> pos.x 50) + (return (float4 pos 1)) + (return (float4 1))) + (return (float4 pos 1))) + (return (float4 0)))) \ No newline at end of file diff --git a/test/parse_all.suite b/test/parse_all.suite index f43cd0e..1a7e38b 100644 --- a/test/parse_all.suite +++ b/test/parse_all.suite @@ -21,6 +21,7 @@ test/inferred_types.ink parse test/meta_block.ink parse test/multiple_functions.ink parse test/multiple_semicolons_everywhere.ink parse +test/nested_if.ink parse test/non_bool_cond.ink parse test/pass_and_access_struct_fields_in_functions.ink parse test/passthrough.ink parse diff --git a/test/semant/nested_if.golden b/test/semant/nested_if.golden new file mode 100644 index 0000000..7d9b85d --- /dev/null +++ b/test/semant/nested_if.golden @@ -0,0 +1,6 @@ +scope (global) [ + [vertex__vs_main] : (pos : float3) -> float4 + scope (vertex__vs_main) [ + [pos] : float3 + ] +] diff --git a/test/semant_all.suite b/test/semant_all.suite index d0bd7b9..feb7162 100644 --- a/test/semant_all.suite +++ b/test/semant_all.suite @@ -16,6 +16,7 @@ test/if_cond_assign.ink semant test/inferred_types.ink semant test/multiple_functions.ink semant test/multiple_semicolons_everywhere.ink semant +test/nested_if.ink semant test/non_bool_cond.ink semant test/pass_and_access_struct_fields_in_functions.ink semant test/passthrough.ink semant From 8ce8651d6b54f9b206564360cb1edec7b295789e Mon Sep 17 00:00:00 2001 From: Niels Bross Date: Wed, 22 Jan 2025 22:30:06 +0100 Subject: [PATCH 15/17] Fix some missing operators not getting parsed properly. Fixed field access type checking with depth more than 1. --- AST.jai | 25 ++++++++++++++++++++++--- Parsing.jai | 25 +++++++++++++++++++++---- Semantic_Analysis.jai | 11 ++++++----- Test.jai | 6 ++++-- test/binary_with_access.ink | 8 ++++++++ 5 files changed, 61 insertions(+), 14 deletions(-) create mode 100644 test/binary_with_access.ink diff --git a/AST.jai b/AST.jai index f38c9dc..65e7c9b 100644 --- a/AST.jai +++ b/AST.jai @@ -150,10 +150,16 @@ Children_Print_Flags :: enum_flags { pretty_print_block :: (node : *AST_Node, indentation : int, builder : *String_Builder, skip_indent := false) { if node.children.count == 0 { - indent(builder, indentation); + if !skip_indent { + indent(builder, indentation); + } append(builder, "()"); } else { - pretty_print_children(node, indentation, builder, flags = .NewLine | .Dont_Skip_Indent_On_First); + flags := Children_Print_Flags.NewLine; + if !skip_indent { + flags |= .Dont_Skip_Indent_On_First; + } + pretty_print_children(node, indentation, builder, flags); } } @@ -210,6 +216,16 @@ op_to_string :: (oper : Token) -> string { return "*"; case .TOKEN_SLASH; return "/"; + case .TOKEN_MINUSEQUALS; + return "-="; + case .TOKEN_PLUSEQUALS; + return "+="; + case .TOKEN_DIVEQUALS; + return "/="; + case .TOKEN_TIMESEQUALS; + return "*="; + case .TOKEN_MODEQUALS; + return "%="; case .TOKEN_ISEQUAL; return "=="; case .TOKEN_ASSIGN; @@ -280,7 +296,10 @@ pretty_print_if :: (node : *AST_Node, indentation : int, builder : *String_Build append(builder, "\n"); body := node.children[1]; - pretty_print_node(body, indentation + 4, builder); + indent(builder,indentation + 4); + append(builder, "("); + pretty_print_node(body, indentation + 5, builder, true); + append(builder, ")"); if node.children.count == 3 { append(builder, "\n"); diff --git a/Parsing.jai b/Parsing.jai index aae0c36..0514b28 100644 --- a/Parsing.jai +++ b/Parsing.jai @@ -101,6 +101,11 @@ parse_rules :: #run -> [(cast(int)Token_Kind.TOKEN_ERROR) + 1]Parse_Rule { rules[Token_Kind.TOKEN_STAR] = .{null, binary, .PREC_FACTOR}; rules[Token_Kind.TOKEN_ISNOTEQUAL] = .{null, binary, .PREC_COMPARISON}; rules[Token_Kind.TOKEN_ASSIGN] = .{null, binary, .PREC_COMPARISON}; + rules[Token_Kind.TOKEN_MINUSEQUALS] = .{null, binary, .PREC_COMPARISON}; + rules[Token_Kind.TOKEN_PLUSEQUALS] = .{null, binary, .PREC_COMPARISON}; + rules[Token_Kind.TOKEN_DIVEQUALS] = .{null, binary, .PREC_COMPARISON}; + rules[Token_Kind.TOKEN_TIMESEQUALS] = .{null, binary, .PREC_COMPARISON}; + rules[Token_Kind.TOKEN_MODEQUALS] = .{null, binary, .PREC_COMPARISON}; rules[Token_Kind.TOKEN_ISEQUAL] = .{null, binary, .PREC_EQUALITY}; rules[Token_Kind.TOKEN_GREATER] = .{null, binary, .PREC_COMPARISON}; rules[Token_Kind.TOKEN_GREATEREQUALS] = .{null, binary, .PREC_COMPARISON}; @@ -410,6 +415,15 @@ check :: (parse_state : *Parse_State, kind : Token_Kind) -> bool { return parse_state.current.kind == kind; } +check_any :: (parse_state : *Parse_State, kinds : ..Token_Kind) -> bool { + for kind : kinds { + if check(parse_state, kind) { + return true; + } + } + return false; +} + //nb - Checks if the next token is of a certain kind check_next :: (parse_state : *Parse_State, kind : Token_Kind) -> bool { return parse_state.tokens[parse_state.current_token_index].kind == kind; @@ -625,7 +639,7 @@ dot :: (parse_state : *Parse_State, left : *AST_Node) -> *AST_Node { source_location : Source_Range; source_location.begin = left.source_location.begin; - if check(parse_state, .TOKEN_ASSIGN) { + if check_any(parse_state, .TOKEN_ASSIGN, .TOKEN_MINUSEQUALS, .TOKEN_PLUSEQUALS, .TOKEN_DIVEQUALS, .TOKEN_MODEQUALS, .TOKEN_TIMESEQUALS) { advance(parse_state); variable := make_node(parse_state, .Variable); variable.source_location = generate_source_location_from_token(parse_state, identifier); @@ -638,12 +652,15 @@ dot :: (parse_state : *Parse_State, left : *AST_Node) -> *AST_Node { add_child(node, left); add_child(node, expression(parse_state)); return node; - } else if check(parse_state, .TOKEN_DOT) { - // @Incomplete(nb): Another level of access - } + } variable := make_node(parse_state, .Variable); variable.name = identifier.ident_value; + if check(parse_state, .TOKEN_DOT) { + advance(parse_state); + dot(parse_state, variable); + } + add_child(left, variable); source_location.end = parse_state.previous; diff --git a/Semantic_Analysis.jai b/Semantic_Analysis.jai index b515ae5..5255fc2 100644 --- a/Semantic_Analysis.jai +++ b/Semantic_Analysis.jai @@ -1621,11 +1621,7 @@ types_compatible :: (checker : *Semantic_Checker, lhs : Type_Variable_Handle, rh case .Texture2D; { return rhs_var.type == lhs_var.type; } - case .Struct; { - if rhs_var.type != .Struct { - return false; - } - + case .Struct; { lhs_node := lhs_var.source_node; rhs_node := rhs_var.source_node; @@ -1639,6 +1635,11 @@ types_compatible :: (checker : *Semantic_Checker, lhs : Type_Variable_Handle, rh } } + if rhs_var.type != .Struct { + return false; + } + + lhs_struct := find_symbol(checker, lhs_var.typename, xx 1); rhs_struct := find_symbol(checker, rhs_var.typename, xx 1); diff --git a/Test.jai b/Test.jai index 67e4f8a..c143b54 100644 --- a/Test.jai +++ b/Test.jai @@ -722,7 +722,8 @@ main :: () { } else if arg == "-compile" { current_suite.test_cases[cases - 1].stage_flags |= .Compile; } else if contains(arg, ".") { - split_path := split(arg, "."); + path_split := split(arg, "\\"); + split_path := split(path_split[path_split.count - 1], "."); extension := split_path[1]; if extension == SHADER_EXTENSION { path := copy_string(arg); @@ -737,7 +738,8 @@ main :: () { } case .None; { if contains(arg, ".") { - split_path := split(arg, "."); + path_split := split(arg, "\\"); + split_path := split(path_split[path_split.count - 1], "."); extension := split_path[1]; if extension == SHADER_EXTENSION { diff --git a/test/binary_with_access.ink b/test/binary_with_access.ink new file mode 100644 index 0000000..d119f38 --- /dev/null +++ b/test/binary_with_access.ink @@ -0,0 +1,8 @@ +props :: properties { + resolution : float2; +} + +vertex main :: (pos : float3 @position) -> float4 @position { + p := float2(1.0 - 2.0 * props.resolution.x, 1.0 - 2.0 * props.resolution.y); + return float4(p, 1.0, 1.0); +} From cd167d1560a313b02fa651f39897c7a0a7a4cf3f Mon Sep 17 00:00:00 2001 From: Niels Bross Date: Thu, 23 Jan 2025 22:47:09 +0100 Subject: [PATCH 16/17] Add missing codegen for minusequals and etc. Do proper type checking on else blocks. Spread single arg constructors not supported in hlsl. --- Codegen.jai | 35 ++++++++++++++++++++++++++++++++++- Semantic_Analysis.jai | 6 +++++- hlsl_builtin.ink | 2 ++ 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/Codegen.jai b/Codegen.jai index 5a980a7..e380144 100644 --- a/Codegen.jai +++ b/Codegen.jai @@ -190,6 +190,24 @@ emit_call :: (state : *Codegen_State, node : *AST_Node, indentation : int) { append(*state.builder, ", "); } } + } else if starts_with(node.name, "float") && node.children[0].children.count == 1 { + args := node.children[0]; + + print_to_builder(*state.builder, "%(", node.name); + + number : string; + number.data = *node.name.data[5]; + number.count = node.name.count - 5; + count := parse_int(*number, s32); + + for i : 0..count - 1 { + child := args.children[0]; + emit_node(state, child, 0); + + if i != count - 1 { + append(*state.builder, ", "); + } + } } else { print_to_builder(*state.builder, "%(", node.name); @@ -353,7 +371,22 @@ emit_operator :: (state : *Codegen_State, op_kind : Token_Kind) { } case .TOKEN_SLASH; { append(*state.builder, "/"); - } + } + case .TOKEN_MINUSEQUALS; { + append(*state.builder, "-="); + } + case .TOKEN_PLUSEQUALS; { + append(*state.builder, "+="); + } + case .TOKEN_DIVEQUALS; { + append(*state.builder, "/="); + } + case .TOKEN_TIMESEQUALS; { + append(*state.builder, "*="); + } + case .TOKEN_MODEQUALS; { + append(*state.builder, "%="); + } case .TOKEN_ISEQUAL; { append(*state.builder, "=="); } diff --git a/Semantic_Analysis.jai b/Semantic_Analysis.jai index 5255fc2..619f7f3 100644 --- a/Semantic_Analysis.jai +++ b/Semantic_Analysis.jai @@ -1506,7 +1506,11 @@ check_node :: (checker : *Semantic_Checker, node : *AST_Node) -> Type_Variable_H body_var := check_block(checker, node.children[1]); if node.children.count == 3 { - else_var := check_node(checker, node.children[2]); + if node.children[2].kind == .If { + check_node(checker, node.children[2]); + } else { + check_block(checker, node.children[2]); + } } } case .Variable; { diff --git a/hlsl_builtin.ink b/hlsl_builtin.ink index e77b01b..d5c5b99 100644 --- a/hlsl_builtin.ink +++ b/hlsl_builtin.ink @@ -285,3 +285,5 @@ int4x4 :: struct { #foreign lerp :: (float2, float2, float) -> float2; #foreign lerp :: (float3, float3, float) -> float3; #foreign lerp :: (float4, float4, float) -> float4; + +#foreign fmod :: (float, float) -> float; From af42b61ed68387e27df97efe0b3952f9dbdb4e19 Mon Sep 17 00:00:00 2001 From: Niels Bross Date: Mon, 27 Jan 2025 21:38:54 +0100 Subject: [PATCH 17/17] Struct output shenanigans --- Parsing.jai | 7 +++++++ module.jai | 1 + test/struct_output_vertex.ink | 15 +++++++++++++++ 3 files changed, 23 insertions(+) create mode 100644 test/struct_output_vertex.ink diff --git a/Parsing.jai b/Parsing.jai index 0514b28..94ec26f 100644 --- a/Parsing.jai +++ b/Parsing.jai @@ -393,6 +393,9 @@ advance :: (parse_state : *Parse_State) { parse_state.previous = parse_state.current; while true { + if parse_state.current_token_index >= parse_state.tokens.count { + break; + } parse_state.current = *parse_state.tokens[parse_state.current_token_index]; parse_state.current_token_index += 1; if parse_state.current.kind != .TOKEN_ERROR break; @@ -799,6 +802,10 @@ argument_list :: (parse_state : *Parse_State) -> *AST_Node { if check(parse_state, .TOKEN_RIGHTPAREN) break; consume(parse_state, .TOKEN_COMMA, "Expect ',' after function argument."); + + if parse_state.result.had_error { + break; + } } consume(parse_state, .TOKEN_RIGHTPAREN, "Expect ')' after function call."); diff --git a/module.jai b/module.jai index 6df2b3f..59c70a5 100644 --- a/module.jai +++ b/module.jai @@ -372,6 +372,7 @@ type_variable_to_field :: (type_variables : []Type_Variable, scope_stack : Scope field_hint.kind = .Target; } else { field_hint.custom_hint_name = copy_string(hint.ident_value); + field_hint.kind = .Custom; } array_add(*field.hints, field_hint); } diff --git a/test/struct_output_vertex.ink b/test/struct_output_vertex.ink new file mode 100644 index 0000000..7ebf857 --- /dev/null +++ b/test/struct_output_vertex.ink @@ -0,0 +1,15 @@ +VS_Out :: struct { + pos : float4 @outposition; +} + +vertex main :: (pos : float3 @position) -> VS_Out { + vs_out : VS_Out; + + vs_out.pos = float4(pos, 1.0); + + return vs_out; +} + +pixel main :: (ps_in : VS_Out) -> float4 @target { + return float4(1, 1, 1, 1); +}