From 51907618c3fd66f1e703120bba0d54527e54dd6f Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Mon, 9 Jan 2023 17:30:35 -0300 Subject: [PATCH] cgen: fix code generated for a match expression, which returns function (#16922) --- vlib/v/gen/c/match.v | 15 ++++- vlib/v/tests/match_return_fn_test.v | 96 +++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 vlib/v/tests/match_return_fn_test.v diff --git a/vlib/v/gen/c/match.v b/vlib/v/gen/c/match.v index ffbdce28ad..5e75c1531a 100644 --- a/vlib/v/gen/c/match.v +++ b/vlib/v/gen/c/match.v @@ -87,7 +87,20 @@ fn (mut g Gen) match_expr(node ast.MatchExpr) { g.empty_line = true cur_line = g.go_before_stmt(0).trim_left(' \t') tmp_var = g.new_tmp_var() - g.writeln('${g.typ(node.return_type)} ${tmp_var} = ${g.type_default(node.return_type)};') + mut func_decl := '' + if g.table.final_sym(node.return_type).kind == .function { + func_sym := g.table.final_sym(node.return_type) + if func_sym.info is ast.FnType { + def := g.fn_var_signature(func_sym.info.func.return_type, func_sym.info.func.params.map(it.typ), + tmp_var) + func_decl = '${def} = &${g.typ(node.return_type)};' + } + } + if func_decl.len > 0 { + g.writeln(func_decl) // func, anon func declaration + } else { + g.writeln('${g.typ(node.return_type)} ${tmp_var} = ${g.type_default(node.return_type)};') + } g.empty_line = true if g.infix_left_var_name.len > 0 { g.writeln('if (${g.infix_left_var_name}) {') diff --git a/vlib/v/tests/match_return_fn_test.v b/vlib/v/tests/match_return_fn_test.v new file mode 100644 index 0000000000..cba1a6e5ef --- /dev/null +++ b/vlib/v/tests/match_return_fn_test.v @@ -0,0 +1,96 @@ +enum Foo { + a + b + c + d + e + f +} + +fn test() string { + return 'c' +} + +fn dummy() string { + return 'b' +} + +fn dummy2() string { + return 'a' +} + +fn dummy3() {} + +fn err() fn () string { + return match Foo.a { + .a { dummy } + .b { dummy } + .c { dummy } + .d { dummy2 } + .e { dummy2 } + else { dummy2 } + } +} + +fn err2() fn () string { + return match Foo.d { + .a { dummy } + .b { dummy } + .c { dummy } + .d { dummy2 } + .e { dummy2 } + .f { dummy } + } +} + +fn err3() fn () string { + return match Foo.f { + .a { dummy } + .b { dummy } + .c { dummy } + .d { dummy } + .e { dummy } + else { test } + } +} + +fn err4() fn () { + return match Foo.f { + .a { dummy3 } + .b { dummy3 } + .c { dummy3 } + .d { dummy3 } + .e { dummy3 } + else { dummy3 } + } +} + +fn err5(f fn ()) fn () { + return match Foo.f { + .a { dummy3 } + .b { dummy3 } + .c { dummy3 } + .d { dummy3 } + .e { dummy3 } + else { f } + } +} + +fn test_main() { + var := main.err()() + assert var == 'b' + + var2 := main.err2()() + assert var2 == 'a' + + var3 := main.err3()() + assert var3 == 'c' + + var4 := err4() + assert var4 == dummy3 + + anon := fn () {} + var5 := err5(anon) + assert var5 == anon + var5() +}