Skip to content

Commit 07eed88

Browse files
authored
v: support in expr with number ranges: if var in 1..4 { (fix #20352) (#22754)
1 parent 2dd6587 commit 07eed88

File tree

8 files changed

+107
-5
lines changed

8 files changed

+107
-5
lines changed

vlib/v/checker/infix.v

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -279,8 +279,15 @@ fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
279279
}
280280
}
281281
else {
282-
c.error('`${node.op.str()}` can only be used with arrays and maps',
283-
node.pos)
282+
if mut node.right is ast.RangeExpr {
283+
if !left_final_sym.is_number() && left_final_sym.kind != .rune {
284+
c.error('`${left_final_sym.name}` is an invalid type for range expression',
285+
node.pos)
286+
}
287+
} else {
288+
c.error('`${node.op.str()}` can only be used with arrays and maps',
289+
node.pos)
290+
}
284291
}
285292
}
286293
if mut node.left is ast.CallExpr {
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
vlib/v/checker/tests/in_range_expr_err.vv:1:13: error: `bool` is an invalid type for range expression
2+
1 | assert true in 0..1
3+
| ~~
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
assert true in 0..1

vlib/v/gen/c/assert.v

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,10 @@ fn (mut g Gen) gen_assert_single_expr(expr ast.Expr, typ ast.Type) {
188188
g.write(ctoslit(expr_str))
189189
}
190190
}
191-
ast.IfExpr, ast.MatchExpr {
191+
ast.ParExpr {
192+
g.gen_assert_single_expr(expr.expr, typ)
193+
}
194+
ast.IfExpr, ast.MatchExpr, ast.RangeExpr {
192195
g.write(ctoslit(expr_str))
193196
}
194197
ast.IndexExpr {

vlib/v/gen/c/cgen.v

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3735,7 +3735,7 @@ fn (mut g Gen) expr(node_ ast.Expr) {
37353735
g.is_amp = false
37363736
}
37373737
ast.RangeExpr {
3738-
// Only used in IndexExpr
3738+
// Only used in IndexExpr and InfixExpr
37393739
}
37403740
ast.SelectExpr {
37413741
g.select_expr(node)

vlib/v/gen/c/infix.v

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -645,12 +645,40 @@ fn (mut g Gen) infix_expr_in_op(node ast.InfixExpr) {
645645
g.write('(')
646646
g.gen_array_contains(node.right_type, node.right, node.left_type, node.left)
647647
g.write(')')
648-
} else if right.unaliased_sym.kind == .string {
648+
} else if right.unaliased_sym.kind == .string && node.right !is ast.RangeExpr {
649649
g.write2('(', 'string_contains(')
650650
g.expr(node.right)
651651
g.write(', ')
652652
g.expr(node.left)
653653
g.write('))')
654+
} else if node.right is ast.RangeExpr {
655+
// call() in min..max
656+
if node.left is ast.CallExpr {
657+
line := g.go_before_last_stmt().trim_space()
658+
g.empty_line = true
659+
tmp_var := g.new_tmp_var()
660+
g.write('${g.styp(node.left.return_type)} ${tmp_var} = ')
661+
g.expr(node.left)
662+
g.writeln(';')
663+
g.write(line)
664+
g.write('(')
665+
g.write('${tmp_var} >= ')
666+
g.expr(node.right.low)
667+
g.write(' && ')
668+
g.write('${tmp_var} < ')
669+
g.expr(node.right.high)
670+
g.write(')')
671+
} else {
672+
g.write('(')
673+
g.expr(node.left)
674+
g.write(' >= ')
675+
g.expr(node.right.low)
676+
g.write(' && ')
677+
g.expr(node.left)
678+
g.write(' < ')
679+
g.expr(node.right.high)
680+
g.write(')')
681+
}
654682
}
655683
}
656684

vlib/v/parser/expr.v

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -745,6 +745,18 @@ fn (mut p Parser) infix_expr(left ast.Expr) ast.Expr {
745745
}
746746
}
747747
if is_key_in {
748+
if p.tok.kind == .dotdot {
749+
p.check(.dotdot)
750+
pos_high := p.tok.pos()
751+
right = ast.RangeExpr{
752+
low: right
753+
has_low: true
754+
high: p.expr(0)
755+
has_high: true
756+
pos: pos_high
757+
is_gated: false
758+
}
759+
}
748760
p.inside_in_array = false
749761
}
750762
p.expecting_type = prev_expecting_type
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
module main
2+
3+
const min = 1
4+
const max = 3
5+
6+
fn t() f64 {
7+
return 1.23
8+
}
9+
10+
fn z() ?f64 {
11+
return 1.22
12+
}
13+
14+
fn r() int {
15+
return 5
16+
}
17+
18+
fn test_main() {
19+
y := 4
20+
21+
assert y in 1..20
22+
assert y !in 5..20
23+
assert y in 4..20
24+
assert y !in min..max
25+
26+
assert (t() !in 1..3) == false
27+
assert r() in 5..6
28+
assert r() in 4..6
29+
assert 1.22 in z()?..t()
30+
assert 1.23 !in z()?..t()
31+
assert 1.221 in z()?..t()
32+
33+
a := {
34+
'f': 2
35+
}
36+
assert a['f'] in 1..3
37+
assert a['f'] in 2..3
38+
assert a['f'] !in 0..2
39+
assert a['f'] in min..max
40+
}
41+
42+
fn test_rune() {
43+
assert `a` in `a`..`h`
44+
assert `h` !in `a`..`h`
45+
46+
assert `f` in `a`..`h`
47+
assert `f` !in `g`..`h`
48+
}

0 commit comments

Comments
 (0)