checker: fix match expr with assign sumtype variable (#13614)

pull/13617/head
yuyi 2022-02-28 16:37:59 +08:00 committed by GitHub
parent bc16c61f6f
commit 81c787ef91
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 129 additions and 1 deletions

View File

@ -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`

View File

@ -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
}