1use std::borrow::Borrow;
2
3use super::{literals::AbstractLiteral, Expression, Literal, Name};
4use serde::{Deserialize, Serialize};
5use uniplate::derive::Uniplate;
6
7#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Uniplate)]
9#[uniplate()]
10#[biplate(to=Literal)]
11#[biplate(to=Expression)]
12#[biplate(to=AbstractLiteral<Literal>,walk_into=[Literal])]
13#[biplate(to=Name)]
14pub enum Atom {
15 Literal(Literal),
16 Reference(Name),
17}
18
19impl Atom {
20 pub fn new_uref(name: &str) -> Atom {
22 Atom::Reference(Name::UserName(name.to_string()))
23 }
24}
25
26impl std::fmt::Display for Atom {
27 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28 match self {
29 Atom::Literal(x) => x.fmt(f),
30 Atom::Reference(x) => x.fmt(f),
31 }
32 }
33}
34
35impl From<Literal> for Atom {
36 fn from(value: Literal) -> Self {
37 Atom::Literal(value)
38 }
39}
40
41impl From<Name> for Atom {
42 fn from(value: Name) -> Self {
43 Atom::Reference(value)
44 }
45}
46
47impl From<i32> for Atom {
48 fn from(value: i32) -> Self {
49 Atom::Literal(value.into())
50 }
51}
52
53impl From<bool> for Atom {
54 fn from(value: bool) -> Self {
55 Atom::Literal(value.into())
56 }
57}
58
59impl TryFrom<Expression> for Atom {
60 type Error = &'static str;
61
62 fn try_from(value: Expression) -> Result<Self, Self::Error> {
63 match value {
64 Expression::Atomic(_, atom) => Ok(atom),
65 _ => Err("Cannot convert non-atomic expression to Atom"),
66 }
67 }
68}
69
70impl<'a> TryFrom<&'a Expression> for &'a Atom {
71 type Error = &'static str;
72
73 fn try_from(value: &'a Expression) -> Result<Self, Self::Error> {
74 match value {
75 Expression::Atomic(_, atom) => Ok(atom),
76 _ => Err("Cannot convert non-atomic expression to Atom"),
77 }
78 }
79}
80
81impl TryFrom<Box<Expression>> for Atom {
82 type Error = &'static str;
83
84 fn try_from(value: Box<Expression>) -> Result<Self, Self::Error> {
85 (*value).try_into()
86 }
87}
88
89impl<'a> TryFrom<&'a Box<Expression>> for &'a Atom {
90 type Error = &'static str;
91
92 fn try_from(value: &'a Box<Expression>) -> Result<Self, Self::Error> {
93 let expr: &'a Expression = value.borrow();
94 expr.try_into()
95 }
96}
97
98impl TryFrom<Atom> for Literal {
99 type Error = &'static str;
100
101 fn try_from(value: Atom) -> Result<Self, Self::Error> {
102 match value {
103 Atom::Literal(l) => Ok(l),
104 _ => Err("Cannot convert non-literal atom to Literal"),
105 }
106 }
107}
108
109impl<'a> TryFrom<&'a Atom> for &'a Literal {
110 type Error = &'static str;
111
112 fn try_from(value: &'a Atom) -> Result<Self, Self::Error> {
113 match value {
114 Atom::Literal(l) => Ok(l),
115 _ => Err("Cannot convert non-literal atom to Literal"),
116 }
117 }
118}
119
120impl TryFrom<Atom> for Name {
121 type Error = &'static str;
122
123 fn try_from(value: Atom) -> Result<Self, Self::Error> {
124 match value {
125 Atom::Reference(n) => Ok(n),
126 _ => Err("Cannot convert non-reference atom to Name"),
127 }
128 }
129}
130
131impl<'a> TryFrom<&'a Atom> for &'a Name {
132 type Error = &'static str;
133
134 fn try_from(value: &'a Atom) -> Result<Self, Self::Error> {
135 match value {
136 Atom::Reference(n) => Ok(n),
137 _ => Err("Cannot convert non-reference atom to Name"),
138 }
139 }
140}
141
142impl TryFrom<Atom> for i32 {
143 type Error = &'static str;
144
145 fn try_from(value: Atom) -> Result<Self, Self::Error> {
146 let lit: Literal = value.try_into()?;
147 lit.try_into()
148 }
149}
150
151impl TryFrom<&Atom> for i32 {
152 type Error = &'static str;
153
154 fn try_from(value: &Atom) -> Result<Self, Self::Error> {
155 let lit: &Literal = value.try_into()?;
156 lit.try_into()
157 }
158}
159
160impl TryFrom<Atom> for bool {
161 type Error = &'static str;
162
163 fn try_from(value: Atom) -> Result<Self, Self::Error> {
164 let lit: Literal = value.try_into()?;
165 lit.try_into()
166 }
167}
168
169impl TryFrom<&Atom> for bool {
170 type Error = &'static str;
171
172 fn try_from(value: &Atom) -> Result<Self, Self::Error> {
173 let lit: &Literal = value.try_into()?;
174 lit.try_into()
175 }
176}