From 53a5aad8559829c78bfed8e77bbc2a0afc0d5eb7 Mon Sep 17 00:00:00 2001 From: yuyi Date: Mon, 1 Feb 2021 21:50:10 +0800 Subject: [PATCH] cgen: fix fixed array of function (#8490) --- vlib/v/checker/checker.v | 6 ++++ vlib/v/gen/cgen.v | 45 +++++++++++++++++++++------ vlib/v/tests/fixed_array_of_fn_test.v | 9 ++++++ 3 files changed, 51 insertions(+), 9 deletions(-) create mode 100644 vlib/v/tests/fixed_array_of_fn_test.v diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 140760b3c6..c5429fe32a 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -1694,6 +1694,12 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type { if elem_typ.info is table.FnType { return elem_typ.info.func.return_type } + } else if sym.kind == .array_fixed { + info := sym.info as table.ArrayFixed + elem_typ := c.table.get_type_symbol(info.elem_type) + if elem_typ.info is table.FnType { + return elem_typ.info.func.return_type + } } found = true return table.string_type diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index 48fa117322..be096f7c3c 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -4198,6 +4198,28 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) { g.write('\n$cur_line*($elem_type_str*)${tmp_opt}.data') } } + } else if sym.kind == .array_fixed { + info := sym.info as table.ArrayFixed + elem_type := info.elem_type + elem_sym := g.table.get_type_symbol(elem_type) + is_fn_index_call := g.is_fn_index_call && elem_sym.info is table.FnType + + if is_fn_index_call { + g.write('(*') + } + if node.left_type.is_ptr() { + g.write('(*') + g.expr(node.left) + g.write(')') + } else { + g.expr(node.left) + } + g.write('[') + g.expr(node.index) + g.write(']') + if is_fn_index_call { + g.write(')') + } } else if sym.kind == .map { info := sym.info as table.Map key_type_str := g.typ(info.key_type) @@ -4328,13 +4350,7 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) { g.expr(node.index) g.write(')') } else { - if sym.kind == .array_fixed && node.left_type.is_ptr() { - g.write('(*') - g.expr(node.left) - g.write(')') - } else { - g.expr(node.left) - } + g.expr(node.left) g.write('[') g.expr(node.index) g.write(']') @@ -5140,8 +5156,19 @@ fn (mut g Gen) write_types(types []table.TypeSymbol) { if fixed.starts_with('C__') { fixed = fixed[3..] } - g.type_definitions.writeln('typedef $fixed $styp [$len];') - // } + elem_type := typ.info.elem_type + elem_sym := g.table.get_type_symbol(elem_type) + if elem_sym.info is table.FnType { + pos := g.out.len + g.write_fn_ptr_decl(&elem_sym.info, '') + fixed = g.out.after(pos) + g.out.go_back(fixed.len) + mut def_str := 'typedef $fixed;' + def_str = def_str.replace_once('(*)', '(*$styp[$len])') + g.type_definitions.writeln(def_str) + } else { + g.type_definitions.writeln('typedef $fixed $styp [$len];') + } } else {} } diff --git a/vlib/v/tests/fixed_array_of_fn_test.v b/vlib/v/tests/fixed_array_of_fn_test.v new file mode 100644 index 0000000000..341f37a733 --- /dev/null +++ b/vlib/v/tests/fixed_array_of_fn_test.v @@ -0,0 +1,9 @@ +fn foo(a string) int { + return 10 + a.len +} + +fn test_fixed_array_fn_index() { + a := [foo]! + println(a[0]('hello')) + assert a[0]('hello') == 15 +}