Skip to content

Commit

Permalink
checker, cgen: implement fixed array methods any() and all()
Browse files Browse the repository at this point in the history
  • Loading branch information
yuyi98 committed Oct 21, 2024
1 parent f31ba78 commit b29a152
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 25 deletions.
59 changes: 59 additions & 0 deletions vlib/builtin/fixed_array_any_all_test.v
Original file line number Diff line number Diff line change
@@ -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
}
15 changes: 15 additions & 0 deletions vlib/v/checker/fn.v
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
90 changes: 65 additions & 25 deletions vlib/v/gen/c/array.v
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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')

Expand All @@ -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 {
Expand Down Expand Up @@ -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')
Expand All @@ -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
Expand Down Expand Up @@ -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}];')
}
}
}

Expand Down
6 changes: 6 additions & 0 deletions vlib/v/gen/c/fn.v
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down

0 comments on commit b29a152

Please sign in to comment.