v.gen.c: fix codegen ordering problem with interfaces with interface fields (#10862)

pull/10866/head weekly.2021.29
Enzo 2021-07-19 18:57:12 +02:00 committed by GitHub
parent 677ef7bb08
commit 1db354c360
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 37 additions and 1 deletions

View File

@ -864,6 +864,11 @@ static inline void __${typ.cname}_pushval($typ.cname ch, $el_stype val) {
}
// Generating interfaces after all the common types have been defined
// to prevent generating interface struct before definition of field types
for typ in g.table.type_symbols {
if typ.kind == .interface_ && typ.name !in c.builtins {
g.write_interface_typedef(typ)
}
}
for typ in g.table.type_symbols {
if typ.kind == .interface_ && typ.name !in c.builtins {
g.write_interface_typesymbol_declaration(typ)
@ -893,13 +898,17 @@ pub fn (mut g Gen) write_alias_typesymbol_declaration(sym ast.TypeSymbol) {
g.type_definitions.writeln('typedef $parent_styp $sym.cname;')
}
pub fn (mut g Gen) write_interface_typedef(sym ast.TypeSymbol) {
struct_name := c_name(sym.cname)
g.type_definitions.writeln('typedef struct $struct_name $struct_name;')
}
pub fn (mut g Gen) write_interface_typesymbol_declaration(sym ast.TypeSymbol) {
info := sym.info as ast.Interface
if info.is_generic {
return
}
struct_name := c_name(sym.cname)
g.type_definitions.writeln('typedef struct $struct_name $struct_name;')
g.type_definitions.writeln('struct $struct_name {')
g.type_definitions.writeln('\tunion {')
g.type_definitions.writeln('\t\tvoid* _object;')
@ -5386,6 +5395,7 @@ fn (mut g Gen) write_builtin_types() {
for builtin_name in c.builtins {
sym := g.table.type_symbols[g.table.type_idxs[builtin_name]]
if sym.kind == .interface_ {
g.write_interface_typedef(sym)
g.write_interface_typesymbol_declaration(sym)
} else {
builtin_types << sym

View File

@ -37,3 +37,29 @@ fn test_interface_nested_field() {
assert ret[0] == 'bar'
assert ret[1] == 'subbar'
}
interface Root {
v View
}
struct MyRoot {
v View
}
interface View {
render() int
}
struct MyView {}
fn (m MyView) render() int {
return 24
}
fn receive_root(r Root) int {
return r.v.render()
}
fn test_nested_interface_fields() {
assert receive_root(MyRoot{MyView{}}) == 24
}