mini_kanren/core/
logic_variable.rs1use std::sync::atomic::{AtomicUsize, Ordering};
2
3static VAR_COUNTER: AtomicUsize = AtomicUsize::new(0);
4
5#[derive(Copy, Clone, PartialEq, Eq, Hash)]
12pub struct Var {
13 name: &'static str,
14 id: usize,
15}
16
17impl Var {
18 pub fn new(name: &'static str) -> Self {
20 let id = VAR_COUNTER.fetch_add(1, Ordering::Relaxed);
22 Var { name, id }
23 }
24
25 pub fn name(&self) -> &str {
27 self.name
28 }
29}
30
31impl From<&'static str> for Var {
32 fn from(name: &'static str) -> Self {
33 Var::new(name)
34 }
35}
36
37impl std::fmt::Debug for Var {
38 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
39 write!(f, "{}", self.name)
40 }
41}
42
43#[derive(Copy, Clone, PartialEq, Eq)]
48pub struct ReifiedVar(pub usize);
49
50impl std::fmt::Debug for ReifiedVar {
51 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
52 write!(f, "_{}", self.0)
53 }
54}
55
56#[cfg(test)]
57mod unit_tests {
58 use super::*;
59
60 #[test]
61 fn can_create_fresh_variables_with_name() {
62 let var = Var::new("x");
63 assert_eq!(var.name(), "x");
64 }
65
66 #[test]
67 fn can_copy_variables() {
68 let var_a = Var::new("x");
69 let var_b = var_a;
70 assert_eq!(var_a.name(), var_b.name());
71 }
72
73 #[test]
74 fn copied_variables_are_equal() {
75 let var_a = Var::new("x");
76 let var_b = var_a;
77 assert_eq!(var_a, var_b);
78 }
79
80 #[test]
81 fn two_variables_with_same_name_are_not_equal() {
82 let var_a = Var::new("x");
83 let var_b = Var::new("x");
84 assert_ne!(var_a, var_b);
85 }
86
87 #[test]
88 fn can_convert_str_to_var() {
89 let var: Var = "foo".into();
90 assert_eq!(var.name(), "foo");
91 }
92}