mirror of
https://github.com/vlang/v.git
synced 2025-09-08 14:51:53 -04:00
cgen: optimize .map(), .any(), .filter() and .all() when using closure (#21256)
This commit is contained in:
parent
1a35a783f1
commit
eb44844ccf
@ -463,15 +463,23 @@ fn (mut g Gen) array_init_with_fields(node ast.ArrayInit, elem_type Type, is_amp
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut g Gen) write_closure_fn(mut expr ast.AnonFn, var_name string) {
|
||||
past := g.past_tmp_var_new()
|
||||
fn_ptr_name := g.fn_var_signature(expr.decl.return_type, expr.decl.params.map(it.typ),
|
||||
past.tmp_var)
|
||||
g.write('${fn_ptr_name} = ')
|
||||
fn (mut g Gen) declare_closure_fn(mut expr ast.AnonFn, var_name string) {
|
||||
decl_var := g.fn_var_signature(expr.decl.return_type, expr.decl.params.map(it.typ),
|
||||
var_name)
|
||||
g.write('${decl_var} = ')
|
||||
g.gen_anon_fn(mut expr)
|
||||
g.writeln(';')
|
||||
g.past_tmp_var_done(past)
|
||||
g.write('(${var_name})') // usually `it`
|
||||
}
|
||||
|
||||
fn (mut g Gen) write_closure_fn(mut expr ast.AnonFn, var_name string, declared_var string) {
|
||||
if declared_var == '' {
|
||||
past := g.past_tmp_var_new()
|
||||
g.declare_closure_fn(mut expr, past.var_name)
|
||||
g.past_tmp_var_done(past)
|
||||
g.write('(${var_name})') // usually `it`
|
||||
} else {
|
||||
g.write('${declared_var}(${var_name})')
|
||||
}
|
||||
}
|
||||
|
||||
// `nums.map(it % 2 == 0)`
|
||||
@ -515,6 +523,15 @@ fn (mut g Gen) gen_array_map(node ast.CallExpr) {
|
||||
has_infix_left_var_name := g.write_prepared_tmp_value(past.tmp_var, node, ret_typ,
|
||||
'{0}')
|
||||
g.writeln('${past.tmp_var} = __new_array${noscan}(0, ${past.tmp_var}_len, sizeof(${ret_elem_type}));\n')
|
||||
|
||||
mut closure_var := ''
|
||||
if mut expr is ast.AnonFn {
|
||||
if expr.inherited_vars.len > 0 {
|
||||
closure_var = g.new_tmp_var()
|
||||
g.declare_closure_fn(mut expr, closure_var)
|
||||
}
|
||||
}
|
||||
|
||||
i := g.new_tmp_var()
|
||||
g.writeln('for (int ${i} = 0; ${i} < ${past.tmp_var}_len; ++${i}) {')
|
||||
g.indent++
|
||||
@ -526,7 +543,7 @@ fn (mut g Gen) gen_array_map(node ast.CallExpr) {
|
||||
ast.AnonFn {
|
||||
g.write('${ret_elem_type} ${tmp_map_expr_result_name} = ')
|
||||
if expr.inherited_vars.len > 0 {
|
||||
g.write_closure_fn(mut expr, var_name)
|
||||
g.write_closure_fn(mut expr, var_name, closure_var)
|
||||
} else {
|
||||
g.gen_anon_fn_decl(mut expr)
|
||||
g.write('${expr.decl.name}(${var_name})')
|
||||
@ -769,11 +786,21 @@ fn (mut g Gen) gen_array_filter(node ast.CallExpr) {
|
||||
noscan := g.check_noscan(info.elem_type)
|
||||
has_infix_left_var_name := g.write_prepared_tmp_value(past.tmp_var, node, styp, '{0}')
|
||||
g.writeln('${past.tmp_var} = __new_array${noscan}(0, ${past.tmp_var}_len, sizeof(${elem_type_str}));\n')
|
||||
|
||||
mut expr := node.args[0].expr
|
||||
var_name := g.get_array_expr_param_name(mut expr)
|
||||
|
||||
mut closure_var := ''
|
||||
if mut expr is ast.AnonFn {
|
||||
if expr.inherited_vars.len > 0 {
|
||||
closure_var = g.new_tmp_var()
|
||||
g.declare_closure_fn(mut expr, closure_var)
|
||||
}
|
||||
}
|
||||
|
||||
i := g.new_tmp_var()
|
||||
g.writeln('for (int ${i} = 0; ${i} < ${past.tmp_var}_len; ++${i}) {')
|
||||
g.indent++
|
||||
mut expr := node.args[0].expr
|
||||
var_name := g.get_array_expr_param_name(mut expr)
|
||||
g.write_prepared_var(var_name, info, elem_type_str, past.tmp_var, i)
|
||||
g.set_current_pos_as_last_stmt_pos()
|
||||
mut is_embed_map_filter := false
|
||||
@ -781,7 +808,7 @@ fn (mut g Gen) gen_array_filter(node ast.CallExpr) {
|
||||
ast.AnonFn {
|
||||
g.write('if (')
|
||||
if expr.inherited_vars.len > 0 {
|
||||
g.write_closure_fn(mut expr, var_name)
|
||||
g.write_closure_fn(mut expr, var_name, closure_var)
|
||||
} else {
|
||||
g.gen_anon_fn_decl(mut expr)
|
||||
g.write('${expr.decl.name}(${var_name})')
|
||||
@ -1163,11 +1190,21 @@ fn (mut g Gen) gen_array_any(node ast.CallExpr) {
|
||||
elem_type_str := g.typ(info.elem_type)
|
||||
has_infix_left_var_name := g.write_prepared_tmp_value(past.tmp_var, node, 'bool',
|
||||
'false')
|
||||
|
||||
mut expr := node.args[0].expr
|
||||
var_name := g.get_array_expr_param_name(mut expr)
|
||||
|
||||
mut closure_var := ''
|
||||
if mut expr is ast.AnonFn {
|
||||
if expr.inherited_vars.len > 0 {
|
||||
closure_var = g.new_tmp_var()
|
||||
g.declare_closure_fn(mut expr, closure_var)
|
||||
}
|
||||
}
|
||||
i := g.new_tmp_var()
|
||||
g.writeln('for (int ${i} = 0; ${i} < ${past.tmp_var}_len; ++${i}) {')
|
||||
g.indent++
|
||||
mut expr := node.args[0].expr
|
||||
var_name := g.get_array_expr_param_name(mut expr)
|
||||
|
||||
g.write_prepared_var(var_name, info, elem_type_str, past.tmp_var, i)
|
||||
g.set_current_pos_as_last_stmt_pos()
|
||||
mut is_embed_map_filter := false
|
||||
@ -1175,7 +1212,7 @@ fn (mut g Gen) gen_array_any(node ast.CallExpr) {
|
||||
ast.AnonFn {
|
||||
g.write('if (')
|
||||
if expr.inherited_vars.len > 0 {
|
||||
g.write_closure_fn(mut expr, var_name)
|
||||
g.write_closure_fn(mut expr, var_name, closure_var)
|
||||
} else {
|
||||
g.gen_anon_fn_decl(mut expr)
|
||||
g.write('${expr.decl.name}(${var_name})')
|
||||
@ -1244,10 +1281,20 @@ fn (mut g Gen) gen_array_all(node ast.CallExpr) {
|
||||
has_infix_left_var_name := g.write_prepared_tmp_value(past.tmp_var, node, 'bool',
|
||||
'true')
|
||||
i := g.new_tmp_var()
|
||||
g.writeln('for (int ${i} = 0; ${i} < ${past.tmp_var}_len; ++${i}) {')
|
||||
g.indent++
|
||||
|
||||
mut expr := node.args[0].expr
|
||||
var_name := g.get_array_expr_param_name(mut expr)
|
||||
|
||||
mut closure_var := ''
|
||||
if mut expr is ast.AnonFn {
|
||||
if expr.inherited_vars.len > 0 {
|
||||
closure_var = g.new_tmp_var()
|
||||
g.declare_closure_fn(mut expr, closure_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.empty_line = true
|
||||
g.set_current_pos_as_last_stmt_pos()
|
||||
@ -1256,7 +1303,7 @@ fn (mut g Gen) gen_array_all(node ast.CallExpr) {
|
||||
ast.AnonFn {
|
||||
g.write('if (!(')
|
||||
if expr.inherited_vars.len > 0 {
|
||||
g.write_closure_fn(mut expr, var_name)
|
||||
g.write_closure_fn(mut expr, var_name, closure_var)
|
||||
} else {
|
||||
g.gen_anon_fn_decl(mut expr)
|
||||
g.write('${expr.decl.name}(${var_name})')
|
||||
|
40
vlib/v/tests/array_ops_create_just_one_closure_test.c.v
Normal file
40
vlib/v/tests/array_ops_create_just_one_closure_test.c.v
Normal file
@ -0,0 +1,40 @@
|
||||
fn setup(fname string) (int, int, []int) {
|
||||
println(fname)
|
||||
return C._closure_cap, 42, []int{len: 5, init: index * 5}
|
||||
}
|
||||
|
||||
fn test_array_filter() {
|
||||
start_closure_cap, x, a := setup(@LOCATION)
|
||||
println(a.filter(fn [x] (i int) bool {
|
||||
println('x: ${x} | i: ${i}')
|
||||
return i < 20
|
||||
}))
|
||||
assert start_closure_cap - C._closure_cap == 1
|
||||
}
|
||||
|
||||
fn test_array_map() {
|
||||
start_closure_cap, x, a := setup(@LOCATION)
|
||||
println(a.map(fn [x] (i int) int {
|
||||
println('x: ${x} | i: ${i}')
|
||||
return x + i
|
||||
}))
|
||||
assert start_closure_cap - C._closure_cap == 1
|
||||
}
|
||||
|
||||
fn test_array_any() {
|
||||
start_closure_cap, x, a := setup(@LOCATION)
|
||||
println(a.any(fn [x] (i int) bool {
|
||||
println('x: ${x} | i: ${i}')
|
||||
return i < x
|
||||
}))
|
||||
assert start_closure_cap - C._closure_cap == 1
|
||||
}
|
||||
|
||||
fn test_array_all() {
|
||||
start_closure_cap, x, a := setup(@LOCATION)
|
||||
println(a.all(fn [x] (i int) bool {
|
||||
println('x: ${x} | i: ${i}')
|
||||
return i < x
|
||||
}))
|
||||
assert start_closure_cap - C._closure_cap == 1
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user