From c4b424717cc54483c9a8c4aabcf157856fb8ee14 Mon Sep 17 00:00:00 2001 From: yuyi Date: Mon, 21 Mar 2022 06:20:55 +0800 Subject: [PATCH] cgen: fix error for map get anon fn value (#13782) --- vlib/v/gen/c/cgen.v | 13 ++++++++++-- vlib/v/gen/c/index.v | 17 ++++++--------- vlib/v/tests/map_get_anon_fn_value_test.v | 25 +++++++++++++++++++++++ 3 files changed, 42 insertions(+), 13 deletions(-) create mode 100644 vlib/v/tests/map_get_anon_fn_value_test.v diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index b3db40405a..3e91f981cd 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -955,7 +955,13 @@ fn (mut g Gen) optional_type_name(t ast.Type) (string, string) { fn (g Gen) optional_type_text(styp string, base string) string { // replace void with something else - size := if base == 'void' { 'byte' } else { base } + size := if base == 'void' { + 'byte' + } else if base.starts_with('anon_fn') { + 'void*' + } else { + base + } ret := 'struct $styp { byte state; IError err; @@ -4826,12 +4832,15 @@ fn (mut g Gen) insert_at(pos int, s string) { // Returns the type of the last stmt fn (mut g Gen) or_block(var_name string, or_block ast.OrExpr, return_type ast.Type) { cvar_name := c_name(var_name) - mr_styp := g.base_type(return_type) + mut mr_styp := g.base_type(return_type) is_none_ok := return_type == ast.ovoid_type g.writeln(';') if is_none_ok { g.writeln('if (${cvar_name}.state != 0 && ${cvar_name}.err._typ != _IError_None___index) {') } else { + if return_type != 0 && g.table.sym(return_type).kind == .function { + mr_styp = 'voidptr' + } g.writeln('if (${cvar_name}.state != 0) { /*or block*/ ') } if or_block.kind == .block { diff --git a/vlib/v/gen/c/index.v b/vlib/v/gen/c/index.v index 24540b51a8..b5027b68f0 100644 --- a/vlib/v/gen/c/index.v +++ b/vlib/v/gen/c/index.v @@ -365,8 +365,11 @@ fn (mut g Gen) index_of_map(node ast.IndexExpr, sym ast.TypeSymbol) { info := sym.info as ast.Map key_type_str := g.typ(info.key_type) elem_type := info.value_type - elem_type_str := g.typ(elem_type) + mut elem_type_str := g.typ(elem_type) elem_typ := g.table.sym(elem_type) + if elem_typ.kind == .function { + elem_type_str = 'voidptr' + } get_and_set_types := elem_typ.kind in [.struct_, .map] if g.is_assign_lhs && !g.is_arraymap_set && !get_and_set_types { if g.assign_op == .assign || info.value_type == ast.string_type { @@ -401,12 +404,8 @@ fn (mut g Gen) index_of_map(node ast.IndexExpr, sym ast.TypeSymbol) { g.is_arraymap_set = old_is_arraymap_set g.is_assign_lhs = old_is_assign_lhs g.write('}') - if elem_typ.kind == .function { - g.write(', &(voidptr[]) { ') - } else { - g.arraymap_set_pos = g.out.len - g.write(', &($elem_type_str[]) { ') - } + g.arraymap_set_pos = g.out.len + g.write(', &($elem_type_str[]) { ') if g.assign_op != .assign && info.value_type != ast.string_type { zero := g.type_default(info.value_type) g.write('$zero })))') @@ -450,8 +449,6 @@ fn (mut g Gen) index_of_map(node ast.IndexExpr, sym ast.TypeSymbol) { g.write_fn_ptr_decl(&elem_typ.info, '') g.write(')(*(voidptr*)map_get(') } - } else if elem_typ.kind == .function { - g.write('(*(voidptr*)map_get(') } else { g.write('(*($elem_type_str*)map_get(') } @@ -477,8 +474,6 @@ fn (mut g Gen) index_of_map(node ast.IndexExpr, sym ast.TypeSymbol) { g.write('))') } else if g.is_fn_index_call { g.write(', &(voidptr[]){ $zero })))') - } else if elem_typ.kind == .function { - g.write(', &(voidptr[]){ $zero }))') } else { g.write(', &($elem_type_str[]){ $zero }))') } diff --git a/vlib/v/tests/map_get_anon_fn_value_test.v b/vlib/v/tests/map_get_anon_fn_value_test.v new file mode 100644 index 0000000000..6b0c10249c --- /dev/null +++ b/vlib/v/tests/map_get_anon_fn_value_test.v @@ -0,0 +1,25 @@ +const numbers = { + 'one': fn () int { + return 1 + } +} + +fn test_map_get_anon_fn_value() { + num1 := numbers['one'] or { + fn () int { + return 2 + } + } + ret1 := num1() + println(ret1) + assert ret1 == 1 + + num2 := numbers['two'] or { + fn () int { + return 2 + } + } + ret2 := num2() + println(ret2) + assert ret2 == 2 +}