diff --git a/vlib/v/checker/assign.v b/vlib/v/checker/assign.v index 1144816050..b48535e26e 100644 --- a/vlib/v/checker/assign.v +++ b/vlib/v/checker/assign.v @@ -11,12 +11,17 @@ pub fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) { defer { c.expected_type = ast.void_type } + is_decl := node.op == .decl_assign right_first := node.right[0] node.left_types = [] mut right_len := node.right.len mut right_type0 := ast.void_type for i, right in node.right { if right in [ast.CallExpr, ast.IfExpr, ast.LockExpr, ast.MatchExpr] { + if right in [ast.IfExpr, ast.MatchExpr] && node.left.len == node.right.len && !is_decl + && node.left[i] in [ast.Ident, ast.SelectorExpr] && !node.left[i].is_blank_ident() { + c.expected_type = c.expr(node.left[i]) + } right_type := c.expr(right) if i == 0 { right_type0 = right_type @@ -66,7 +71,6 @@ pub fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) { return } - is_decl := node.op == .decl_assign for i, left in node.left { if left is ast.CallExpr { // ban `foo() = 10` diff --git a/vlib/v/tests/match_expr_with_assign_sumtype_test.v b/vlib/v/tests/match_expr_with_assign_sumtype_test.v new file mode 100644 index 0000000000..3e1a17aafc --- /dev/null +++ b/vlib/v/tests/match_expr_with_assign_sumtype_test.v @@ -0,0 +1,124 @@ +fn test_match_expr_with_assign_sumtype() { + parse_args(['1', '+', '-', '*', '/', ' ']) or { println(err) } +} + +enum Operator { + add + subtract + multiply + divide +} + +type Value = Operator | int + +struct Expression { + left ?&Expression = none + val Value + right ?&Expression = none +} + +enum State { + expecting + parse_num + parse_operator +} + +fn tokenise(args string) ?[]Value { + mut rv := []Value{} + + mut state := State.expecting + mut cur_value := Value(0) + for i in args.runes() { + match state { + .expecting { + match i { + `0`...`9` { + state = .parse_num + cur_value = int(i.str().parse_uint(10, 8) ?) + } + `+`, `-`, `*`, `/` { + state = .parse_operator + cur_value = match i { + `+` { + Operator.add + } + `-` { + Operator.subtract + } + `*` { + Operator.multiply + } + `/` { + Operator.divide + } + else { + Value(0) + } + } + } + ` ` { + state = .expecting + } + else { + return error('invalid token $i') + } + } + } + .parse_num { + match i { + `0`...`9` { + cur_value = 10 + int(i.str().parse_uint(10, 8) ?) + } + `+`, `-`, `*`, `/` { + state = .parse_operator + rv << cur_value + cur_value = match i { + `+` { Operator.add } + `-` { Operator.subtract } + `*` { Operator.multiply } + `/` { Operator.divide } + else { Value(0) } + } + } + ` ` { + state = .expecting + rv << cur_value + } + else { + return error('invalid token $i') + } + } + } + .parse_operator { + match i { + `0`...`9` { + state = .parse_num + rv << cur_value + cur_value = int(i.str().parse_uint(10, 8) ?) + } + ` ` { + state = .expecting + rv << cur_value + } + else { + return error('invalid token $i') + } + } + } + } + } + + return rv +} + +fn parse_args(argv []string) ?Expression { + rv := Expression{ + val: 1 + } + tokens := tokenise(argv.join(' ')) ? + + println(tokens) + assert '$tokens' == '[Value(1), Value(add), Value(subtract), Value(multiply), Value(divide)]' + + return rv +}