Skip to content

Commit

Permalink
add VarDecl support for struct-method call syntax
Browse files Browse the repository at this point in the history
implements #3306
  • Loading branch information
mikdusan authored and andrewrk committed Sep 24, 2019
1 parent 56b1818 commit 9983501
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 11 deletions.
40 changes: 29 additions & 11 deletions src/ir.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
} 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;

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);
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;
Expand Down
1 change: 1 addition & 0 deletions test/stage1/behavior.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
39 changes: 39 additions & 0 deletions test/stage1/behavior/fn_delegation.zig
Original file line number Diff line number Diff line change
@@ -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);
}

0 comments on commit 9983501

Please sign in to comment.