ability to call member functions directly

see #14
master
Andrew Kelley 2016-01-28 16:55:54 -07:00
parent bb4f783528
commit 974d69ea3d
3 changed files with 50 additions and 13 deletions

View File

@ -3694,17 +3694,17 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import
} else if (struct_type->id == TypeTableEntryIdInvalid) { } else if (struct_type->id == TypeTableEntryIdInvalid) {
return struct_type; return struct_type;
} else if (struct_type->id == TypeTableEntryIdMetaType) { } else if (struct_type->id == TypeTableEntryIdMetaType) {
TypeTableEntry *enum_type = resolve_type(g, first_param_expr); TypeTableEntry *child_type = resolve_type(g, first_param_expr);
if (enum_type->id == TypeTableEntryIdInvalid) { if (child_type->id == TypeTableEntryIdInvalid) {
return g->builtin_types.entry_invalid; return g->builtin_types.entry_invalid;
} else if (enum_type->id == TypeTableEntryIdEnum) { } else if (child_type->id == TypeTableEntryIdEnum) {
Buf *field_name = &fn_ref_expr->data.field_access_expr.field_name; Buf *field_name = &fn_ref_expr->data.field_access_expr.field_name;
int param_count = node->data.fn_call_expr.params.length; int param_count = node->data.fn_call_expr.params.length;
if (param_count > 1) { if (param_count > 1) {
add_node_error(g, first_executing_node(node->data.fn_call_expr.params.at(1)), add_node_error(g, first_executing_node(node->data.fn_call_expr.params.at(1)),
buf_sprintf("enum values accept only one parameter")); buf_sprintf("enum values accept only one parameter"));
return enum_type; return child_type;
} else { } else {
AstNode *value_node; AstNode *value_node;
if (param_count == 1) { if (param_count == 1) {
@ -3714,7 +3714,19 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import
} }
return analyze_enum_value_expr(g, import, context, fn_ref_expr, value_node, return analyze_enum_value_expr(g, import, context, fn_ref_expr, value_node,
enum_type, field_name); child_type, field_name);
}
} else if (child_type->id == TypeTableEntryIdStruct) {
Buf *field_name = &fn_ref_expr->data.field_access_expr.field_name;
auto entry = child_type->data.structure.fn_table.maybe_get(field_name);
if (entry) {
return analyze_fn_call_raw(g, import, context, expected_type, node,
entry->value, nullptr);
} else {
add_node_error(g, node,
buf_sprintf("struct '%s' has no function called '%s'",
buf_ptr(&child_type->name), buf_ptr(field_name)));
return g->builtin_types.entry_invalid;
} }
} else { } else {
add_node_error(g, first_param_expr, buf_sprintf("member reference base type not struct or enum")); add_node_error(g, first_param_expr, buf_sprintf("member reference base type not struct or enum"));

View File

@ -496,7 +496,9 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {
assert(struct_type->data.pointer.child_type->id == TypeTableEntryIdStruct); assert(struct_type->data.pointer.child_type->id == TypeTableEntryIdStruct);
fn_table_entry = node->data.fn_call_expr.fn_entry; fn_table_entry = node->data.fn_call_expr.fn_entry;
} else if (struct_type->id == TypeTableEntryIdMetaType) { } else if (struct_type->id == TypeTableEntryIdMetaType) {
TypeTableEntry *enum_type = get_type_for_type_node(first_param_expr); TypeTableEntry *child_type = get_type_for_type_node(first_param_expr);
if (child_type->id == TypeTableEntryIdEnum) {
int param_count = node->data.fn_call_expr.params.length; int param_count = node->data.fn_call_expr.params.length;
AstNode *arg1_node; AstNode *arg1_node;
if (param_count == 1) { if (param_count == 1) {
@ -505,7 +507,14 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {
assert(param_count == 0); assert(param_count == 0);
arg1_node = nullptr; arg1_node = nullptr;
} }
return gen_enum_value_expr(g, fn_ref_expr, enum_type, arg1_node); return gen_enum_value_expr(g, fn_ref_expr, child_type, arg1_node);
} else if (child_type->id == TypeTableEntryIdStruct) {
struct_type = nullptr;
first_param_expr = nullptr;
fn_table_entry = node->data.fn_call_expr.fn_entry;
} else {
zig_unreachable();
}
} else { } else {
zig_unreachable(); zig_unreachable();
} }

View File

@ -1407,6 +1407,22 @@ pub fn main(args: [][]u8) -> %void {
%%stdout.printf("BAD\n"); %%stdout.printf("BAD\n");
} }
%%stdout.printf("OK\n"); %%stdout.printf("OK\n");
}
)SOURCE", "OK\n");
add_simple_case("call member function directly", R"SOURCE(
import "std.zig";
struct Foo {
x: i32,
fn member(foo: Foo) -> i32 { foo.x }
}
pub fn main(args: [][]u8) -> %void {
const instance = Foo { .x = 1234, };
const result = Foo.member(instance);
if (result != 1234) {
%%stdout.printf("BAD\n");
}
%%stdout.printf("OK\n");
} }
)SOURCE", "OK\n"); )SOURCE", "OK\n");
} }