-
-
Save durka/d040140aaa3293b87b8e to your computer and use it in GitHub Desktop.
let...else macro
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![allow(dead_code, unused_variables)] | |
//#![feature(trace_macros)] trace_macros!(true); | |
// strategy: scan the pattern for idents and pull them out, so we can create a let statement in the enclosing scope | |
macro_rules! guard { | |
(@as_stmt $s:stmt) => { $s }; | |
(@collect () -> ($($idents:ident)*), [($pattern:pat) ($rhs:expr) ($diverge:expr)]) => { | |
guard!(@as_stmt let ($($idents,)*) = if let $pattern = $rhs { ($($idents,)*) } else { $diverge }) | |
}; | |
(@collect (($($inside:tt)*) $($tail:tt)*) -> ($($idents:ident)*), $thru:tt) => { | |
guard!(@collect ($($inside)* $($tail)*) -> ($($idents)*), $thru) | |
}; | |
(@collect ({$($inside:tt)*} $($tail:tt)*) -> ($($idents:ident)*), $thru:tt) => { | |
guard!(@collect ($($inside)* $($tail)*) -> ($($idents)*), $thru) | |
}; | |
(@collect (, $($tail:tt)*) -> ($($idents:ident)*), $thru:tt) => { | |
guard!(@collect ($($tail)*) -> ($($idents)*), $thru) | |
}; | |
(@collect (.. $($tail:tt)*) -> ($($idents:ident)*), $thru:tt) => { | |
guard!(@collect ($($tail)*) -> ($($idents)*), $thru) | |
}; | |
(@collect ($id:ident: $($tail:tt)*) -> ($($idents:ident)*), $thru:tt) => { | |
guard!(@collect ($($tail)*) -> ($($idents)*), $thru) | |
}; | |
(@collect ($pathcomp:ident :: $($tail:tt)*) -> $idents:tt, $thru:tt) => { | |
guard!(@collect ($($tail)*) -> $idents, $thru) | |
}; | |
(@collect ($id:ident ($($inside:tt)*) $($tail:tt)*) -> ($($idents:ident)*), $thru:tt) => { | |
guard!(@collect ($($inside)* $($tail)*) -> ($($idents)*), $thru) | |
}; | |
(@collect ($id:ident {$($inside:tt)*} $($tail:tt)*) -> ($($idents:ident)*), $thru:tt) => { | |
guard!(@collect ($($inside)* $($tail)*) -> ($($idents)*), $thru) | |
}; | |
(@collect ($id:ident $($tail:tt)*) -> ($($idents:ident)*), $thru:tt) => { | |
guard!(@collect ($($tail)*) -> ($($idents)* $id), $thru) | |
}; | |
({ $($diverge:tt)* } unless $rhs:expr => $($pattern:tt)*) => { | |
guard!(@collect ($($pattern)*) -> (), [($($pattern)*) ($rhs) ({$($diverge)*})]) | |
} | |
} | |
enum Stuff { | |
A(Option<i32>, Option<i32>), | |
B(i32), | |
C { foo: Result<i32, i32>, bar: i32 }, | |
D | |
} | |
fn main() { | |
let opt = Stuff::A(Some(42), Some(43)); | |
guard!({ return } unless opt => Stuff::A(Some(x), Some(y))); | |
println!("{} {}", x, y); | |
guard!({ return } unless Stuff::C { foo: Ok(44), bar: 45 } => Stuff::C { foo: Ok(x), .. }); | |
println!("{}", x); | |
guard!({ return } unless opt => Stuff::B(x)); | |
unreachable!(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment