add match guards (#9621)

## description

this pr adds [match
guards](https://doc.rust-lang.org/reference/expressions/match-expr.html#match-guards)
to match patterns
```nushell
match $x {
   _ if $x starts-with 'nu' => {},
   $x => {}
}
```

these work pretty much like rust's match guards, with few limitations:

1. multiple matches using the `|` are not (yet?) supported
 
```nushell
match $num {
    0 | _ if (is-odd $num) => {},
    _ => {}
}
```

2. blocks cannot be used as guards, (yet?)

```nushell
match $num {
    $x if { $x ** $x == inf } => {},
     _ => {}
}
```

## checklist
- [x] syntax
- [x] syntax highlighting[^1]
- [x] semantics
- [x] tests
- [x] clean up

[^1]: defered for another pr
This commit is contained in:
mike
2023-07-16 03:25:12 +03:00
committed by GitHub
parent 57d96c09fa
commit 5bfec20244
6 changed files with 165 additions and 26 deletions

View File

@ -1,12 +1,11 @@
use serde::{Deserialize, Serialize};
use crate::{Span, VarId};
use super::Expression;
use crate::{Span, VarId};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct MatchPattern {
pub pattern: Pattern,
pub guard: Option<Expression>,
pub span: Span,
}

View File

@ -1073,6 +1073,18 @@ pub enum ShellError {
#[label("This operation was interrupted")]
span: Option<Span>,
},
/// An attempt to use, as a match guard, an expression that
/// does not resolve into a boolean
#[error("Match guard not bool")]
#[diagnostic(
code(nu::shell::match_guard_not_bool),
help("Match guards should evaluate to a boolean")
)]
MatchGuardNotBool {
#[label("not a boolean expression")]
span: Span,
},
}
impl From<std::io::Error> for ShellError {