From a370dd2867917b532ac68432523384c1dc3ece2d Mon Sep 17 00:00:00 2001 From: Ruofan XU <47302112+SleepyRoy@users.noreply.github.com> Date: Wed, 22 Jul 2020 08:30:44 +0800 Subject: [PATCH] cgen: further fixes to and array/map of fns (#5916) --- vlib/v/gen/cgen.v | 97 +++++++++++----------- vlib/v/tests/map_and_array_with_fns_test.v | 6 ++ 2 files changed, 53 insertions(+), 50 deletions(-) diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index 7af97a19ea..00074ad9f6 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -912,6 +912,7 @@ fn (mut g Gen) for_in(it ast.ForInStmt) { // `for num in nums {` g.writeln('// FOR IN array') styp := g.typ(it.val_type) + val_sym := g.table.get_type_symbol(it.val_type) cond_type_is_ptr := it.cond_type.is_ptr() atmp := g.new_tmp_var() atmp_type := if cond_type_is_ptr { 'array *' } else { 'array' } @@ -922,7 +923,13 @@ fn (mut g Gen) for_in(it ast.ForInStmt) { op_field := if cond_type_is_ptr { '->' } else { '.' } g.writeln('for (int $i = 0; $i < $atmp${op_field}len; ++$i) {') if it.val_var != '_' { - g.writeln('\t$styp ${c_name(it.val_var)} = (($styp*)$atmp${op_field}data)[$i];') + if val_sym.kind == .function { + g.write('\t') + g.write_fn_ptr_decl(val_sym.info as table.FnType, c_name(it.val_var)) + g.writeln(' = ((voidptr*)$atmp${op_field}data)[$i];') + } else { + g.write('\t$styp ${c_name(it.val_var)} = (($styp*)$atmp${op_field}data)[$i];') + } } g.stmts(it.stmts) g.writeln('}') @@ -931,6 +938,7 @@ fn (mut g Gen) for_in(it ast.ForInStmt) { g.writeln('// FOR IN map') key_styp := g.typ(it.key_type) val_styp := g.typ(it.val_type) + val_sym := g.table.get_type_symbol(it.val_type) keys_tmp := 'keys_' + g.new_tmp_var() idx := g.new_tmp_var() key := if it.key_var in ['', '_'] { g.new_tmp_var() } else { it.key_var } @@ -949,8 +957,13 @@ fn (mut g Gen) for_in(it ast.ForInStmt) { g.writeln('\t$key_styp $key = /*kkkk*/ (($key_styp*)${keys_tmp}.data)[$idx];') } if it.val_var != '_' { - g.write('\t$val_styp ${c_name(it.val_var)} = /*vvv*/ (*($val_styp*)map_get($atmp') - g.writeln(', $key, &($val_styp[]){ $zero }));') + if val_sym.kind == .function { + g.write('\t') + g.write_fn_ptr_decl(val_sym.info as table.FnType, c_name(it.val_var)) + g.writeln(' = (*(voidptr*)map_get($atmp, $key, &(voidptr[]){ $zero }));') + } else { + g.writeln('\t$val_styp ${c_name(it.val_var)} = (*($val_styp*)map_get($atmp, $key, &($val_styp[]){ $zero }));') + } } g.stmts(it.stmts) g.writeln('}') @@ -1142,6 +1155,20 @@ fn (mut g Gen) gen_assert_single_expr(e ast.Expr, t table.Type) { g.write(' /* typeof: ' + typeof(e) + ' type: ' + t.str() + ' */ ') } +fn (g &Gen) write_fn_ptr_decl(func &table.FnType, ptr_name string) { + ret_styp := g.typ(func.func.return_type) + g.write('$ret_styp (*$ptr_name) (') + arg_len := func.func.args.len + for i, arg in func.func.args { + arg_typ := g.table.get_type_symbol(arg.typ) + g.write('$arg_typ.str() $arg.name') + if i < arg_len - 1 { + g.write(', ') + } + } + g.write(')') +} + fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) { if assign_stmt.is_static { g.write('static ') @@ -1198,23 +1225,13 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) { for i, left in assign_stmt.left { match left { ast.Ident { - var_type := assign_stmt.left_types[i] - left_sym := g.table.get_type_symbol(var_type) + left_typ := assign_stmt.left_types[i] + left_sym := g.table.get_type_symbol(left_typ) if left_sym.kind == .function { - func := left_sym.info as table.FnType - ret_styp := g.typ(func.func.return_type) - g.write('$ret_styp (*_var_$left.pos.pos) (') - arg_len := func.func.args.len - for j, arg in func.func.args { - arg_type := g.table.get_type_symbol(arg.typ) - g.write('$arg_type.str() $arg.name') - if j < arg_len - 1 { - g.write(', ') - } - } - g.writeln(') = $left.name;') + g.write_fn_ptr_decl(left_sym.info as table.FnType, '_var_$left.pos.pos') + g.writeln(' = $left.name;') } else { - styp := g.typ(var_type) + styp := g.typ(left_typ) g.writeln('$styp _var_$left.pos.pos = $left.name;') } } @@ -1222,24 +1239,14 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) { sym := g.table.get_type_symbol(left.left_type) if sym.kind == .array { info := sym.info as table.Array - styp := g.typ(info.elem_type) elem_typ := g.table.get_type_symbol(info.elem_type) if elem_typ.kind == .function { - var_type := assign_stmt.left_types[i] - left_sym := g.table.get_type_symbol(var_type) - func := left_sym.info as table.FnType - ret_styp := g.typ(func.func.return_type) - g.write('$ret_styp (*_var_$left.pos.pos) (') - arg_len := func.func.args.len - for j, arg in func.func.args { - arg_type := g.table.get_type_symbol(arg.typ) - g.write('$arg_type.str() $arg.name') - if j < arg_len - 1 { - g.write(', ') - } - } - g.write(') = *(voidptr*)array_get(') + left_typ := assign_stmt.left_types[i] + left_sym := g.table.get_type_symbol(left_typ) + g.write_fn_ptr_decl(left_sym.info as table.FnType, '_var_$left.pos.pos') + g.write(' = *(voidptr*)array_get(') } else { + styp := g.typ(info.elem_type) g.write('$styp _var_$left.pos.pos = *($styp*)array_get(') } if left.left_type.is_ptr() { @@ -1253,22 +1260,12 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) { info := sym.info as table.Map styp := g.typ(info.value_type) zero := g.type_default(info.value_type) - value_typ := g.table.get_type_symbol(info.value_type) - if value_typ.kind == .function { - var_type := assign_stmt.left_types[i] - left_sym := g.table.get_type_symbol(var_type) - func := left_sym.info as table.FnType - ret_styp := g.typ(func.func.return_type) - g.write('$ret_styp (*_var_$left.pos.pos) (') - arg_len := func.func.args.len - for j, arg in func.func.args { - arg_type := g.table.get_type_symbol(arg.typ) - g.write('$arg_type.str() $arg.name') - if j < arg_len - 1 { - g.write(', ') - } - } - g.write(') = *(voidptr*)map_get(') + val_typ := g.table.get_type_symbol(info.value_type) + if val_typ.kind == .function { + left_type := assign_stmt.left_types[i] + left_sym := g.table.get_type_symbol(left_type) + g.write_fn_ptr_decl(left_sym.info as table.FnType, '_var_$left.pos.pos') + g.write(' = *(voidptr*)map_get(') } else { g.write('$styp _var_$left.pos.pos = *($styp*)map_get(') } @@ -1278,7 +1275,7 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) { g.expr(left.left) g.write(', ') g.expr(left.index) - if value_typ.kind == .function { + if val_typ.kind == .function { g.writeln(', &(voidptr[]){ $zero });') } else { g.writeln(', &($styp[]){ $zero });') diff --git a/vlib/v/tests/map_and_array_with_fns_test.v b/vlib/v/tests/map_and_array_with_fns_test.v index 98640a435c..5eac3c9d3b 100644 --- a/vlib/v/tests/map_and_array_with_fns_test.v +++ b/vlib/v/tests/map_and_array_with_fns_test.v @@ -24,6 +24,9 @@ fn test_array_with_fns() { b[0] = a[0] f4 := b[0] assert f4('bbbbbb') == 26 + for func in b { + assert func('ccccccc') == 27 + } } fn test_map_with_fns() { @@ -42,4 +45,7 @@ fn test_map_with_fns() { b['one'] = a['one'] f4 := b['one'] assert f4('bbbbbb') == 26 + for _, func in b { + assert func('ccccccc') == 27 + } }