diff --git a/src/parser.odin b/src/parser.odin index ac58531..2ef7f33 100644 --- a/src/parser.odin +++ b/src/parser.odin @@ -600,13 +600,30 @@ parser_parse_factor :: proc(parser: ^Parser) -> (ret: ^Node) { parser_next(parser) prev := parser.can_be_function parser.can_be_function = false - if accept(parser, .Dot) { + + for accept(parser, .Dot) { + if parser.tok.kind != .Identifier { + append( + &g_message_list, + message_create( + .Error, + fmt.aprintf("Expected identifier after '.' but got {}", parser.tok.kind), + parser.tok.range, + ), + ) + continue + } + + right := node_create_value(.Identifier, parser.tok.range, parser.tok.value) + parser_next(parser) + ret = node_create_field_access( - SourceLocation{{ret.range.range.start, parser.tok.range.range.start}, ret.range.file}, + SourceLocation{{ret.range.range.start, right.range.range.end}, ret.range.file}, ret, - parser_parse_factor(parser), + right, ) } + parser.can_be_function = prev if parser.can_be_function && parser.tok.kind != .CloseParen && diff --git a/src/type_checker.odin b/src/type_checker.odin index e6b2e0f..c1712d0 100644 --- a/src/type_checker.odin +++ b/src/type_checker.odin @@ -236,50 +236,81 @@ type_check :: proc(ast: ^Node, parent_ast: ^Node) { lhs := ast.children[0] rhs := ast.children[1] // FIXME: Add support for nesting - if lhs.kind != .Identifier { - append( - &g_message_list, - message_create(.Error, fmt.aprintf("Field access lhs is not an identifier"), lhs.range), - ) - break + struct_: ^Struct + if lhs.kind != .FieldAccess { + struct_var := scope_variable_lookup(lhs.value.([dynamic]u8)) + if struct_var == nil { + append( + &g_message_list, + message_create( + .Error, + fmt.aprintf("Cannot find struct of name: `%s`", lhs.value.([dynamic]u8)), + lhs.range, + ), + ) + break + } + + struct_ = scope_struct_lookup(struct_var.struct_type.name) + if struct_ == nil { + append( + &g_message_list, + message_create( + .Error, + fmt.aprintf("Cannot find struct of type name: `%s`", lhs.value.([dynamic]u8)), + lhs.range, + ), + ) + break + } } + if rhs.kind != .Identifier { append( &g_message_list, - message_create(.Error, fmt.aprintf("Field access rhs is not an identifier"), rhs.range), - ) + message_create(.Error, fmt.aprintf("Field access rhs is not an identifier or field access: {}", rhs.kind), rhs.range), + ) break } - struct_var := scope_variable_lookup(lhs.value.([dynamic]u8)) - if struct_var == nil { + if lhs.kind == .FieldAccess { + type_check(lhs, ast) + if lhs.return_type.kind != .Struct { + append( + &g_message_list, + message_create( + .Error, + fmt.aprintf("LHS is not a Struct type"), + lhs.range, + ), + ) + } + + struct_ = scope_struct_lookup(lhs.return_type.struct_type.name) + if struct_ == nil { + append( + &g_message_list, + message_create( + .Error, + fmt.aprintf("Cannot find struct of type name: `%s`", lhs.value.([dynamic]u8)), + lhs.range, + ), + ) + break + } + } else if lhs.kind != .Identifier { append( &g_message_list, - message_create( - .Error, - fmt.aprintf("Cannot find struct of name: `%s`", lhs.value.([dynamic]u8)), - rhs.range, - ), + message_create(.Error, fmt.aprintf("Field access lhs is not an identifier or FieldAccess"), lhs.range), ) break } - struct_ := scope_struct_lookup(struct_var.struct_type.name) - if struct_ == nil { - append( - &g_message_list, - message_create( - .Error, - fmt.aprintf("Cannot find struct of type name: `%s`", lhs.value.([dynamic]u8)), - rhs.range, - ), - ) - break - } - - found_field := false struct_index: u64 = 0 + found_field := false + fmt.println("==") for &field, i in struct_.fields { + fmt.printf("- %s\n", field.name) if compare_dyn_arrs(&field.name, &rhs.value.([dynamic]u8)) { ast.return_type = field.type found_field = true @@ -436,11 +467,11 @@ type_check :: proc(ast: ^Node, parent_ast: ^Node) { ) } } else if ast.value_token_kind == .Equals || - ast.value_token_kind == .NotEquals || - ast.value_token_kind == .GreaterThan || - ast.value_token_kind == .GreaterThanOrEqual || - ast.value_token_kind == .LessThan || - ast.value_token_kind == .LessThanOrEqual { + ast.value_token_kind == .NotEquals || + ast.value_token_kind == .GreaterThan || + ast.value_token_kind == .GreaterThanOrEqual || + ast.value_token_kind == .LessThan || + ast.value_token_kind == .LessThanOrEqual { ast.return_type = type_create_integer(1, true) } // FIXME: Verify that the operation is possible