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
126
127
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));
            });
    }
}