mirror of
https://github.com/vlang/v.git
synced 2025-08-03 17:57:59 -04:00
v.gen.c: support inter-dependent function types (#20638)
This commit is contained in:
parent
d750d1f5a0
commit
a09bd7cff3
@ -1515,11 +1515,7 @@ static inline void __${sym.cname}_pushval(${sym.cname} ch, ${push_arg} val) {
|
||||
g.write_alias_typesymbol_declaration(sym)
|
||||
}
|
||||
}
|
||||
for sym in g.table.type_symbols {
|
||||
if sym.kind == .function && sym.name !in c.builtins {
|
||||
g.write_fn_typesymbol_declaration(sym)
|
||||
}
|
||||
}
|
||||
g.write_sorted_fn_typesymbol_declaration()
|
||||
// Generating interfaces after all the common types have been defined
|
||||
// to prevent generating interface struct before definition of field types
|
||||
for sym in g.table.type_symbols {
|
||||
@ -6382,6 +6378,63 @@ fn (mut g Gen) sort_globals_consts() {
|
||||
}
|
||||
}
|
||||
|
||||
// sort functions by dependent arguments and return value
|
||||
// As functions may depend on one another, make sure they are
|
||||
// defined in the correct order: add non dependent ones first.
|
||||
fn (mut g Gen) write_sorted_fn_typesymbol_declaration() {
|
||||
util.timing_start(@METHOD)
|
||||
defer {
|
||||
util.timing_measure(@METHOD)
|
||||
}
|
||||
mut syms := []&ast.TypeSymbol{} // functions to be defined
|
||||
for sym in g.table.type_symbols {
|
||||
if sym.kind == .function && sym.name !in c.builtins {
|
||||
syms << sym
|
||||
}
|
||||
}
|
||||
mut pending := []&ast.TypeSymbol{} // functions with a dependency
|
||||
for {
|
||||
// Add non dependent functions or functions which
|
||||
// dependency has been added.
|
||||
next: for sym in syms {
|
||||
info := sym.info as ast.FnType
|
||||
func := info.func
|
||||
return_sym := g.table.sym(func.return_type)
|
||||
if return_sym in syms {
|
||||
pending << sym
|
||||
continue
|
||||
}
|
||||
for param in func.params {
|
||||
param_sym := g.table.sym(param.typ)
|
||||
if param_sym in syms {
|
||||
pending << sym
|
||||
continue next
|
||||
}
|
||||
}
|
||||
g.write_fn_typesymbol_declaration(sym)
|
||||
}
|
||||
if pending.len == 0 {
|
||||
// All functions were added.
|
||||
break
|
||||
}
|
||||
if syms.len == pending.len {
|
||||
// Could not add any function: there is a circular
|
||||
// dependency.
|
||||
mut deps := []string{}
|
||||
for sym in pending {
|
||||
deps << sym.name
|
||||
}
|
||||
verror(
|
||||
'cgen.write_sorted_fn_typesymbol_declaration(): the following functions form a dependency cycle:\n' +
|
||||
deps.join(','))
|
||||
}
|
||||
unsafe {
|
||||
// Swap the to-be-processed and the dependent functions.
|
||||
syms, pending = pending, syms[..0]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// sort structs by dependent fields
|
||||
fn (mut g Gen) sort_structs(typesa []&ast.TypeSymbol) []&ast.TypeSymbol {
|
||||
util.timing_start(@METHOD)
|
||||
|
4
vlib/v/gen/c/testdata/func_type_dependency.c.must_have
vendored
Normal file
4
vlib/v/gen/c/testdata/func_type_dependency.c.must_have
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
typedef void (*gdi__Function_ptr)();
|
||||
typedef void (*gdi__Function_ptr2)();
|
||||
typedef gdi__Function_ptr* (*gdi__Get_proc_address)(i8*);
|
||||
typedef void (*gdi__Set_proc_address)(gdi__Function_ptr2*);
|
8
vlib/v/gen/c/testdata/func_type_dependency.vv
vendored
Normal file
8
vlib/v/gen/c/testdata/func_type_dependency.vv
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
// vtest vflags: -shared
|
||||
module gdi
|
||||
|
||||
pub type Get_proc_address = fn(&i8) &Function_ptr
|
||||
pub type Set_proc_address = fn(&Function_ptr2)
|
||||
|
||||
pub type Function_ptr = fn ()
|
||||
pub type Function_ptr2 = fn ()
|
Loading…
x
Reference in New Issue
Block a user