authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-28 16:55:54-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-28 16:55:54-07:00
log974d69ea3d0db71b97af00e325fdfb421c0906c2
tree05c145b633277b78735765d8f9c15f78d504b2ed
parentbb4f7835286f047fc596715101ee0318c8e7f924

ability to call member functions directly

see #14

3 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);
36983698
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 }
37153715
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(
1414import "std.zig";
1415struct Foo {
1416 x: i32,
1417 fn member(foo: Foo) -> i32 { foo.x }
1418}
1419pub 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}