1use super::Dynamic;
2
3use std::ops::{Neg, Not};
4impl Neg for Dynamic {
5 type Output = Self;
6 fn neg(self) -> Self::Output {
7 use Dynamic::*;
8 match self {
9 I8(i) => I8(i.wrapping_neg()),
10 I16(i) => I16(i.wrapping_neg()),
11 I32(i) => I32(i.wrapping_neg()),
12 I64(i) => I64(i.wrapping_neg()),
13 F32(f) => F32(-f),
14 F64(f) => F64(-f),
15 _ => Null,
16 }
17 }
18}
19
20impl Not for Dynamic {
21 type Output = Self;
22 fn not(self) -> Self::Output {
23 match self {
24 Self::Bool(b) => Self::Bool(!b),
25 Self::I8(i) => Self::I8(!i),
26 Self::I16(i) => Self::I16(!i),
27 Self::I32(i) => Self::I32(!i),
28 Self::I64(i) => Self::I64(!i),
29 Self::U8(i) => Self::U8(!i),
30 Self::U16(i) => Self::U16(!i),
31 Self::U32(i) => Self::U32(!i),
32 Self::U64(i) => Self::U64(!i),
33 _ => Self::Null,
34 }
35 }
36}
37
38use std::ops::{Add, Div, Mul, Rem, Sub};
39
40impl Add for Dynamic {
41 type Output = Self;
42 fn add(self, rhs: Self) -> Self::Output {
43 if self.is_list() {
44 self.clone().append(rhs);
45 return self;
46 } else if rhs.is_list() {
47 rhs.clone().append(self);
48 return rhs;
49 }
50 match (self, rhs) {
51 (Self::StringBuf(mut left), Self::StringBuf(right)) => {
52 left.push_str(&right);
53 return Self::StringBuf(left);
54 }
55 (Self::StringBuf(mut left), Self::String(right)) => {
56 left.push_str(right.as_str());
57 return Self::StringBuf(left);
58 }
59 (Self::StringBuf(mut left), right) => {
60 left.push_str(&right.to_string());
61 return Self::StringBuf(left);
62 }
63 (Self::String(left), Self::StringBuf(right)) => {
64 let mut out = String::with_capacity(left.len() + right.len());
65 out.push_str(left.as_str());
66 out.push_str(&right);
67 return Self::StringBuf(out);
68 }
69 (Self::String(left), Self::String(right)) => {
70 let mut out = String::with_capacity(left.len() + right.len());
71 out.push_str(left.as_str());
72 out.push_str(right.as_str());
73 return Self::StringBuf(out);
74 }
75 (Self::String(left), right) => {
76 let right = right.to_string();
77 let mut out = String::with_capacity(left.len() + right.len());
78 out.push_str(left.as_str());
79 out.push_str(&right);
80 return Self::StringBuf(out);
81 }
82 (left, Self::StringBuf(right)) => {
83 let left = left.to_string();
84 let mut out = String::with_capacity(left.len() + right.len());
85 out.push_str(&left);
86 out.push_str(&right);
87 return Self::StringBuf(out);
88 }
89 (left, Self::String(right)) => {
90 let left = left.to_string();
91 let mut out = String::with_capacity(left.len() + right.len());
92 out.push_str(&left);
93 out.push_str(right.as_str());
94 return Self::StringBuf(out);
95 }
96 (left, right) => {
97 if left.is_f64() || right.is_f64() {
98 return Dynamic::F64(left.as_float().unwrap_or(0.0) + right.as_float().unwrap_or(0.0));
99 } else if left.is_f32() || right.is_f32() {
100 return Dynamic::F32(left.as_float().unwrap_or(0.0) as f32 + right.as_float().unwrap_or(0.0) as f32);
101 }
102 if left.is_int() || right.is_int() {
103 return Self::I64(left.as_int().unwrap() + right.as_int().unwrap());
104 }
105 if left.is_uint() || right.is_uint() {
106 return Self::U64(left.as_uint().unwrap() + right.as_uint().unwrap());
107 }
108 if left.is_map() && right.is_map() {
109 left.append(right);
110 }
111 left
112 }
113 }
114 }
115}
116
117impl Mul for Dynamic {
118 type Output = Self;
119 fn mul(self, rhs: Self) -> Self::Output {
120 if self.is_f64() || rhs.is_f64() {
121 return Dynamic::F64(self.as_float().unwrap_or(0.0) * rhs.as_float().unwrap_or(0.0));
122 } else if self.is_f32() || rhs.is_f32() {
123 return Dynamic::F32(self.as_float().unwrap_or(0.0) as f32 * rhs.as_float().unwrap_or(0.0) as f32);
124 }
125 if self.is_int() || rhs.is_int() {
126 return Self::I64(self.as_int().unwrap_or(0) * rhs.as_int().unwrap_or(0));
127 }
128 if self.is_uint() || rhs.is_uint() {
129 return Self::U64(self.as_uint().unwrap_or(0) * rhs.as_uint().unwrap_or(0));
130 }
131 self
132 }
133}
134
135impl Sub for Dynamic {
136 type Output = Self;
137 fn sub(self, rhs: Self) -> Self::Output {
138 if self.is_f64() || rhs.is_f64() {
139 return Dynamic::F64(self.as_float().unwrap() - rhs.as_float().unwrap());
140 } else if self.is_f32() || rhs.is_f32() {
141 return Dynamic::F32(self.as_float().unwrap() as f32 - rhs.as_float().unwrap() as f32);
142 }
143 if self.is_int() || rhs.is_int() || self.is_uint() || rhs.is_uint() {
144 return Self::I64(self.as_int().unwrap() - rhs.as_int().unwrap());
145 }
146 if self.is_list() && rhs.is_list() {
147 if self.len() == rhs.len() {}
148 }
149 self
150 }
151}
152
153impl Div for Dynamic {
154 type Output = Self;
155 fn div(self, rhs: Self) -> Self::Output {
156 if self.is_f64() || rhs.is_f64() {
157 return Dynamic::F64(self.as_float().unwrap() / rhs.as_float().unwrap());
158 } else if self.is_f32() || rhs.is_f32() {
159 return Dynamic::F32(self.as_float().unwrap() as f32 / rhs.as_float().unwrap() as f32);
160 }
161 if self.is_int() || rhs.is_int() || self.is_uint() || rhs.is_uint() {
162 return match self.as_int().unwrap().checked_div(rhs.as_int().unwrap()) {
163 Some(value) => Self::I64(value),
164 None => {
165 crate::set_fault("整数除零");
166 Self::Null
167 }
168 };
169 }
170 self
171 }
172}
173
174impl Rem for Dynamic {
175 type Output = Self;
176 fn rem(self, rhs: Self) -> Self::Output {
177 if self.is_int() || rhs.is_int() || self.is_uint() || rhs.is_uint() {
178 return match self.as_int().unwrap().checked_rem(rhs.as_int().unwrap()) {
179 Some(value) => Self::I64(value),
180 None => {
181 crate::set_fault("整数取余除零");
182 Self::Null
183 }
184 };
185 }
186 self
187 }
188}
189
190use std::ops::{Shl, Shr};
191
192impl Shl for Dynamic {
193 type Output = Self;
194 fn shl(self, rhs: Self) -> Self::Output {
195 use Dynamic::*;
196 let shift = u64::try_from(rhs).unwrap();
197 match self {
198 I8(i) => I8(i << shift),
199 I16(i) => I16(i << shift),
200 I32(i) => I32(i << shift),
201 I64(i) => I64(i << shift),
202 U8(i) => U8(i << shift),
203 U16(i) => U16(i << shift),
204 U32(i) => U32(i << shift),
205 U64(i) => U64(i << shift),
206 _ => Dynamic::I64(0),
207 }
208 }
209}
210
211impl Shr for Dynamic {
212 type Output = Self;
213 fn shr(self, rhs: Self) -> Self::Output {
214 use Dynamic::*;
215 let shift = u64::try_from(rhs).unwrap();
216 match self {
217 I8(i) => I8(i >> shift),
218 I16(i) => I16(i >> shift),
219 I32(i) => I32(i >> shift),
220 I64(i) => I64(i >> shift),
221 U8(i) => U8(i >> shift),
222 U16(i) => U16(i >> shift),
223 U32(i) => U32(i >> shift),
224 U64(i) => U64(i >> shift),
225 _ => Dynamic::I64(0),
226 }
227 }
228}
229
230use std::ops::{BitAnd, BitOr, BitXor};
231impl BitAnd for Dynamic {
232 type Output = Self;
233 fn bitand(self, rhs: Self) -> Self::Output {
234 let ty = self.get_type() + rhs.get_type();
235 let left = ty.force(self).unwrap();
236 let right = ty.force(rhs).unwrap();
237 match (left, right) {
238 (Dynamic::I8(l), Dynamic::I8(r)) => Dynamic::I8(l & r),
239 (Dynamic::I16(l), Dynamic::I16(r)) => Dynamic::I16(l & r),
240 (Dynamic::I32(l), Dynamic::I32(r)) => Dynamic::I32(l & r),
241 (Dynamic::I64(l), Dynamic::I64(r)) => Dynamic::I64(l & r),
242 (Dynamic::U8(l), Dynamic::U8(r)) => Dynamic::U8(l & r),
243 (Dynamic::U16(l), Dynamic::U16(r)) => Dynamic::U16(l & r),
244 (Dynamic::U32(l), Dynamic::U32(r)) => Dynamic::U32(l & r),
245 (Dynamic::U64(l), Dynamic::U64(r)) => Dynamic::U64(l & r),
246 (_, _) => Dynamic::Null,
247 }
248 }
249}
250
251#[cfg(test)]
252mod tests {
253 use super::*;
254
255 #[test]
256 fn negating_signed_min_values_does_not_panic() {
257 assert_eq!(-Dynamic::I8(i8::MIN), Dynamic::I8(i8::MIN));
258 assert_eq!(-Dynamic::I16(i16::MIN), Dynamic::I16(i16::MIN));
259 assert_eq!(-Dynamic::I32(i32::MIN), Dynamic::I32(i32::MIN));
260 assert_eq!(-Dynamic::I64(i64::MIN), Dynamic::I64(i64::MIN));
261 }
262
263 #[test]
264 fn not_is_logical_for_bool_and_bitwise_for_ints() {
265 assert_eq!(!Dynamic::Bool(false), Dynamic::Bool(true));
266 assert_eq!(!Dynamic::I32(0b1010), Dynamic::I32(!0b1010));
267 assert_eq!(!Dynamic::U32(0b1010), Dynamic::U32(!0b1010));
268 }
269}
270
271impl BitOr for Dynamic {
272 type Output = Self;
273 fn bitor(self, rhs: Self) -> Self::Output {
274 let ty = self.get_type() + rhs.get_type();
275 let left = ty.force(self).unwrap();
276 let right = ty.force(rhs).unwrap();
277 match (left, right) {
278 (Dynamic::I8(l), Dynamic::I8(r)) => Dynamic::I8(l | r),
279 (Dynamic::I16(l), Dynamic::I16(r)) => Dynamic::I16(l | r),
280 (Dynamic::I32(l), Dynamic::I32(r)) => Dynamic::I32(l | r),
281 (Dynamic::I64(l), Dynamic::I64(r)) => Dynamic::I64(l | r),
282 (Dynamic::U8(l), Dynamic::U8(r)) => Dynamic::U8(l | r),
283 (Dynamic::U16(l), Dynamic::U16(r)) => Dynamic::U16(l | r),
284 (Dynamic::U32(l), Dynamic::U32(r)) => Dynamic::U32(l | r),
285 (Dynamic::U64(l), Dynamic::U64(r)) => Dynamic::U64(l | r),
286 (_, _) => Dynamic::Null,
287 }
288 }
289}
290
291impl BitXor for Dynamic {
292 type Output = Self;
293 fn bitxor(self, rhs: Self) -> Self::Output {
294 let ty = self.get_type() + rhs.get_type();
295 let left = ty.force(self).unwrap();
296 let right = ty.force(rhs).unwrap();
297 match (left, right) {
298 (Dynamic::I8(l), Dynamic::I8(r)) => Dynamic::I8(l ^ r),
299 (Dynamic::I16(l), Dynamic::I16(r)) => Dynamic::I16(l ^ r),
300 (Dynamic::I32(l), Dynamic::I32(r)) => Dynamic::I32(l ^ r),
301 (Dynamic::I64(l), Dynamic::I64(r)) => Dynamic::I64(l ^ r),
302 (Dynamic::U8(l), Dynamic::U8(r)) => Dynamic::U8(l ^ r),
303 (Dynamic::U16(l), Dynamic::U16(r)) => Dynamic::U16(l ^ r),
304 (Dynamic::U32(l), Dynamic::U32(r)) => Dynamic::U32(l ^ r),
305 (Dynamic::U64(l), Dynamic::U64(r)) => Dynamic::U64(l ^ r),
306 (_, _) => Dynamic::Null,
307 }
308 }
309}