mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
gen: fix interface pointers
This commit is contained in:
parent
40aad27a67
commit
b09fd66aa2
@ -3660,6 +3660,14 @@ _Interface I_${cctype}_to_Interface_${interface_name}(${cctype}* x) {
|
||||
._object = (void*) (x),
|
||||
._interface_idx = ${interface_index_name}
|
||||
};
|
||||
}
|
||||
|
||||
_Interface* I_${cctype}_to_Interface_${interface_name}_ptr(${cctype}* x) {
|
||||
/* TODO Remove memdup */
|
||||
return (_Interface*) memdup(&(_Interface) {
|
||||
._object = (void*) (x),
|
||||
._interface_idx = ${interface_index_name}
|
||||
}, sizeof(_Interface));
|
||||
}')
|
||||
methods_struct.writeln('\t{')
|
||||
st_sym := g.table.get_type_symbol(st)
|
||||
@ -3766,7 +3774,11 @@ fn (mut g Gen) array_init(it ast.ArrayInit) {
|
||||
fn (g &Gen) interface_call(typ, interface_type table.Type) {
|
||||
interface_styp := g.cc_type(interface_type)
|
||||
styp := g.cc_type(typ)
|
||||
g.write('/* $interface_styp */ I_${styp}_to_Interface_${interface_styp}(')
|
||||
mut cast_fn_name := 'I_${styp}_to_Interface_${interface_styp}'
|
||||
if interface_type.is_ptr() {
|
||||
cast_fn_name += '_ptr'
|
||||
}
|
||||
g.write('${cast_fn_name}(')
|
||||
if !typ.is_ptr() {
|
||||
g.write('&')
|
||||
}
|
||||
|
@ -298,9 +298,10 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
||||
// Speaker_name_table[s._interface_idx].speak(s._object)
|
||||
g.write('${c_name(receiver_type_name)}_name_table[')
|
||||
g.expr(node.left)
|
||||
g.write('._interface_idx].${node.name}(')
|
||||
dot := if node.left_type.is_ptr() { '->' } else { '.' }
|
||||
g.write('${dot}_interface_idx].${node.name}(')
|
||||
g.expr(node.left)
|
||||
g.write('._object')
|
||||
g.write('${dot}_object')
|
||||
if node.args.len > 0 {
|
||||
g.write(', ')
|
||||
g.call_args(node.args, node.expected_arg_types)
|
||||
@ -554,11 +555,14 @@ fn (mut g Gen) call_args(args []ast.CallArg, expected_types []table.Type) {
|
||||
// styp := g.typ(arg.typ) // g.table.get_type_symbol(arg.typ)
|
||||
if exp_sym.kind == .interface_ {
|
||||
g.interface_call(arg.typ, expected_types[i])
|
||||
// g.write('/*Z*/I_${styp}_to_${exp_styp}(')
|
||||
is_interface = true
|
||||
}
|
||||
}
|
||||
g.ref_or_deref_arg(arg, expected_types[i])
|
||||
if is_interface {
|
||||
g.expr(arg.expr)
|
||||
} else {
|
||||
g.ref_or_deref_arg(arg, expected_types[i])
|
||||
}
|
||||
} else {
|
||||
g.expr(arg.expr)
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ struct Dog {
|
||||
}
|
||||
|
||||
struct Cat {
|
||||
mut:
|
||||
breed string
|
||||
}
|
||||
|
||||
@ -25,6 +26,10 @@ fn (c Cat) name_detailed(pet_name string) string {
|
||||
return '$pet_name the ${typeof(c)}, breed:${c.breed}'
|
||||
}
|
||||
|
||||
fn (c mut Cat) set_breed(new string) {
|
||||
c.breed = new
|
||||
}
|
||||
|
||||
// utility function to convert to string, as a sample
|
||||
fn (c Cat) str() string {
|
||||
return 'Cat: $c.breed'
|
||||
@ -44,6 +49,10 @@ fn (d Dog) name_detailed(pet_name string) string {
|
||||
return '$pet_name the ${typeof(d)}, breed:${d.breed}'
|
||||
}
|
||||
|
||||
fn (d mut Dog) set_breed(new string) {
|
||||
println('Nah')
|
||||
}
|
||||
|
||||
// do not add to Dog the utility function 'str', as a sample
|
||||
fn test_todo() {
|
||||
if true {
|
||||
@ -62,11 +71,23 @@ fn perform_speak(a Animal) {
|
||||
println(a.name())
|
||||
}
|
||||
|
||||
fn perform_speak_on_ptr(a &Animal) {
|
||||
a.speak('Hi !')
|
||||
assert true
|
||||
name := a.name()
|
||||
assert name == 'Dog' || name == 'Cat'
|
||||
// if a is Dog {
|
||||
// assert name == 'Dog'
|
||||
// }
|
||||
println(a.name())
|
||||
}
|
||||
|
||||
fn test_perform_speak() {
|
||||
dog := Dog{
|
||||
breed: 'Labrador Retriever'
|
||||
}
|
||||
perform_speak(dog)
|
||||
perform_speak_on_ptr(dog)
|
||||
cat := Cat{
|
||||
breed: 'Persian'
|
||||
}
|
||||
@ -74,6 +95,10 @@ fn test_perform_speak() {
|
||||
perform_speak(Cat{
|
||||
breed: 'Persian'
|
||||
})
|
||||
perform_speak_on_ptr(cat)
|
||||
perform_speak_on_ptr(Cat{
|
||||
breed: 'Persian'
|
||||
})
|
||||
handle_animals([dog, cat])
|
||||
/*
|
||||
f := Foo {
|
||||
@ -82,6 +107,19 @@ fn test_perform_speak() {
|
||||
*/
|
||||
}
|
||||
|
||||
fn change_animal_breed(a &Animal, new string) {
|
||||
a.set_breed(new)
|
||||
}
|
||||
|
||||
fn test_interface_ptr_modification() {
|
||||
mut cat := Cat{
|
||||
breed: 'Persian'
|
||||
}
|
||||
// TODO Should fail and require `mut cat`
|
||||
change_animal_breed(cat, 'Siamese')
|
||||
assert cat.breed == 'Siamese'
|
||||
}
|
||||
|
||||
fn perform_name_detailed(a Animal) {
|
||||
name_full := a.name_detailed('MyPet')
|
||||
println(name_full)
|
||||
@ -142,6 +180,7 @@ interface Animal {
|
||||
name() string
|
||||
name_detailed(pet_name string) string
|
||||
speak(s string)
|
||||
set_breed(s string)
|
||||
}
|
||||
|
||||
fn test_interface_array() {
|
||||
@ -150,6 +189,7 @@ fn test_interface_array() {
|
||||
animals = [Cat{}, Dog{
|
||||
breed: 'Labrador Retriever'
|
||||
}]
|
||||
assert true
|
||||
animals << Cat{}
|
||||
assert true
|
||||
// TODO .str() from the real types should be called
|
||||
@ -157,3 +197,14 @@ fn test_interface_array() {
|
||||
// println('Animals array contains: ${animals}') // implicit call to 'str' function
|
||||
assert animals.len == 3
|
||||
}
|
||||
|
||||
fn test_interface_ptr_array() {
|
||||
mut animals := []&Animal{}
|
||||
animals = [Cat{}, Dog{
|
||||
breed: 'Labrador Retriever'
|
||||
}]
|
||||
assert true
|
||||
animals << Cat{}
|
||||
assert true
|
||||
assert animals.len == 3
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user