#[derive(Clone, Copy, PartialEq, Eq)]
pub struct Op {
bits: u32,
}
impl Op {
#[inline]
pub fn assign(arg: u32) -> Self {
Self::new(0, arg)
}
#[inline]
pub fn add(arg: u32) -> Self {
Self::new(1, arg)
}
#[inline]
pub fn or(arg: u32) -> Self {
Self::new(2, arg)
}
#[inline]
pub fn and_not(arg: u32) -> Self {
Self::new(3, arg)
}
#[inline]
pub fn xor(arg: u32) -> Self {
Self::new(4, arg)
}
#[inline]
pub fn assign_bit(bit: u32) -> Self {
Self::new(8, bit)
}
#[inline]
pub fn add_bit(bit: u32) -> Self {
Self::new(9, bit)
}
#[inline]
pub fn set_bit(bit: u32) -> Self {
Self::new(10, bit)
}
#[inline]
pub fn clear_bit(bit: u32) -> Self {
Self::new(11, bit)
}
#[inline]
pub fn toggle_bit(bit: u32) -> Self {
Self::new(12, bit)
}
#[inline]
fn new(op: u32, value: u32) -> Self {
if value >= 1 << 12 {
panic!("Value too large: {}", value);
}
Self {
bits: value << 12 | op << 28,
}
}
}
impl std::fmt::Debug for Op {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let op = match self.bits >> 28 {
0 => "assign",
1 => "add",
2 => "or",
3 => "and_not",
4 => "xor",
8 => "assign_bit",
9 => "add_bit",
10 => "set_bit",
11 => "clear_bit",
12 => "toggle_bit",
_ => "invalid",
};
write!(f, "Op::{}({})", op, self.bits >> 12 & 0xFFF)
}
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct Cmp {
bits: u32,
}
impl Cmp {
#[inline]
pub fn eq(value: u32) -> Self {
Self::new(0, value)
}
#[inline]
pub fn ne(value: u32) -> Self {
Self::new(1, value)
}
#[inline]
pub fn lt(value: u32) -> Self {
Self::new(2, value)
}
#[inline]
pub fn le(value: u32) -> Self {
Self::new(3, value)
}
#[inline]
pub fn gt(value: u32) -> Self {
Self::new(4, value)
}
#[inline]
pub fn ge(value: u32) -> Self {
Self::new(5, value)
}
#[inline]
fn new(op: u32, value: u32) -> Self {
if value >= 1 << 12 {
panic!("Value too large: {}", value);
}
Self {
bits: value | op << 24,
}
}
}
impl std::fmt::Debug for Cmp {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let op = match self.bits >> 24 & 0xF {
0 => "eq",
1 => "ne",
2 => "lt",
3 => "le",
4 => "gt",
5 => "ge",
_ => "invalid",
};
write!(f, "Cmp::{}({})", op, self.bits & 0xFFF)
}
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct OpAndCmp {
bits: u32,
}
impl OpAndCmp {
#[inline]
pub const fn from_raw_bits(bits: u32) -> Self {
Self { bits }
}
#[inline]
pub const fn raw_bits(self) -> u32 {
self.bits
}
}
impl std::ops::Add<Cmp> for Op {
type Output = OpAndCmp;
#[inline]
fn add(self, cmp: Cmp) -> OpAndCmp {
OpAndCmp {
bits: self.bits | cmp.bits,
}
}
}
impl std::fmt::Debug for OpAndCmp {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(
f,
"{:?} + {:?}",
Op { bits: self.bits },
Cmp { bits: self.bits }
)
}
}