From 6cbc0e84f0fc4098a897af6d4109040cfe10c4e1 Mon Sep 17 00:00:00 2001 From: yuyi Date: Thu, 2 Jul 2020 17:09:26 +0800 Subject: [PATCH] cgen: fix cross assign with mutable args (fix #5609 #5610 #5611) (#5614) --- vlib/builtin/array_test.v | 13 ------ vlib/builtin/map_test.v | 9 ---- vlib/v/gen/cgen.v | 12 ++++- vlib/v/tests/cross_assign_test.v | 80 ++++++++++++++++++++++++++++++++ vlib/v/tests/struct_test.v | 14 ------ 5 files changed, 91 insertions(+), 37 deletions(-) create mode 100644 vlib/v/tests/cross_assign_test.v diff --git a/vlib/builtin/array_test.v b/vlib/builtin/array_test.v index 063a04df67..ffde01cce7 100644 --- a/vlib/builtin/array_test.v +++ b/vlib/builtin/array_test.v @@ -877,16 +877,3 @@ fn test_plus_assign_string() { a[0] += 'abc' assert a == ['abc'] } - -fn test_cross_assign() { - mut a := [0, 1] - a[0], a[1] = a[1], a[0] - assert a[0] == 1 - assert a[1] == 0 - - mut b1 := [1, 2, 3] - mut b2 := 4 - b1[2], b2, b1[0] = b1[0], b1[2], 5 - assert b1 == [5, 2, 1] - assert b2 == 3 -} diff --git a/vlib/builtin/map_test.v b/vlib/builtin/map_test.v index 8fbaa3e0fd..a265e2bc99 100644 --- a/vlib/builtin/map_test.v +++ b/vlib/builtin/map_test.v @@ -291,7 +291,6 @@ fn test_plus_assign_string() { assert m['one'] == '1' } - fn test_map_keys_to_array() { m := {'a': 'b', 'c': 'd'} mut arr := []string{} @@ -302,11 +301,3 @@ fn test_map_keys_to_array() { println(sarr) assert sarr == "['a', 'c']" } - -fn test_map_cross_assign() { - mut a := {'one':1, 'two':2} - a['one'], a['two'] = a['two'], a['one'] - println(a) - assert a['one'] == 2 - assert a['two'] == 1 -} diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index 146ea20abc..f856e17a55 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -1099,6 +1099,9 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) { info := sym.info as table.Array styp := g.typ(info.elem_type) g.write('$styp _var_$left.pos.pos = *($styp*)array_get(') + if left.left_type.is_ptr() { + g.write('*') + } g.expr(left.left) g.write(', ') g.expr(left.index) @@ -1108,6 +1111,9 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) { styp := g.typ(info.value_type) zero := g.type_default(info.value_type) g.write('$styp _var_$left.pos.pos = *($styp*)map_get(') + if left.left_type.is_ptr() { + g.write('*') + } g.expr(left.left) g.write(', ') g.expr(left.index) @@ -1118,7 +1124,11 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) { styp := g.typ(left.typ) g.write('$styp _var_$left.pos.pos = ') g.expr(left.expr) - g.writeln('.$left.field_name;') + if left.expr_type.is_ptr() { + g.writeln('->$left.field_name;') + } else { + g.writeln('.$left.field_name;') + } } else {} } diff --git a/vlib/v/tests/cross_assign_test.v b/vlib/v/tests/cross_assign_test.v new file mode 100644 index 0000000000..61f3bc1478 --- /dev/null +++ b/vlib/v/tests/cross_assign_test.v @@ -0,0 +1,80 @@ +// Test cross assign of array elements +fn test_cross_assign_of_array() { + mut a := [0, 1] + a[0], a[1] = a[1], a[0] + assert a[0] == 1 + assert a[1] == 0 + + mut b1 := [1, 2, 3] + mut b2 := 4 + b1[2], b2, b1[0] = b1[0], b1[2], 5 + assert b1 == [5, 2, 1] + assert b2 == 3 +} + +// Test cross assign of array elements in function +fn foo1(mut arr []int) { + arr[0], arr[1] = arr[1], arr[0] +} + +fn test_cross_assign_of_array_in_fn() { + mut arr := [1,2] + foo1(mut arr) + assert arr[0] == 2 + assert arr[1] == 1 +} + +// Test cross assign of map values +fn test_cross_assign_of_map() { + mut a := {'one':1, 'two':2} + a['one'], a['two'] = a['two'], a['one'] + println(a) + assert a['one'] == 2 + assert a['two'] == 1 +} + +// Test cross assign of map values in function +fn foo2(mut a map[string]int) { + a['one'], a['two'] = a['two'], a['one'] +} + +fn test_cross_assign_of_map_in_fn() { + mut a := {'one':1, 'two':2} + foo2(mut a) + assert a['one'] == 2 + assert a['two'] == 1 +} + +// Test cross assign of struct fields +struct Zoo { +mut: + a int + b int +} + +fn test_cross_assign_of_struct() { + mut x := Zoo{a:1, b:2} + x.a, x.b = x.b, x.a + //println(x) + assert x.a == 2 + assert x.b == 1 +} + +// Test cross assign of struct fields in function +struct Foo { +mut: + a int + b int +} + +fn foo3(mut f &Foo) { + f.a, f.b = f.b, f.a +} + +fn test_cross_assign_of_struct_in_fn() { + mut a := Foo{a:1, b:2} + foo3(mut a) + println(a) + assert a.a == 2 + assert a.b == 1 +} diff --git a/vlib/v/tests/struct_test.v b/vlib/v/tests/struct_test.v index e6baeaf601..f6695f2097 100644 --- a/vlib/v/tests/struct_test.v +++ b/vlib/v/tests/struct_test.v @@ -313,17 +313,3 @@ fn test_struct_with_default_values_no_init() { assert s2.field_optional == 3 assert s3.field_optional == 2 } - -struct Zoo { -mut: - a int - b int -} - -fn test_struct_field_cross_assign() { - mut x := Zoo{a:1, b:2} - x.a, x.b = x.b, x.a - //println(x) - assert x.a == 2 - assert x.b == 1 -}