Add support for multiple field accesses in parser and type checker

Signed-off-by: Slendi <slendi@socopon.com>
This commit is contained in:
Slendi 2024-04-27 04:03:51 +03:00
parent 464532d9fe
commit c5747a103e
2 changed files with 85 additions and 37 deletions

View File

@ -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 &&

View File

@ -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