gen: fix interface pointers
parent
40aad27a67
commit
b09fd66aa2
|
@ -3660,6 +3660,14 @@ _Interface I_${cctype}_to_Interface_${interface_name}(${cctype}* x) {
|
||||||
._object = (void*) (x),
|
._object = (void*) (x),
|
||||||
._interface_idx = ${interface_index_name}
|
._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{')
|
methods_struct.writeln('\t{')
|
||||||
st_sym := g.table.get_type_symbol(st)
|
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) {
|
fn (g &Gen) interface_call(typ, interface_type table.Type) {
|
||||||
interface_styp := g.cc_type(interface_type)
|
interface_styp := g.cc_type(interface_type)
|
||||||
styp := g.cc_type(typ)
|
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() {
|
if !typ.is_ptr() {
|
||||||
g.write('&')
|
g.write('&')
|
||||||
}
|
}
|
||||||
|
|
|
@ -298,9 +298,10 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
||||||
// Speaker_name_table[s._interface_idx].speak(s._object)
|
// Speaker_name_table[s._interface_idx].speak(s._object)
|
||||||
g.write('${c_name(receiver_type_name)}_name_table[')
|
g.write('${c_name(receiver_type_name)}_name_table[')
|
||||||
g.expr(node.left)
|
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.expr(node.left)
|
||||||
g.write('._object')
|
g.write('${dot}_object')
|
||||||
if node.args.len > 0 {
|
if node.args.len > 0 {
|
||||||
g.write(', ')
|
g.write(', ')
|
||||||
g.call_args(node.args, node.expected_arg_types)
|
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)
|
// styp := g.typ(arg.typ) // g.table.get_type_symbol(arg.typ)
|
||||||
if exp_sym.kind == .interface_ {
|
if exp_sym.kind == .interface_ {
|
||||||
g.interface_call(arg.typ, expected_types[i])
|
g.interface_call(arg.typ, expected_types[i])
|
||||||
// g.write('/*Z*/I_${styp}_to_${exp_styp}(')
|
|
||||||
is_interface = true
|
is_interface = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if is_interface {
|
||||||
|
g.expr(arg.expr)
|
||||||
|
} else {
|
||||||
g.ref_or_deref_arg(arg, expected_types[i])
|
g.ref_or_deref_arg(arg, expected_types[i])
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
g.expr(arg.expr)
|
g.expr(arg.expr)
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ struct Dog {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Cat {
|
struct Cat {
|
||||||
|
mut:
|
||||||
breed string
|
breed string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,6 +26,10 @@ fn (c Cat) name_detailed(pet_name string) string {
|
||||||
return '$pet_name the ${typeof(c)}, breed:${c.breed}'
|
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
|
// utility function to convert to string, as a sample
|
||||||
fn (c Cat) str() string {
|
fn (c Cat) str() string {
|
||||||
return 'Cat: $c.breed'
|
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}'
|
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
|
// do not add to Dog the utility function 'str', as a sample
|
||||||
fn test_todo() {
|
fn test_todo() {
|
||||||
if true {
|
if true {
|
||||||
|
@ -62,11 +71,23 @@ fn perform_speak(a Animal) {
|
||||||
println(a.name())
|
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() {
|
fn test_perform_speak() {
|
||||||
dog := Dog{
|
dog := Dog{
|
||||||
breed: 'Labrador Retriever'
|
breed: 'Labrador Retriever'
|
||||||
}
|
}
|
||||||
perform_speak(dog)
|
perform_speak(dog)
|
||||||
|
perform_speak_on_ptr(dog)
|
||||||
cat := Cat{
|
cat := Cat{
|
||||||
breed: 'Persian'
|
breed: 'Persian'
|
||||||
}
|
}
|
||||||
|
@ -74,6 +95,10 @@ fn test_perform_speak() {
|
||||||
perform_speak(Cat{
|
perform_speak(Cat{
|
||||||
breed: 'Persian'
|
breed: 'Persian'
|
||||||
})
|
})
|
||||||
|
perform_speak_on_ptr(cat)
|
||||||
|
perform_speak_on_ptr(Cat{
|
||||||
|
breed: 'Persian'
|
||||||
|
})
|
||||||
handle_animals([dog, cat])
|
handle_animals([dog, cat])
|
||||||
/*
|
/*
|
||||||
f := Foo {
|
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) {
|
fn perform_name_detailed(a Animal) {
|
||||||
name_full := a.name_detailed('MyPet')
|
name_full := a.name_detailed('MyPet')
|
||||||
println(name_full)
|
println(name_full)
|
||||||
|
@ -142,6 +180,7 @@ interface Animal {
|
||||||
name() string
|
name() string
|
||||||
name_detailed(pet_name string) string
|
name_detailed(pet_name string) string
|
||||||
speak(s string)
|
speak(s string)
|
||||||
|
set_breed(s string)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_interface_array() {
|
fn test_interface_array() {
|
||||||
|
@ -150,6 +189,7 @@ fn test_interface_array() {
|
||||||
animals = [Cat{}, Dog{
|
animals = [Cat{}, Dog{
|
||||||
breed: 'Labrador Retriever'
|
breed: 'Labrador Retriever'
|
||||||
}]
|
}]
|
||||||
|
assert true
|
||||||
animals << Cat{}
|
animals << Cat{}
|
||||||
assert true
|
assert true
|
||||||
// TODO .str() from the real types should be called
|
// 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
|
// println('Animals array contains: ${animals}') // implicit call to 'str' function
|
||||||
assert animals.len == 3
|
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