Skip to content

Instantly share code, notes, and snippets.

@brendanzab
Last active August 29, 2015 14:05
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 brendanzab/f3bdbc11e8aee7ea0b6d to your computer and use it in GitHub Desktop.
Save brendanzab/f3bdbc11e8aee7ea0b6d to your computer and use it in GitHub Desktop.
#![feature(macro_rules)]
macro_rules! flag {
($Flag:ident) => {
flag!($Flag { Yes, No })
};
($Flag:ident { $Yes:ident, $No:ident, }) => {
flag!($Flag { $Yes, $No })
};
($Flag:ident { $Yes:ident, $No:ident }) => {
pub mod $Flag {
use std::fmt;
#[deriving(PartialEq, PartialOrd, Eq, Ord, Hash, Rand)]
pub enum T { $Yes, $No }
pub fn from_bool(x: bool) -> T {
if x { $Yes } else { $No }
}
impl T {
pub fn to_bool(self) -> bool {
self == $Yes
}
pub fn and(self, f: || -> T) -> T {
from_bool(self.to_bool() && f().to_bool())
}
pub fn or(self, f: || -> T) -> T {
from_bool(self.to_bool() || f().to_bool())
}
}
impl Not<T> for T {
fn not(&self) -> T {
from_bool(!(*self).to_bool())
}
}
impl BitAnd<T, T> for T {
fn bitand(&self, other: &T) -> T {
from_bool((*self).to_bool() && (*other).to_bool())
}
}
impl BitOr<T, T> for T {
fn bitor(&self, other: &T) -> T {
from_bool((*self).to_bool() || (*other).to_bool())
}
}
impl BitXor<T, T> for T {
fn bitxor(&self, other: &T) -> T {
from_bool((*self).to_bool() ^ (*other).to_bool())
}
}
impl fmt::Show for T {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
$Yes => write!(f, "{}::{}", stringify!($Flag), stringify!($Yes)),
$No => write!(f, "{}::{}", stringify!($Flag), stringify!($No)),
}
}
}
}
};
}
flag!(IsFoo)
fn main() {
assert_eq!(IsFoo::Yes.to_bool(), true);
assert_eq!(IsFoo::No.to_bool(), false);
assert_eq!(IsFoo::Yes, IsFoo::from_bool(true));
assert_eq!(IsFoo::No, IsFoo::from_bool(false));
assert_eq!(IsFoo::Yes.or(|| IsFoo::Yes), IsFoo::Yes);
assert_eq!(IsFoo::Yes.or(|| IsFoo::No), IsFoo::Yes);
assert_eq!(IsFoo::No.or(|| IsFoo::Yes), IsFoo::Yes);
assert_eq!(IsFoo::No.or(|| IsFoo::No), IsFoo::No);
assert_eq!(IsFoo::Yes.and(|| IsFoo::Yes), IsFoo::Yes);
assert_eq!(IsFoo::Yes.and(|| IsFoo::No), IsFoo::No);
assert_eq!(IsFoo::No.and(|| IsFoo::Yes), IsFoo::No);
assert_eq!(IsFoo::No.and(|| IsFoo::No), IsFoo::No);
assert_eq!(!IsFoo::Yes, IsFoo::No);
assert_eq!(!IsFoo::No, IsFoo::Yes);
assert_eq!(IsFoo::Yes | IsFoo::Yes, IsFoo::Yes);
assert_eq!(IsFoo::Yes | IsFoo::No, IsFoo::Yes);
assert_eq!(IsFoo::No | IsFoo::Yes, IsFoo::Yes);
assert_eq!(IsFoo::No | IsFoo::No, IsFoo::No);
assert_eq!(IsFoo::Yes & IsFoo::Yes, IsFoo::Yes);
assert_eq!(IsFoo::Yes & IsFoo::No, IsFoo::No);
assert_eq!(IsFoo::No & IsFoo::Yes, IsFoo::No);
assert_eq!(IsFoo::No & IsFoo::No, IsFoo::No);
assert_eq!(IsFoo::Yes ^ IsFoo::Yes, IsFoo::No);
assert_eq!(IsFoo::Yes ^ IsFoo::No, IsFoo::Yes);
assert_eq!(IsFoo::No ^ IsFoo::Yes, IsFoo::Yes);
assert_eq!(IsFoo::No ^ IsFoo::No, IsFoo::No);
assert_eq!(format!("{}", IsFoo::Yes), "IsFoo::Yes".to_string());
assert_eq!(format!("{}", IsFoo::No), "IsFoo::No".to_string());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment