From 8ce8651d6b54f9b206564360cb1edec7b295789e Mon Sep 17 00:00:00 2001 From: Niels Bross Date: Wed, 22 Jan 2025 22:30:06 +0100 Subject: [PATCH] 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); +}