Skip to main content

mini_kanren/core/
value.rs

1//! Dynamic values
2use crate::core::logic_variable::{ReifiedVar, Var};
3use crate::core::pair::Pair;
4use crate::core::structure::{Atomic, Structure};
5use crate::core::substitution::Substitution;
6use std::fmt::Formatter;
7use std::sync::Arc;
8
9/// Dynamic value
10#[derive(Clone)]
11pub struct Value(Arc<dyn Structure>);
12
13impl PartialEq for Value {
14    fn eq(&self, other: &Self) -> bool {
15        Arc::ptr_eq(&self.0, &other.0) || self.0.eqv(&other)
16    }
17}
18
19impl Value {
20    /// Construct a new value
21    pub fn new(val: impl Into<Value>) -> Self {
22        val.into()
23    }
24
25    /// Construct pre-Arc'd value
26    pub fn from_arc<T: Structure>(x: Arc<T>) -> Self {
27        Value(x)
28    }
29
30    /// Construct a value representing a variable
31    pub fn var(v: Var) -> Self {
32        Value::new(v)
33    }
34
35    /// Construct a value representing a reified variable
36    pub fn rv(i: usize) -> Self {
37        Value::new(ReifiedVar(i))
38    }
39
40    /// Construct a pair from two values
41    pub fn cons(car: impl Into<Value>, cdr: impl Into<Value>) -> Self {
42        Value::new((car.into(), cdr.into()))
43    }
44
45    /// Cast to `Var` if the value represents a variable
46    pub fn try_as_var(&self) -> Option<Var> {
47        self.downcast_ref().copied()
48    }
49
50    /// Try to cast to concrete type
51    pub fn downcast_ref<T: 'static>(&self) -> Option<&T> {
52        self.0.as_any().downcast_ref()
53    }
54
55    pub(super) fn occurs<'s>(&self, x: &Var, s: &Substitution<'s>) -> bool {
56        self.0.occurs(x, s)
57    }
58
59    pub(super) fn unify<'s>(&self, v: &Value, s: Substitution<'s>) -> Option<Substitution<'s>> {
60        self.0.unify(v, s)
61    }
62
63    pub(super) fn walk_star(&self, s: &Substitution<'_>) -> Value {
64        self.0.clone().walk_star(s)
65    }
66
67    pub(super) fn reify_s<'s>(&self, s: Substitution<'s>) -> Substitution<'s> {
68        self.0.reify_s(s)
69    }
70}
71
72impl PartialEq<Var> for Value {
73    fn eq(&self, v: &Var) -> bool {
74        self.0
75            .as_any()
76            .downcast_ref::<Var>()
77            .map(|sv| sv == v)
78            .unwrap_or(false)
79    }
80}
81
82impl<T: Structure> From<T> for Value {
83    fn from(v: T) -> Self {
84        Value(Arc::new(v))
85    }
86}
87
88impl<T: 'static + Atomic + PartialEq> PartialEq<T> for Value {
89    fn eq(&self, other: &T) -> bool {
90        self.0
91            .as_any()
92            .downcast_ref::<T>()
93            .map(|x| x == other)
94            .unwrap_or(false)
95    }
96}
97
98impl std::fmt::Debug for Value {
99    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
100        write!(f, "{:?}", self.0)
101    }
102}
103
104impl From<Vec<Value>> for Value {
105    /// Convert `Vec<Value>` into a linked list of values.
106    fn from(items: Vec<Value>) -> Self {
107        let mut list = Value::from(());
108        for v in items.into_iter().rev() {
109            list = Value::cons(v, list);
110        }
111        list
112    }
113}
114
115impl<A: Into<Value>, D: Into<Value>> From<(A, D)> for Value {
116    fn from(pair: (A, D)) -> Self {
117        let pair = (pair.0.into(), pair.1.into());
118        Value::new(Pair::from(pair))
119    }
120}