add VarDecl support for struct-method call syntax

implements #3306
master
Michael Dusan 2019-09-24 17:53:05 -04:00 committed by Andrew Kelley
parent 56b1818beb
commit 9983501ff2
3 changed files with 69 additions and 11 deletions

View File

@ -17675,18 +17675,36 @@ static IrInstruction *ir_analyze_container_member_access_inner(IrAnalyze *ira,
assert(container_scope != nullptr);
auto entry = container_scope->decl_table.maybe_get(field_name);
Tld *tld = entry ? entry->value : nullptr;
if (tld && tld->id == TldIdFn) {
resolve_top_level_decl(ira->codegen, tld, source_instr->source_node, false);
if (tld->resolution == TldResolutionInvalid)
return ira->codegen->invalid_instruction;
TldFn *tld_fn = (TldFn *)tld;
ZigFn *fn_entry = tld_fn->fn_entry;
if (type_is_invalid(fn_entry->type_entry))
return ira->codegen->invalid_instruction;
if (tld) {
if (tld->id == TldIdFn) {
resolve_top_level_decl(ira->codegen, tld, source_instr->source_node, false);
if (tld->resolution == TldResolutionInvalid)
return ira->codegen->invalid_instruction;
TldFn *tld_fn = (TldFn *)tld;
ZigFn *fn_entry = tld_fn->fn_entry;
if (type_is_invalid(fn_entry->type_entry))
return ira->codegen->invalid_instruction;
IrInstruction *bound_fn_value = ir_build_const_bound_fn(&ira->new_irb, source_instr->scope,
source_instr->source_node, fn_entry, container_ptr);
return ir_get_ref(ira, source_instr, bound_fn_value, true, false);
IrInstruction *bound_fn_value = ir_build_const_bound_fn(&ira->new_irb, source_instr->scope,
source_instr->source_node, fn_entry, container_ptr);
return ir_get_ref(ira, source_instr, bound_fn_value, true, false);
} else if (tld->id == TldIdVar) {
resolve_top_level_decl(ira->codegen, tld, source_instr->source_node, false);
if (tld->resolution == TldResolutionInvalid)
return ira->codegen->invalid_instruction;
TldVar *tld_var = (TldVar *)tld;
ZigVar *var = tld_var->var;
if (type_is_invalid(var->var_type))
return ira->codegen->invalid_instruction;
if (var->const_value->type->id == ZigTypeIdFn) {
ir_assert(var->const_value->data.x_ptr.special == ConstPtrSpecialFunction, source_instr);
ZigFn *fn = var->const_value->data.x_ptr.data.fn.fn_entry;
IrInstruction *bound_fn_value = ir_build_const_bound_fn(&ira->new_irb, source_instr->scope,
source_instr->source_node, fn, container_ptr);
return ir_get_ref(ira, source_instr, bound_fn_value, true, false);
}
}
}
}
const char *prefix_name;

View File

@ -58,6 +58,7 @@ comptime {
_ = @import("behavior/floatop.zig");
_ = @import("behavior/fn.zig");
_ = @import("behavior/fn_in_struct_in_comptime.zig");
_ = @import("behavior/fn_delegation.zig");
_ = @import("behavior/for.zig");
_ = @import("behavior/generics.zig");
_ = @import("behavior/hasdecl.zig");

View File

@ -0,0 +1,39 @@
const expect = @import("std").testing.expect;
const Foo = struct {
a: u64 = 10,
fn one(self: Foo) u64 {
return self.a + 1;
}
const two = __two;
fn __two(self: Foo) u64 {
return self.a + 2;
}
const three = __three;
const four = custom(Foo, 4);
};
fn __three(self: Foo) u64 {
return self.a + 3;
}
fn custom(comptime T: type, comptime num: u64) fn (T) u64 {
return struct {
fn function(self: T) u64 {
return self.a + num;
}
}.function;
}
test "fn delegation" {
const foo = Foo{};
expect(foo.one() == 11);
expect(foo.two() == 12);
expect(foo.three() == 13);
expect(foo.four() == 14);
}