Skip to content

Instantly share code, notes, and snippets.

Created October 6, 2015 16:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save anonymous/a16dec8e8eb48b94ff93 to your computer and use it in GitHub Desktop.
Save anonymous/a16dec8e8eb48b94ff93 to your computer and use it in GitHub Desktop.
Shared via Rust Playground
#![allow(dead_code, unused_variables)]
//#![feature(trace_macros)] trace_macros!(true);
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