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
25 where
26 T: Into<Self>,
27 {
28 Self::Record(ExprRecord::from_iter(items))
29 }
30
31 pub fn record_from_vec(fields: Vec<Self>) -> Self {
32 Self::Record(ExprRecord::from_vec(fields))
33 }
34
35 pub fn is_record(&self) -> bool {
36 matches!(self, Self::Record(_))
37 }
38
39 pub fn as_record(&self) -> Option<&ExprRecord> {
40 match self {
41 Self::Record(expr_record) => Some(expr_record),
42 _ => None,
43 }
44 }
45
46 pub fn as_record_unwrap(&self) -> &ExprRecord {
47 match self {
48 Self::Record(expr_record) => expr_record,
49 _ => panic!("self={self:#?}"),
50 }
51 }
52
53 pub fn as_record_mut(&mut self) -> &mut ExprRecord {
54 match self {
55 Self::Record(expr_record) => expr_record,
56 _ => panic!(),
57 }
58 }
59
60 pub fn into_record(self) -> ExprRecord {
61 match self {
62 Self::Record(expr_record) => expr_record,
63 _ => panic!(),
64 }
65 }
66
67 pub fn record_len(&self) -> Option<usize> {
68 match self {
69 Expr::Record(expr_record) => Some(expr_record.len()),
70 Expr::Value(Value::Record(value_record)) => Some(value_record.len()),
71 _ => None,
72 }
73 }
74
75 pub fn into_record_items(self) -> Option<impl Iterator<Item = Expr>> {
76 let ret: Option<Box<dyn Iterator<Item = Expr>>> = match self {
77 Expr::Record(expr_record) => Some(Box::new(expr_record.into_iter())),
78 Expr::Value(Value::Record(value_record)) => {
79 Some(Box::new(value_record.into_iter().map(Expr::Value)))
80 }
81 _ => None,
82 };
83
84 ret
85 }
86}
87
88impl ExprRecord {
89 pub fn from_vec(fields: Vec<Expr>) -> Self {
90 Self { fields }
91 }
92
93 pub fn push(&mut self, expr: Expr) {
94 self.fields.push(expr)
95 }
96
97 pub fn resize(&mut self, new_len: usize, value: impl Into<stmt::Expr>) {
98 self.fields.resize(new_len, value.into());
99 }
100}
101
102impl<A> FromIterator<A> for ExprRecord
103where
104 A: Into<Expr>,
105{
106 fn from_iter<T: IntoIterator<Item = A>>(iter: T) -> Self {
107 Self::from_vec(iter.into_iter().map(Into::into).collect())
108 }
109}
110
111impl ops::Deref for ExprRecord {
112 type Target = [Expr];
113
114 fn deref(&self) -> &Self::Target {
115 &self.fields[..]
116 }
117}
118
119impl ops::DerefMut for ExprRecord {
120 fn deref_mut(&mut self) -> &mut Self::Target {
121 &mut self.fields[..]
122 }
123}
124
125impl ops::Index<usize> for ExprRecord {
126 type Output = Expr;
127
128 fn index(&self, index: usize) -> &Self::Output {
129 &self.fields[index]
130 }
131}
132
133impl ops::IndexMut<usize> for ExprRecord {
134 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
135 &mut self.fields[index]
136 }
137}
138
139impl IntoIterator for ExprRecord {
140 type Item = Expr;
141 type IntoIter = std::vec::IntoIter<Expr>;
142
143 fn into_iter(self) -> Self::IntoIter {
144 self.fields.into_iter()
145 }
146}
147
148impl<'a> IntoIterator for &'a ExprRecord {
149 type Item = &'a Expr;
150 type IntoIter = std::slice::Iter<'a, Expr>;
151
152 fn into_iter(self) -> Self::IntoIter {
153 self.fields.iter()
154 }
155}
156
157impl<'a> IntoIterator for &'a mut ExprRecord {
158 type Item = &'a mut Expr;
159 type IntoIter = std::slice::IterMut<'a, Expr>;
160
161 fn into_iter(self) -> Self::IntoIter {
162 self.fields.iter_mut()
163 }
164}
165
166impl AsRef<[Expr]> for ExprRecord {
167 fn as_ref(&self) -> &[Expr] {
168 self.fields.as_ref()
169 }
170}
171
172impl From<ExprRecord> for Expr {
173 fn from(value: ExprRecord) -> Self {
174 Self::Record(value)
175 }
176}
177
178macro_rules! impl_for_tuple {
179 ( $len:literal; $(($T:ident, $idx:tt)),+ ) => {
180 impl<$($T),+> From<($($T,)+)> for ExprRecord
181 where
182 $($T: Into<Expr>,)+
183 {
184 fn from(src: ($($T,)+)) -> Self {
185 Self {
186 fields: vec![$(src.$idx.into()),+],
187 }
188 }
189 }
190
191 impl<$($T),+> PartialEq<($($T,)+)> for Expr
192 where
193 $(Expr: PartialEq<$T>,)+
194 $(Value: PartialEq<$T>,)+
195 {
196 fn eq(&self, other: &($($T,)+)) -> bool {
197 match self {
198 Expr::Record(r) => {
199 r.fields.len() == $len
200 $(&& r.fields[$idx].eq(&other.$idx))+
201 }
202 Expr::Value(Value::Record(r)) => {
203 r.fields.len() == $len
204 $(&& r.fields[$idx].eq(&other.$idx))+
205 }
206 _ => false,
207 }
208 }
209 }
210
211 impl<$($T),+> PartialEq<Expr> for ($($T,)+)
212 where
213 Expr: PartialEq<($($T,)+)>,
214 {
215 fn eq(&self, other: &Expr) -> bool {
216 other.eq(self)
217 }
218 }
219 };
220}
221
222impl_for_tuple!(1; (T0, 0));
223impl_for_tuple!(2; (T0, 0), (T1, 1));
224impl_for_tuple!(3; (T0, 0), (T1, 1), (T2, 2));
225impl_for_tuple!(4; (T0, 0), (T1, 1), (T2, 2), (T3, 3));
226impl_for_tuple!(5; (T0, 0), (T1, 1), (T2, 2), (T3, 3), (T4, 4));
227impl_for_tuple!(6; (T0, 0), (T1, 1), (T2, 2), (T3, 3), (T4, 4), (T5, 5));
228impl_for_tuple!(7; (T0, 0), (T1, 1), (T2, 2), (T3, 3), (T4, 4), (T5, 5), (T6, 6));
229impl_for_tuple!(8; (T0, 0), (T1, 1), (T2, 2), (T3, 3), (T4, 4), (T5, 5), (T6, 6), (T7, 7));
230impl_for_tuple!(9; (T0, 0), (T1, 1), (T2, 2), (T3, 3), (T4, 4), (T5, 5), (T6, 6), (T7, 7), (T8, 8));
231impl_for_tuple!(10; (T0, 0), (T1, 1), (T2, 2), (T3, 3), (T4, 4), (T5, 5), (T6, 6), (T7, 7), (T8, 8), (T9, 9));
232impl_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));
233impl_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));
234
235impl Node for ExprRecord {
236 fn visit<V: Visit>(&self, mut visit: V) {
237 visit.visit_expr_record(self);
238 }
239
240 fn visit_mut<V: VisitMut>(&mut self, mut visit: V) {
241 visit.visit_expr_record_mut(self);
242 }
243}
244
245impl fmt::Debug for ExprRecord {
246 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
247 self.fields.as_slice().fmt(f)
248 }
249}