use crate::dag::{InternalSharing, PostOrderIterItem};
use crate::jet::Jet;
use crate::types::{self, arrow::Arrow};
use crate::{Cmr, Error, FailEntropy, Value};
use std::marker::PhantomData;
use std::sync::Arc;
use super::{
Constructible, CoreConstructible, DisconnectConstructible, JetConstructible,
WitnessConstructible,
};
use super::{Converter, Hide, Inner, Marker, NoWitness, Node, Redeem, RedeemData, RedeemNode};
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
pub enum WitnessId {}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
pub struct Witness<J> {
never: std::convert::Infallible,
phantom: std::marker::PhantomData<J>,
}
impl<J: Jet> Marker for Witness<J> {
type CachedData = WitnessData<J>;
type Witness = Option<Arc<Value>>;
type Disconnect = Option<Arc<WitnessNode<J>>>;
type SharingId = WitnessId;
type Jet = J;
fn compute_sharing_id(_: Cmr, _: &WitnessData<J>) -> Option<WitnessId> {
None
}
}
pub type WitnessNode<J> = Node<Witness<J>>;
impl<J: Jet> WitnessNode<J> {
#[must_use]
pub fn pruned(&self) -> Arc<Self> {
let new_data = WitnessData {
must_prune: true,
..self.data.clone()
};
Arc::new(WitnessNode {
data: new_data,
cmr: self.cmr,
inner: self
.inner
.as_ref()
.map(Arc::clone)
.map_disconnect(Option::<Arc<_>>::clone)
.map_witness(|wit| wit.as_ref().map(Arc::clone)),
})
}
pub fn arrow(&self) -> &Arrow {
&self.data.arrow
}
pub fn must_prune(&self) -> bool {
self.data.must_prune
}
pub fn prune_and_retype(&self) -> Arc<Self> {
struct Retyper<J>(PhantomData<J>);
impl<J: Jet> Converter<Witness<J>, Witness<J>> for Retyper<J> {
type Error = types::Error;
fn convert_witness(
&mut self,
_: &PostOrderIterItem<&WitnessNode<J>>,
wit: &Option<Arc<Value>>,
) -> Result<Option<Arc<Value>>, Self::Error> {
Ok(wit.as_ref().map(Arc::clone))
}
fn prune_case(
&mut self,
_: &PostOrderIterItem<&WitnessNode<J>>,
left: &Arc<WitnessNode<J>>,
right: &Arc<WitnessNode<J>>,
) -> Result<Hide, Self::Error> {
if left.cached_data().must_prune {
Ok(Hide::Left)
} else if right.cached_data().must_prune {
Ok(Hide::Right)
} else {
Ok(Hide::Neither)
}
}
fn convert_disconnect(
&mut self,
_: &PostOrderIterItem<&WitnessNode<J>>,
maybe_converted: Option<&Arc<WitnessNode<J>>>,
_: &Option<Arc<WitnessNode<J>>>,
) -> Result<Option<Arc<WitnessNode<J>>>, Self::Error> {
Ok(maybe_converted.map(Arc::clone))
}
fn convert_data(
&mut self,
data: &PostOrderIterItem<&WitnessNode<J>>,
inner: Inner<
&Arc<WitnessNode<J>>,
J,
&Option<Arc<WitnessNode<J>>>,
&Option<Arc<Value>>,
>,
) -> Result<WitnessData<J>, Self::Error> {
let converted_inner = inner
.map(|node| node.cached_data())
.map_witness(|wit| wit.as_ref().map(Arc::clone));
let mut retyped = WitnessData::from_inner(converted_inner)?;
if data.node.data.must_prune {
retyped.must_prune = true;
}
Ok(retyped)
}
}
self.convert::<InternalSharing, _, _>(&mut Retyper(PhantomData))
.expect("type inference won't fail if it succeeded before")
}
pub fn finalize(&self) -> Result<Arc<RedeemNode<J>>, Error> {
struct Finalizer<J>(PhantomData<J>);
impl<J: Jet> Converter<Witness<J>, Redeem<J>> for Finalizer<J> {
type Error = Error;
fn convert_witness(
&mut self,
_: &PostOrderIterItem<&WitnessNode<J>>,
wit: &Option<Arc<Value>>,
) -> Result<Arc<Value>, Self::Error> {
if let Some(ref wit) = wit {
Ok(Arc::clone(wit))
} else {
Err(Error::IncompleteFinalization)
}
}
fn convert_disconnect(
&mut self,
_: &PostOrderIterItem<&WitnessNode<J>>,
maybe_converted: Option<&Arc<RedeemNode<J>>>,
_: &Option<Arc<WitnessNode<J>>>,
) -> Result<Arc<RedeemNode<J>>, Self::Error> {
if let Some(child) = maybe_converted {
Ok(Arc::clone(child))
} else {
Err(Error::DisconnectRedeemTime)
}
}
fn convert_data(
&mut self,
data: &PostOrderIterItem<&WitnessNode<J>>,
inner: Inner<&Arc<RedeemNode<J>>, J, &Arc<RedeemNode<J>>, &Arc<Value>>,
) -> Result<Arc<RedeemData<J>>, Self::Error> {
let converted_data = inner
.map(|node| node.cached_data())
.map_disconnect(|node| node.cached_data())
.map_witness(Arc::clone);
Ok(Arc::new(RedeemData::new(
data.node.arrow().finalize()?,
converted_data,
)))
}
}
let pruned_self = self.prune_and_retype();
let unit_ty = types::Type::unit();
pruned_self
.arrow()
.source
.unify(&unit_ty, "setting root source to unit")?;
pruned_self
.arrow()
.target
.unify(&unit_ty, "setting root source to unit")?;
pruned_self.convert::<InternalSharing, _, _>(&mut Finalizer(PhantomData))
}
}
#[derive(Clone, Debug)]
pub struct WitnessData<J> {
arrow: Arrow,
must_prune: bool,
phantom: PhantomData<J>,
}
impl<J> CoreConstructible for WitnessData<J> {
fn iden() -> Self {
WitnessData {
arrow: Arrow::iden(),
must_prune: false,
phantom: PhantomData,
}
}
fn unit() -> Self {
WitnessData {
arrow: Arrow::unit(),
must_prune: false,
phantom: PhantomData,
}
}
fn injl(child: &Self) -> Self {
WitnessData {
arrow: Arrow::injl(&child.arrow),
must_prune: child.must_prune,
phantom: PhantomData,
}
}
fn injr(child: &Self) -> Self {
WitnessData {
arrow: Arrow::injr(&child.arrow),
must_prune: child.must_prune,
phantom: PhantomData,
}
}
fn take(child: &Self) -> Self {
WitnessData {
arrow: Arrow::take(&child.arrow),
must_prune: child.must_prune,
phantom: PhantomData,
}
}
fn drop_(child: &Self) -> Self {
WitnessData {
arrow: Arrow::drop_(&child.arrow),
must_prune: child.must_prune,
phantom: PhantomData,
}
}
fn comp(left: &Self, right: &Self) -> Result<Self, types::Error> {
Ok(WitnessData {
arrow: Arrow::comp(&left.arrow, &right.arrow)?,
must_prune: left.must_prune || right.must_prune,
phantom: PhantomData,
})
}
fn case(left: &Self, right: &Self) -> Result<Self, types::Error> {
Ok(WitnessData {
arrow: Arrow::case(&left.arrow, &right.arrow)?,
must_prune: left.must_prune && right.must_prune,
phantom: PhantomData,
})
}
fn assertl(left: &Self, right: Cmr) -> Result<Self, types::Error> {
Ok(WitnessData {
arrow: Arrow::assertl(&left.arrow, right)?,
must_prune: left.must_prune,
phantom: PhantomData,
})
}
fn assertr(left: Cmr, right: &Self) -> Result<Self, types::Error> {
Ok(WitnessData {
arrow: Arrow::assertr(left, &right.arrow)?,
must_prune: right.must_prune,
phantom: PhantomData,
})
}
fn pair(left: &Self, right: &Self) -> Result<Self, types::Error> {
Ok(WitnessData {
arrow: Arrow::pair(&left.arrow, &right.arrow)?,
must_prune: left.must_prune || right.must_prune,
phantom: PhantomData,
})
}
fn fail(entropy: FailEntropy) -> Self {
WitnessData {
arrow: Arrow::fail(entropy),
must_prune: true,
phantom: PhantomData,
}
}
fn const_word(word: Arc<Value>) -> Self {
WitnessData {
arrow: Arrow::const_word(word),
must_prune: false,
phantom: PhantomData,
}
}
}
impl<J: Jet> DisconnectConstructible<Option<Arc<WitnessNode<J>>>> for WitnessData<J> {
fn disconnect(left: &Self, right: &Option<Arc<WitnessNode<J>>>) -> Result<Self, types::Error> {
let right = right.as_ref();
Ok(WitnessData {
arrow: Arrow::disconnect(&left.arrow, &right.map(|n| n.arrow()))?,
must_prune: left.must_prune || right.map(|n| n.must_prune()).unwrap_or(false),
phantom: PhantomData,
})
}
}
impl<J> WitnessConstructible<Option<Arc<Value>>> for WitnessData<J> {
fn witness(witness: Option<Arc<Value>>) -> Self {
WitnessData {
arrow: Arrow::witness(NoWitness),
must_prune: witness.is_none(),
phantom: PhantomData,
}
}
}
impl<J: Jet> JetConstructible<J> for WitnessData<J> {
fn jet(jet: J) -> Self {
WitnessData {
arrow: Arrow::jet(jet),
must_prune: false,
phantom: PhantomData,
}
}
}