v/vlib/v/tests/methods_as_fields_test.v

120 lines
2.0 KiB
V

struct Foo {
s string
mut:
i int
}
fn (f Foo) get_s() string {
return f.s
}
fn (f &Foo) get_s_ref() string {
return f.s
}
fn (f Foo) add(a int) int {
return a + f.i
}
fn (f &Foo) add_ref(a int) int {
return a + f.i
}
fn (mut f Foo) set(a int) {
f.i = a
}
fn (f_ Foo) set_val(a int) int {
mut f := unsafe { &f_ }
old := f.i
f.i = a
return old
}
fn test_methods_as_fields() {
mut f := Foo{
s: 'hello'
i: 1
}
get_s := f.get_s
get_s_ref := unsafe { f.get_s_ref }
add := f.add
add_ref := unsafe { f.add_ref }
set := unsafe { f.set }
set_val := f.set_val
assert typeof(get_s).str() == 'fn () string'
assert typeof(get_s_ref).str() == 'fn () string'
assert typeof(add).str() == 'fn (int) int'
assert typeof(add_ref).str() == 'fn (int) int'
assert get_s() == 'hello'
assert get_s_ref() == 'hello'
assert add(2) == 3
assert add_ref(2) == 3
assert f.i == 1
set(2)
assert f.i == 2
old := set_val(3)
assert f.i == 2
new := set_val(5)
assert old == new && old == 1
}
// the difference between these two tests is that here `f` is &Foo
fn test_methods_as_fields_ref() {
mut f := &Foo{
s: 'hello'
i: 1
}
get_s := f.get_s
get_s_ref := unsafe { f.get_s_ref }
add := f.add
add_ref := unsafe { f.add_ref }
set := unsafe { f.set }
set_val := f.set_val
assert typeof(get_s).str() == 'fn () string'
assert typeof(get_s_ref).str() == 'fn () string'
assert typeof(add).str() == 'fn (int) int'
assert typeof(add_ref).str() == 'fn (int) int'
assert get_s() == 'hello'
assert get_s_ref() == 'hello'
assert add(2) == 3
assert add_ref(2) == 3
assert f.i == 1
set(2)
assert f.i == 2
old := set_val(3)
assert f.i == 2
new := set_val(5)
assert old == new && old == 1
}
struct GG_Ctx {
frame_fn fn (voidptr) int
}
[heap]
struct App {
msg string = 'hello'
}
fn (app &App) frame() int {
return app.msg.len
}
fn test_ctx_arg_expected() {
mut app := &App{}
mut ctx := &GG_Ctx{
frame_fn: app.frame
}
assert typeof(ctx.frame_fn).str() == 'fn (voidptr) int'
assert ctx.frame_fn(app) == 5
}