Skip to content

Instantly share code, notes, and snippets.

@pshc
Created December 2, 2015 05:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pshc/deef35c62ebb8b0c6694 to your computer and use it in GitHub Desktop.
Save pshc/deef35c62ebb8b0c6694 to your computer and use it in GitHub Desktop.
macro_rules! guard {
(let $($tt:tt)*) => {
let guard!(@lets (_) let $($tt)*)
= guard!(@step (()) let $($tt)*)
};
(match $($tt:tt)*) => {
let guard!(@lets (_) match $($tt)*)
= guard!(@step (()) match $($tt)*)
};
// the @lets rules discard all but the very last statement's `let` pattern.
// the @step rules do all the actual matching.
// the @else rules skip statements until the next `else` statement.
// plain match;
(@lets ($last:pat) match $e:expr { $pat:pat }; $($tt:tt)*) => {
guard!(@lets (_) $($tt)*)
};
(@step ($last:expr) match $e:expr { $pat:pat }; $($tt:tt)*) => {
match $e { $pat => guard!(@step (()) $($tt)*), _ => guard!(@else $($tt)*) }
};
(@else match $e:expr { $pat:pat }; $($tt:tt)*) => (guard!(@else $($tt)*));
// match if condition;
(@lets ($last:pat) match $e:expr { $pat:pat if $cond:expr }; $($tt:tt)*) => {
guard!(@lets (_) $($tt)*)
};
(@step ($last:expr) match $e:expr { $pat:pat if $cond:expr }; $($tt:tt)*) => {
match $e { $pat if $cond => guard!(@step (()) $($tt)*), _ => guard!(@else $($tt)*) }
};
(@else match $e:expr { $pat:pat if $cond:expr }; $($tt:tt)*) => (guard!(@else $($tt)*));
// let tuple = match;
(@lets ($last:pat) let ($($a:ident),+) = match $e:expr { $pat:pat }; $($tt:tt)*) => {
guard!(@lets (($($a),+)) $($tt)*)
};
(@step ($last:expr) let ($($a:ident),+) = match $e:expr { $pat:pat }; $($tt:tt)*) => {
match $e { $pat => guard!(@step (($($a),+)) $($tt)*), _ => guard!(@else $($tt)*) };
};
(@else let ($($a:ident),+) = match $e:expr { $pat:pat }; $($tt:tt)*) => (guard!(@else $($tt)*));
// let tuple = match if condition;
(@lets ($last:pat) let ($($a:ident),+) = match $e:expr { $pat:pat if $cond:expr }; $($tt:tt)*) => {
guard!(@lets (($($a),+)) $($tt)*)
};
(@step ($last:expr) let ($($a:ident),+) = match $e:expr { $pat:pat if $cond:expr }; $($tt:tt)*) => {
match $e { $pat if $cond => guard!(@step (($($a),+)) $($tt)*), _ => guard!(@else $($tt)*) };
};
(@else let ($($a:ident),+) = match $e:expr { $pat:pat if $cond:expr }; $($tt:tt)*) => (guard!(@else $($tt)*));
// let var = match;
(@lets ($last:pat) let $a:ident = match $e:expr { $pat:pat }; $($tt:tt)*) => {
guard!(@lets ($a) $($tt)*)
};
(@step ($last:expr) let $a:ident = match $e:expr { $pat:pat }; $($tt:tt)*) => {
match $e { $pat => guard!(@step ($a) $($tt)*), _ => guard!(@else $($tt)*) }
};
(@else let $a:ident = match $e:expr { $pat:pat }; $($tt:tt)*) => (guard!(@else $($tt)*));
// let var = match if condition;
(@lets ($last:pat) let $a:ident = match $e:expr { $pat:pat if $cond:expr }; $($tt:tt)*) => {
guard!(@lets ($a) $($tt)*)
};
(@step ($last:expr) let $a:ident = match $e:expr { $pat:pat if $cond:expr }; $($tt:tt)*) => {
match $e { $pat if $cond => guard!(@step ($a) $($tt)*), _ => guard!(@else $($tt)*) }
};
(@else let $a:ident = match $e:expr { $pat:pat if $cond:expr }; $($tt:tt)*) => (guard!(@else $(tt)*));
// else err;
(@lets ($last:pat) else $err:expr; $($tt:tt)+) => (guard!(@lets ($last) $($tt)+));
(@step ($last:expr) else $err:expr; $($tt:tt)+) => (guard!(@step ($last) $($tt)+));
(@else else $err:expr; $($tt:tt)+) => ($err);
// end condition
(@lets ($last:pat) else $err:expr) => ($last);
(@step ($last:expr) else $err:expr) => ($last);
(@else else $err:expr) => ($err);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment