microcad_lang/value/
array.rs1use crate::{ty::*, value::*};
7use derive_more::{Deref, DerefMut};
8
9#[derive(Clone, Debug, Deref, DerefMut)]
11pub struct Array {
12 #[deref]
14 #[deref_mut]
15 items: ValueList,
16 ty: Type,
18}
19
20impl Array {
21 pub fn new(items: ValueList, ty: Type) -> Self {
23 Self { items, ty }
24 }
25
26 pub fn fetch(&self) -> Vec<Value> {
28 self.items.iter().cloned().collect::<Vec<_>>()
29 }
30}
31
32impl PartialEq for Array {
33 fn eq(&self, other: &Self) -> bool {
34 self.ty == other.ty && self.items == other.items
35 }
36}
37
38impl IntoIterator for Array {
39 type Item = Value;
40 type IntoIter = std::vec::IntoIter<Self::Item>;
41
42 fn into_iter(self) -> Self::IntoIter {
43 self.items.into_iter()
44 }
45}
46
47impl TryFrom<ValueList> for Array {
48 type Error = ValueError;
49 fn try_from(items: ValueList) -> ValueResult<Array> {
50 match items.types().common_type() {
51 Some(ty) => Ok(Array::new(items, ty)),
52 None => Err(ValueError::CommonTypeExpected),
53 }
54 }
55}
56
57impl FromIterator<Value> for Array {
58 fn from_iter<T: IntoIterator<Item = Value>>(iter: T) -> Self {
59 let items: ValueList = iter.into_iter().collect();
60 let ty = items.types().common_type().expect("Common type");
61 Self { ty, items }
62 }
63}
64
65impl std::fmt::Display for Array {
66 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
67 write!(
68 f,
69 "[{items}]",
70 items = self
71 .items
72 .iter()
73 .map(|v| v.to_string())
74 .collect::<Vec<_>>()
75 .join(", ")
76 )
77 }
78}
79
80impl crate::ty::Ty for Array {
81 fn ty(&self) -> Type {
82 Type::Array(Box::new(self.ty.clone()))
83 }
84}
85
86impl std::ops::Add<Value> for Array {
88 type Output = ValueResult;
89
90 fn add(self, rhs: Value) -> Self::Output {
91 if self.ty.is_add_compatible_to(&rhs.ty()) {
92 Ok(Value::Array(Self::new(
93 ValueList::new(
94 self.items
95 .iter()
96 .map(|value| value.clone() + rhs.clone())
97 .collect::<Result<Vec<_>, _>>()?,
98 ),
99 self.ty,
100 )))
101 } else {
102 Err(ValueError::InvalidOperator("+".into()))
103 }
104 }
105}
106
107impl std::ops::Sub<Value> for Array {
109 type Output = ValueResult;
110
111 fn sub(self, rhs: Value) -> Self::Output {
112 if self.ty.is_add_compatible_to(&rhs.ty()) {
113 Ok(Value::Array(Self::new(
114 ValueList::new(
115 self.items
116 .iter()
117 .map(|value| value.clone() - rhs.clone())
118 .collect::<Result<Vec<_>, _>>()?,
119 ),
120 self.ty,
121 )))
122 } else {
123 Err(ValueError::InvalidOperator("-".into()))
124 }
125 }
126}
127
128impl std::ops::Mul<Value> for Array {
130 type Output = ValueResult;
131
132 fn mul(self, rhs: Value) -> Self::Output {
133 match self.ty {
134 Type::Quantity(_) | Type::Integer => Ok(Value::Array(Array::new(
136 ValueList::new({
137 self.iter()
138 .map(|value| value.clone() * rhs.clone())
139 .collect::<Result<Vec<_>, _>>()?
140 }),
141 self.ty * rhs.ty().clone(),
142 ))),
143 _ => Err(ValueError::InvalidOperator("*".into())),
144 }
145 }
146}
147
148impl std::ops::Div<Value> for Array {
150 type Output = ValueResult;
151
152 fn div(self, rhs: Value) -> Self::Output {
153 let values = ValueList::new(
154 self.iter()
155 .map(|value| value.clone() / rhs.clone())
156 .collect::<Result<Vec<_>, _>>()?,
157 );
158
159 match (&self.ty, rhs.ty()) {
160 (Type::Integer, Type::Integer) => Ok(Value::Array(Array::new(
162 values,
163 self.ty / rhs.ty().clone(),
164 ))),
165 (Type::Quantity(_), _) => Ok(Value::Array(values.try_into()?)),
166 _ => Err(ValueError::InvalidOperator("/".into())),
167 }
168 }
169}
170
171impl std::ops::Neg for Array {
172 type Output = ValueResult;
173
174 fn neg(self) -> Self::Output {
175 let items: ValueList = self
176 .iter()
177 .map(|value| -value.clone())
178 .collect::<Result<Vec<_>, _>>()?
179 .into_iter()
180 .collect();
181 Ok(Value::Array(items.try_into()?))
182 }
183}