aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2016-01-28 16:45:17 -0700
committerAndrew Kelley <superjoe30@gmail.com>2016-01-28 16:45:17 -0700
commitbb4f7835286f047fc596715101ee0318c8e7f924 (patch)
tree4860d7b895c592e11ca32f451a256e4720d956ba
parent13220ccb51b7d2cf7b8d72a662eece95784116c3 (diff)
downloadzig-bb4f7835286f047fc596715101ee0318c8e7f924.tar.gz
zig-bb4f7835286f047fc596715101ee0318c8e7f924.zip
ability to refer to member function directly
See #14
-rw-r--r--src/analyze.cpp21
-rw-r--r--src/codegen.cpp8
-rw-r--r--test/run_tests.cpp20
3 files changed, 41 insertions, 8 deletions
diff --git a/src/analyze.cpp b/src/analyze.cpp
index abc161ce72..cd743710e2 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -27,6 +27,7 @@ static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *
static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
TypeTableEntry *expected_type, AstNode *node);
static TypeTableEntry *resolve_expr_const_val_as_void(CodeGen *g, AstNode *node);
+static TypeTableEntry *resolve_expr_const_val_as_fn(CodeGen *g, AstNode *node, FnTableEntry *fn);
static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *node);
static AstNode *first_executing_node(AstNode *node) {
@@ -1895,13 +1896,23 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
return g->builtin_types.entry_invalid;
}
} else if (struct_type->id == TypeTableEntryIdMetaType) {
- TypeTableEntry *enum_type = resolve_type(g, struct_expr_node);
+ TypeTableEntry *child_type = resolve_type(g, struct_expr_node);
- if (enum_type->id == TypeTableEntryIdInvalid) {
+ if (child_type->id == TypeTableEntryIdInvalid) {
return g->builtin_types.entry_invalid;
- } else if (enum_type->id == TypeTableEntryIdEnum) {
- return analyze_enum_value_expr(g, import, context, node, nullptr, enum_type, field_name);
- } else if (enum_type->id == TypeTableEntryIdPureError) {
+ } else if (child_type->id == TypeTableEntryIdEnum) {
+ return analyze_enum_value_expr(g, import, context, node, nullptr, child_type, field_name);
+ } else if (child_type->id == TypeTableEntryIdStruct) {
+ auto entry = child_type->data.structure.fn_table.maybe_get(field_name);
+ if (entry) {
+ return resolve_expr_const_val_as_fn(g, node, entry->value);
+ } 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 if (child_type->id == TypeTableEntryIdPureError) {
return analyze_error_literal_expr(g, import, context, node, field_name);
} else {
add_node_error(g, node,
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 2d55000cc4..6f4ba6c58f 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -816,8 +816,12 @@ static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node, bool is_lva
}
} else if (struct_type->id == TypeTableEntryIdMetaType) {
assert(!is_lvalue);
- TypeTableEntry *enum_type = get_type_for_type_node(struct_expr);
- return gen_enum_value_expr(g, node, enum_type, nullptr);
+ TypeTableEntry *child_type = get_type_for_type_node(struct_expr);
+ if (child_type->id == TypeTableEntryIdEnum) {
+ return gen_enum_value_expr(g, node, child_type, nullptr);
+ } else {
+ zig_unreachable();
+ }
} else {
zig_unreachable();
}
diff --git a/test/run_tests.cpp b/test/run_tests.cpp
index 5b4f5a5694..b15f6e2ec4 100644
--- a/test/run_tests.cpp
+++ b/test/run_tests.cpp
@@ -1386,9 +1386,27 @@ pub fn main(args: [][]u8) -> %void {
if (*ptr != 6) {
%%stdout.printf("BAD\n");
}
- %%stdout.printf("OK\n");
free(ptr);
+
+ %%stdout.printf("OK\n");
+}
+ )SOURCE", "OK\n");
+
+ add_simple_case("store member function in variable", 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 member_fn = Foo.member;
+ const result = member_fn(instance);
+ if (result != 1234) {
+ %%stdout.printf("BAD\n");
+ }
+ %%stdout.printf("OK\n");
}
)SOURCE", "OK\n");
}