all: implement `if foo in [Foo1, Foo2, Foo3]` (#11486)
parent
12ec900d20
commit
8862c3af0f
|
@ -1356,13 +1356,14 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
|
||||||
.key_in, .not_in {
|
.key_in, .not_in {
|
||||||
match right_final.kind {
|
match right_final.kind {
|
||||||
.array {
|
.array {
|
||||||
|
if left_sym.kind !in [.sum_type, .interface_] {
|
||||||
elem_type := right_final.array_info().elem_type
|
elem_type := right_final.array_info().elem_type
|
||||||
// if left_default.kind != right_sym.kind {
|
|
||||||
c.check_expected(left_type, elem_type) or {
|
c.check_expected(left_type, elem_type) or {
|
||||||
c.error('left operand to `$node.op` does not match the array element type: $err.msg',
|
c.error('left operand to `$node.op` does not match the array element type: $err.msg',
|
||||||
left_right_pos)
|
left_right_pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
.map {
|
.map {
|
||||||
map_info := right_final.map_info()
|
map_info := right_final.map_info()
|
||||||
c.check_expected(left_type, map_info.key_type) or {
|
c.check_expected(left_type, map_info.key_type) or {
|
||||||
|
@ -4522,10 +4523,12 @@ pub fn (mut c Checker) array_init(mut node ast.ArrayInit) ast.Type {
|
||||||
c.expected_type = elem_type
|
c.expected_type = elem_type
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if expr !is ast.TypeNode {
|
||||||
c.check_expected(typ, elem_type) or {
|
c.check_expected(typ, elem_type) or {
|
||||||
c.error('invalid array element: $err.msg', expr.position())
|
c.error('invalid array element: $err.msg', expr.position())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if node.is_fixed {
|
if node.is_fixed {
|
||||||
idx := c.table.find_or_register_array_fixed(elem_type, node.exprs.len, ast.empty_expr())
|
idx := c.table.find_or_register_array_fixed(elem_type, node.exprs.len, ast.empty_expr())
|
||||||
if elem_type.has_flag(.generic) {
|
if elem_type.has_flag(.generic) {
|
||||||
|
|
|
@ -313,6 +313,15 @@ fn (mut g Gen) infix_expr_cmp_op(node ast.InfixExpr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) infix_expr_in_sumtype_interface_array(infix_exprs []ast.InfixExpr) {
|
||||||
|
for i in 0 .. infix_exprs.len {
|
||||||
|
g.infix_expr_is_op(infix_exprs[i])
|
||||||
|
if i != infix_exprs.len - 1 {
|
||||||
|
g.write(' || ')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// infix_expr_in_op generates code for `in` and `!in`
|
// infix_expr_in_op generates code for `in` and `!in`
|
||||||
fn (mut g Gen) infix_expr_in_op(node ast.InfixExpr) {
|
fn (mut g Gen) infix_expr_in_op(node ast.InfixExpr) {
|
||||||
left := g.unwrap(node.left_type)
|
left := g.unwrap(node.left_type)
|
||||||
|
@ -321,6 +330,26 @@ fn (mut g Gen) infix_expr_in_op(node ast.InfixExpr) {
|
||||||
g.write('!')
|
g.write('!')
|
||||||
}
|
}
|
||||||
if right.unaliased_sym.kind == .array {
|
if right.unaliased_sym.kind == .array {
|
||||||
|
if left.sym.kind in [.sum_type, .interface_] {
|
||||||
|
if mut node.right is ast.ArrayInit {
|
||||||
|
if node.right.exprs.len > 0 {
|
||||||
|
mut infix_exprs := []ast.InfixExpr{}
|
||||||
|
for i in 0 .. node.right.exprs.len {
|
||||||
|
infix_exprs << ast.InfixExpr{
|
||||||
|
op: .key_is
|
||||||
|
left: node.left
|
||||||
|
left_type: node.left_type
|
||||||
|
right: node.right.exprs[i]
|
||||||
|
right_type: node.right.expr_types[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g.write('(')
|
||||||
|
g.infix_expr_in_sumtype_interface_array(infix_exprs)
|
||||||
|
g.write(')')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if mut node.right is ast.ArrayInit {
|
if mut node.right is ast.ArrayInit {
|
||||||
if node.right.exprs.len > 0 {
|
if node.right.exprs.len > 0 {
|
||||||
// `a in [1,2,3]` optimization => `a == 1 || a == 2 || a == 3`
|
// `a in [1,2,3]` optimization => `a == 1 || a == 2 || a == 3`
|
||||||
|
|
|
@ -472,7 +472,15 @@ fn (mut p Parser) infix_expr(left ast.Expr) ast.Expr {
|
||||||
if op in [.key_is, .not_is] {
|
if op in [.key_is, .not_is] {
|
||||||
p.expecting_type = true
|
p.expecting_type = true
|
||||||
}
|
}
|
||||||
|
is_key_in := op in [.key_in, .not_in]
|
||||||
|
if is_key_in {
|
||||||
|
p.inside_in_array = true
|
||||||
|
}
|
||||||
right = p.expr(precedence)
|
right = p.expr(precedence)
|
||||||
|
if is_key_in {
|
||||||
|
p.inside_in_array = false
|
||||||
|
}
|
||||||
|
|
||||||
p.expecting_type = prev_expecting_type
|
p.expecting_type = prev_expecting_type
|
||||||
if p.pref.is_vet && op in [.key_in, .not_in] && right is ast.ArrayInit
|
if p.pref.is_vet && op in [.key_in, .not_in] && right is ast.ArrayInit
|
||||||
&& (right as ast.ArrayInit).exprs.len == 1 {
|
&& (right as ast.ArrayInit).exprs.len == 1 {
|
||||||
|
|
|
@ -44,6 +44,7 @@ mut:
|
||||||
inside_unsafe_fn bool
|
inside_unsafe_fn bool
|
||||||
inside_str_interp bool
|
inside_str_interp bool
|
||||||
inside_array_lit bool
|
inside_array_lit bool
|
||||||
|
inside_in_array bool
|
||||||
or_is_handled bool // ignore `or` in this expression
|
or_is_handled bool // ignore `or` in this expression
|
||||||
builtin_mod bool // are we in the `builtin` module?
|
builtin_mod bool // are we in the `builtin` module?
|
||||||
mod string // current module name
|
mod string // current module name
|
||||||
|
@ -2233,6 +2234,18 @@ pub fn (mut p Parser) name_expr() ast.Expr {
|
||||||
// JS. function call with more than 1 dot
|
// JS. function call with more than 1 dot
|
||||||
node = p.call_expr(language, mod)
|
node = p.call_expr(language, mod)
|
||||||
} else {
|
} else {
|
||||||
|
if p.inside_in_array && ((lit0_is_capital && !known_var && language == .v)
|
||||||
|
|| (p.peek_tok.kind == .dot && p.peek_token(2).lit.len > 0
|
||||||
|
&& p.peek_token(2).lit[0].is_capital())
|
||||||
|
|| p.table.find_type_idx(p.mod + '.' + p.tok.lit) > 0) {
|
||||||
|
type_pos := p.tok.position()
|
||||||
|
typ := p.parse_type()
|
||||||
|
return ast.TypeNode{
|
||||||
|
typ: typ
|
||||||
|
pos: type_pos
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ident := p.parse_ident(language)
|
ident := p.parse_ident(language)
|
||||||
node = ident
|
node = ident
|
||||||
if p.inside_defer {
|
if p.inside_defer {
|
||||||
|
|
|
@ -264,3 +264,20 @@ fn test_in_expression_numeric() {
|
||||||
assert 1.0625 in f2
|
assert 1.0625 in f2
|
||||||
assert 3.5 !in f2
|
assert 3.5 !in f2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Foo1 {}
|
||||||
|
|
||||||
|
struct Foo2 {}
|
||||||
|
|
||||||
|
struct Foo3 {}
|
||||||
|
|
||||||
|
type Foo = Foo1 | Foo2 | Foo3
|
||||||
|
|
||||||
|
fn test_in_sumtype_array() {
|
||||||
|
foo := Foo(Foo3{})
|
||||||
|
|
||||||
|
if foo in [Foo1, Foo3] {
|
||||||
|
println(foo)
|
||||||
|
assert true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue