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