all: support generic `chan` (#8188)
parent
35279a15a4
commit
5cc591b2b6
|
@ -1523,6 +1523,14 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
|
||||||
idx := c.table.find_or_register_array(call_expr.generic_type)
|
idx := c.table.find_or_register_array(call_expr.generic_type)
|
||||||
return table.new_type(idx)
|
return table.new_type(idx)
|
||||||
}
|
}
|
||||||
|
} else if return_sym.kind == .chan {
|
||||||
|
elem_info := return_sym.info as table.Chan
|
||||||
|
elem_sym := c.table.get_type_symbol(elem_info.elem_type)
|
||||||
|
if elem_sym.name == 'T' {
|
||||||
|
idx := c.table.find_or_register_chan(elem_info.elem_type, elem_info.elem_type.nr_muls() >
|
||||||
|
0)
|
||||||
|
return table.new_type(idx)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if call_expr.generic_type.is_full() && !method.is_generic {
|
if call_expr.generic_type.is_full() && !method.is_generic {
|
||||||
|
@ -1862,6 +1870,12 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type {
|
||||||
typ := table.new_type(idx)
|
typ := table.new_type(idx)
|
||||||
call_expr.return_type = typ
|
call_expr.return_type = typ
|
||||||
return typ
|
return typ
|
||||||
|
} else if return_sym.kind == .chan && return_sym.name.contains('T') {
|
||||||
|
idx := c.table.find_or_register_chan(call_expr.generic_type, call_expr.generic_type.nr_muls() >
|
||||||
|
0)
|
||||||
|
typ := table.new_type(idx)
|
||||||
|
call_expr.return_type = typ
|
||||||
|
return typ
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if call_expr.generic_type.is_full() && !f.is_generic {
|
if call_expr.generic_type.is_full() && !f.is_generic {
|
||||||
|
|
|
@ -681,17 +681,20 @@ typedef struct {
|
||||||
if typ.name != 'chan' {
|
if typ.name != 'chan' {
|
||||||
g.type_definitions.writeln('typedef chan $typ.cname;')
|
g.type_definitions.writeln('typedef chan $typ.cname;')
|
||||||
chan_inf := typ.chan_info()
|
chan_inf := typ.chan_info()
|
||||||
el_stype := g.typ(chan_inf.elem_type)
|
chan_elem_type := chan_inf.elem_type
|
||||||
g.channel_definitions.writeln('
|
if !chan_elem_type.has_flag(.generic) {
|
||||||
|
el_stype := g.typ(chan_elem_type)
|
||||||
|
g.channel_definitions.writeln('
|
||||||
static inline $el_stype __${typ.cname}_popval($typ.cname ch) {
|
static inline $el_stype __${typ.cname}_popval($typ.cname ch) {
|
||||||
$el_stype val;
|
$el_stype val;
|
||||||
sync__Channel_try_pop_priv(ch, &val, false);
|
sync__Channel_try_pop_priv(ch, &val, false);
|
||||||
return val;
|
return val;
|
||||||
}')
|
}')
|
||||||
g.channel_definitions.writeln('
|
g.channel_definitions.writeln('
|
||||||
static inline void __${typ.cname}_pushval($typ.cname ch, $el_stype val) {
|
static inline void __${typ.cname}_pushval($typ.cname ch, $el_stype val) {
|
||||||
sync__Channel_try_push_priv(ch, &val, false);
|
sync__Channel_try_push_priv(ch, &val, false);
|
||||||
}')
|
}')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.map {
|
.map {
|
||||||
|
@ -712,7 +715,7 @@ pub fn (mut g Gen) write_fn_typesymbol_declaration(sym table.TypeSymbol) {
|
||||||
func := info.func
|
func := info.func
|
||||||
is_fn_sig := func.name == ''
|
is_fn_sig := func.name == ''
|
||||||
not_anon := !info.is_anon
|
not_anon := !info.is_anon
|
||||||
if !info.has_decl && (not_anon || is_fn_sig) {
|
if !info.has_decl && (not_anon || is_fn_sig) && !func.return_type.has_flag(.generic) {
|
||||||
fn_name := sym.cname
|
fn_name := sym.cname
|
||||||
g.type_definitions.write('typedef ${g.typ(func.return_type)} (*$fn_name)(')
|
g.type_definitions.write('typedef ${g.typ(func.return_type)} (*$fn_name)(')
|
||||||
for i, param in func.params {
|
for i, param in func.params {
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
fn mk_chan<T>(f fn () T) chan T {
|
||||||
|
gench := chan T{cap: 1}
|
||||||
|
// // This does not work, yet
|
||||||
|
// go fn(ch2 chan T, f2 fn() T) {
|
||||||
|
// res := f2()
|
||||||
|
// ch2 <- res
|
||||||
|
// }(gench, f)
|
||||||
|
return gench
|
||||||
|
}
|
||||||
|
|
||||||
|
fn g(x f64, y f64) f64 {
|
||||||
|
return x * x + y * y
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_generic_chan_return() {
|
||||||
|
ch := mk_chan<f64>(fn () f64 {
|
||||||
|
return g(3, 4)
|
||||||
|
})
|
||||||
|
ch <- 13.4
|
||||||
|
res := <-ch
|
||||||
|
assert res == 13.4
|
||||||
|
}
|
Loading…
Reference in New Issue