From 7e13518cc2a1cd24be0c83cca9285c1127c9268c Mon Sep 17 00:00:00 2001 From: Swastik Baranwal Date: Sat, 3 Oct 2020 19:00:58 +0530 Subject: [PATCH] parser: disallow match expr at certain places (#6490) --- doc/docs.md | 2 ++ vlib/v/checker/tests/for_match_err.out | 7 +++++ vlib/v/checker/tests/for_match_err.vv | 15 +++++++++ vlib/v/checker/tests/if_match_expr_err.out | 7 +++++ vlib/v/checker/tests/if_match_expr_err.vv | 13 ++++++++ vlib/v/parser/for.v | 3 ++ vlib/v/parser/if_match.v | 6 ++++ vlib/v/tests/for_loops_2_test.v | 36 +++++++++++----------- 8 files changed, 71 insertions(+), 18 deletions(-) create mode 100644 vlib/v/checker/tests/for_match_err.out create mode 100644 vlib/v/checker/tests/for_match_err.vv create mode 100644 vlib/v/checker/tests/if_match_expr_err.out create mode 100644 vlib/v/checker/tests/if_match_expr_err.vv diff --git a/doc/docs.md b/doc/docs.md index 236f735078..b2cf74ed9b 100644 --- a/doc/docs.md +++ b/doc/docs.md @@ -933,6 +933,8 @@ Note that the ranges use `...` (three dots) rather than `..` (two dots). This is because the range is *inclusive* of the last element, rather than exclusive (as `..` ranges are). Using `..` in a match branch will throw an error. +Note: `match` as an expression is not usable in `for` loop and `if` statements. + ### Defer A defer statement defers the execution of a block of statements until the surrounding function returns. diff --git a/vlib/v/checker/tests/for_match_err.out b/vlib/v/checker/tests/for_match_err.out new file mode 100644 index 0000000000..4e2aa9083d --- /dev/null +++ b/vlib/v/checker/tests/for_match_err.out @@ -0,0 +1,7 @@ +vlib/v/checker/tests/for_match_err.vv:3:7: error: cannot use `match` in `for` loop + 1 | fn main() { + 2 | mut a := 2 + 3 | for match a { + | ~~~~~ + 4 | 2 { + 5 | println('a == 2') diff --git a/vlib/v/checker/tests/for_match_err.vv b/vlib/v/checker/tests/for_match_err.vv new file mode 100644 index 0000000000..910f39fb4b --- /dev/null +++ b/vlib/v/checker/tests/for_match_err.vv @@ -0,0 +1,15 @@ +fn main() { + mut a := 2 + for match a { + 2 { + println('a == 2') + a = 0 + } + 0 { + println('a == 0') + } + else { + println('unexpected branch') + } + } +} diff --git a/vlib/v/checker/tests/if_match_expr_err.out b/vlib/v/checker/tests/if_match_expr_err.out new file mode 100644 index 0000000000..25b13cb189 --- /dev/null +++ b/vlib/v/checker/tests/if_match_expr_err.out @@ -0,0 +1,7 @@ +vlib/v/checker/tests/if_match_expr_err.vv:3:8: error: cannot use `match` with `if` statements + 1 | fn main() { + 2 | a := 0 + 3 | if match a { + | ~~~~~ + 4 | 0 { + 5 | println('a is zero') diff --git a/vlib/v/checker/tests/if_match_expr_err.vv b/vlib/v/checker/tests/if_match_expr_err.vv new file mode 100644 index 0000000000..511bbc7b65 --- /dev/null +++ b/vlib/v/checker/tests/if_match_expr_err.vv @@ -0,0 +1,13 @@ +fn main() { + a := 0 + if match a { + 0 { + println('a is zero') + } + else { + println('unreachable branch') + } + } 5 < 7 { + println('5 is less than 7') + } +} diff --git a/vlib/v/parser/for.v b/vlib/v/parser/for.v index 8dfdb66632..fb93886207 100644 --- a/vlib/v/parser/for.v +++ b/vlib/v/parser/for.v @@ -11,6 +11,9 @@ fn (mut p Parser) for_stmt() ast.Stmt { pos := p.tok.position() p.open_scope() p.inside_for = true + if p.tok.kind == .key_match { + p.error('cannot use `match` in `for` loop') + } // defer { p.close_scope() } // Infinite loop if p.tok.kind == .lcbr { diff --git a/vlib/v/parser/if_match.v b/vlib/v/parser/if_match.v index 20c0da30b2..4fc0358cc0 100644 --- a/vlib/v/parser/if_match.v +++ b/vlib/v/parser/if_match.v @@ -34,6 +34,9 @@ fn (mut p Parser) if_expr(is_comptime bool) ast.IfExpr { comments << p.eat_comments() p.check(.key_else) comments << p.eat_comments() + if p.tok.kind == .key_match { + p.error('cannot use `match` with `if` statements') + } if p.tok.kind == .lcbr { // else { has_else = true @@ -72,6 +75,9 @@ fn (mut p Parser) if_expr(is_comptime bool) ast.IfExpr { } // `if` or `else if` p.check(.key_if) + if p.tok.kind == .key_match { + p.error('cannot use `match` with `if` statements') + } comments << p.eat_comments() // `if mut name is T` mut mut_name := false diff --git a/vlib/v/tests/for_loops_2_test.v b/vlib/v/tests/for_loops_2_test.v index 8db5c284c8..5def00b15d 100644 --- a/vlib/v/tests/for_loops_2_test.v +++ b/vlib/v/tests/for_loops_2_test.v @@ -1,24 +1,24 @@ fn test_for_match() { mut a := 2 mut b := 0 - for match a { - 2 { - println('a == 2') - a = 0 - true + for { + match a { + 2 { + println('a == 2') + a = 0 + continue + } + 0 { + println('a == 0') + a = 5 + b++ + break + } + else { + println('unexpected branch') + break + } } - 0 { - println('a == 0') - a = 5 - false - } - else { - println('unexpected branch') - false - } - } { - b++ - println('${b}. run') } assert a == 5 assert b == 1 @@ -34,7 +34,7 @@ fn test_for_select() { x := <-ch1 { a += x } - y := <- ch2 { + y := <-ch2 { a += int(y) } } {