parser: support `x = a[k] ?` propagation for arrays and maps (#8199)
parent
15cc1cd884
commit
5067046538
|
@ -1394,33 +1394,45 @@ fn (mut p Parser) index_expr(left ast.Expr) ast.IndexExpr {
|
||||||
// [expr]
|
// [expr]
|
||||||
pos := start_pos.extend(p.tok.position())
|
pos := start_pos.extend(p.tok.position())
|
||||||
p.check(.rsbr)
|
p.check(.rsbr)
|
||||||
// a[i] or { ... }
|
mut or_kind := ast.OrKind.absent
|
||||||
if p.tok.kind == .key_orelse && !p.or_is_handled {
|
mut or_stmts := []ast.Stmt{}
|
||||||
was_inside_or_expr := p.inside_or_expr
|
mut or_pos := token.Position{}
|
||||||
mut or_pos := p.tok.position()
|
if !p.or_is_handled {
|
||||||
p.next()
|
// a[i] or { ... }
|
||||||
p.open_scope()
|
if p.tok.kind == .key_orelse {
|
||||||
or_stmts := p.parse_block_no_scope(false)
|
was_inside_or_expr := p.inside_or_expr
|
||||||
or_pos = or_pos.extend(p.prev_tok.position())
|
or_pos = p.tok.position()
|
||||||
p.close_scope()
|
p.next()
|
||||||
p.inside_or_expr = was_inside_or_expr
|
p.open_scope()
|
||||||
return ast.IndexExpr{
|
or_stmts = p.parse_block_no_scope(false)
|
||||||
left: left
|
or_pos = or_pos.extend(p.prev_tok.position())
|
||||||
index: expr
|
p.close_scope()
|
||||||
pos: pos
|
p.inside_or_expr = was_inside_or_expr
|
||||||
or_expr: ast.OrExpr{
|
return ast.IndexExpr{
|
||||||
kind: .block
|
left: left
|
||||||
stmts: or_stmts
|
index: expr
|
||||||
pos: or_pos
|
pos: pos
|
||||||
|
or_expr: ast.OrExpr{
|
||||||
|
kind: .block
|
||||||
|
stmts: or_stmts
|
||||||
|
pos: or_pos
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// `a[i] ?`
|
||||||
|
if p.tok.kind == .question {
|
||||||
|
p.next()
|
||||||
|
or_kind = .propagate
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ast.IndexExpr{
|
return ast.IndexExpr{
|
||||||
left: left
|
left: left
|
||||||
index: expr
|
index: expr
|
||||||
pos: pos
|
pos: pos
|
||||||
or_expr: ast.OrExpr{
|
or_expr: ast.OrExpr{
|
||||||
kind: .absent
|
kind: or_kind
|
||||||
|
stmts: or_stmts
|
||||||
|
pos: or_pos
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
vlib/v/parser/tests/or_default_missing.vv:4:3: error: `or` block must provide a default value of type `int`, or return/exit/continue/break/panic
|
||||||
|
2 | m := [3, 4, 5]
|
||||||
|
3 | el := m[4] or {
|
||||||
|
4 | println('error')
|
||||||
|
| ~~~~~~~~~~~~~~~~
|
||||||
|
5 | }
|
||||||
|
6 | println(el)
|
||||||
|
vlib/v/parser/tests/or_default_missing.vv:16:16: error: last statement in the `or {}` block should be an expression of type `int` or exit parent scope
|
||||||
|
14 | }
|
||||||
|
15 | mut testvar := 0
|
||||||
|
16 | el := m['pp'] or {
|
||||||
|
| ~~~~
|
||||||
|
17 | testvar = 12
|
||||||
|
18 | }
|
|
@ -0,0 +1,20 @@
|
||||||
|
fn test_array_or() {
|
||||||
|
m := [3, 4, 5]
|
||||||
|
el := m[4] or {
|
||||||
|
println('error')
|
||||||
|
}
|
||||||
|
println(el)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_map_or() {
|
||||||
|
m := {
|
||||||
|
'as': 3
|
||||||
|
'qw': 4
|
||||||
|
'kl': 5
|
||||||
|
}
|
||||||
|
mut testvar := 0
|
||||||
|
el := m['pp'] or {
|
||||||
|
testvar = 12
|
||||||
|
}
|
||||||
|
println('$el $testvar')
|
||||||
|
}
|
|
@ -33,3 +33,57 @@ fn test_map_or() {
|
||||||
assert el == 7
|
assert el == 7
|
||||||
assert good == 5
|
assert good == 5
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn get_map_el(key string) ?int {
|
||||||
|
m := {'as': 3, 'qw': 4, 'kl': 5}
|
||||||
|
r := m[key] ?
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_arr_el(i int) ?int {
|
||||||
|
m := [3, 4, 5]
|
||||||
|
r := m[i] ?
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_propagation() {
|
||||||
|
mut testvar1 := 12
|
||||||
|
mut testvar2 := 78
|
||||||
|
e := get_map_el('vv') or {
|
||||||
|
testvar1 = -34
|
||||||
|
7
|
||||||
|
}
|
||||||
|
f := get_map_el('as') or {
|
||||||
|
testvar1 = 67
|
||||||
|
23
|
||||||
|
}
|
||||||
|
g := get_arr_el(3) or {
|
||||||
|
testvar2 = 99
|
||||||
|
12
|
||||||
|
}
|
||||||
|
h := get_arr_el(0) or {
|
||||||
|
testvar2 = 177
|
||||||
|
int(-67)
|
||||||
|
}
|
||||||
|
assert testvar1 == -34
|
||||||
|
assert testvar2 == 99
|
||||||
|
assert e == 7
|
||||||
|
assert f == 3
|
||||||
|
assert g == 12
|
||||||
|
assert h == 3
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_arr_el_nested(i int) ?int {
|
||||||
|
ind := [2, 1, 0, 5]
|
||||||
|
m := [3, 4, 5]
|
||||||
|
r := m[ind[i]] ?
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_nested_array_propagation() {
|
||||||
|
g := get_arr_el_nested(3) or {
|
||||||
|
12
|
||||||
|
}
|
||||||
|
assert g == 12
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue