From 40a393926de52798bd3853cd5e8f2dc2ddf0b111 Mon Sep 17 00:00:00 2001 From: yuyi Date: Thu, 2 Jul 2020 00:43:14 +0800 Subject: [PATCH] cgen: fix cross assign of struct fields (#5606) --- vlib/v/gen/cgen.v | 19 +++++++++++++++++++ vlib/v/parser/assign.v | 7 +++++++ vlib/v/tests/struct_test.v | 14 ++++++++++++++ 3 files changed, 40 insertions(+) diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index c6713e1b83..79c5a86cd0 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -1108,6 +1108,12 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) { g.writeln(', &($styp[]){ $zero });') } } + ast.SelectorExpr { + styp := g.typ(left.typ) + g.write('$styp _var_$left.pos.pos = ') + g.expr(left.expr) + g.writeln('.$left.field_name;') + } else {} } } @@ -1331,6 +1337,19 @@ fn (mut g Gen) gen_cross_tmp_variable(left []ast.Expr, val ast.Expr) { g.gen_cross_tmp_variable(left, val.expr) g.write(val.op.str()) } + ast.SelectorExpr { + mut has_var := false + for lx in left { + if val_.str() == lx.str() { + g.write('_var_${lx.position().pos}') + has_var = true + break + } + } + if !has_var { + g.expr(val_) + } + } else { g.expr(val_) } diff --git a/vlib/v/parser/assign.v b/vlib/v/parser/assign.v index ccf5075ba6..4166b1ed6a 100644 --- a/vlib/v/parser/assign.v +++ b/vlib/v/parser/assign.v @@ -66,6 +66,13 @@ fn (mut p Parser) check_cross_variables(exprs []ast.Expr, val ast.Expr) bool { ast.InfixExpr { return p.check_cross_variables(exprs, val_.left) || p.check_cross_variables(exprs, val_.right) } ast.PrefixExpr { return p.check_cross_variables(exprs, val_.right) } ast.PostfixExpr { return p.check_cross_variables(exprs, val_.expr) } + ast.SelectorExpr { + for expr in exprs { + if expr.str() == val.str() { + return true + } + } + } else {} } return false diff --git a/vlib/v/tests/struct_test.v b/vlib/v/tests/struct_test.v index f6695f2097..e6baeaf601 100644 --- a/vlib/v/tests/struct_test.v +++ b/vlib/v/tests/struct_test.v @@ -313,3 +313,17 @@ 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 +}