diff --git a/vlib/v/gen/c/array.v b/vlib/v/gen/c/array.v index b04dbc84f4..b5c296a7a4 100644 --- a/vlib/v/gen/c/array.v +++ b/vlib/v/gen/c/array.v @@ -153,12 +153,17 @@ fn (mut g Gen) gen_array_map(node ast.CallExpr) { verror('map() requires an array') } g.empty_line = true + g.writeln('$ret_typ $tmp;') + if g.infix_left_var_name.len > 0 { + g.writeln('if ($g.infix_left_var_name) {') + g.indent++ + } g.write('${g.typ(node.left_type)} ${tmp}_orig = ') g.expr(node.left) g.writeln(';') g.writeln('int ${tmp}_len = ${tmp}_orig.len;') noscan := g.check_noscan(ret_info.elem_type) - g.writeln('$ret_typ $tmp = __new_array${noscan}(0, ${tmp}_len, sizeof($ret_elem_type));\n') + g.writeln('$tmp = __new_array${noscan}(0, ${tmp}_len, sizeof($ret_elem_type));\n') i := g.new_tmp_var() g.writeln('for (int $i = 0; $i < ${tmp}_len; ++$i) {') g.writeln('\t$inp_elem_type it = (($inp_elem_type*) ${tmp}_orig.data)[$i];') @@ -206,6 +211,10 @@ fn (mut g Gen) gen_array_map(node ast.CallExpr) { g.stmt_path_pos << g.out.len } g.write('\n') + if g.infix_left_var_name.len > 0 { + g.indent-- + g.writeln('}') + } g.write(s) g.write(tmp) g.inside_lambda = false @@ -327,12 +336,17 @@ fn (mut g Gen) gen_array_filter(node ast.CallExpr) { styp := g.typ(node.return_type) elem_type_str := g.typ(info.elem_type) g.empty_line = true + g.writeln('$styp $tmp;') + if g.infix_left_var_name.len > 0 { + g.writeln('if ($g.infix_left_var_name) {') + g.indent++ + } g.write('${g.typ(node.left_type)} ${tmp}_orig = ') g.expr(node.left) g.writeln(';') g.writeln('int ${tmp}_len = ${tmp}_orig.len;') noscan := g.check_noscan(info.elem_type) - g.writeln('$styp $tmp = __new_array${noscan}(0, ${tmp}_len, sizeof($elem_type_str));\n') + g.writeln('$tmp = __new_array${noscan}(0, ${tmp}_len, sizeof($elem_type_str));\n') i := g.new_tmp_var() g.writeln('for (int $i = 0; $i < ${tmp}_len; ++$i) {') g.writeln('\t$elem_type_str it = (($elem_type_str*) ${tmp}_orig.data)[$i];') @@ -380,6 +394,10 @@ fn (mut g Gen) gen_array_filter(node ast.CallExpr) { g.stmt_path_pos << g.out.len } g.write('\n') + if g.infix_left_var_name.len > 0 { + g.indent-- + g.writeln('}') + } g.write(s) g.write(tmp) } diff --git a/vlib/v/gen/c/infix_expr.v b/vlib/v/gen/c/infix_expr.v index 4678ed9a79..fc62621557 100644 --- a/vlib/v/gen/c/infix_expr.v +++ b/vlib/v/gen/c/infix_expr.v @@ -608,6 +608,41 @@ fn (mut g Gen) infix_expr_left_shift_op(node ast.InfixExpr) { } } +fn (mut g Gen) need_tmp_var_in_array_call(node ast.Expr) bool { + match node { + ast.CallExpr { + if node.left_type != 0 && g.table.get_type_symbol(node.left_type).kind == .array + && node.name in ['all', 'any', 'filter', 'map'] { + return true + } + } + ast.IndexExpr { + return g.need_tmp_var_in_array_call(node.left) + } + ast.InfixExpr { + return g.need_tmp_var_in_array_call(node.left) + || g.need_tmp_var_in_array_call(node.right) + } + ast.ParExpr { + return g.need_tmp_var_in_array_call(node.expr) + } + ast.PostfixExpr { + return g.need_tmp_var_in_array_call(node.expr) + } + ast.PrefixExpr { + return g.need_tmp_var_in_array_call(node.right) + } + ast.RangeExpr { + return g.need_tmp_var_in_array_call(node.low) || g.need_tmp_var_in_array_call(node.high) + } + ast.SelectorExpr { + return g.need_tmp_var_in_array_call(node.expr) + } + else {} + } + return false +} + // infix_expr_and_or_op generates code for `&&` and `||` fn (mut g Gen) infix_expr_and_or_op(node ast.InfixExpr) { if node.right is ast.IfExpr { @@ -630,24 +665,20 @@ fn (mut g Gen) infix_expr_and_or_op(node ast.InfixExpr) { return } g.inside_ternary = prev_inside_ternary - } else if node.right is ast.CallExpr { - if node.right.left_type != 0 { - sym := g.table.get_type_symbol(node.right.left_type) - if sym.kind == .array && node.right.name in ['map', 'filter', 'all', 'any'] { - tmp := g.new_tmp_var() - cur_line := g.go_before_stmt(0).trim_space() - g.empty_line = true - g.write('bool $tmp = (') - g.expr(node.left) - g.writeln(');') - g.stmt_path_pos << g.out.len - g.write('$cur_line $tmp $node.op.str() ') - g.infix_left_var_name = if node.op == .and { tmp } else { '!$tmp' } - g.expr(node.right) - g.infix_left_var_name = '' - return - } - } + } else if g.need_tmp_var_in_array_call(node.right) { + // if a == 0 || arr.any(it.is_letter()) + tmp := g.new_tmp_var() + cur_line := g.go_before_stmt(0).trim_space() + g.empty_line = true + g.write('bool $tmp = (') + g.expr(node.left) + g.writeln(');') + g.stmt_path_pos << g.out.len + g.write('$cur_line $tmp $node.op.str() ') + g.infix_left_var_name = if node.op == .and { tmp } else { '!$tmp' } + g.expr(node.right) + g.infix_left_var_name = '' + return } g.gen_plain_infix_expr(node) } diff --git a/vlib/v/tests/if_expr_with_array_call_test.v b/vlib/v/tests/if_expr_with_array_call_test.v index 89866ce563..65f368288e 100644 --- a/vlib/v/tests/if_expr_with_array_call_test.v +++ b/vlib/v/tests/if_expr_with_array_call_test.v @@ -1,4 +1,4 @@ -fn test_if_expr_with_array_all_any() { +fn test_if_expr_with_array_call() { arr := [''] for i in arr { @@ -8,10 +8,46 @@ fn test_if_expr_with_array_all_any() { } } + for i in arr { + if i.len == 0 || (i[1..].bytes().all(it.is_letter())) { + println('empty or all char from second is letter!') + assert true + } + } + for i in arr { if i.len == 0 || i[1..].bytes().any(it.is_letter()) { println('empty or all char from second is letter!') assert true } } + + for i in arr { + if i.len == 0 || (i[1..].bytes().any(it.is_letter())) { + println('empty or all char from second is letter!') + assert true + } + } + + arr2 := ['abc'] + + if arr2.len == 1 || arr2[1].bytes().map(it.is_letter())[0] { + println('yes') + assert true + } + + if arr2.len == 1 || (arr2[1].bytes().map(it.is_letter())[0]) { + println('yes') + assert true + } + + if arr2.len == 1 || arr2[1].bytes().filter(it.is_letter()).len == 0 { + println('yes') + assert true + } + + if arr2.len == 1 || (arr2[1].bytes().filter(it.is_letter()).len == 0) { + println('yes') + assert true + } }