From: Brendan Hansen Date: Wed, 16 Jun 2021 15:56:42 +0000 (-0500) Subject: field access bugfix and added overloading operator '[]' X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=9fe01bd319f4a4c0fcadabcbf37d6e1d62017ea0;p=onyx.git field access bugfix and added overloading operator '[]' --- diff --git a/bin/onyx b/bin/onyx index 383ec51d..a477f85f 100755 Binary files a/bin/onyx and b/bin/onyx differ diff --git a/core/builtin.onyx b/core/builtin.onyx index 254d7d54..b7bde249 100644 --- a/core/builtin.onyx +++ b/core/builtin.onyx @@ -179,4 +179,4 @@ CallSite :: struct { file : str; line : u32; column : u32; -} \ No newline at end of file +} diff --git a/include/onyxastnodes.h b/include/onyxastnodes.h index e1aaed02..85777886 100644 --- a/include/onyxastnodes.h +++ b/include/onyxastnodes.h @@ -294,6 +294,8 @@ typedef enum BinaryOp { Binary_Op_Range = 34, Binary_Op_Method_Call = 35, + Binary_Op_Subscript = 36, + Binary_Op_Count } BinaryOp; @@ -512,10 +514,22 @@ struct AstLocal { AstTyped_base; }; struct AstArgument { AstTyped_base; AstTyped *value; VarArgKind va_kind; b32 is_baked : 1; }; struct AstAddressOf { AstTyped_base; AstTyped *expr; }; struct AstDereference { AstTyped_base; AstTyped *expr; }; -struct AstArrayAccess { AstTyped_base; AstTyped *addr; AstTyped *expr; u64 elem_size; }; -struct AstFieldAccess { AstTyped_base; AstTyped *expr; u32 offset; u32 idx; char* field; }; // If token is null, defer to field struct AstSizeOf { AstTyped_base; AstType *so_ast_type; Type *so_type; u64 size; }; struct AstAlignOf { AstTyped_base; AstType *ao_ast_type; Type *ao_type; u64 alignment; }; +struct AstArrayAccess { + AstTyped_base; + BinaryOp __unused_operation; // This will be set to Binary_Op_Subscript + AstTyped *addr; + AstTyped *expr; + u64 elem_size; +}; +struct AstFieldAccess { + AstTyped_base; + AstTyped *expr; + u32 offset; + u32 idx; + char* field; // If token is null, defer to field +}; struct AstFileContents { AstTyped_base; diff --git a/src/onyxastnodes.c b/src/onyxastnodes.c index 531090b2..09ed6cc2 100644 --- a/src/onyxastnodes.c +++ b/src/onyxastnodes.c @@ -105,7 +105,9 @@ const char *binaryop_string[Binary_Op_Count] = { "&=", "|=", "^=", "<<=", ">>=", ">>>=", "NONE", - "|>", "..", + "|>", "..", "->", + + "[]", }; const char* entity_state_strings[Entity_State_Count] = { diff --git a/src/onyxchecker.c b/src/onyxchecker.c index fbc4c6be..9829b1d0 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -38,7 +38,7 @@ CheckStatus check_compound(AstCompound* compound); CheckStatus check_expression(AstTyped** expr); CheckStatus check_address_of(AstAddressOf* aof); CheckStatus check_dereference(AstDereference* deref); -CheckStatus check_array_access(AstArrayAccess* expr); +CheckStatus check_array_access(AstArrayAccess** paa); CheckStatus check_field_access(AstFieldAccess** pfield); CheckStatus check_method_call(AstBinaryOp** mcall); CheckStatus check_size_of(AstSizeOf* so); @@ -1288,10 +1288,27 @@ CheckStatus check_dereference(AstDereference* deref) { return Check_Success; } -CheckStatus check_array_access(AstArrayAccess* aa) { +CheckStatus check_array_access(AstArrayAccess** paa) { + AstArrayAccess* aa = *paa; CHECK(expression, &aa->addr); CHECK(expression, &aa->expr); + // NOTE: Try operator overloading before checking everything else. + if ((aa->addr->type != NULL && aa->expr->type != NULL) && + (aa->addr->type->kind != Type_Kind_Basic || aa->expr->type->kind != Type_Kind_Basic)) { + // AstArrayAccess is the same as AstBinaryOp for the first sizeof(AstBinaryOp) bytes + AstBinaryOp* binop = (AstBinaryOp *) aa; + AstCall *implicit_call = binaryop_try_operator_overload(binop); + + if (implicit_call != NULL) { + CHECK(call, implicit_call); + + // NOTE: Not an array access + *paa = (AstArrayAccess *) implicit_call; + return Check_Success; + } + } + if (!type_is_array_accessible(aa->addr->type)) { onyx_report_error(aa->token->pos, "Expected pointer or array type for left of array access, got '%s'.", @@ -1374,7 +1391,7 @@ CheckStatus check_field_access(AstFieldAccess** pfield) { return Check_Error; } - if (!is_lval((AstNode *) field->expr)) { + if (field->expr->type->kind != Type_Kind_Pointer && !is_lval((AstNode *) field->expr)) { onyx_report_error(field->token->pos, "Cannot access field '%b'. Expression is not an lval.", field->token->text, @@ -1382,6 +1399,11 @@ CheckStatus check_field_access(AstFieldAccess** pfield) { return Check_Error; } + // HACK: (*foo).bar does not work without this. + if (field->expr->kind == Ast_Kind_Dereference) { + field->expr = ((AstDereference *) field->expr)->expr; + } + StructMember smem; if (field->token != NULL && field->field == NULL) { token_toggle_end(field->token); @@ -1512,7 +1534,7 @@ CheckStatus check_expression(AstTyped** pexpr) { case Ast_Kind_Address_Of: retval = check_address_of((AstAddressOf *) expr); break; case Ast_Kind_Dereference: retval = check_dereference((AstDereference *) expr); break; case Ast_Kind_Slice: - case Ast_Kind_Array_Access: retval = check_array_access((AstArrayAccess *) expr); break; + case Ast_Kind_Array_Access: retval = check_array_access((AstArrayAccess **) pexpr); break; case Ast_Kind_Field_Access: retval = check_field_access((AstFieldAccess **) pexpr); break; case Ast_Kind_Method_Call: retval = check_method_call((AstBinaryOp **) pexpr); break; case Ast_Kind_Size_Of: retval = check_size_of((AstSizeOf *) expr); break; diff --git a/src/onyxparser.c b/src/onyxparser.c index 91991152..44347d15 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -615,6 +615,7 @@ static AstTyped* parse_factor(OnyxParser* parser) { aa_node->token = open_bracket; aa_node->addr = retval; aa_node->expr = expr; + aa_node->__unused_operation = Binary_Op_Subscript; retval = (AstTyped *) aa_node; expect_token(parser, ']'); @@ -765,6 +766,7 @@ static BinaryOp binary_op_from_token_type(TokenType t) { case Token_Type_Pipe: return Binary_Op_Pipe; case Token_Type_Dot_Dot: return Binary_Op_Range; + case '[': return Binary_Op_Subscript; default: return Binary_Op_Count; } } @@ -827,6 +829,7 @@ static AstTyped* parse_expression(OnyxParser* parser, b32 assignment_allowed) { bin_op_kind = binary_op_from_token_type(parser->curr->type); if (bin_op_kind == Binary_Op_Count) goto expression_done; if (binop_is_assignment(bin_op_kind) && !assignment_allowed) goto expression_done; + if (bin_op_kind == Binary_Op_Subscript) goto expression_done; bin_op_tok = parser->curr; consume_token(parser); @@ -2331,6 +2334,7 @@ static void parse_top_level_statement(OnyxParser* parser) { BinaryOp op = binary_op_from_token_type(parser->curr->type); consume_token(parser); + if (op == Binary_Op_Subscript) expect_token(parser, ']'); // #operator [] ... needs to consume the other ']' if (op == Binary_Op_Count) { onyx_report_error(parser->curr->pos, "Invalid binary operator."); diff --git a/src/onyxtypes.c b/src/onyxtypes.c index 6bdb5c89..0e307106 100644 --- a/src/onyxtypes.c +++ b/src/onyxtypes.c @@ -332,13 +332,13 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) { mem_alignment = type_alignment_of((*member)->type); if (mem_alignment <= 0) { - if ((*member)->type->kind == Type_Kind_Struct) { - AstStructType* member_node = (AstStructType *) (*member)->type->ast_type; - if (member_node->stcache_is_valid) { - s_node->stcache_is_valid = 0; - return NULL; - } - } + // if ((*member)->type->kind == Type_Kind_Struct) { + // AstStructType* member_node = (AstStructType *) (*member)->type->ast_type; + // if (member_node->stcache_is_valid) { + // s_node->stcache_is_valid = 0; + // return NULL; + // } + // } onyx_report_error((*member)->token->pos, "Invalid member type: %s", type_get_name((*member)->type)); return NULL; @@ -427,6 +427,7 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) { case Ast_Kind_Enum_Type: { AstEnumType* enum_node = (AstEnumType *) type_node; if (enum_node->etcache) return enum_node->etcache; + if (enum_node->backing_type == NULL) return NULL; Type* enum_type = bh_alloc(alloc, sizeof(Type)); enum_node->etcache = enum_type;