microcad_lang/value/
array.rs1use crate::{ty::*, value::*};
7use derive_more::{Deref, DerefMut};
8
9#[derive(Clone, Deref, DerefMut)]
11pub struct Array {
12 #[deref]
14 #[deref_mut]
15 items: ValueList,
16 ty: Type,
18}
19
20impl Array {
21 pub fn new(ty: Type) -> Self {
23 Self {
24 items: ValueList::default(),
25 ty,
26 }
27 }
28
29 pub fn from_values(items: ValueList, ty: Type) -> Self {
31 Self { items, ty }
32 }
33
34 pub fn fetch(&self) -> Vec<Value> {
36 self.items.iter().cloned().collect::<Vec<_>>()
37 }
38
39 pub fn head(&self) -> Value {
41 self.items.iter().next().cloned().unwrap_or(Value::None)
42 }
43
44 pub fn tail(&self) -> Array {
46 Array::from_values(
47 self.items.iter().skip(1).cloned().collect(),
48 self.ty.clone(),
49 )
50 }
51}
52
53impl PartialEq for Array {
54 fn eq(&self, other: &Self) -> bool {
55 self.ty == other.ty && self.items == other.items
56 }
57}
58
59impl IntoIterator for Array {
60 type Item = Value;
61 type IntoIter = std::vec::IntoIter<Self::Item>;
62
63 fn into_iter(self) -> Self::IntoIter {
64 self.items.into_iter()
65 }
66}
67
68impl TryFrom<ValueList> for Array {
69 type Error = ValueError;
70 fn try_from(items: ValueList) -> ValueResult<Array> {
71 match items.types().common_type() {
72 Some(ty) => Ok(Array::from_values(items, ty)),
73 None => Err(ValueError::CommonTypeExpected),
74 }
75 }
76}
77
78impl FromIterator<Value> for Array {
79 fn from_iter<T: IntoIterator<Item = Value>>(iter: T) -> Self {
80 let items: ValueList = iter.into_iter().collect();
81 let ty = items.types().common_type().expect("Common type");
82 Self { ty, items }
83 }
84}
85
86impl std::fmt::Display for Array {
87 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
88 write!(
89 f,
90 "[{items}]",
91 items = self
92 .items
93 .iter()
94 .map(|v| v.to_string())
95 .collect::<Vec<_>>()
96 .join(", ")
97 )
98 }
99}
100
101impl std::fmt::Debug for Array {
102 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
103 write!(
104 f,
105 "[{items}]",
106 items = self
107 .items
108 .iter()
109 .map(|v| format!("{v:?}"))
110 .collect::<Vec<_>>()
111 .join(", ")
112 )
113 }
114}
115
116impl crate::ty::Ty for Array {
117 fn ty(&self) -> Type {
118 Type::Array(Box::new(self.ty.clone()))
119 }
120}
121
122impl std::ops::Add<Value> for Array {
124 type Output = ValueResult;
125
126 fn add(self, rhs: Value) -> Self::Output {
127 if self.ty.is_compatible_to(&rhs.ty()) {
128 Ok(Value::Array(Self::from_values(
129 ValueList::new(
130 self.items
131 .iter()
132 .map(|value| value.clone() + rhs.clone())
133 .collect::<Result<Vec<_>, _>>()?,
134 ),
135 self.ty,
136 )))
137 } else {
138 Err(ValueError::InvalidOperator("+".into()))
139 }
140 }
141}
142
143impl std::ops::Sub<Value> for Array {
145 type Output = ValueResult;
146
147 fn sub(self, rhs: Value) -> Self::Output {
148 if self.ty.is_compatible_to(&rhs.ty()) {
149 Ok(Value::Array(Self::from_values(
150 ValueList::new(
151 self.items
152 .iter()
153 .map(|value| value.clone() - rhs.clone())
154 .collect::<Result<Vec<_>, _>>()?,
155 ),
156 self.ty,
157 )))
158 } else {
159 Err(ValueError::InvalidOperator("-".into()))
160 }
161 }
162}
163
164impl std::ops::Mul<Value> for Array {
166 type Output = ValueResult;
167
168 fn mul(self, rhs: Value) -> Self::Output {
169 match self.ty {
170 Type::Quantity(_) | Type::Integer => Ok(Value::Array(Array::from_values(
172 ValueList::new({
173 self.iter()
174 .map(|value| value.clone() * rhs.clone())
175 .collect::<Result<Vec<_>, _>>()?
176 }),
177 self.ty * rhs.ty().clone(),
178 ))),
179 _ => Err(ValueError::InvalidOperator("*".into())),
180 }
181 }
182}
183
184impl std::ops::Div<Value> for Array {
186 type Output = ValueResult;
187
188 fn div(self, rhs: Value) -> Self::Output {
189 let values = ValueList::new(
190 self.iter()
191 .map(|value| value.clone() / rhs.clone())
192 .collect::<Result<Vec<_>, _>>()?,
193 );
194
195 match (&self.ty, rhs.ty()) {
196 (Type::Integer, Type::Integer) => Ok(Value::Array(Array::from_values(
198 values,
199 self.ty / rhs.ty().clone(),
200 ))),
201 (Type::Quantity(_), _) => Ok(Value::Array(values.try_into()?)),
202 _ => Err(ValueError::InvalidOperator("/".into())),
203 }
204 }
205}
206
207impl std::ops::Neg for Array {
208 type Output = ValueResult;
209
210 fn neg(self) -> Self::Output {
211 let items: ValueList = self
212 .iter()
213 .map(|value| -value.clone())
214 .collect::<Result<Vec<_>, _>>()?
215 .into_iter()
216 .collect();
217 Ok(Value::Array(items.try_into()?))
218 }
219}
220
221#[test]
222fn test_array_debug() {
223 let val1 = Value::Target(Target::new("my::name1".into(), Some("my::target1".into())));
224 let val2 = Value::Target(Target::new("my::name2".into(), None));
225
226 let mut array = Array::new(Type::Target);
227 array.push(val1);
228 array.push(val2);
229
230 log::info!("{array}");
231 log::info!("{array:?}");
232}