From b29a152738f56c2f4bdbfdbadd138ee8a5b55f1c Mon Sep 17 00:00:00 2001 From: yuyi Date: Mon, 21 Oct 2024 21:13:10 +0800 Subject: [PATCH] checker, cgen: implement fixed array methods any() and all() --- vlib/builtin/fixed_array_any_all_test.v | 59 ++++++++++++++++ vlib/v/checker/fn.v | 15 +++++ vlib/v/gen/c/array.v | 90 ++++++++++++++++++------- vlib/v/gen/c/fn.v | 6 ++ 4 files changed, 145 insertions(+), 25 deletions(-) create mode 100644 vlib/builtin/fixed_array_any_all_test.v diff --git a/vlib/builtin/fixed_array_any_all_test.v b/vlib/builtin/fixed_array_any_all_test.v new file mode 100644 index 00000000000000..bbf2846d1ffc6a --- /dev/null +++ b/vlib/builtin/fixed_array_any_all_test.v @@ -0,0 +1,59 @@ +fn test_any_all_of_ints() { + ia := [1, 2, 3]! + mut ii := ia.any(it > 2) + println(ii) + assert ii + + ii = ia.all(it > 1) + println(ii) + assert !ii + + ii = ia.any(it == 2) + println(ii) + assert ii + + ii = ia.all(it == 3) + println(ii) + assert !ii +} + +fn test_any_all_of_strings() { + sa := ['a', 'b', 'c']! + mut si := sa.any(it == 'b') + println(si) + assert si + + si = sa.all(it == 'c') + println(si) + assert !si +} + +fn test_any_all_of_voidptrs() { + pa := [voidptr(123), voidptr(45), voidptr(99)]! + mut pi := pa.any(it == voidptr(45)) + println(pi) + assert pi + + pi = pa.all(it == voidptr(123)) + println(pi) + assert !pi +} + +fn a() {} + +fn b() {} + +fn c() {} + +fn v() {} + +fn test_any_all_of_fns() { + fa := [a, b, c]! + mut fi := fa.any(it == b) + println(fi) + assert fi + + fi = fa.all(it == v) + println(fi) + assert !fi +} diff --git a/vlib/v/checker/fn.v b/vlib/v/checker/fn.v index ed75454a523408..ad71f65df33b03 100644 --- a/vlib/v/checker/fn.v +++ b/vlib/v/checker/fn.v @@ -3493,6 +3493,21 @@ fn (mut c Checker) fixed_array_builtin_method_call(mut node ast.CallExpr, left_t node.args[i].typ = c.expr(mut arg.expr) } node.return_type = ast.int_type + } else if method_name in ['any', 'all'] { + if node.args.len > 0 && mut node.args[0].expr is ast.LambdaExpr { + if node.args[0].expr.params.len != 1 { + c.error('lambda expressions used in the builtin array methods require exactly 1 parameter', + node.args[0].expr.pos) + return ast.void_type + } + c.support_lambda_expr_one_param(elem_typ, ast.bool_type, mut node.args[0].expr) + } else { + // position of `it` doesn't matter + scope_register_it(mut node.scope, node.pos, elem_typ) + } + c.expr(mut node.args[0].expr) + c.check_map_and_filter(false, elem_typ, node) + node.return_type = ast.bool_type } return node.return_type } diff --git a/vlib/v/gen/c/array.v b/vlib/v/gen/c/array.v index bbb242069c553e..b7612dff13c19c 100644 --- a/vlib/v/gen/c/array.v +++ b/vlib/v/gen/c/array.v @@ -513,7 +513,8 @@ fn (mut g Gen) gen_array_map(node ast.CallExpr) { g.writeln('for (int ${i} = 0; ${i} < ${past.tmp_var}_len; ++${i}) {') g.indent++ var_name := g.get_array_expr_param_name(mut expr) - g.write_prepared_var(var_name, inp_info, inp_elem_type, past.tmp_var, i) + g.write_prepared_var(var_name, inp_info.elem_type, inp_elem_type, past.tmp_var, i, + true) g.set_current_pos_as_last_stmt_pos() mut is_embed_map_filter := false match mut expr { @@ -788,7 +789,7 @@ fn (mut g Gen) gen_array_filter(node ast.CallExpr) { i := g.new_tmp_var() g.writeln('for (int ${i} = 0; ${i} < ${past.tmp_var}_len; ++${i}) {') g.indent++ - g.write_prepared_var(var_name, info, elem_type_str, past.tmp_var, i) + g.write_prepared_var(var_name, info.elem_type, elem_type_str, past.tmp_var, i, true) g.set_current_pos_as_last_stmt_pos() mut is_embed_map_filter := false match mut expr { @@ -1267,9 +1268,13 @@ fn (mut g Gen) gen_array_any(node ast.CallExpr) { } sym := g.table.final_sym(node.left_type) - info := sym.info as ast.Array - // styp := g.styp(node.return_type) - elem_type_str := g.styp(info.elem_type) + left_is_array := sym.kind == .array + elem_type := if left_is_array { + (sym.info as ast.Array).elem_type + } else { + (sym.info as ast.ArrayFixed).elem_type + } + elem_type_str := g.styp(elem_type) has_infix_left_var_name := g.write_prepared_tmp_value(past.tmp_var, node, 'bool', 'false') @@ -1287,7 +1292,7 @@ fn (mut g Gen) gen_array_any(node ast.CallExpr) { g.writeln('for (int ${i} = 0; ${i} < ${past.tmp_var}_len; ++${i}) {') g.indent++ - g.write_prepared_var(var_name, info, elem_type_str, past.tmp_var, i) + g.write_prepared_var(var_name, elem_type, elem_type_str, past.tmp_var, i, left_is_array) g.set_current_pos_as_last_stmt_pos() mut is_embed_map_filter := false match mut expr { @@ -1356,9 +1361,13 @@ fn (mut g Gen) gen_array_all(node ast.CallExpr) { } sym := g.table.final_sym(node.left_type) - info := sym.info as ast.Array - // styp := g.styp(node.return_type) - elem_type_str := g.styp(info.elem_type) + left_is_array := sym.kind == .array + elem_type := if left_is_array { + (sym.info as ast.Array).elem_type + } else { + (sym.info as ast.ArrayFixed).elem_type + } + elem_type_str := g.styp(elem_type) has_infix_left_var_name := g.write_prepared_tmp_value(past.tmp_var, node, 'bool', 'true') @@ -1377,7 +1386,7 @@ fn (mut g Gen) gen_array_all(node ast.CallExpr) { g.writeln('for (int ${i} = 0; ${i} < ${past.tmp_var}_len; ++${i}) {') g.indent++ - g.write_prepared_var(var_name, info, elem_type_str, past.tmp_var, i) + g.write_prepared_var(var_name, elem_type, elem_type_str, past.tmp_var, i, left_is_array) g.empty_line = true g.set_current_pos_as_last_stmt_pos() mut is_embed_map_filter := false @@ -1455,26 +1464,57 @@ fn (mut g Gen) write_prepared_tmp_value(tmp string, node &ast.CallExpr, tmp_styp } else { node.left_type } - g.write('${g.styp(left_type)} ${tmp}_orig = ') - if !node.left_type.has_flag(.shared_f) && node.left_type.is_ptr() { - g.write('*') - } - g.expr(node.left) - if node.left_type.has_flag(.shared_f) { - g.write('->val') + left_sym := g.table.final_sym(left_type) + if left_sym.kind == .array { + g.write('${g.styp(left_type)} ${tmp}_orig = ') + if !node.left_type.has_flag(.shared_f) && node.left_type.is_ptr() { + g.write('*') + } + g.expr(node.left) + if node.left_type.has_flag(.shared_f) { + g.write('->val') + } + g.writeln(';') + g.writeln('int ${tmp}_len = ${tmp}_orig.len;') + } else if left_sym.kind == .array_fixed { + left_info := left_sym.info as ast.ArrayFixed + left_styp := g.styp(left_type) + g.writeln('${left_styp} ${tmp}_orig;') + g.write('memcpy(&${tmp}_orig, &') + if !node.left_type.has_flag(.shared_f) && node.left_type.is_ptr() { + g.write('*') + } + g.expr(node.left) + if node.left_type.has_flag(.shared_f) { + g.write('->val') + } + g.writeln(', sizeof(${left_styp}));') + g.writeln('int ${tmp}_len = ${left_info.size};') } - g.writeln(';') - g.writeln('int ${tmp}_len = ${tmp}_orig.len;') return has_infix_left_var_name } -fn (mut g Gen) write_prepared_var(var_name string, inp_info ast.Array, inp_elem_type string, tmp string, - i string) { - if g.table.sym(inp_info.elem_type).kind == .array_fixed { - g.writeln('${inp_elem_type} ${var_name};') - g.writeln('memcpy(&${var_name}, ((${inp_elem_type}*) ${tmp}_orig.data)[${i}], sizeof(${inp_elem_type}));') +fn (mut g Gen) write_prepared_var(var_name string, elem_type ast.Type, inp_elem_type string, tmp string, + i string, is_array bool) { + elem_sym := g.table.sym(elem_type) + if is_array { + if elem_sym.kind == .array_fixed { + g.writeln('${inp_elem_type} ${var_name};') + g.writeln('memcpy(&${var_name}, ((${inp_elem_type}*) ${tmp}_orig.data)[${i}], sizeof(${inp_elem_type}));') + } else if elem_sym.kind == .function { + g.writeln('voidptr ${var_name} = ((${inp_elem_type}*) ${tmp}_orig.data)[${i}];') + } else { + g.writeln('${inp_elem_type} ${var_name} = ((${inp_elem_type}*) ${tmp}_orig.data)[${i}];') + } } else { - g.writeln('${inp_elem_type} ${var_name} = ((${inp_elem_type}*) ${tmp}_orig.data)[${i}];') + if elem_sym.kind == .array_fixed { + g.writeln('${inp_elem_type} ${var_name};') + g.writeln('memcpy(&${var_name}, &${tmp}_orig[${i}], sizeof(${inp_elem_type}));') + } else if elem_sym.kind == .function { + g.writeln('voidptr ${var_name} = (voidptr)${tmp}_orig[${i}];') + } else { + g.writeln('${inp_elem_type} ${var_name} = ${tmp}_orig[${i}];') + } } } diff --git a/vlib/v/gen/c/fn.v b/vlib/v/gen/c/fn.v index 38eab7ea65dc11..b9c25340bdfb07 100644 --- a/vlib/v/gen/c/fn.v +++ b/vlib/v/gen/c/fn.v @@ -1194,6 +1194,12 @@ fn (mut g Gen) gen_fixed_array_method_call(node ast.CallExpr, left_type ast.Type 'index' { g.gen_array_index(node) } + 'any' { + g.gen_array_any(node) + } + 'all' { + g.gen_array_all(node) + } else { return false }