mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
parser, checker, cgen: fix swapping arrays (#18204)
This commit is contained in:
parent
332235548e
commit
94217571cd
@ -258,7 +258,7 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
|
|||||||
if !is_decl && left is ast.Ident && !is_blank_ident && !left_type.is_real_pointer()
|
if !is_decl && left is ast.Ident && !is_blank_ident && !left_type.is_real_pointer()
|
||||||
&& right_type.is_real_pointer() && !right_type.has_flag(.shared_f) {
|
&& right_type.is_real_pointer() && !right_type.has_flag(.shared_f) {
|
||||||
left_sym := c.table.sym(left_type)
|
left_sym := c.table.sym(left_type)
|
||||||
if left_sym.kind != .function {
|
if left_sym.kind !in [.function, .array] {
|
||||||
c.warn(
|
c.warn(
|
||||||
'cannot assign a reference to a value (this will be an error soon) left=${c.table.type_str(left_type)} ${left_type.is_ptr()} ' +
|
'cannot assign a reference to a value (this will be an error soon) left=${c.table.type_str(left_type)} ${left_type.is_ptr()} ' +
|
||||||
'right=${c.table.type_str(right_type)} ${right_type.is_real_pointer()} ptr=${right_type.is_ptr()}',
|
'right=${c.table.type_str(right_type)} ${right_type.is_real_pointer()} ptr=${right_type.is_ptr()}',
|
||||||
|
@ -843,6 +843,7 @@ fn (mut g Gen) gen_assign_vars_autofree(node &ast.AssignStmt) {
|
|||||||
|
|
||||||
fn (mut g Gen) gen_cross_var_assign(node &ast.AssignStmt) {
|
fn (mut g Gen) gen_cross_var_assign(node &ast.AssignStmt) {
|
||||||
for i, left in node.left {
|
for i, left in node.left {
|
||||||
|
left_is_auto_deref_var := left.is_auto_deref_var()
|
||||||
match left {
|
match left {
|
||||||
ast.Ident {
|
ast.Ident {
|
||||||
left_typ := node.left_types[i]
|
left_typ := node.left_types[i]
|
||||||
@ -851,9 +852,20 @@ fn (mut g Gen) gen_cross_var_assign(node &ast.AssignStmt) {
|
|||||||
if left_sym.kind == .function {
|
if left_sym.kind == .function {
|
||||||
g.write_fn_ptr_decl(left_sym.info as ast.FnType, '_var_${left.pos.pos}')
|
g.write_fn_ptr_decl(left_sym.info as ast.FnType, '_var_${left.pos.pos}')
|
||||||
g.writeln(' = ${anon_ctx}${c_name(left.name)};')
|
g.writeln(' = ${anon_ctx}${c_name(left.name)};')
|
||||||
|
} else if left_is_auto_deref_var {
|
||||||
|
styp := g.typ(left_typ).trim('*')
|
||||||
|
if left_sym.kind == .array {
|
||||||
|
g.writeln('${styp} _var_${left.pos.pos} = array_clone(${anon_ctx}${c_name(left.name)});')
|
||||||
|
} else {
|
||||||
|
g.writeln('${styp} _var_${left.pos.pos} = *${anon_ctx}${c_name(left.name)};')
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
styp := g.typ(left_typ)
|
styp := g.typ(left_typ)
|
||||||
g.writeln('${styp} _var_${left.pos.pos} = ${anon_ctx}${c_name(left.name)};')
|
if left_sym.kind == .array {
|
||||||
|
g.writeln('${styp} _var_${left.pos.pos} = array_clone(&${anon_ctx}${c_name(left.name)});')
|
||||||
|
} else {
|
||||||
|
g.writeln('${styp} _var_${left.pos.pos} = ${anon_ctx}${c_name(left.name)};')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.IndexExpr {
|
ast.IndexExpr {
|
||||||
@ -1009,18 +1021,36 @@ fn (mut g Gen) gen_cross_tmp_variable(left []ast.Expr, val ast.Expr) {
|
|||||||
g.write(')')
|
g.write(')')
|
||||||
}
|
}
|
||||||
ast.CallExpr {
|
ast.CallExpr {
|
||||||
mut fn_name := val.name.replace('.', '__')
|
if val.is_method {
|
||||||
if val.concrete_types.len > 0 {
|
rec_cc_type := g.cc_type(val.receiver_type, false)
|
||||||
fn_name = g.generic_fn_name(val.concrete_types, fn_name)
|
mut rec_typ_name := util.no_dots(rec_cc_type)
|
||||||
}
|
if g.table.sym(val.receiver_type).kind == .array {
|
||||||
g.write('${fn_name}(')
|
rec_typ_name = 'array'
|
||||||
for i, arg in val.args {
|
|
||||||
g.gen_cross_tmp_variable(left, arg.expr)
|
|
||||||
if i != val.args.len - 1 {
|
|
||||||
g.write(', ')
|
|
||||||
}
|
}
|
||||||
|
fn_name := util.no_dots('${rec_typ_name}_${val.name}')
|
||||||
|
g.write('${fn_name}(&')
|
||||||
|
g.gen_cross_tmp_variable(left, val.left)
|
||||||
|
for i, arg in val.args {
|
||||||
|
g.gen_cross_tmp_variable(left, arg.expr)
|
||||||
|
if i != val.args.len - 1 {
|
||||||
|
g.write(', ')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g.write(')')
|
||||||
|
} else {
|
||||||
|
mut fn_name := val.name.replace('.', '__')
|
||||||
|
if val.concrete_types.len > 0 {
|
||||||
|
fn_name = g.generic_fn_name(val.concrete_types, fn_name)
|
||||||
|
}
|
||||||
|
g.write('${fn_name}(')
|
||||||
|
for i, arg in val.args {
|
||||||
|
g.gen_cross_tmp_variable(left, arg.expr)
|
||||||
|
if i != val.args.len - 1 {
|
||||||
|
g.write(', ')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g.write(')')
|
||||||
}
|
}
|
||||||
g.write(')')
|
|
||||||
}
|
}
|
||||||
ast.PrefixExpr {
|
ast.PrefixExpr {
|
||||||
g.write(val.op.str())
|
g.write(val.op.str())
|
||||||
|
@ -157,6 +157,9 @@ fn (mut p Parser) check_cross_variables(exprs []ast.Expr, val ast.Expr) bool {
|
|||||||
return p.check_cross_variables(exprs, val.expr)
|
return p.check_cross_variables(exprs, val.expr)
|
||||||
}
|
}
|
||||||
ast.CallExpr {
|
ast.CallExpr {
|
||||||
|
if p.check_cross_variables(exprs, val.left) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
for arg in val.args {
|
for arg in val.args {
|
||||||
if p.check_cross_variables(exprs, arg.expr) {
|
if p.check_cross_variables(exprs, arg.expr) {
|
||||||
return true
|
return true
|
||||||
|
19
vlib/v/tests/swap_array_test.v
Normal file
19
vlib/v/tests/swap_array_test.v
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
fn test_swap_array() {
|
||||||
|
mut array1 := []int{len: 10, init: 1}
|
||||||
|
|
||||||
|
println(array1)
|
||||||
|
swaper(mut array1)
|
||||||
|
println(array1)
|
||||||
|
|
||||||
|
assert array1 == [22, 2, 2, 2, 2, 2, 2, 2, 2, 2]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn swaper(mut array1 []int) {
|
||||||
|
mut array2 := []int{len: 10, init: 2}
|
||||||
|
array1[0] = 11
|
||||||
|
array2[0] = 22
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
array1, array2 = array2, array1
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user