Skip to content

Commit

Permalink
parser,checker: improve the position underlining, for last statements…
Browse files Browse the repository at this point in the history
… in branches of `if` expressions (#22845)
  • Loading branch information
Delta456 authored Nov 13, 2024
1 parent 8ebbace commit f4d3c7e
Show file tree
Hide file tree
Showing 6 changed files with 29 additions and 8 deletions.
5 changes: 4 additions & 1 deletion vlib/v/checker/if.v
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ fn (mut c Checker) if_expr(mut node ast.IfExpr) ast.Type {
stmts := node.branches[0].stmts
if stmts.len > 0 && stmts.last() is ast.ExprStmt && stmts.last().typ != ast.void_type {
node_is_expr = true
} else if node.is_expr {
node_is_expr = true
}
}
if c.expected_type == ast.void_type && node_is_expr {
Expand Down Expand Up @@ -520,8 +522,9 @@ fn (mut c Checker) if_expr(mut node ast.IfExpr) ast.Type {
}
}
} else if !node.is_comptime && stmt !in [ast.Return, ast.BranchStmt] {
pos := if node_is_expr { stmt.pos } else { branch.pos }
c.error('`${if_kind}` expression requires an expression as the last statement of every branch',
branch.pos)
pos)
}
} else if !node.is_comptime {
c.error('`${if_kind}` expression requires an expression as the last statement of every branch',
Expand Down
7 changes: 7 additions & 0 deletions vlib/v/checker/tests/if_expr_last_branch_stmt_err.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
vlib/v/checker/tests/if_expr_last_branch_stmt_err.vv:5:30: error: `if` expression requires an expression as the last statement of every branch
3 | mut start := 0
4 |
5 | start = if val < 20 { start += 1 } else { start }
| ~~
6 | dump(start)
7 | }
7 changes: 7 additions & 0 deletions vlib/v/checker/tests/if_expr_last_branch_stmt_err.vv
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
fn main() {
val := 15
mut start := 0

start = if val < 20 { start += 1 } else { start }
dump(start)
}
8 changes: 6 additions & 2 deletions vlib/v/parser/expr.v
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ fn (mut p Parser) check_expr(precedence int) !ast.Expr {
p.is_stmt_ident = is_stmt_ident
}
.key_if {
return p.if_expr(true)
return p.if_expr(true, false)
}
else {
return p.unexpected_with_pos(p.peek_tok.pos(),
Expand Down Expand Up @@ -222,7 +222,11 @@ fn (mut p Parser) check_expr(precedence int) !ast.Expr {
if p.peek_tok.kind in [.lpar, .lsbr] && p.peek_tok.is_next_to(p.tok) {
node = p.call_expr(p.language, p.mod)
} else {
node = p.if_expr(false)
mut is_expr := false
if p.prev_tok.kind.is_assign() {
is_expr = true
}
node = p.if_expr(false, is_expr)
}
}
.key_unsafe {
Expand Down
6 changes: 3 additions & 3 deletions vlib/v/parser/if_match.v
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ module parser
import v.ast
import v.token

fn (mut p Parser) if_expr(is_comptime bool) ast.IfExpr {
fn (mut p Parser) if_expr(is_comptime bool, is_expr bool) ast.IfExpr {
was_inside_if_expr := p.inside_if_expr
was_inside_ct_if_expr := p.inside_ct_if_expr
defer {
p.inside_if_expr = was_inside_if_expr
p.inside_ct_if_expr = was_inside_ct_if_expr
}
p.inside_if_expr = true
is_expr := p.prev_tok.kind == .key_return
is_expr_ := p.prev_tok.kind == .key_return || is_expr
mut pos := p.tok.pos()
if is_comptime {
p.inside_ct_if_expr = true
Expand Down Expand Up @@ -213,7 +213,7 @@ fn (mut p Parser) if_expr(is_comptime bool) ast.IfExpr {
post_comments: comments
pos: pos
has_else: has_else
is_expr: is_expr
is_expr: is_expr_
}
}

Expand Down
4 changes: 2 additions & 2 deletions vlib/v/parser/parser.v
Original file line number Diff line number Diff line change
Expand Up @@ -795,7 +795,7 @@ fn (mut p Parser) top_stmt() ast.Stmt {
comptime_for_stmt := p.comptime_for()
return p.other_stmts(comptime_for_stmt)
} else if p.peek_tok.kind == .key_if {
if_expr := p.if_expr(true)
if_expr := p.if_expr(true, false)
cur_stmt := ast.ExprStmt{
expr: if_expr
pos: if_expr.pos
Expand Down Expand Up @@ -1077,7 +1077,7 @@ fn (mut p Parser) stmt(is_top_level bool) ast.Stmt {
match p.peek_tok.kind {
.key_if {
mut pos := p.tok.pos()
expr := p.if_expr(true)
expr := p.if_expr(true, false)
pos.update_last_line(p.prev_tok.line_nr)
return ast.ExprStmt{
expr: expr
Expand Down

0 comments on commit f4d3c7e

Please sign in to comment.