cgen: more interface fixes

pull/4678/head
Alexander Medvednikov 2020-05-02 00:28:42 +02:00
parent 7038f59ca5
commit 2f64594ce0
3 changed files with 18 additions and 12 deletions

View File

@ -3364,6 +3364,7 @@ fn (g Gen) type_to_fmt(typ table.Type) string {
} }
// Generates interface table and interface indexes // Generates interface table and interface indexes
// TODO remove all `replace()`
fn (v &Gen) interface_table() string { fn (v &Gen) interface_table() string {
mut sb := strings.new_builder(100) mut sb := strings.new_builder(100)
for _, t in v.table.types { for _, t in v.table.types {
@ -3378,10 +3379,10 @@ fn (v &Gen) interface_table() string {
sb.writeln('// NR gen_types= $info.gen_types.len') sb.writeln('// NR gen_types= $info.gen_types.len')
for i, gen_type in info.gen_types { for i, gen_type in info.gen_types {
// ptr_ctype can be for example Cat OR Cat_ptr: // ptr_ctype can be for example Cat OR Cat_ptr:
ptr_ctype := gen_type.replace('*', '_ptr') ptr_ctype := gen_type.replace('*', '_ptr').replace('.', '__')
// cctype is the Cleaned Concrete Type name, *without ptr*, // cctype is the Cleaned Concrete Type name, *without ptr*,
// i.e. cctype is always just Cat, not Cat_ptr: // i.e. cctype is always just Cat, not Cat_ptr:
cctype := gen_type.replace('*', '') cctype := gen_type.replace('*', '').replace('.', '__')
// Speaker_Cat_index = 0 // Speaker_Cat_index = 0
interface_index_name := '_${interface_name}_${ptr_ctype}_index' interface_index_name := '_${interface_name}_${ptr_ctype}_index'
generated_casting_functions += ' generated_casting_functions += '
@ -3457,9 +3458,11 @@ fn (mut g Gen) array_init(it ast.ArrayInit) {
g.write('($elem_type_str[$len]){\n\t\t') g.write('($elem_type_str[$len]){\n\t\t')
for i, expr in it.exprs { for i, expr in it.exprs {
if it.is_interface { if it.is_interface {
sym := g.table.get_type_symbol(it.interface_types[i]) // sym := g.table.get_type_symbol(it.interface_types[i])
isym := g.table.get_type_symbol(it.interface_type) // isym := g.table.get_type_symbol(it.interface_type)
g.write('I_${sym.name}_to_${isym.name}(') interface_styp := g.typ(it.interface_type)
styp := g.typ(it.interface_types[i])
g.write('I_${styp}_to_${interface_styp}(')
} }
g.expr(expr) g.expr(expr)
if it.is_interface { if it.is_interface {

View File

@ -277,7 +277,8 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
verror('method receiver type is 0, this means there are some uchecked exprs') verror('method receiver type is 0, this means there are some uchecked exprs')
} }
typ_sym := g.table.get_type_symbol(node.receiver_type) typ_sym := g.table.get_type_symbol(node.receiver_type)
mut receiver_name := typ_sym.name // mut receiver_type_name := g.typ(node.receiver_type)
mut receiver_type_name := typ_sym.name.replace('.', '__') // TODO g.typ() ?
if typ_sym.kind == .interface_ { if typ_sym.kind == .interface_ {
// Find the index of the method // Find the index of the method
mut idx := -1 mut idx := -1
@ -292,7 +293,7 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
sret_type := g.typ(node.return_type) sret_type := g.typ(node.return_type)
g.writeln('// interface method call') g.writeln('// interface method call')
// `((void (*)())(Speaker_name_table[s._interface_idx][1]))(s._object);` // `((void (*)())(Speaker_name_table[s._interface_idx][1]))(s._object);`
g.write('(($sret_type (*)())(${receiver_name}_name_table[') g.write('(($sret_type (*)())(${receiver_type_name}_name_table[')
g.expr(node.left) g.expr(node.left)
g.write('._interface_idx][$idx]))(') g.write('._interface_idx][$idx]))(')
g.expr(node.left) g.expr(node.left)
@ -327,13 +328,13 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
// && rec_sym.name == 'array' { // && rec_sym.name == 'array' {
// && rec_sym.name == 'array' && receiver_name.starts_with('array') { // && rec_sym.name == 'array' && receiver_name.starts_with('array') {
// `array_byte_clone` => `array_clone` // `array_byte_clone` => `array_clone`
receiver_name = 'array' receiver_type_name = 'array'
if node.name in ['last', 'first'] { if node.name in ['last', 'first'] {
return_type_str := g.typ(node.return_type) return_type_str := g.typ(node.return_type)
g.write('*($return_type_str*)') g.write('*($return_type_str*)')
} }
} }
name := '${receiver_name}_$node.name'.replace('.', '__') name := '${receiver_type_name}_$node.name'.replace('.', '__')
// if node.receiver_type != 0 { // if node.receiver_type != 0 {
// g.write('/*${g.typ(node.receiver_type)}*/') // g.write('/*${g.typ(node.receiver_type)}*/')
// g.write('/*expr_type=${g.typ(node.left_type)} rec type=${g.typ(node.receiver_type)}*/') // g.write('/*expr_type=${g.typ(node.left_type)} rec type=${g.typ(node.receiver_type)}*/')
@ -509,9 +510,10 @@ fn (mut g Gen) call_args(args []ast.CallArg, expected_types []table.Type) {
// Cast a type to interface // Cast a type to interface
// `foo(dog)` => `foo(I_Dog_to_Animal(dog))` // `foo(dog)` => `foo(I_Dog_to_Animal(dog))`
exp_sym := g.table.get_type_symbol(expected_types[arg_no]) exp_sym := g.table.get_type_symbol(expected_types[arg_no])
sym := g.table.get_type_symbol(arg.typ) exp_styp := g.typ(expected_types[arg_no]) // g.table.get_type_symbol(expected_types[arg_no])
styp := g.typ(arg.typ) // g.table.get_type_symbol(arg.typ)
if exp_sym.kind == .interface_ { if exp_sym.kind == .interface_ {
g.write('I_${sym.name}_to_${exp_sym.name}(') g.write('/*i*/I_${styp}_to_${exp_styp}(')
is_interface = true is_interface = true
} }
} }

View File

@ -490,7 +490,8 @@ pub fn (t &Table) check(got, expected Type) bool {
mut info := exp_type_sym.info as Interface mut info := exp_type_sym.info as Interface
// println('gen_types before') // println('gen_types before')
// println(info.gen_types) // println(info.gen_types)
if got_type_sym.name !in info.gen_types { if got_type_sym.name !in info.gen_types && got_type_sym.kind != .interface_ {
// TODO `got` should never be an interface?
info.gen_types << got_type_sym.name info.gen_types << got_type_sym.name
} }
// println('adding gen_type $got_type_sym.name') // println('adding gen_type $got_type_sym.name')