From aaeda22fa3ec1e4e0094377893c00e0cfd85deba Mon Sep 17 00:00:00 2001 From: Niels Bross Date: Mon, 13 Jan 2025 16:33:03 +0100 Subject: [PATCH] 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); +} +