| author | |
| committer | |
| log | 974d69ea3d0db71b97af00e325fdfb421c0906c2 |
| tree | 05c145b633277b78735765d8f9c15f78d504b2ed |
| parent | bb4f7835286f047fc596715101ee0318c8e7f924 |
see #143 files changed, 50 insertions(+), 13 deletions(-)
src/analyze.cpp+17-5| ... | @@ -3694,17 +3694,17 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import | ... | @@ -3694,17 +3694,17 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import |
| 3694 | } else if (struct_type->id == TypeTableEntryIdInvalid) { | 3694 | } else if (struct_type->id == TypeTableEntryIdInvalid) { |
| 3695 | return struct_type; | 3695 | return struct_type; |
| 3696 | } else if (struct_type->id == TypeTableEntryIdMetaType) { | 3696 | } else if (struct_type->id == TypeTableEntryIdMetaType) { |
| 3697 | TypeTableEntry *enum_type = resolve_type(g, first_param_expr); | 3697 | TypeTableEntry *child_type = resolve_type(g, first_param_expr); |
| 3698 | 3698 | ||
| 3699 | if (enum_type->id == TypeTableEntryIdInvalid) { | 3699 | if (child_type->id == TypeTableEntryIdInvalid) { |
| 3700 | return g->builtin_types.entry_invalid; | 3700 | return g->builtin_types.entry_invalid; |
| 3701 | } else if (enum_type->id == TypeTableEntryIdEnum) { | 3701 | } else if (child_type->id == TypeTableEntryIdEnum) { |
| 3702 | Buf *field_name = &fn_ref_expr->data.field_access_expr.field_name; | 3702 | Buf *field_name = &fn_ref_expr->data.field_access_expr.field_name; |
| 3703 | int param_count = node->data.fn_call_expr.params.length; | 3703 | int param_count = node->data.fn_call_expr.params.length; |
| 3704 | if (param_count > 1) { | 3704 | if (param_count > 1) { |
| 3705 | add_node_error(g, first_executing_node(node->data.fn_call_expr.params.at(1)), | 3705 | add_node_error(g, first_executing_node(node->data.fn_call_expr.params.at(1)), |
| 3706 | buf_sprintf("enum values accept only one parameter")); | 3706 | buf_sprintf("enum values accept only one parameter")); |
| 3707 | return enum_type; | 3707 | return child_type; |
| 3708 | } else { | 3708 | } else { |
| 3709 | AstNode *value_node; | 3709 | AstNode *value_node; |
| 3710 | if (param_count == 1) { | 3710 | if (param_count == 1) { |
| ... | @@ -3714,7 +3714,19 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import | ... | @@ -3714,7 +3714,19 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import |
| 3714 | } | 3714 | } |
| 3715 | 3715 | ||
| 3716 | return analyze_enum_value_expr(g, import, context, fn_ref_expr, value_node, | 3716 | return analyze_enum_value_expr(g, import, context, fn_ref_expr, value_node, |
| 3717 | enum_type, field_name); | 3717 | child_type, field_name); |
| 3718 | } | ||
| 3719 | } else if (child_type->id == TypeTableEntryIdStruct) { | ||
| 3720 | Buf *field_name = &fn_ref_expr->data.field_access_expr.field_name; | ||
| 3721 | auto entry = child_type->data.structure.fn_table.maybe_get(field_name); | ||
| 3722 | if (entry) { | ||
| 3723 | return analyze_fn_call_raw(g, import, context, expected_type, node, | ||
| 3724 | entry->value, nullptr); | ||
| 3725 | } else { | ||
| 3726 | add_node_error(g, node, | ||
| 3727 | buf_sprintf("struct '%s' has no function called '%s'", | ||
| 3728 | buf_ptr(&child_type->name), buf_ptr(field_name))); | ||
| 3729 | return g->builtin_types.entry_invalid; | ||
| 3718 | } | 3730 | } |
| 3719 | } else { | 3731 | } else { |
| 3720 | add_node_error(g, first_param_expr, buf_sprintf("member reference base type not struct or enum")); | 3732 | add_node_error(g, first_param_expr, buf_sprintf("member reference base type not struct or enum")); |
src/codegen.cpp+17-8| ... | @@ -496,16 +496,25 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) { | ... | @@ -496,16 +496,25 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) { |
| 496 | assert(struct_type->data.pointer.child_type->id == TypeTableEntryIdStruct); | 496 | assert(struct_type->data.pointer.child_type->id == TypeTableEntryIdStruct); |
| 497 | fn_table_entry = node->data.fn_call_expr.fn_entry; | 497 | fn_table_entry = node->data.fn_call_expr.fn_entry; |
| 498 | } else if (struct_type->id == TypeTableEntryIdMetaType) { | 498 | } else if (struct_type->id == TypeTableEntryIdMetaType) { |
| 499 | TypeTableEntry *enum_type = get_type_for_type_node(first_param_expr); | 499 | TypeTableEntry *child_type = get_type_for_type_node(first_param_expr); |
| 500 | int param_count = node->data.fn_call_expr.params.length; | 500 | |
| 501 | AstNode *arg1_node; | 501 | if (child_type->id == TypeTableEntryIdEnum) { |
| 502 | if (param_count == 1) { | 502 | int param_count = node->data.fn_call_expr.params.length; |
| 503 | arg1_node = node->data.fn_call_expr.params.at(0); | 503 | AstNode *arg1_node; |
| 504 | if (param_count == 1) { | ||
| 505 | arg1_node = node->data.fn_call_expr.params.at(0); | ||
| 506 | } else { | ||
| 507 | assert(param_count == 0); | ||
| 508 | arg1_node = nullptr; | ||
| 509 | } | ||
| 510 | return gen_enum_value_expr(g, fn_ref_expr, child_type, arg1_node); | ||
| 511 | } else if (child_type->id == TypeTableEntryIdStruct) { | ||
| 512 | struct_type = nullptr; | ||
| 513 | first_param_expr = nullptr; | ||
| 514 | fn_table_entry = node->data.fn_call_expr.fn_entry; | ||
| 504 | } else { | 515 | } else { |
| 505 | assert(param_count == 0); | 516 | zig_unreachable(); |
| 506 | arg1_node = nullptr; | ||
| 507 | } | 517 | } |
| 508 | return gen_enum_value_expr(g, fn_ref_expr, enum_type, arg1_node); | ||
| 509 | } else { | 518 | } else { |
| 510 | zig_unreachable(); | 519 | zig_unreachable(); |
| 511 | } | 520 | } |
test/run_tests.cpp+16| ... | @@ -1407,6 +1407,22 @@ pub fn main(args: [][]u8) -> %void { | ... | @@ -1407,6 +1407,22 @@ pub fn main(args: [][]u8) -> %void { |
| 1407 | %%stdout.printf("BAD\n"); | 1407 | %%stdout.printf("BAD\n"); |
| 1408 | } | 1408 | } |
| 1409 | %%stdout.printf("OK\n"); | 1409 | %%stdout.printf("OK\n"); |
| 1410 | } | ||
| 1411 | )SOURCE", "OK\n"); | ||
| 1412 | |||
| 1413 | add_simple_case("call member function directly", R"SOURCE( | ||
| 1414 | import "std.zig"; | ||
| 1415 | struct Foo { | ||
| 1416 | x: i32, | ||
| 1417 | fn member(foo: Foo) -> i32 { foo.x } | ||
| 1418 | } | ||
| 1419 | pub fn main(args: [][]u8) -> %void { | ||
| 1420 | const instance = Foo { .x = 1234, }; | ||
| 1421 | const result = Foo.member(instance); | ||
| 1422 | if (result != 1234) { | ||
| 1423 | %%stdout.printf("BAD\n"); | ||
| 1424 | } | ||
| 1425 | %%stdout.printf("OK\n"); | ||
| 1410 | } | 1426 | } |
| 1411 | )SOURCE", "OK\n"); | 1427 | )SOURCE", "OK\n"); |
| 1412 | } | 1428 | } |