checker: fix match expr with assign sumtype variable (#13614)
							parent
							
								
									bc16c61f6f
								
							
						
					
					
						commit
						81c787ef91
					
				| 
						 | 
				
			
			@ -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`
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue