use std::collections::HashMap;
use std::hash::Hash;
use std::clone::Clone;
use std::fmt::Debug;
use quickcheck::{Arbitrary,Gen};
use {Result,Str,Variable};
#[macro_export]
macro_rules! define_table_ref {
( $name:ident ) => {
#[derive(Hash,Clone,Copy,Debug,PartialEq,Eq,PartialOrd,Ord)]
pub struct $name (usize);
impl $name {
pub fn index(&self) -> usize { self.0 }
pub fn new(i: usize) -> $name { $name(i) }
}
impl From<usize> for $name {
fn from(i: usize) -> $name { $name::new(i) }
}
impl Into<usize> for $name {
fn into(self) -> usize { self.index() }
}
};
}
define_table_ref!(NameRef);
define_table_ref!(SegmentRef);
define_table_ref!(StrRef);
#[derive(Hash,Clone,Debug,PartialEq,Eq,PartialOrd,Ord)]
pub struct Name {
base: Str,
subscript: Option<usize>,
}
impl Name {
pub fn new<S: Into<Option<usize>> + Sized>(s: Str, o: S) -> Name {
Name{
base: s,
subscript: o.into(),
}
}
pub fn base<'a>(&'a self) -> &'a Str { &self.base }
pub fn subscript(&self) -> Option<usize> { self.subscript }
}
#[derive(Debug,Clone)]
pub struct Table<V: Hash + Debug + Clone + Eq,R: Clone + Copy + From<usize> + Into<usize>> {
refs: HashMap<V,R>,
values: Vec<V>,
facade: bool
}
impl<V: Hash + Debug + Clone + Eq,R: Clone + Copy + From<usize> + Into<usize>> Table<V,R> {
pub fn with_capacity(cap: usize) -> Table<V,R> {
Table{
refs: HashMap::with_capacity(cap),
values: Vec::with_capacity(cap),
facade: false,
}
}
pub fn insert(&mut self, v: &V) -> R {
if let Some(i) = self.refs.get(v).cloned() {
i
} else {
let i = self.values.len();
self.refs.insert(v.clone(),i.into());
self.values.push(v.clone());
i.into()
}
}
pub fn index(&self, s: &V) -> Result<R> {
match self.refs.get(s).map(|&x| x) {
Some(s) => Ok(s),
None if self.facade => Ok(0.into()),
None => Err("name not part of this set".into()),
}
}
pub fn value<'a>(&'a self, i: R) -> Result<&'a V> {
if self.facade {
Ok(&self.values[0])
} else {
Ok(&self.values[i.into()])
}
}
pub fn len(&self) -> usize {
self.values.len()
}
#[cfg(test)]
pub fn facade(v: &V) -> Table<V,R> {
let mut ret = Table{
refs: HashMap::default(),
values: Vec::default(),
facade: true,
};
ret.insert(v);
ret
}
}
impl Table<Name,NameRef> {
pub fn base_name(&self, idx: NameRef) -> Result<NameRef> {
let name = self.value(idx)?;
match name {
&Name{ ref base, subscript: Some(_) } => {
self.index(&Name{ base: base.clone(), subscript: None })
}
&Name{ subscript: None,.. } => {
Ok(idx)
}
}
}
pub fn var<S: Into<Str>>(&mut self, name: S, subscript: Option<usize>, bits: usize) -> Result<Variable> {
let i = self.insert(&Name::new(name.into(),subscript));
Variable::new(i,bits)
}
}
impl Table<Name,SegmentRef> {
pub fn base_name(&self, idx: SegmentRef) -> Result<SegmentRef> {
let seg = self.value(idx)?;
match seg {
&Name{ ref base, subscript: Some(_) } => {
self.index(&Name{ base: base.clone(), subscript: None })
}
&Name{ subscript: None,.. } => {
Ok(idx)
}
}
}
}
impl<V: Hash + Debug + Clone + Eq,R: Clone + Copy + From<usize> + Into<usize>> Default for Table<V,R> {
fn default() -> Table<V,R> {
Table{
refs: HashMap::default(),
values: Vec::default(),
facade: false,
}
}
}
impl Arbitrary for NameRef {
fn arbitrary<G: Gen>(g: &mut G) -> Self {
NameRef::new(g.gen_range(0,100))
}
}
impl Arbitrary for StrRef {
fn arbitrary<G: Gen>(g: &mut G) -> Self {
StrRef::new(g.gen_range(0,100))
}
}
pub type Strings = Table<Str,StrRef>;
pub type Names = Table<Name,NameRef>;
pub type Segments = Table<Name,SegmentRef>;