mirror of
https://github.com/vlang/v.git
synced 2025-09-09 15:27:05 -04:00
checker: support lambda expressions in array methods like a.map(|x|x*10)
too (#19424)
This commit is contained in:
parent
9954f89e3f
commit
a685088fbd
35
vlib/builtin/lambda_expr_array_test.v
Normal file
35
vlib/builtin/lambda_expr_array_test.v
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
const a = [4, 5, 1, 2, 5, 9]
|
||||||
|
|
||||||
|
fn test_map() {
|
||||||
|
assert a.map(it) == a
|
||||||
|
assert a.map(it * 10) == [40, 50, 10, 20, 50, 90]
|
||||||
|
//
|
||||||
|
assert a.map(|x| x) == a
|
||||||
|
assert a.map(|x| x * 10) == [40, 50, 10, 20, 50, 90]
|
||||||
|
assert a.map(|x| 'x: ${x}') == ['x: 4', 'x: 5', 'x: 1', 'x: 2', 'x: 5', 'x: 9']
|
||||||
|
assert a.map(|x| f64(x) * 10.0) == [40.0, 50.0, 10.0, 20.0, 50.0, 90.0]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_filter() {
|
||||||
|
assert a.filter(it > 4) == [5, 5, 9]
|
||||||
|
assert a.filter(it < 4) == [1, 2]
|
||||||
|
//
|
||||||
|
assert a.filter(|x| x > 4) == [5, 5, 9]
|
||||||
|
assert a.filter(|x| x < 4) == [1, 2]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_any() {
|
||||||
|
assert a.any(it > 4)
|
||||||
|
assert !a.any(it > 40)
|
||||||
|
|
||||||
|
assert a.any(|x| x > 4)
|
||||||
|
assert !a.any(|x| x > 40)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_all() {
|
||||||
|
assert !a.all(it > 4)
|
||||||
|
assert a.all(it < 40)
|
||||||
|
|
||||||
|
assert !a.all(|x| x > 4)
|
||||||
|
assert a.all(|x| x < 40)
|
||||||
|
}
|
@ -1786,9 +1786,9 @@ pub:
|
|||||||
|
|
||||||
pub struct LambdaExpr {
|
pub struct LambdaExpr {
|
||||||
pub:
|
pub:
|
||||||
pos token.Pos
|
pos token.Pos
|
||||||
params []Ident
|
|
||||||
pub mut:
|
pub mut:
|
||||||
|
params []Ident
|
||||||
pos_expr token.Pos
|
pos_expr token.Pos
|
||||||
expr Expr
|
expr Expr
|
||||||
pos_end token.Pos
|
pos_end token.Pos
|
||||||
|
@ -2587,6 +2587,7 @@ fn (mut c Checker) array_builtin_method_call(mut node ast.CallExpr, left_type as
|
|||||||
mut elem_typ := ast.void_type
|
mut elem_typ := ast.void_type
|
||||||
if method_name == 'slice' && !c.is_builtin_mod {
|
if method_name == 'slice' && !c.is_builtin_mod {
|
||||||
c.error('.slice() is a private method, use `x[start..end]` instead', node.pos)
|
c.error('.slice() is a private method, use `x[start..end]` instead', node.pos)
|
||||||
|
return ast.void_type
|
||||||
}
|
}
|
||||||
array_info := if left_sym.info is ast.Array {
|
array_info := if left_sym.info is ast.Array {
|
||||||
left_sym.info as ast.Array
|
left_sym.info as ast.Array
|
||||||
@ -2595,10 +2596,27 @@ fn (mut c Checker) array_builtin_method_call(mut node ast.CallExpr, left_type as
|
|||||||
}
|
}
|
||||||
elem_typ = array_info.elem_type
|
elem_typ = array_info.elem_type
|
||||||
if method_name in ['filter', 'map', 'any', 'all'] {
|
if method_name in ['filter', 'map', 'any', 'all'] {
|
||||||
// position of `it` doesn't matter
|
if node.args.len > 0 && mut node.args[0].expr is ast.LambdaExpr {
|
||||||
scope_register_it(mut node.scope, node.pos, elem_typ)
|
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
|
||||||
|
}
|
||||||
|
if method_name == 'map' {
|
||||||
|
c.lambda_expr_fix_type_of_param(mut node.args[0].expr, mut node.args[0].expr.params[0],
|
||||||
|
elem_typ)
|
||||||
|
le_type := c.expr(mut node.args[0].expr.expr)
|
||||||
|
// eprintln('>>>>> node.args[0].expr: ${ast.Expr(node.args[0].expr)} | elem_typ: ${elem_typ} | etype: ${le_type}')
|
||||||
|
c.support_lambda_expr_one_param(elem_typ, le_type, mut node.args[0].expr)
|
||||||
|
} else {
|
||||||
|
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)
|
||||||
|
}
|
||||||
} else if method_name == 'sorted_with_compare' && node.args.len == 1 {
|
} else if method_name == 'sorted_with_compare' && node.args.len == 1 {
|
||||||
if mut node.args[0].expr is ast.LambdaExpr {
|
if node.args.len > 0 && mut node.args[0].expr is ast.LambdaExpr {
|
||||||
c.support_lambda_expr_in_sort(elem_typ.ref(), ast.int_type, mut node.args[0].expr)
|
c.support_lambda_expr_in_sort(elem_typ.ref(), ast.int_type, mut node.args[0].expr)
|
||||||
}
|
}
|
||||||
} else if method_name == 'sort' || method_name == 'sorted' {
|
} else if method_name == 'sort' || method_name == 'sorted' {
|
||||||
@ -2671,6 +2689,7 @@ fn (mut c Checker) array_builtin_method_call(mut node ast.CallExpr, left_type as
|
|||||||
arg_type = c.check_expr_opt_call(arg.expr, c.expr(mut arg.expr))
|
arg_type = c.check_expr_opt_call(arg.expr, c.expr(mut arg.expr))
|
||||||
}
|
}
|
||||||
if method_name == 'map' {
|
if method_name == 'map' {
|
||||||
|
// eprintln('>>>>>>> map node.args[0].expr: ${node.args[0].expr}, left_type: ${left_type} | elem_typ: ${elem_typ} | arg_type: ${arg_type}')
|
||||||
// check fn
|
// check fn
|
||||||
c.check_map_and_filter(true, elem_typ, node)
|
c.check_map_and_filter(true, elem_typ, node)
|
||||||
arg_sym := c.table.sym(arg_type)
|
arg_sym := c.table.sym(arg_type)
|
||||||
@ -2777,25 +2796,19 @@ fn (mut c Checker) array_builtin_method_call(mut node ast.CallExpr, left_type as
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn scope_register_it(mut s ast.Scope, pos token.Pos, typ ast.Type) {
|
fn scope_register_it(mut s ast.Scope, pos token.Pos, typ ast.Type) {
|
||||||
|
scope_register_var_name(mut s, pos, typ, 'it')
|
||||||
|
}
|
||||||
|
|
||||||
|
fn scope_register_a_b(mut s ast.Scope, pos token.Pos, typ ast.Type) {
|
||||||
|
scope_register_var_name(mut s, pos, typ.ref(), 'a')
|
||||||
|
scope_register_var_name(mut s, pos, typ.ref(), 'b')
|
||||||
|
}
|
||||||
|
|
||||||
|
fn scope_register_var_name(mut s ast.Scope, pos token.Pos, typ ast.Type, name string) {
|
||||||
s.register(ast.Var{
|
s.register(ast.Var{
|
||||||
name: 'it'
|
name: name
|
||||||
pos: pos
|
pos: pos
|
||||||
typ: typ
|
typ: typ
|
||||||
is_used: true
|
is_used: true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scope_register_a_b(mut s ast.Scope, pos token.Pos, typ ast.Type) {
|
|
||||||
s.register(ast.Var{
|
|
||||||
name: 'a'
|
|
||||||
pos: pos
|
|
||||||
typ: typ.ref()
|
|
||||||
is_used: true
|
|
||||||
})
|
|
||||||
s.register(ast.Var{
|
|
||||||
name: 'b'
|
|
||||||
pos: pos
|
|
||||||
typ: typ.ref()
|
|
||||||
is_used: true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
@ -33,17 +33,7 @@ pub fn (mut c Checker) lambda_expr(mut node ast.LambdaExpr, exp_typ ast.Type) as
|
|||||||
eparam := exp_sym.info.func.params[idx]
|
eparam := exp_sym.info.func.params[idx]
|
||||||
eparam_type := eparam.typ
|
eparam_type := eparam.typ
|
||||||
eparam_auto_deref := eparam.typ.is_ptr()
|
eparam_auto_deref := eparam.typ.is_ptr()
|
||||||
if mut v := node.scope.find(x.name) {
|
c.lambda_expr_fix_type_of_param(mut node, mut x, eparam_type)
|
||||||
if mut v is ast.Var {
|
|
||||||
v.is_arg = true
|
|
||||||
v.typ = eparam_type
|
|
||||||
v.expr = ast.empty_expr
|
|
||||||
v.is_auto_deref = eparam_auto_deref
|
|
||||||
}
|
|
||||||
}
|
|
||||||
c.ident(mut x)
|
|
||||||
x.obj.typ = eparam_type
|
|
||||||
|
|
||||||
params << ast.Param{
|
params << ast.Param{
|
||||||
pos: x.pos
|
pos: x.pos
|
||||||
name: x.name
|
name: x.name
|
||||||
@ -100,6 +90,19 @@ pub fn (mut c Checker) lambda_expr(mut node ast.LambdaExpr, exp_typ ast.Type) as
|
|||||||
return exp_typ
|
return exp_typ
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn (mut c Checker) lambda_expr_fix_type_of_param(mut node ast.LambdaExpr, mut pident ast.Ident, ptype ast.Type) {
|
||||||
|
if mut v := node.scope.find(pident.name) {
|
||||||
|
if mut v is ast.Var {
|
||||||
|
v.is_arg = true
|
||||||
|
v.typ = ptype
|
||||||
|
v.is_auto_deref = ptype.is_ptr()
|
||||||
|
v.expr = ast.empty_expr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.ident(mut pident)
|
||||||
|
pident.obj.typ = ptype
|
||||||
|
}
|
||||||
|
|
||||||
pub fn (mut c Checker) support_lambda_expr_in_sort(param_type ast.Type, return_type ast.Type, mut expr ast.LambdaExpr) {
|
pub fn (mut c Checker) support_lambda_expr_in_sort(param_type ast.Type, return_type ast.Type, mut expr ast.LambdaExpr) {
|
||||||
is_auto_rec := param_type.is_ptr()
|
is_auto_rec := param_type.is_ptr()
|
||||||
mut expected_fn := ast.Fn{
|
mut expected_fn := ast.Fn{
|
||||||
@ -121,3 +124,19 @@ pub fn (mut c Checker) support_lambda_expr_in_sort(param_type ast.Type, return_t
|
|||||||
false))
|
false))
|
||||||
c.lambda_expr(mut expr, expected_fn_type)
|
c.lambda_expr(mut expr, expected_fn_type)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn (mut c Checker) support_lambda_expr_one_param(param_type ast.Type, return_type ast.Type, mut expr ast.LambdaExpr) {
|
||||||
|
mut expected_fn := ast.Fn{
|
||||||
|
params: [
|
||||||
|
ast.Param{
|
||||||
|
name: 'xx'
|
||||||
|
typ: param_type
|
||||||
|
is_auto_rec: param_type.is_ptr()
|
||||||
|
},
|
||||||
|
]
|
||||||
|
return_type: return_type
|
||||||
|
}
|
||||||
|
cb_type := c.table.find_or_register_fn_type(expected_fn, true, false)
|
||||||
|
expected_fn_type := ast.new_type(cb_type)
|
||||||
|
c.lambda_expr(mut expr, expected_fn_type)
|
||||||
|
}
|
||||||
|
12
vlib/v/checker/tests/lambda_expression_in_map.out
Normal file
12
vlib/v/checker/tests/lambda_expression_in_map.out
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
vlib/v/checker/tests/lambda_expression_in_map.vv:3:12: error: lambda expressions used in the builtin array methods require exactly 1 parameter
|
||||||
|
1 | a := [4, 5]
|
||||||
|
2 | dump(a.map(it))
|
||||||
|
3 | dump(a.map(|| 5))
|
||||||
|
| ~~
|
||||||
|
4 | dump(a.map(|x| 5 * x))
|
||||||
|
5 | dump(a.map(|x| x))
|
||||||
|
vlib/v/checker/tests/lambda_expression_in_map.vv:6:12: error: lambda expressions used in the builtin array methods require exactly 1 parameter
|
||||||
|
4 | dump(a.map(|x| 5 * x))
|
||||||
|
5 | dump(a.map(|x| x))
|
||||||
|
6 | dump(a.map(|x, y| x))
|
||||||
|
| ^
|
6
vlib/v/checker/tests/lambda_expression_in_map.vv
Normal file
6
vlib/v/checker/tests/lambda_expression_in_map.vv
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
a := [4, 5]
|
||||||
|
dump(a.map(it))
|
||||||
|
dump(a.map(|| 5))
|
||||||
|
dump(a.map(|x| 5 * x))
|
||||||
|
dump(a.map(|x| x))
|
||||||
|
dump(a.map(|x, y| x))
|
@ -455,7 +455,7 @@ 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) {
|
fn (mut g Gen) write_closure_fn(mut expr ast.AnonFn, var_name string) {
|
||||||
past := g.past_tmp_var_new()
|
past := g.past_tmp_var_new()
|
||||||
fn_ptr_name := g.fn_var_signature(expr.decl.return_type, expr.decl.params.map(it.typ),
|
fn_ptr_name := g.fn_var_signature(expr.decl.return_type, expr.decl.params.map(it.typ),
|
||||||
past.tmp_var)
|
past.tmp_var)
|
||||||
@ -463,7 +463,7 @@ fn (mut g Gen) write_closure_fn(mut expr ast.AnonFn) {
|
|||||||
g.gen_anon_fn(mut expr)
|
g.gen_anon_fn(mut expr)
|
||||||
g.writeln(';')
|
g.writeln(';')
|
||||||
g.past_tmp_var_done(past)
|
g.past_tmp_var_done(past)
|
||||||
g.write('(it)')
|
g.write('(${var_name})') // usually `it`
|
||||||
}
|
}
|
||||||
|
|
||||||
// `nums.map(it % 2 == 0)`
|
// `nums.map(it % 2 == 0)`
|
||||||
@ -490,14 +490,16 @@ fn (mut g Gen) gen_array_map(node ast.CallExpr) {
|
|||||||
verror('map() requires an array')
|
verror('map() requires an array')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mut expr := node.args[0].expr
|
||||||
mut closure_var_decl := ''
|
mut closure_var_decl := ''
|
||||||
if node.args[0].expr is ast.SelectorExpr {
|
tmp_map_expr_result_name := g.new_tmp_var()
|
||||||
if node.args[0].expr.typ != ast.void_type {
|
if mut expr is ast.SelectorExpr {
|
||||||
var_sym := g.table.sym(node.args[0].expr.typ)
|
if expr.typ != ast.void_type {
|
||||||
|
var_sym := g.table.sym(expr.typ)
|
||||||
if var_sym.info is ast.FnType {
|
if var_sym.info is ast.FnType {
|
||||||
ret_elem_type = 'voidptr'
|
ret_elem_type = 'voidptr'
|
||||||
closure_var_decl = g.fn_var_signature(var_sym.info.func.return_type, var_sym.info.func.params.map(it.typ),
|
closure_var_decl = g.fn_var_signature(var_sym.info.func.return_type, var_sym.info.func.params.map(it.typ),
|
||||||
'ti')
|
tmp_map_expr_result_name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -508,34 +510,34 @@ fn (mut g Gen) gen_array_map(node ast.CallExpr) {
|
|||||||
i := g.new_tmp_var()
|
i := g.new_tmp_var()
|
||||||
g.writeln('for (int ${i} = 0; ${i} < ${past.tmp_var}_len; ++${i}) {')
|
g.writeln('for (int ${i} = 0; ${i} < ${past.tmp_var}_len; ++${i}) {')
|
||||||
g.indent++
|
g.indent++
|
||||||
g.write_prepared_it(inp_info, inp_elem_type, past.tmp_var, i)
|
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.set_current_pos_as_last_stmt_pos()
|
g.set_current_pos_as_last_stmt_pos()
|
||||||
mut is_embed_map_filter := false
|
mut is_embed_map_filter := false
|
||||||
mut expr := node.args[0].expr
|
|
||||||
match mut expr {
|
match mut expr {
|
||||||
ast.AnonFn {
|
ast.AnonFn {
|
||||||
g.write('${ret_elem_type} ti = ')
|
g.write('${ret_elem_type} ${tmp_map_expr_result_name} = ')
|
||||||
if expr.inherited_vars.len > 0 {
|
if expr.inherited_vars.len > 0 {
|
||||||
g.write_closure_fn(mut expr)
|
g.write_closure_fn(mut expr, var_name)
|
||||||
} else {
|
} else {
|
||||||
g.gen_anon_fn_decl(mut expr)
|
g.gen_anon_fn_decl(mut expr)
|
||||||
g.write('${expr.decl.name}(it)')
|
g.write('${expr.decl.name}(${var_name})')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.Ident {
|
ast.Ident {
|
||||||
g.write('${ret_elem_type} ti = ')
|
g.write('${ret_elem_type} ${tmp_map_expr_result_name} = ')
|
||||||
if expr.kind == .function {
|
if expr.kind == .function {
|
||||||
g.write('${c_name(expr.name)}(it)')
|
g.write('${c_name(expr.name)}(${var_name})')
|
||||||
} else if expr.kind == .variable {
|
} else if expr.kind == .variable {
|
||||||
var_info := expr.var_info()
|
var_info := expr.var_info()
|
||||||
sym := g.table.sym(var_info.typ)
|
sym := g.table.sym(var_info.typ)
|
||||||
if sym.kind == .function {
|
if sym.kind == .function {
|
||||||
g.write('${c_name(expr.name)}(it)')
|
g.write('${c_name(expr.name)}(${var_name})')
|
||||||
} else {
|
} else {
|
||||||
g.expr(node.args[0].expr)
|
g.expr(expr)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
g.expr(node.args[0].expr)
|
g.expr(expr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.CallExpr {
|
ast.CallExpr {
|
||||||
@ -543,8 +545,8 @@ fn (mut g Gen) gen_array_map(node ast.CallExpr) {
|
|||||||
is_embed_map_filter = true
|
is_embed_map_filter = true
|
||||||
g.set_current_pos_as_last_stmt_pos()
|
g.set_current_pos_as_last_stmt_pos()
|
||||||
}
|
}
|
||||||
g.write('${ret_elem_type} ti = ')
|
g.write('${ret_elem_type} ${tmp_map_expr_result_name} = ')
|
||||||
g.expr(node.args[0].expr)
|
g.expr(expr)
|
||||||
}
|
}
|
||||||
ast.CastExpr {
|
ast.CastExpr {
|
||||||
// value.map(Type(it)) when `value` is a comptime var
|
// value.map(Type(it)) when `value` is a comptime var
|
||||||
@ -554,20 +556,24 @@ fn (mut g Gen) gen_array_map(node ast.CallExpr) {
|
|||||||
expr.expr_type = g.table.value_type(ctyp)
|
expr.expr_type = g.table.value_type(ctyp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g.write('${ret_elem_type} ti = ')
|
g.write('${ret_elem_type} ${tmp_map_expr_result_name} = ')
|
||||||
g.expr(node.args[0].expr)
|
g.expr(expr)
|
||||||
|
}
|
||||||
|
ast.LambdaExpr {
|
||||||
|
g.write('${ret_elem_type} ${tmp_map_expr_result_name} = ')
|
||||||
|
g.expr(expr.expr)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if closure_var_decl != '' {
|
if closure_var_decl != '' {
|
||||||
g.write('${closure_var_decl} = ')
|
g.write('${closure_var_decl} = ')
|
||||||
} else {
|
} else {
|
||||||
g.write('${ret_elem_type} ti = ')
|
g.write('${ret_elem_type} ${tmp_map_expr_result_name} = ')
|
||||||
}
|
}
|
||||||
g.expr(node.args[0].expr)
|
g.expr(expr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g.writeln(';')
|
g.writeln(';')
|
||||||
g.writeln('array_push${noscan}((array*)&${past.tmp_var}, &ti);')
|
g.writeln('array_push${noscan}((array*)&${past.tmp_var}, &${tmp_map_expr_result_name});')
|
||||||
g.indent--
|
g.indent--
|
||||||
g.writeln('}')
|
g.writeln('}')
|
||||||
if !is_embed_map_filter {
|
if !is_embed_map_filter {
|
||||||
@ -742,34 +748,35 @@ fn (mut g Gen) gen_array_filter(node ast.CallExpr) {
|
|||||||
i := g.new_tmp_var()
|
i := g.new_tmp_var()
|
||||||
g.writeln('for (int ${i} = 0; ${i} < ${past.tmp_var}_len; ++${i}) {')
|
g.writeln('for (int ${i} = 0; ${i} < ${past.tmp_var}_len; ++${i}) {')
|
||||||
g.indent++
|
g.indent++
|
||||||
g.write_prepared_it(info, elem_type_str, past.tmp_var, i)
|
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()
|
g.set_current_pos_as_last_stmt_pos()
|
||||||
mut is_embed_map_filter := false
|
mut is_embed_map_filter := false
|
||||||
mut expr := node.args[0].expr
|
|
||||||
match mut expr {
|
match mut expr {
|
||||||
ast.AnonFn {
|
ast.AnonFn {
|
||||||
g.write('if (')
|
g.write('if (')
|
||||||
if expr.inherited_vars.len > 0 {
|
if expr.inherited_vars.len > 0 {
|
||||||
g.write_closure_fn(mut expr)
|
g.write_closure_fn(mut expr, var_name)
|
||||||
} else {
|
} else {
|
||||||
g.gen_anon_fn_decl(mut expr)
|
g.gen_anon_fn_decl(mut expr)
|
||||||
g.write('${expr.decl.name}(it)')
|
g.write('${expr.decl.name}(${var_name})')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.Ident {
|
ast.Ident {
|
||||||
g.write('if (')
|
g.write('if (')
|
||||||
if expr.kind == .function {
|
if expr.kind == .function {
|
||||||
g.write('${c_name(expr.name)}(it)')
|
g.write('${c_name(expr.name)}(${var_name})')
|
||||||
} else if expr.kind == .variable {
|
} else if expr.kind == .variable {
|
||||||
var_info := expr.var_info()
|
var_info := expr.var_info()
|
||||||
sym_t := g.table.sym(var_info.typ)
|
sym_t := g.table.sym(var_info.typ)
|
||||||
if sym_t.kind == .function {
|
if sym_t.kind == .function {
|
||||||
g.write('${c_name(expr.name)}(it)')
|
g.write('${c_name(expr.name)}(${var_name})')
|
||||||
} else {
|
} else {
|
||||||
g.expr(node.args[0].expr)
|
g.expr(expr)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
g.expr(node.args[0].expr)
|
g.expr(expr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.CallExpr {
|
ast.CallExpr {
|
||||||
@ -778,15 +785,19 @@ fn (mut g Gen) gen_array_filter(node ast.CallExpr) {
|
|||||||
g.set_current_pos_as_last_stmt_pos()
|
g.set_current_pos_as_last_stmt_pos()
|
||||||
}
|
}
|
||||||
g.write('if (')
|
g.write('if (')
|
||||||
g.expr(node.args[0].expr)
|
g.expr(expr)
|
||||||
|
}
|
||||||
|
ast.LambdaExpr {
|
||||||
|
g.write('if (')
|
||||||
|
g.expr(expr.expr)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
g.write('if (')
|
g.write('if (')
|
||||||
g.expr(node.args[0].expr)
|
g.expr(expr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g.writeln(') {')
|
g.writeln(') {')
|
||||||
g.writeln('\tarray_push${noscan}((array*)&${past.tmp_var}, &it);')
|
g.writeln('\tarray_push${noscan}((array*)&${past.tmp_var}, &${var_name});')
|
||||||
g.writeln('}')
|
g.writeln('}')
|
||||||
g.indent--
|
g.indent--
|
||||||
g.writeln('}')
|
g.writeln('}')
|
||||||
@ -1127,34 +1138,35 @@ fn (mut g Gen) gen_array_any(node ast.CallExpr) {
|
|||||||
i := g.new_tmp_var()
|
i := g.new_tmp_var()
|
||||||
g.writeln('for (int ${i} = 0; ${i} < ${past.tmp_var}_len; ++${i}) {')
|
g.writeln('for (int ${i} = 0; ${i} < ${past.tmp_var}_len; ++${i}) {')
|
||||||
g.indent++
|
g.indent++
|
||||||
g.write_prepared_it(info, elem_type_str, past.tmp_var, i)
|
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()
|
g.set_current_pos_as_last_stmt_pos()
|
||||||
mut is_embed_map_filter := false
|
mut is_embed_map_filter := false
|
||||||
mut expr := node.args[0].expr
|
|
||||||
match mut expr {
|
match mut expr {
|
||||||
ast.AnonFn {
|
ast.AnonFn {
|
||||||
g.write('if (')
|
g.write('if (')
|
||||||
if expr.inherited_vars.len > 0 {
|
if expr.inherited_vars.len > 0 {
|
||||||
g.write_closure_fn(mut expr)
|
g.write_closure_fn(mut expr, var_name)
|
||||||
} else {
|
} else {
|
||||||
g.gen_anon_fn_decl(mut expr)
|
g.gen_anon_fn_decl(mut expr)
|
||||||
g.write('${expr.decl.name}(it)')
|
g.write('${expr.decl.name}(${var_name})')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.Ident {
|
ast.Ident {
|
||||||
g.write('if (')
|
g.write('if (')
|
||||||
if expr.kind == .function {
|
if expr.kind == .function {
|
||||||
g.write('${c_name(expr.name)}(it)')
|
g.write('${c_name(expr.name)}(${var_name})')
|
||||||
} else if expr.kind == .variable {
|
} else if expr.kind == .variable {
|
||||||
var_info := expr.var_info()
|
var_info := expr.var_info()
|
||||||
sym_t := g.table.sym(var_info.typ)
|
sym_t := g.table.sym(var_info.typ)
|
||||||
if sym_t.kind == .function {
|
if sym_t.kind == .function {
|
||||||
g.write('${c_name(expr.name)}(it)')
|
g.write('${c_name(expr.name)}(${var_name})')
|
||||||
} else {
|
} else {
|
||||||
g.expr(node.args[0].expr)
|
g.expr(expr)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
g.expr(node.args[0].expr)
|
g.expr(expr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.CallExpr {
|
ast.CallExpr {
|
||||||
@ -1163,11 +1175,15 @@ fn (mut g Gen) gen_array_any(node ast.CallExpr) {
|
|||||||
g.set_current_pos_as_last_stmt_pos()
|
g.set_current_pos_as_last_stmt_pos()
|
||||||
}
|
}
|
||||||
g.write('if (')
|
g.write('if (')
|
||||||
g.expr(node.args[0].expr)
|
g.expr(expr)
|
||||||
|
}
|
||||||
|
ast.LambdaExpr {
|
||||||
|
g.write('if (')
|
||||||
|
g.expr(expr.expr)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
g.write('if (')
|
g.write('if (')
|
||||||
g.expr(node.args[0].expr)
|
g.expr(expr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g.writeln(') {')
|
g.writeln(') {')
|
||||||
@ -1202,35 +1218,36 @@ fn (mut g Gen) gen_array_all(node ast.CallExpr) {
|
|||||||
i := g.new_tmp_var()
|
i := g.new_tmp_var()
|
||||||
g.writeln('for (int ${i} = 0; ${i} < ${past.tmp_var}_len; ++${i}) {')
|
g.writeln('for (int ${i} = 0; ${i} < ${past.tmp_var}_len; ++${i}) {')
|
||||||
g.indent++
|
g.indent++
|
||||||
g.write_prepared_it(info, elem_type_str, past.tmp_var, i)
|
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.empty_line = true
|
g.empty_line = true
|
||||||
g.set_current_pos_as_last_stmt_pos()
|
g.set_current_pos_as_last_stmt_pos()
|
||||||
mut is_embed_map_filter := false
|
mut is_embed_map_filter := false
|
||||||
mut expr := node.args[0].expr
|
|
||||||
match mut expr {
|
match mut expr {
|
||||||
ast.AnonFn {
|
ast.AnonFn {
|
||||||
g.write('if (!(')
|
g.write('if (!(')
|
||||||
if expr.inherited_vars.len > 0 {
|
if expr.inherited_vars.len > 0 {
|
||||||
g.write_closure_fn(mut expr)
|
g.write_closure_fn(mut expr, var_name)
|
||||||
} else {
|
} else {
|
||||||
g.gen_anon_fn_decl(mut expr)
|
g.gen_anon_fn_decl(mut expr)
|
||||||
g.write('${expr.decl.name}(it)')
|
g.write('${expr.decl.name}(${var_name})')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.Ident {
|
ast.Ident {
|
||||||
g.write('if (!(')
|
g.write('if (!(')
|
||||||
if expr.kind == .function {
|
if expr.kind == .function {
|
||||||
g.write('${c_name(expr.name)}(it)')
|
g.write('${c_name(expr.name)}(${var_name})')
|
||||||
} else if expr.kind == .variable {
|
} else if expr.kind == .variable {
|
||||||
var_info := expr.var_info()
|
var_info := expr.var_info()
|
||||||
sym_t := g.table.sym(var_info.typ)
|
sym_t := g.table.sym(var_info.typ)
|
||||||
if sym_t.kind == .function {
|
if sym_t.kind == .function {
|
||||||
g.write('${c_name(expr.name)}(it)')
|
g.write('${c_name(expr.name)}(${var_name})')
|
||||||
} else {
|
} else {
|
||||||
g.expr(node.args[0].expr)
|
g.expr(expr)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
g.expr(node.args[0].expr)
|
g.expr(expr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.CallExpr {
|
ast.CallExpr {
|
||||||
@ -1239,11 +1256,15 @@ fn (mut g Gen) gen_array_all(node ast.CallExpr) {
|
|||||||
g.set_current_pos_as_last_stmt_pos()
|
g.set_current_pos_as_last_stmt_pos()
|
||||||
}
|
}
|
||||||
g.write('if (!(')
|
g.write('if (!(')
|
||||||
g.expr(node.args[0].expr)
|
g.expr(expr)
|
||||||
|
}
|
||||||
|
ast.LambdaExpr {
|
||||||
|
g.write('if (!(')
|
||||||
|
g.expr(expr.expr)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
g.write('if (!(')
|
g.write('if (!(')
|
||||||
g.expr(node.args[0].expr)
|
g.expr(expr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g.writeln(')) {')
|
g.writeln(')) {')
|
||||||
@ -1290,12 +1311,12 @@ fn (mut g Gen) write_prepared_tmp_value(tmp string, node &ast.CallExpr, tmp_styp
|
|||||||
return has_infix_left_var_name
|
return has_infix_left_var_name
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) write_prepared_it(inp_info ast.Array, inp_elem_type string, tmp string, i string) {
|
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 {
|
if g.table.sym(inp_info.elem_type).kind == .array_fixed {
|
||||||
g.writeln('${inp_elem_type} it;')
|
g.writeln('${inp_elem_type} ${var_name};')
|
||||||
g.writeln('memcpy(&it, ((${inp_elem_type}*) ${tmp}_orig.data)[${i}], sizeof(${inp_elem_type}));')
|
g.writeln('memcpy(&${var_name}, ((${inp_elem_type}*) ${tmp}_orig.data)[${i}], sizeof(${inp_elem_type}));')
|
||||||
} else {
|
} else {
|
||||||
g.writeln('${inp_elem_type} it = ((${inp_elem_type}*) ${tmp}_orig.data)[${i}];')
|
g.writeln('${inp_elem_type} ${var_name} = ((${inp_elem_type}*) ${tmp}_orig.data)[${i}];')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1313,3 +1334,11 @@ fn (mut g Gen) fixed_array_var_init(expr ast.Expr, size int) {
|
|||||||
}
|
}
|
||||||
g.write('}')
|
g.write('}')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) get_array_expr_param_name(mut expr ast.Expr) string {
|
||||||
|
return if mut expr is ast.LambdaExpr {
|
||||||
|
expr.params[0].name
|
||||||
|
} else {
|
||||||
|
'it'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user