use traits::{self, SymbolId};
pub type PoolId = usize;
pub trait Types {
type Symbol: Symbol;
type Input: ?Sized;
type Output: ?Sized;
}
pub trait Pool {
type Symbol: Symbol;
#[cfg(debug_assertions)]
fn id(&self) -> PoolId;
fn create_symbol(&self, id: <Self::Symbol as Symbol>::Id) -> Self::Symbol;
}
pub trait Symbol: traits::Symbol {
type Id: SymbolId;
#[cfg(debug_assertions)]
fn pool_id(&self) -> PoolId;
fn id(&self) -> Self::Id;
fn id_ref(&self) -> &Self::Id;
#[cfg(debug_assertions)]
fn create(id: Self::Id, pool_id: PoolId) -> Self;
#[cfg(not(debug_assertions))]
fn create(id: Self::Id) -> Self;
}
impl<'a, T> Types for &'a T
where T: Types
{
type Symbol = T::Symbol;
type Input = T::Input;
type Output = T::Output;
}
impl<'a, T> Types for &'a mut T
where T: Types
{
type Symbol = T::Symbol;
type Input = T::Input;
type Output = T::Output;
}
macro_rules! make_sym {
() => {};
(@impl $name:ident < $I: ident > ( $wrapped: path ) ; $($bound: tt)+ ) => {
impl<$I> ::sym::Symbol for $name<$I>
where $I: $($bound)+,
$wrapped: ::sym::Symbol
{
type Id = <$wrapped as ::sym::Symbol>::Id;
#[cfg(debug_assertions)]
fn pool_id(&self) -> ::sym::PoolId {
self.wrapped.pool_id()
}
fn id(&self) -> Self::Id { self.wrapped.id() }
fn id_ref(&self) -> &Self::Id { self.wrapped.id_ref() }
#[cfg(not(debug_assertions))]
fn create(id: Self::Id) -> Self {
$name{wrapped: <$wrapped as ::sym::Symbol>::create(id)}
}
#[cfg(debug_assertions)]
fn create(id: Self::Id, pool_id: ::sym::PoolId) -> Self {
$name{wrapped: <$wrapped as ::sym::Symbol>::create(id, pool_id)}
}
}
impl<$I> From<$wrapped> for $name<$I>
where $I: $($bound)+
{
fn from(wrapped: $wrapped) -> Self {
$name{wrapped: wrapped}
}
}
};
(@impl $name:ident < $I: ident > ; $($bound: tt)+) => {
impl<$I> ::sym::Symbol for $name<$I>
where $I: $($bound)+
{
type Id = $I;
#[cfg(debug_assertions)]
fn pool_id(&self) -> ::sym::PoolId {
self.pool_id
}
fn id(&self) -> Self::Id { self.id }
fn id_ref(&self) -> &Self::Id { &self.id }
#[cfg(not(debug_assertions))]
fn create(id: Self::Id) -> Self {
$name{id: id}
}
#[cfg(debug_assertions)]
fn create(id: Self::Id, pool_id: ::sym::PoolId) -> Self {
$name{id: id, pool_id: pool_id}
}
}
};
(@struct $name:ident < $I: ident > ( $wrapped: path ) : $doc:expr ; $($bound: tt)+) => {
#[doc = $doc]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct $name<$I: $($bound)+ > {
wrapped: $wrapped,
}
};
(@struct $name:ident < $I: ident > : $doc:expr; $($bound: tt)+) => {
#[doc = $doc]
#[cfg(not(debug_assertions))]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct $name<$I: $($bound)+> {
id: $I,
}
#[doc = $doc]
#[cfg(debug_assertions)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct $name<$I: $($bound)+> {
id: $I,
pool_id: ::sym::PoolId,
}
};
($(#[$attr: meta])*
pub $name:ident < $I:ident $(: $bound: ident $(+ $rbound: ident)*)* > : $doc: expr; $($rest: tt)*)
=> {$(#[$attr])*
make_sym!(@struct $name<$I> : $doc; SymbolId $(+ $bound $( + $rbound)*)*);
$(#[$attr])*
make_sym!(@impl $name<$I> ; SymbolId $(+ $bound $( + $rbound)*)*);
make_sym!($($rest)*); };
($(#[$attr: meta])*
pub $name: ident < $I:ident $(: $bound: ident $(+ $rbound: ident)*)* >($wrapped: path) : $doc: expr; $($rest: tt)*)
=> {$(#[$attr])*
make_sym!(@struct $name<$I>($wrapped) : $doc; SymbolId $(+ $bound $( + $rbound)*)*);
$(#[$attr])*
make_sym!(@impl $name<$I>($wrapped) ; SymbolId $(+ $bound $( + $rbound)*)*);
make_sym!($($rest)*); };
}