Add support for multiple field accesses in parser and type checker
Signed-off-by: Slendi <slendi@socopon.com>
This commit is contained in:
parent
464532d9fe
commit
c5747a103e
@ -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 &&
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user