mirror of
https://github.com/nushell/nushell.git
synced 2025-05-17 00:10:53 +02:00
## 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
58 lines
1.5 KiB
Rust
58 lines
1.5 KiB
Rust
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,
|
|
}
|
|
|
|
impl MatchPattern {
|
|
pub fn variables(&self) -> Vec<VarId> {
|
|
self.pattern.variables()
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
|
pub enum Pattern {
|
|
Record(Vec<(String, MatchPattern)>),
|
|
List(Vec<MatchPattern>),
|
|
Value(Expression),
|
|
Variable(VarId),
|
|
Or(Vec<MatchPattern>),
|
|
Rest(VarId), // the ..$foo pattern
|
|
IgnoreRest, // the .. pattern
|
|
IgnoreValue, // the _ pattern
|
|
Garbage,
|
|
}
|
|
|
|
impl Pattern {
|
|
pub fn variables(&self) -> Vec<VarId> {
|
|
let mut output = vec![];
|
|
match self {
|
|
Pattern::Record(items) => {
|
|
for item in items {
|
|
output.append(&mut item.1.variables());
|
|
}
|
|
}
|
|
Pattern::List(items) => {
|
|
for item in items {
|
|
output.append(&mut item.variables());
|
|
}
|
|
}
|
|
Pattern::Variable(var_id) => output.push(*var_id),
|
|
Pattern::Or(patterns) => {
|
|
for pattern in patterns {
|
|
output.append(&mut pattern.variables());
|
|
}
|
|
}
|
|
Pattern::Rest(var_id) => output.push(*var_id),
|
|
Pattern::Value(_) | Pattern::IgnoreValue | Pattern::Garbage | Pattern::IgnoreRest => {}
|
|
}
|
|
|
|
output
|
|
}
|
|
}
|