checker, cgen: allow static (fixed) arrays in `in` operator (#14121)

master
ChAoS_UnItY 2022-04-21 15:32:29 +08:00 committed by GitHub
parent c789ea5a15
commit c5824c36f2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 66 additions and 1 deletions

View File

@ -662,6 +662,15 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
} }
node.left_type = map_info.key_type node.left_type = map_info.key_type
} }
.array_fixed {
if left_sym.kind !in [.sum_type, .interface_] {
elem_type := right_final.array_fixed_info().elem_type
c.check_expected(left_type, elem_type) or {
c.error('left operand to `$node.op` does not match the fixed array element type: $err.msg()',
left_right_pos)
}
}
}
else { else {
c.error('`$node.op.str()` can only be used with arrays and maps', c.error('`$node.op.str()` can only be used with arrays and maps',
node.pos) node.pos)

View File

@ -441,6 +441,54 @@ fn (mut g Gen) infix_expr_in_op(node ast.InfixExpr) {
g.expr(node.right) g.expr(node.right)
} }
g.write(')') g.write(')')
} else if right.unaliased_sym.kind == .array_fixed {
if left.sym.kind in [.sum_type, .interface_] {
if 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 node.right is ast.ArrayInit {
if node.right.exprs.len > 0 {
// `a in [1,2,3]!` optimization => `a == 1 || a == 2 || a == 3`
// avoids an allocation
g.write('(')
g.infix_expr_in_optimization(node.left, node.right)
g.write(')')
return
}
}
if right.sym.info is ast.Array {
elem_type := right.sym.info.elem_type
elem_type_ := g.unwrap(elem_type)
if elem_type_.sym.kind == .sum_type {
if node.left_type in elem_type_.sym.sumtype_info().variants {
new_node_left := ast.CastExpr{
arg: ast.EmptyExpr{}
typ: elem_type
expr: node.left
expr_type: node.left_type
}
g.gen_array_contains(node.right_type, node.right, new_node_left)
return
}
}
}
g.gen_array_contains(node.right_type, node.right, node.left)
} else if right.unaliased_sym.kind == .string { } else if right.unaliased_sym.kind == .string {
g.write('string_contains(') g.write('string_contains(')
g.expr(node.right) g.expr(node.right)

View File

@ -282,7 +282,7 @@ fn (mut g JsGen) infix_in_not_in_op(node ast.InfixExpr) {
if node.op == .not_in { if node.op == .not_in {
g.write('!') g.write('!')
} }
if r_sym.unaliased_sym.kind == .array { if r_sym.unaliased_sym.kind in [.array, .array_fixed] {
fn_name := g.gen_array_contains_method(node.right_type) fn_name := g.gen_array_contains_method(node.right_type)
g.write('(${fn_name}(') g.write('(${fn_name}(')
g.expr(node.right) g.expr(node.right)

View File

@ -0,0 +1,8 @@
fn test_fixed_array_in_op() {
assert 1 in [1, 2]!
assert `a` in [`a`, `b`]!
assert 'a' in ['a', 'b']!
ch := `"`
assert ch in [`"`, `'`]!
}