1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

cgen: fix sumtype with fntype using fn directly (fix #15674) (#15679)

This commit is contained in:
yuyi 2022-09-07 01:33:39 +08:00 committed by GitHub
parent 1c63ce479c
commit ca99a1d355
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 61 additions and 11 deletions

View File

@ -2098,16 +2098,22 @@ fn (mut g Gen) write_sumtype_casting_fn(fun SumtypeCastingFn) {
got_sym, exp_sym := g.table.sym(got), g.table.sym(exp) got_sym, exp_sym := g.table.sym(got), g.table.sym(exp)
mut got_cname, exp_cname := got_sym.cname, exp_sym.cname mut got_cname, exp_cname := got_sym.cname, exp_sym.cname
mut type_idx := g.type_sidx(got) mut type_idx := g.type_sidx(got)
mut sb := strings.new_builder(128)
mut is_anon_fn := false
if got_sym.info is ast.FnType { if got_sym.info is ast.FnType {
if got_sym.info.is_anon { if got_sym.info.is_anon || g.table.known_fn(got_sym.name) {
got_name := 'fn ${g.table.fn_type_source_signature(got_sym.info.func)}' got_name := 'fn ${g.table.fn_type_source_signature(got_sym.info.func)}'
got_cname = 'anon_fn_${g.table.fn_type_signature(got_sym.info.func)}' got_cname = 'anon_fn_${g.table.fn_type_signature(got_sym.info.func)}'
type_idx = g.table.type_idxs[got_name].str() type_idx = g.table.type_idxs[got_name].str()
sb.writeln('static inline $exp_cname ${fun.fn_name}($got_cname x) {')
sb.writeln('\t$got_cname ptr = x;')
is_anon_fn = true
} }
} }
mut sb := strings.new_builder(128) if !is_anon_fn {
sb.writeln('static inline $exp_cname ${fun.fn_name}($got_cname* x) {') sb.writeln('static inline $exp_cname ${fun.fn_name}($got_cname* x) {')
sb.writeln('\t$got_cname* ptr = memdup(x, sizeof($got_cname));') sb.writeln('\t$got_cname* ptr = memdup(x, sizeof($got_cname));')
}
for embed_hierarchy in g.table.get_embeds(got_sym) { for embed_hierarchy in g.table.get_embeds(got_sym) {
// last embed in the hierarchy // last embed in the hierarchy
mut embed_cname := '' mut embed_cname := ''
@ -2149,14 +2155,14 @@ fn (mut g Gen) write_sumtype_casting_fn(fun SumtypeCastingFn) {
g.auto_fn_definitions << sb.str() g.auto_fn_definitions << sb.str()
} }
fn (mut g Gen) call_cfn_for_casting_expr(fname string, expr ast.Expr, exp_is_ptr bool, exp_styp string, got_is_ptr bool, got_styp string) { fn (mut g Gen) call_cfn_for_casting_expr(fname string, expr ast.Expr, exp_is_ptr bool, exp_styp string, got_is_ptr bool, got_is_fn bool, got_styp string) {
mut rparen_n := 1 mut rparen_n := 1
if exp_is_ptr { if exp_is_ptr {
g.write('HEAP($exp_styp, ') g.write('HEAP($exp_styp, ')
rparen_n++ rparen_n++
} }
g.write('${fname}(') g.write('${fname}(')
if !got_is_ptr { if !got_is_ptr && !got_is_fn {
if !expr.is_lvalue() if !expr.is_lvalue()
|| (expr is ast.Ident && (expr as ast.Ident).obj.is_simple_define_const()) { || (expr is ast.Ident && (expr as ast.Ident).obj.is_simple_define_const()) {
// Note: the `_to_sumtype_` family of functions do call memdup internally, making // Note: the `_to_sumtype_` family of functions do call memdup internally, making
@ -2207,7 +2213,7 @@ fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type_raw ast.Type, expected_typ
fname = g.generic_fn_name(exp_sym.info.concrete_types, fname) fname = g.generic_fn_name(exp_sym.info.concrete_types, fname)
} }
g.call_cfn_for_casting_expr(fname, expr, expected_is_ptr, exp_styp, true, g.call_cfn_for_casting_expr(fname, expr, expected_is_ptr, exp_styp, true,
got_styp) false, got_styp)
g.inside_cast_in_heap-- g.inside_cast_in_heap--
} else { } else {
got_styp := g.cc_type(got_type, true) got_styp := g.cc_type(got_type, true)
@ -2227,16 +2233,18 @@ fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type_raw ast.Type, expected_typ
fname = g.generic_fn_name(exp_sym.info.concrete_types, fname) fname = g.generic_fn_name(exp_sym.info.concrete_types, fname)
} }
g.call_cfn_for_casting_expr(fname, expr, expected_is_ptr, exp_styp, got_is_ptr, g.call_cfn_for_casting_expr(fname, expr, expected_is_ptr, exp_styp, got_is_ptr,
got_styp) false, got_styp)
} }
return return
} }
// cast to sum type // cast to sum type
exp_styp := g.typ(expected_type) exp_styp := g.typ(expected_type)
mut got_styp := g.typ(got_type) mut got_styp := g.typ(got_type)
mut got_is_fn := false
if got_sym.info is ast.FnType { if got_sym.info is ast.FnType {
if got_sym.info.is_anon { if got_sym.info.is_anon {
got_styp = 'anon_fn_${g.table.fn_type_signature(got_sym.info.func)}' got_styp = 'anon_fn_${g.table.fn_type_signature(got_sym.info.func)}'
got_is_fn = true
} }
} }
if expected_type != ast.void_type { if expected_type != ast.void_type {
@ -2276,7 +2284,7 @@ fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type_raw ast.Type, expected_typ
} }
fname := g.get_sumtype_casting_fn(unwrapped_got_type, unwrapped_expected_type) fname := g.get_sumtype_casting_fn(unwrapped_got_type, unwrapped_expected_type)
g.call_cfn_for_casting_expr(fname, expr, expected_is_ptr, unwrapped_exp_sym.cname, g.call_cfn_for_casting_expr(fname, expr, expected_is_ptr, unwrapped_exp_sym.cname,
got_is_ptr, got_styp) got_is_ptr, got_is_fn, got_styp)
} }
return return
} }
@ -5074,7 +5082,13 @@ fn (mut g Gen) write_types(symbols []&ast.TypeSymbol) {
g.type_definitions.writeln('\tunion {') g.type_definitions.writeln('\tunion {')
for variant in sym.info.variants { for variant in sym.info.variants {
variant_sym := g.table.sym(variant) variant_sym := g.table.sym(variant)
g.type_definitions.writeln('\t\t${g.typ(variant.ref())} _$variant_sym.cname;') mut var := variant.ref()
if variant_sym.info is ast.FnType {
if variant_sym.info.is_anon {
var = variant
}
}
g.type_definitions.writeln('\t\t${g.typ(var)} _$variant_sym.cname;')
} }
g.type_definitions.writeln('\t};') g.type_definitions.writeln('\t};')
g.type_definitions.writeln('\tint _typ;') g.type_definitions.writeln('\tint _typ;')
@ -5608,7 +5622,11 @@ fn (mut g Gen) as_cast(node ast.AsCast) {
mut expr_type_sym := g.table.sym(g.unwrap_generic(node.expr_type)) mut expr_type_sym := g.table.sym(g.unwrap_generic(node.expr_type))
if mut expr_type_sym.info is ast.SumType { if mut expr_type_sym.info is ast.SumType {
dot := if node.expr_type.is_ptr() { '->' } else { '.' } dot := if node.expr_type.is_ptr() { '->' } else { '.' }
if sym.info is ast.FnType {
g.write('/* as */ ($styp)__as_cast(')
} else {
g.write('/* as */ *($styp*)__as_cast(') g.write('/* as */ *($styp*)__as_cast(')
}
g.write('(') g.write('(')
g.expr(node.expr) g.expr(node.expr)
g.write(')') g.write(')')

View File

@ -0,0 +1,32 @@
type Expr = fn () int | fn (int) int
fn id(n int) int {
return n
}
fn func() Expr {
return id
}
fn test_sumtype_with_fntype() {
f := func()
f1 := f as fn (int) int
println(123)
assert f1(123) == 123
if f is fn (int) int {
ret := f(123)
println(ret)
assert ret == 123
}
match f {
fn (int) int {
ret := f(321)
println(ret)
assert ret == 321
}
else {}
}
}