1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
use crate::{Domain, DomainType, IntoVal, LVar, ResolvedState, Val};
use std::fmt::Debug;

/// Extract a fully resolved `T` from a [`Val<T>`](crate::value::Val).
///
/// Used by [query](crate::Query) to ensure that result values are fully and
/// recursively resolved.
pub trait ReifyIn<'a, D>: Sized {
    /// The "concrete" type that `Self` reifies to.
    type Reified;

    /// Extract a reified `Self` from a compatible
    /// [`ResolvedState`](crate::state::ResolvedState). This trait is usually
    /// used indirectly through the [`Query`](crate::Query) trait.
    ///
    /// # Examples:
    /// Simple values are typically copied or cloned (since the `Val` stores in
    /// an [Rc](std::rc::Rc) internally).
    /// ```
    /// use canrun::{Val, val, var, ReifyIn, IterResolved, State, ResolvedState};
    /// use canrun::example::{I32, TupleI32};
    /// State::new()
    ///     .iter_resolved()
    ///     .for_each(|state: ResolvedState<I32>| {
    ///         let x = val!(1);
    ///         assert_eq!(x.reify_in(&state), Some(1));
    ///     });
    /// ```
    /// Structures containing additional `Val`s should be recursively reified.
    /// ```
    /// # use canrun::{Val, val, var, ReifyIn, IterResolved, State, ResolvedState};
    /// # use canrun::example::{I32, TupleI32};
    /// State::new()
    ///     .iter_resolved()
    ///     .for_each(|state: ResolvedState<TupleI32>| {
    ///         let x = (val!(1), val!(2));
    ///         assert_eq!(x.reify_in(&state), Some((1, 2)));
    ///     });
    /// ```
    /// Returns `None` if the [`Val`] is unresolved.
    /// ```
    /// # use canrun::{Val, val, var, ReifyIn, IterResolved, State, ResolvedState};
    /// # use canrun::example::{I32, TupleI32};
    /// State::new()
    ///     .iter_resolved()
    ///     .for_each(|state: ResolvedState<I32>| {
    ///         let x: Val<i32> = val!(var());
    ///         assert_eq!(x.reify_in(&state), None);
    ///     });
    /// ```
    /// Also returns `None` if `Self` is a structure containing any unresolved
    /// `Val`s.
    /// ```
    /// # use canrun::{Val, val, var, ReifyIn, IterResolved, State, ResolvedState};
    /// # use canrun::example::{I32, TupleI32};
    /// State::new()
    ///     .iter_resolved()
    ///     .for_each(|state: ResolvedState<TupleI32>| {
    ///         let x: Val<i32> = val!(var());
    ///         let y = (x, val!(2));
    ///         assert_eq!(y.reify_in(&state), None);
    ///     });
    /// ```
    fn reify_in(&self, state: &ResolvedState<D>) -> Option<Self::Reified>;
}

impl<'a, T, D> ReifyIn<'a, D> for LVar<T>
where
    T: ReifyIn<'a, D> + Debug,
    D: DomainType<'a, T> + 'a,
{
    type Reified = T::Reified;
    fn reify_in(&self, state: &ResolvedState<D>) -> Option<Self::Reified> {
        self.into_val().reify_in(state)
    }
}

impl<'a, T, D> ReifyIn<'a, D> for Val<T>
where
    T: ReifyIn<'a, D> + Debug,
    D: DomainType<'a, T> + 'a,
{
    type Reified = T::Reified;
    fn reify_in(&self, state: &ResolvedState<D>) -> Option<Self::Reified> {
        let resolved = state.resolve_val(self).resolved().ok()?;
        resolved.reify_in(state)
    }
}

impl<'a, T, D> ReifyIn<'a, D> for &T
where
    T: ReifyIn<'a, D>,
    D: Domain<'a> + 'a,
{
    type Reified = T::Reified;
    fn reify_in(&self, state: &ResolvedState<D>) -> Option<Self::Reified> {
        (*self).reify_in(state)
    }
}

#[cfg(test)]
mod tests {
    use crate::example::I32;
    use crate::{val, var, IterResolved, ReifyIn, ResolvedState, State, Val};

    #[test]
    fn reify_var() {
        let x: Val<i32> = val!(var());
        State::new()
            .iter_resolved()
            .for_each(|state: ResolvedState<I32>| {
                assert_eq!(x.reify_in(&state), None);
            });
    }

    #[test]
    fn reify_resolved() {
        let x = val!(1);
        State::new()
            .iter_resolved()
            .for_each(|state: ResolvedState<I32>| {
                assert_eq!(x.reify_in(&state), Some(1));
            });
    }
}