1use super::{Expr, Node, Visit, VisitMut};
2use crate::stmt::{self, Value};
3
4use std::{fmt, ops};
5
6#[derive(Clone, Default, PartialEq)]
18pub struct ExprRecord {
19 pub fields: Vec<Expr>,
21}
22
23impl Expr {
24 pub fn record<T>(items: impl IntoIterator<Item = T>) -> Self
26 where
27 T: Into<Self>,
28 {
29 Self::Record(ExprRecord::from_iter(items))
30 }
31
32 pub fn record_from_vec(fields: Vec<Self>) -> Self {
34 Self::Record(ExprRecord::from_vec(fields))
35 }
36
37 pub fn is_record(&self) -> bool {
39 matches!(self, Self::Record(_))
40 }
41
42 pub fn as_record(&self) -> Option<&ExprRecord> {
45 match self {
46 Self::Record(expr_record) => Some(expr_record),
47 _ => None,
48 }
49 }
50
51 #[track_caller]
57 pub fn as_record_unwrap(&self) -> &ExprRecord {
58 self.as_record()
59 .unwrap_or_else(|| panic!("expected Expr::Record; actual={self:#?}"))
60 }
61
62 pub fn as_record_mut(&mut self) -> Option<&mut ExprRecord> {
65 match self {
66 Self::Record(expr_record) => Some(expr_record),
67 _ => None,
68 }
69 }
70
71 #[track_caller]
77 pub fn as_record_mut_unwrap(&mut self) -> &mut ExprRecord {
78 match self {
79 Self::Record(expr_record) => expr_record,
80 _ => panic!("expected Expr::Record"),
81 }
82 }
83
84 pub fn into_record(self) -> ExprRecord {
90 match self {
91 Self::Record(expr_record) => expr_record,
92 _ => panic!(),
93 }
94 }
95
96 pub fn record_len(&self) -> Option<usize> {
100 match self {
101 Expr::Record(expr_record) => Some(expr_record.len()),
102 Expr::Value(Value::Record(value_record)) => Some(value_record.len()),
103 _ => None,
104 }
105 }
106
107 pub fn into_record_items(self) -> Option<impl Iterator<Item = Expr>> {
110 let ret: Option<Box<dyn Iterator<Item = Expr>>> = match self {
111 Expr::Record(expr_record) => Some(Box::new(expr_record.into_iter())),
112 Expr::Value(Value::Record(value_record)) => {
113 Some(Box::new(value_record.into_iter().map(Expr::Value)))
114 }
115 _ => None,
116 };
117
118 ret
119 }
120}
121
122impl ExprRecord {
123 pub fn from_vec(fields: Vec<Expr>) -> Self {
125 Self { fields }
126 }
127
128 pub fn push(&mut self, expr: Expr) {
130 self.fields.push(expr)
131 }
132
133 pub fn resize(&mut self, new_len: usize, value: impl Into<stmt::Expr>) {
135 self.fields.resize(new_len, value.into());
136 }
137}
138
139impl<A> FromIterator<A> for ExprRecord
140where
141 A: Into<Expr>,
142{
143 fn from_iter<T: IntoIterator<Item = A>>(iter: T) -> Self {
144 Self::from_vec(iter.into_iter().map(Into::into).collect())
145 }
146}
147
148impl ops::Deref for ExprRecord {
149 type Target = [Expr];
150
151 fn deref(&self) -> &Self::Target {
152 &self.fields[..]
153 }
154}
155
156impl ops::DerefMut for ExprRecord {
157 fn deref_mut(&mut self) -> &mut Self::Target {
158 &mut self.fields[..]
159 }
160}
161
162impl ops::Index<usize> for ExprRecord {
163 type Output = Expr;
164
165 fn index(&self, index: usize) -> &Self::Output {
166 &self.fields[index]
167 }
168}
169
170impl ops::IndexMut<usize> for ExprRecord {
171 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
172 &mut self.fields[index]
173 }
174}
175
176impl IntoIterator for ExprRecord {
177 type Item = Expr;
178 type IntoIter = std::vec::IntoIter<Expr>;
179
180 fn into_iter(self) -> Self::IntoIter {
181 self.fields.into_iter()
182 }
183}
184
185impl<'a> IntoIterator for &'a ExprRecord {
186 type Item = &'a Expr;
187 type IntoIter = std::slice::Iter<'a, Expr>;
188
189 fn into_iter(self) -> Self::IntoIter {
190 self.fields.iter()
191 }
192}
193
194impl<'a> IntoIterator for &'a mut ExprRecord {
195 type Item = &'a mut Expr;
196 type IntoIter = std::slice::IterMut<'a, Expr>;
197
198 fn into_iter(self) -> Self::IntoIter {
199 self.fields.iter_mut()
200 }
201}
202
203impl AsRef<[Expr]> for ExprRecord {
204 fn as_ref(&self) -> &[Expr] {
205 self.fields.as_ref()
206 }
207}
208
209impl From<ExprRecord> for Expr {
210 fn from(value: ExprRecord) -> Self {
211 Self::Record(value)
212 }
213}
214
215macro_rules! impl_for_tuple {
216 ( $len:literal; $(($T:ident, $idx:tt)),+ ) => {
217 impl<$($T),+> From<($($T,)+)> for ExprRecord
218 where
219 $($T: Into<Expr>,)+
220 {
221 fn from(src: ($($T,)+)) -> Self {
222 Self {
223 fields: vec![$(src.$idx.into()),+],
224 }
225 }
226 }
227
228 impl<$($T),+> PartialEq<($($T,)+)> for Expr
229 where
230 $(Expr: PartialEq<$T>,)+
231 $(Value: PartialEq<$T>,)+
232 {
233 fn eq(&self, other: &($($T,)+)) -> bool {
234 match self {
235 Expr::Record(r) => {
236 r.fields.len() == $len
237 $(&& r.fields[$idx].eq(&other.$idx))+
238 }
239 Expr::Value(Value::Record(r)) => {
240 r.fields.len() == $len
241 $(&& r.fields[$idx].eq(&other.$idx))+
242 }
243 _ => false,
244 }
245 }
246 }
247
248 impl<$($T),+> PartialEq<Expr> for ($($T,)+)
249 where
250 Expr: PartialEq<($($T,)+)>,
251 {
252 fn eq(&self, other: &Expr) -> bool {
253 other.eq(self)
254 }
255 }
256 };
257}
258
259impl_for_tuple!(1; (T0, 0));
260impl_for_tuple!(2; (T0, 0), (T1, 1));
261impl_for_tuple!(3; (T0, 0), (T1, 1), (T2, 2));
262impl_for_tuple!(4; (T0, 0), (T1, 1), (T2, 2), (T3, 3));
263impl_for_tuple!(5; (T0, 0), (T1, 1), (T2, 2), (T3, 3), (T4, 4));
264impl_for_tuple!(6; (T0, 0), (T1, 1), (T2, 2), (T3, 3), (T4, 4), (T5, 5));
265impl_for_tuple!(7; (T0, 0), (T1, 1), (T2, 2), (T3, 3), (T4, 4), (T5, 5), (T6, 6));
266impl_for_tuple!(8; (T0, 0), (T1, 1), (T2, 2), (T3, 3), (T4, 4), (T5, 5), (T6, 6), (T7, 7));
267impl_for_tuple!(9; (T0, 0), (T1, 1), (T2, 2), (T3, 3), (T4, 4), (T5, 5), (T6, 6), (T7, 7), (T8, 8));
268impl_for_tuple!(10; (T0, 0), (T1, 1), (T2, 2), (T3, 3), (T4, 4), (T5, 5), (T6, 6), (T7, 7), (T8, 8), (T9, 9));
269impl_for_tuple!(11; (T0, 0), (T1, 1), (T2, 2), (T3, 3), (T4, 4), (T5, 5), (T6, 6), (T7, 7), (T8, 8), (T9, 9), (T10, 10));
270impl_for_tuple!(12; (T0, 0), (T1, 1), (T2, 2), (T3, 3), (T4, 4), (T5, 5), (T6, 6), (T7, 7), (T8, 8), (T9, 9), (T10, 10), (T11, 11));
271
272impl Node for ExprRecord {
273 fn visit<V: Visit>(&self, mut visit: V) {
274 visit.visit_expr_record(self);
275 }
276
277 fn visit_mut<V: VisitMut>(&mut self, mut visit: V) {
278 visit.visit_expr_record_mut(self);
279 }
280}
281
282impl fmt::Debug for ExprRecord {
283 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
284 self.fields.as_slice().fmt(f)
285 }
286}