compiler: stabilize the interface code generation a little
parent
8fafaf38a3
commit
c6107276df
|
@ -470,23 +470,38 @@ fn (v &V) interface_table() string {
|
||||||
if t.cat != .interface_ {
|
if t.cat != .interface_ {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
// interface_name is for example Speaker
|
||||||
interface_name := t.name
|
interface_name := t.name
|
||||||
mut methods := ''
|
mut methods := ''
|
||||||
|
mut generated_casting_functions := ''
|
||||||
sb.writeln('// NR methods = $t.gen_types.len')
|
sb.writeln('// NR methods = $t.gen_types.len')
|
||||||
for i, gen_type in t.gen_types {
|
for i, gen_type in t.gen_types {
|
||||||
gen_concrete_type_name := gen_type.replace('*', '')
|
// ptr_ctype can be for example Cat OR Cat_ptr:
|
||||||
|
ptr_ctype := gen_type.replace('*', '_ptr')
|
||||||
|
// cctype is the Cleaned Concrete Type name, *without ptr*,
|
||||||
|
// i.e. cctype is always just Cat, not Cat_ptr:
|
||||||
|
cctype := gen_type.replace('*', '')
|
||||||
|
|
||||||
|
// Speaker_Cat_index = 0
|
||||||
|
interface_index_name := '_${interface_name}_${ptr_ctype}_index'
|
||||||
|
|
||||||
|
generated_casting_functions += '
|
||||||
|
${interface_name} I_${cctype}_to_${interface_name}(${cctype} x) {
|
||||||
|
return (${interface_name}){
|
||||||
|
._object = (void*) memdup(&x, sizeof(${cctype})),
|
||||||
|
._interface_idx = ${interface_index_name} };
|
||||||
|
}
|
||||||
|
'
|
||||||
methods += '{\n'
|
methods += '{\n'
|
||||||
for j, method in t.methods {
|
for j, method in t.methods {
|
||||||
// Cat_speak
|
// Cat_speak
|
||||||
methods += ' (void*) ${gen_concrete_type_name}_${method.name}'
|
methods += ' (void*) ${cctype}_${method.name}'
|
||||||
if j < t.methods.len - 1 {
|
if j < t.methods.len - 1 {
|
||||||
methods += ', \n'
|
methods += ', \n'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
methods += '\n},\n\n'
|
methods += '\n},\n\n'
|
||||||
// Speaker_Cat_index = 0
|
sb.writeln('int ${interface_index_name} = $i;')
|
||||||
concrete_type_name := gen_type.replace('*', '_ptr')
|
|
||||||
sb.writeln('int _${interface_name}_${concrete_type_name}_index = $i;')
|
|
||||||
}
|
}
|
||||||
if t.gen_types.len > 0 {
|
if t.gen_types.len > 0 {
|
||||||
// methods = '{TCCSKIP(0)}'
|
// methods = '{TCCSKIP(0)}'
|
||||||
|
@ -499,7 +514,10 @@ fn (v &V) interface_table() string {
|
||||||
// See https://github.com/zenith391/vgtk3/issues/7
|
// See https://github.com/zenith391/vgtk3/issues/7
|
||||||
sb.writeln('void* (* ${interface_name}_name_table[][1]) = ' + '{ {NULL} }; ')
|
sb.writeln('void* (* ${interface_name}_name_table[][1]) = ' + '{ {NULL} }; ')
|
||||||
}
|
}
|
||||||
continue
|
if generated_casting_functions.len > 0 {
|
||||||
|
sb.writeln('// Casting functions for interface "${interface_name}" :')
|
||||||
|
sb.writeln( generated_casting_functions )
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return sb.str()
|
return sb.str()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1115,12 +1115,18 @@ fn (p mut Parser) fn_call_args(f mut Fn, generic_param_types []string) {
|
||||||
if arg.typ.ends_with('er') || arg.typ[0] == `I` {
|
if arg.typ.ends_with('er') || arg.typ[0] == `I` {
|
||||||
t := p.table.find_type(arg.typ)
|
t := p.table.find_type(arg.typ)
|
||||||
if t.cat == .interface_ {
|
if t.cat == .interface_ {
|
||||||
// perform((Speaker) { ._object = &dog,
|
// NB: here concrete_type_name can be 'Dog' OR 'Dog_ptr'
|
||||||
// _interface_idx = _Speaker_Dog_index })
|
// cgen should have generated a _I_Dog_to_Speaker conversion function
|
||||||
if !f.is_method {
|
// C: perform( _I_Dog_to_Speaker((Dog){...}) )
|
||||||
concrete_type_name := typ.replace('*', '_ptr')
|
// In case of _ptr, there is no need for conversion, so the generated
|
||||||
p.cgen.set_placeholder(ph, '($arg.typ) { ._object = &')
|
// code will be just:
|
||||||
p.gen(', ._interface_idx = _${arg.typ}_${concrete_type_name}_index} ')
|
// C: perform( dog_ptr )
|
||||||
|
concrete_type_name := typ.replace('*', '_ptr')
|
||||||
|
// concrete_type_name here can be say Dog, or ui__Group_ptr (in vui)
|
||||||
|
//eprintln('arg.typ: $arg.typ | concrete_type_name: $concrete_type_name ')
|
||||||
|
if !concrete_type_name.ends_with('_ptr') {
|
||||||
|
p.cgen.set_placeholder(ph, 'I_${concrete_type_name}_to_${arg.typ}(')
|
||||||
|
p.gen(')')
|
||||||
}
|
}
|
||||||
p.table.add_gen_type(arg.typ, typ)
|
p.table.add_gen_type(arg.typ, typ)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
module main
|
||||||
|
|
||||||
|
interface Speaker {
|
||||||
|
say() string
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ChatRoom {
|
||||||
|
mut:
|
||||||
|
talkers map[string]Speaker
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_room() &ChatRoom {
|
||||||
|
return &ChatRoom{
|
||||||
|
talkers: map[string]Speaker
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (r mut ChatRoom) add(name string, s Speaker) {
|
||||||
|
r.talkers[name] = s
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_using_a_map_of_speaker_interfaces(){
|
||||||
|
mut room := new_room()
|
||||||
|
room.add('my cat', Cat{name: 'Tigga'} )
|
||||||
|
room.add('my dog', Dog{name: 'Pirin'} )
|
||||||
|
room.add('stray dog', Dog{name: 'Anoni'} )
|
||||||
|
room.add('me', Human{name: 'Bilbo'} )
|
||||||
|
room.add('she', Human{name: 'Maria'} )
|
||||||
|
mut text := ''
|
||||||
|
for name, subject in room.talkers {
|
||||||
|
line := '${name:12s}: ${subject.say()}'
|
||||||
|
println(line)
|
||||||
|
text += line
|
||||||
|
}
|
||||||
|
assert text.contains(' meows ')
|
||||||
|
assert text.contains(' barks ')
|
||||||
|
assert text.contains(' says ')
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
struct Cat { name string }
|
||||||
|
fn (c &Cat) say() string { return '${c.name} meows "MEOW!"' }
|
||||||
|
|
||||||
|
struct Dog { name string }
|
||||||
|
fn (d &Dog) say() string { return '${d.name} barks "Bau Bau!"' }
|
||||||
|
|
||||||
|
struct Human { name string }
|
||||||
|
fn (h &Human) say() string { return '${h.name} says "Hello"' }
|
Loading…
Reference in New Issue