parser: fixes or block position (#6736)

pull/6750/head
Daniel Däschle 2020-11-04 15:02:01 +01:00 committed by GitHub
parent fff70368b7
commit a2fc19880a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 26 additions and 39 deletions

View File

@ -1618,10 +1618,10 @@ pub fn (mut c Checker) check_expr_opt_call(expr ast.Expr, ret_type table.Type) t
return ret_type
} else if expr.or_block.kind == .block {
c.error('unexpected `or` block, the function `$expr.name` does not return an optional',
expr.pos)
expr.or_block.pos)
} else if expr.or_block.kind == .propagate {
c.error('unexpected `?`, the function `$expr.name`, does not return an optional',
expr.pos)
expr.or_block.pos)
}
}
return ret_type

View File

@ -1,8 +1,8 @@
vlib/v/checker/tests/or_err.vv:4:6: error: last statement in the `or {}` block should be an expression of type `&int` or exit parent scope
vlib/v/checker/tests/or_err.vv:4:10: error: last statement in the `or {}` block should be an expression of type `&int` or exit parent scope
2 | return none
3 | }
4 | a := f() or {
| ~~~
| ~~~~
5 | {}
6 | }
vlib/v/checker/tests/or_err.vv:11:2: error: wrong return type `rune` in the `or {}` block, expected `&int`

View File

@ -1,6 +1,6 @@
vlib/v/checker/tests/unexpected_or.vv:6:6: error: unexpected `or` block, the function `ret_zero` does not return an optional
4 |
vlib/v/checker/tests/unexpected_or.vv:6:17: error: unexpected `or` block, the function `ret_zero` does not return an optional
4 |
5 | fn main() {
6 | _ = ret_zero() or { 1 }
| ~~~~~~~~~~
| ~~~~~~~~
7 | }

View File

@ -1,7 +1,7 @@
vlib/v/checker/tests/unexpected_or_propagate.vv:6:7: error: unexpected `?`, the function `ret_zero`, does not return an optional
4 |
vlib/v/checker/tests/unexpected_or_propagate.vv:6:17: error: unexpected `?`, the function `ret_zero`, does not return an optional
4 |
5 | fn opt_fn() ?int {
6 | a := ret_zero()?
| ~~~~~~~~~~
| ^
7 | return a
8 | }

View File

@ -1,7 +1,7 @@
vlib/v/checker/tests/wrong_propagate_ret_type.vv:6:7: error: to propagate the optional call, `opt_call` must itself return an optional
4 |
vlib/v/checker/tests/wrong_propagate_ret_type.vv:6:17: error: to propagate the optional call, `opt_call` must itself return an optional
4 |
5 | fn opt_call() int {
6 | a := ret_none()?
| ~~~~~~~~~~
| ^
7 | return a
8 | }

View File

@ -54,6 +54,7 @@ pub fn (mut p Parser) call_expr(language table.Language, mod string) ast.CallExp
len: last_pos.pos - first_pos.pos + last_pos.len
}
mut or_stmts := []ast.Stmt{}
mut or_pos := p.tok.position()
if p.tok.kind == .key_orelse {
// `foo() or {}``
was_inside_or_expr := p.inside_or_expr
@ -74,6 +75,7 @@ pub fn (mut p Parser) call_expr(language table.Language, mod string) ast.CallExp
})
or_kind = .block
or_stmts = p.parse_block_no_scope(false)
or_pos = or_pos.extend(p.prev_tok.position())
p.close_scope()
p.inside_or_expr = was_inside_or_expr
}
@ -89,37 +91,18 @@ pub fn (mut p Parser) call_expr(language table.Language, mod string) ast.CallExp
fn_name = registered.name
}
}
/*
call_expr := ast.CallExpr{
name: fn_name
args: args
mod: fn_mod
pos: pos
language: language
generic_type: generic_type
}
if or_kind != .absent {
return ast.OrExpr2{
call_expr: call_expr
stmts: or_stmts
kind: or_kind
pos: pos
}
}
return call_expr
*/
return ast.CallExpr{
name: fn_name
args: args
mod: fn_mod
pos: pos
language: language
generic_type: generic_type
or_block: ast.OrExpr{
stmts: or_stmts
kind: or_kind
pos: pos
pos: or_pos
}
generic_type: generic_type
}
}

View File

@ -1238,6 +1238,7 @@ fn (mut p Parser) dot_expr(left ast.Expr) ast.Expr {
p.check(.rpar)
mut or_stmts := []ast.Stmt{}
mut or_kind := ast.OrKind.absent
mut or_pos := p.tok.position()
if p.tok.kind == .key_orelse {
p.next()
p.open_scope()
@ -1255,6 +1256,7 @@ fn (mut p Parser) dot_expr(left ast.Expr) ast.Expr {
})
or_kind = .block
or_stmts = p.parse_block_no_scope(false)
or_pos = or_pos.extend(p.prev_tok.position())
p.close_scope()
}
// `foo()?`
@ -1278,7 +1280,7 @@ fn (mut p Parser) dot_expr(left ast.Expr) ast.Expr {
or_block: ast.OrExpr{
stmts: or_stmts
kind: or_kind
pos: pos
pos: or_pos
}
}
if is_filter || field_name == 'sort' {

View File

@ -355,6 +355,7 @@ fn (mut p Parser) prefix_expr() ast.PrefixExpr {
}
mut or_stmts := []ast.Stmt{}
mut or_kind := ast.OrKind.absent
mut or_pos := p.tok.position()
// allow `x := <-ch or {...}` to handle closed channel
if op == .arrow {
if p.tok.kind == .key_orelse {
@ -374,6 +375,7 @@ fn (mut p Parser) prefix_expr() ast.PrefixExpr {
})
or_kind = .block
or_stmts = p.parse_block_no_scope(false)
or_pos = or_pos.extend(p.prev_tok.position())
p.close_scope()
}
if p.tok.kind == .question {
@ -388,7 +390,7 @@ fn (mut p Parser) prefix_expr() ast.PrefixExpr {
or_block: ast.OrExpr{
stmts: or_stmts
kind: or_kind
pos: pos
pos: or_pos
}
}
}

View File

@ -13,16 +13,16 @@ vlib/v/parser/tests/prefix_first.vv:26:3: warning: move infix `&` operator befor
27 | }
28 | }
vlib/v/parser/tests/prefix_first.vv:13:6: error: `if` expression requires an expression as the last statement of every branch
11 |
11 |
12 | // later this should compile correctly
13 | _ = if true {
| ~~~~~~~
14 | v = 1
15 | -1
vlib/v/parser/tests/prefix_first.vv:24:6: error: last statement in the `or {}` block should be an expression of type `&int` or exit parent scope
vlib/v/parser/tests/prefix_first.vv:24:12: error: last statement in the `or {}` block should be an expression of type `&int` or exit parent scope
22 | // later this should compile correctly
23 | v := 3
24 | _ = opt() or {
| ~~~~~
| ~~~~
25 | _ = 1
26 | &v