use std::num::Wrapping;
use std::u64;
use quickcheck::{Arbitrary,Gen};
use {NameRef,Result,SegmentRef};
#[derive(Clone,Copy,PartialEq,Eq,PartialOrd,Ord,Debug,Hash)]
pub struct Variable {
pub name: NameRef,
pub bits: usize,
}
impl Variable {
pub fn new(name: NameRef, bits: usize) -> Result<Variable> {
if bits == 0 { return Err("Variable can't have size 0".into()); }
Ok(Variable{
name: name,
bits: bits
})
}
}
#[derive(Clone,Copy,PartialEq,Eq,PartialOrd,Ord,Debug,Hash)]
pub struct Constant {
pub value: u64,
pub bits: usize,
}
impl Constant {
pub fn new(value: u64, bits: usize) -> Result<Constant> {
if bits == 0 { return Err("Variable can't have size 0".into()); }
Ok(Constant{
value: value,
bits: bits
})
}
pub fn mask(&self) -> Wrapping<u64> {
Wrapping(if self.bits < 64 { (1u64 << self.bits) - 1 } else { u64::MAX })
}
}
impl Into<Wrapping<u64>> for Constant {
fn into(self) -> Wrapping<u64> {
Wrapping(self.value) & self.mask()
}
}
#[derive(Clone,Copy,PartialEq,Eq,PartialOrd,Ord,Debug,Hash)]
pub enum Value {
Undefined,
Variable(Variable),
Constant(Constant),
}
impl Value {
pub fn val(val: u64, bits: usize) -> Result<Value> {
Ok(Value::Constant(Constant::new(val,bits)?))
}
pub fn var(name: NameRef, bits: usize) -> Result<Value> {
Ok(Value::Variable(Variable::new(name,bits)?))
}
pub fn undef() -> Value {
Value::Undefined
}
pub fn bits(&self) -> Option<usize> {
match self {
&Value::Variable(Variable{ bits,.. }) => Some(bits),
&Value::Constant(Constant{ bits,.. }) => Some(bits),
&Value::Undefined => None,
}
}
}
impl From<Variable> for Value {
fn from(v: Variable) -> Value {
Value::Variable(v)
}
}
impl From<Constant> for Value {
fn from(v: Constant) -> Value {
Value::Constant(v)
}
}
#[derive(Clone,Copy,PartialEq,Eq,Debug,Hash)]
pub struct Segment {
pub name: SegmentRef,
}
impl Arbitrary for Variable {
fn arbitrary<G: Gen>(g: &mut G) -> Self {
Variable {
name: NameRef::arbitrary(g),
bits: 1 << g.gen_range(0, 11),
}
}
}
impl Arbitrary for Constant {
fn arbitrary<G: Gen>(g: &mut G) -> Self {
Constant{
value: g.gen(),
bits: 1 << g.gen_range(0, 11),
}
}
}
impl Arbitrary for Segment {
fn arbitrary<G: Gen>(g: &mut G) -> Self {
Segment{ name: SegmentRef::new(g.gen_range(0,100)) }
}
}
impl Arbitrary for Value {
fn arbitrary<G: Gen>(g: &mut G) -> Self {
match g.gen_range(0, 2) {
0 => Value::Undefined,
1 => Value::Variable(Variable::arbitrary(g)),
2 => Value::Constant(Constant::arbitrary(g)),
_ => unreachable!(),
}
}
}