diff options
| author | Andrew Kelley <superjoe30@gmail.com> | 2016-01-28 16:45:17 -0700 |
|---|---|---|
| committer | Andrew Kelley <superjoe30@gmail.com> | 2016-01-28 16:45:17 -0700 |
| commit | bb4f7835286f047fc596715101ee0318c8e7f924 (patch) | |
| tree | 4860d7b895c592e11ca32f451a256e4720d956ba | |
| parent | 13220ccb51b7d2cf7b8d72a662eece95784116c3 (diff) | |
| download | zig-bb4f7835286f047fc596715101ee0318c8e7f924.tar.gz zig-bb4f7835286f047fc596715101ee0318c8e7f924.zip | |
ability to refer to member function directly
See #14
| -rw-r--r-- | src/analyze.cpp | 21 | ||||
| -rw-r--r-- | src/codegen.cpp | 8 | ||||
| -rw-r--r-- | test/run_tests.cpp | 20 |
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"); } |
