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
40fn int_fault(reason: &'static str) -> Dynamic {
41 crate::set_fault(reason);
42 Dynamic::Null
43}
44
45fn checked_i64(left: &Dynamic, right: &Dynamic, reason: &'static str) -> Option<(i64, i64)> {
46 match (left.as_int(), right.as_int()) {
47 (Some(left), Some(right)) => Some((left, right)),
48 _ => {
49 crate::set_fault(reason);
50 None
51 }
52 }
53}
54
55impl Add for Dynamic {
56 type Output = Self;
57 fn add(self, rhs: Self) -> Self::Output {
58 if self.is_list() {
59 self.clone().append(rhs);
60 return self;
61 } else if rhs.is_list() {
62 rhs.clone().append(self);
63 return rhs;
64 }
65 match (self, rhs) {
66 (Self::StringBuf(mut left), Self::StringBuf(right)) => {
67 left.push_str(&right);
68 return Self::StringBuf(left);
69 }
70 (Self::StringBuf(mut left), Self::String(right)) => {
71 left.push_str(right.as_str());
72 return Self::StringBuf(left);
73 }
74 (Self::StringBuf(mut left), right) => {
75 left.push_str(&right.to_string());
76 return Self::StringBuf(left);
77 }
78 (Self::String(left), Self::StringBuf(right)) => {
79 let mut out = String::with_capacity(left.len() + right.len());
80 out.push_str(left.as_str());
81 out.push_str(&right);
82 return Self::StringBuf(out);
83 }
84 (Self::String(left), Self::String(right)) => {
85 let mut out = String::with_capacity(left.len() + right.len());
86 out.push_str(left.as_str());
87 out.push_str(right.as_str());
88 return Self::StringBuf(out);
89 }
90 (Self::String(left), right) => {
91 let right = right.to_string();
92 let mut out = String::with_capacity(left.len() + right.len());
93 out.push_str(left.as_str());
94 out.push_str(&right);
95 return Self::StringBuf(out);
96 }
97 (left, Self::StringBuf(right)) => {
98 let left = left.to_string();
99 let mut out = String::with_capacity(left.len() + right.len());
100 out.push_str(&left);
101 out.push_str(&right);
102 return Self::StringBuf(out);
103 }
104 (left, Self::String(right)) => {
105 let left = left.to_string();
106 let mut out = String::with_capacity(left.len() + right.len());
107 out.push_str(&left);
108 out.push_str(right.as_str());
109 return Self::StringBuf(out);
110 }
111 (left, right) => {
112 if left.is_f64() || right.is_f64() {
113 return Dynamic::F64(left.as_float().unwrap_or(0.0) + right.as_float().unwrap_or(0.0));
114 } else if left.is_f32() || right.is_f32() {
115 return Dynamic::F32(left.as_float().unwrap_or(0.0) as f32 + right.as_float().unwrap_or(0.0) as f32);
116 }
117 if left.is_int() || right.is_int() {
118 let Some((left, right)) = checked_i64(&left, &right, "整数加法类型或范围错误") else {
119 return Dynamic::Null;
120 };
121 return left.checked_add(right).map(Self::I64).unwrap_or_else(|| int_fault("整数加法溢出"));
122 }
123 if left.is_uint() || right.is_uint() {
124 let (Some(left), Some(right)) = (left.as_uint(), right.as_uint()) else {
125 return int_fault("无符号整数加法类型错误");
126 };
127 return left.checked_add(right).map(Self::U64).unwrap_or_else(|| int_fault("无符号整数加法溢出"));
128 }
129 if left.is_map() && right.is_map() {
130 left.append(right);
131 }
132 left
133 }
134 }
135 }
136}
137
138impl Mul for Dynamic {
139 type Output = Self;
140 fn mul(self, rhs: Self) -> Self::Output {
141 if self.is_f64() || rhs.is_f64() {
142 return Dynamic::F64(self.as_float().unwrap_or(0.0) * rhs.as_float().unwrap_or(0.0));
143 } else if self.is_f32() || rhs.is_f32() {
144 return Dynamic::F32(self.as_float().unwrap_or(0.0) as f32 * rhs.as_float().unwrap_or(0.0) as f32);
145 }
146 if self.is_int() || rhs.is_int() {
147 let Some((left, right)) = checked_i64(&self, &rhs, "整数乘法类型或范围错误") else {
148 return Dynamic::Null;
149 };
150 return left.checked_mul(right).map(Self::I64).unwrap_or_else(|| int_fault("整数乘法溢出"));
151 }
152 if self.is_uint() || rhs.is_uint() {
153 let (Some(left), Some(right)) = (self.as_uint(), rhs.as_uint()) else {
154 return int_fault("无符号整数乘法类型错误");
155 };
156 return left.checked_mul(right).map(Self::U64).unwrap_or_else(|| int_fault("无符号整数乘法溢出"));
157 }
158 self
159 }
160}
161
162impl Sub for Dynamic {
163 type Output = Self;
164 fn sub(self, rhs: Self) -> Self::Output {
165 if self.is_f64() || rhs.is_f64() {
166 return Dynamic::F64(self.as_float().unwrap() - rhs.as_float().unwrap());
167 } else if self.is_f32() || rhs.is_f32() {
168 return Dynamic::F32(self.as_float().unwrap() as f32 - rhs.as_float().unwrap() as f32);
169 }
170 if self.is_int() || rhs.is_int() || self.is_uint() || rhs.is_uint() {
171 let Some((left, right)) = checked_i64(&self, &rhs, "整数减法类型或范围错误") else {
172 return Dynamic::Null;
173 };
174 return left.checked_sub(right).map(Self::I64).unwrap_or_else(|| int_fault("整数减法溢出"));
175 }
176 if self.is_list() && rhs.is_list() {
177 if self.len() == rhs.len() {}
178 }
179 self
180 }
181}
182
183impl Div for Dynamic {
184 type Output = Self;
185 fn div(self, rhs: Self) -> Self::Output {
186 if self.is_f64() || rhs.is_f64() {
187 return Dynamic::F64(self.as_float().unwrap() / rhs.as_float().unwrap());
188 } else if self.is_f32() || rhs.is_f32() {
189 return Dynamic::F32(self.as_float().unwrap() as f32 / rhs.as_float().unwrap() as f32);
190 }
191 if self.is_int() || rhs.is_int() || self.is_uint() || rhs.is_uint() {
192 let Some((left, right)) = checked_i64(&self, &rhs, "整数除法类型或范围错误") else {
193 return Dynamic::Null;
194 };
195 return match left.checked_div(right) {
196 Some(value) => Self::I64(value),
197 None => {
198 crate::set_fault("整数除零");
199 Self::Null
200 }
201 };
202 }
203 self
204 }
205}
206
207impl Rem for Dynamic {
208 type Output = Self;
209 fn rem(self, rhs: Self) -> Self::Output {
210 if self.is_int() || rhs.is_int() || self.is_uint() || rhs.is_uint() {
211 let Some((left, right)) = checked_i64(&self, &rhs, "整数取余类型或范围错误") else {
212 return Dynamic::Null;
213 };
214 return match left.checked_rem(right) {
215 Some(value) => Self::I64(value),
216 None => {
217 crate::set_fault("整数取余除零");
218 Self::Null
219 }
220 };
221 }
222 self
223 }
224}
225
226use std::ops::{Shl, Shr};
227
228impl Shl for Dynamic {
229 type Output = Self;
230 fn shl(self, rhs: Self) -> Self::Output {
231 use Dynamic::*;
232 let Some(shift) = rhs.as_int().and_then(|value| u32::try_from(value).ok()).or_else(|| rhs.as_uint().and_then(|value| u32::try_from(value).ok())) else {
233 return int_fault("位移数量类型或范围错误");
234 };
235 match self {
236 I8(i) => i.checked_shl(shift).map(I8).unwrap_or_else(|| int_fault("左移溢出")),
237 I16(i) => i.checked_shl(shift).map(I16).unwrap_or_else(|| int_fault("左移溢出")),
238 I32(i) => i.checked_shl(shift).map(I32).unwrap_or_else(|| int_fault("左移溢出")),
239 I64(i) => i.checked_shl(shift).map(I64).unwrap_or_else(|| int_fault("左移溢出")),
240 U8(i) => i.checked_shl(shift).map(U8).unwrap_or_else(|| int_fault("左移溢出")),
241 U16(i) => i.checked_shl(shift).map(U16).unwrap_or_else(|| int_fault("左移溢出")),
242 U32(i) => i.checked_shl(shift).map(U32).unwrap_or_else(|| int_fault("左移溢出")),
243 U64(i) => i.checked_shl(shift).map(U64).unwrap_or_else(|| int_fault("左移溢出")),
244 _ => Dynamic::I64(0),
245 }
246 }
247}
248
249impl Shr for Dynamic {
250 type Output = Self;
251 fn shr(self, rhs: Self) -> Self::Output {
252 use Dynamic::*;
253 let Some(shift) = rhs.as_int().and_then(|value| u32::try_from(value).ok()).or_else(|| rhs.as_uint().and_then(|value| u32::try_from(value).ok())) else {
254 return int_fault("位移数量类型或范围错误");
255 };
256 match self {
257 I8(i) => i.checked_shr(shift).map(I8).unwrap_or_else(|| int_fault("右移溢出")),
258 I16(i) => i.checked_shr(shift).map(I16).unwrap_or_else(|| int_fault("右移溢出")),
259 I32(i) => i.checked_shr(shift).map(I32).unwrap_or_else(|| int_fault("右移溢出")),
260 I64(i) => i.checked_shr(shift).map(I64).unwrap_or_else(|| int_fault("右移溢出")),
261 U8(i) => i.checked_shr(shift).map(U8).unwrap_or_else(|| int_fault("右移溢出")),
262 U16(i) => i.checked_shr(shift).map(U16).unwrap_or_else(|| int_fault("右移溢出")),
263 U32(i) => i.checked_shr(shift).map(U32).unwrap_or_else(|| int_fault("右移溢出")),
264 U64(i) => i.checked_shr(shift).map(U64).unwrap_or_else(|| int_fault("右移溢出")),
265 _ => Dynamic::I64(0),
266 }
267 }
268}
269
270use std::ops::{BitAnd, BitOr, BitXor};
271impl BitAnd for Dynamic {
272 type Output = Self;
273 fn bitand(self, rhs: Self) -> Self::Output {
274 let ty = self.get_type() + rhs.get_type();
275 let Ok(left) = ty.force(self) else {
276 return int_fault("按位与左操作数类型错误");
277 };
278 let Ok(right) = ty.force(rhs) else {
279 return int_fault("按位与右操作数类型错误");
280 };
281 match (left, right) {
282 (Dynamic::I8(l), Dynamic::I8(r)) => Dynamic::I8(l & r),
283 (Dynamic::I16(l), Dynamic::I16(r)) => Dynamic::I16(l & r),
284 (Dynamic::I32(l), Dynamic::I32(r)) => Dynamic::I32(l & r),
285 (Dynamic::I64(l), Dynamic::I64(r)) => Dynamic::I64(l & r),
286 (Dynamic::U8(l), Dynamic::U8(r)) => Dynamic::U8(l & r),
287 (Dynamic::U16(l), Dynamic::U16(r)) => Dynamic::U16(l & r),
288 (Dynamic::U32(l), Dynamic::U32(r)) => Dynamic::U32(l & r),
289 (Dynamic::U64(l), Dynamic::U64(r)) => Dynamic::U64(l & r),
290 (_, _) => Dynamic::Null,
291 }
292 }
293}
294
295#[cfg(test)]
296mod tests {
297 use super::*;
298
299 #[test]
300 fn negating_signed_min_values_does_not_panic() {
301 assert_eq!(-Dynamic::I8(i8::MIN), Dynamic::I8(i8::MIN));
302 assert_eq!(-Dynamic::I16(i16::MIN), Dynamic::I16(i16::MIN));
303 assert_eq!(-Dynamic::I32(i32::MIN), Dynamic::I32(i32::MIN));
304 assert_eq!(-Dynamic::I64(i64::MIN), Dynamic::I64(i64::MIN));
305 }
306
307 #[test]
308 fn not_is_logical_for_bool_and_bitwise_for_ints() {
309 assert_eq!(!Dynamic::Bool(false), Dynamic::Bool(true));
310 assert_eq!(!Dynamic::I32(0b1010), Dynamic::I32(!0b1010));
311 assert_eq!(!Dynamic::U32(0b1010), Dynamic::U32(!0b1010));
312 }
313}
314
315impl BitOr for Dynamic {
316 type Output = Self;
317 fn bitor(self, rhs: Self) -> Self::Output {
318 let ty = self.get_type() + rhs.get_type();
319 let Ok(left) = ty.force(self) else {
320 return int_fault("按位或左操作数类型错误");
321 };
322 let Ok(right) = ty.force(rhs) else {
323 return int_fault("按位或右操作数类型错误");
324 };
325 match (left, right) {
326 (Dynamic::I8(l), Dynamic::I8(r)) => Dynamic::I8(l | r),
327 (Dynamic::I16(l), Dynamic::I16(r)) => Dynamic::I16(l | r),
328 (Dynamic::I32(l), Dynamic::I32(r)) => Dynamic::I32(l | r),
329 (Dynamic::I64(l), Dynamic::I64(r)) => Dynamic::I64(l | r),
330 (Dynamic::U8(l), Dynamic::U8(r)) => Dynamic::U8(l | r),
331 (Dynamic::U16(l), Dynamic::U16(r)) => Dynamic::U16(l | r),
332 (Dynamic::U32(l), Dynamic::U32(r)) => Dynamic::U32(l | r),
333 (Dynamic::U64(l), Dynamic::U64(r)) => Dynamic::U64(l | r),
334 (_, _) => Dynamic::Null,
335 }
336 }
337}
338
339impl BitXor for Dynamic {
340 type Output = Self;
341 fn bitxor(self, rhs: Self) -> Self::Output {
342 let ty = self.get_type() + rhs.get_type();
343 let Ok(left) = ty.force(self) else {
344 return int_fault("按位异或左操作数类型错误");
345 };
346 let Ok(right) = ty.force(rhs) else {
347 return int_fault("按位异或右操作数类型错误");
348 };
349 match (left, right) {
350 (Dynamic::I8(l), Dynamic::I8(r)) => Dynamic::I8(l ^ r),
351 (Dynamic::I16(l), Dynamic::I16(r)) => Dynamic::I16(l ^ r),
352 (Dynamic::I32(l), Dynamic::I32(r)) => Dynamic::I32(l ^ r),
353 (Dynamic::I64(l), Dynamic::I64(r)) => Dynamic::I64(l ^ r),
354 (Dynamic::U8(l), Dynamic::U8(r)) => Dynamic::U8(l ^ r),
355 (Dynamic::U16(l), Dynamic::U16(r)) => Dynamic::U16(l ^ r),
356 (Dynamic::U32(l), Dynamic::U32(r)) => Dynamic::U32(l ^ r),
357 (Dynamic::U64(l), Dynamic::U64(r)) => Dynamic::U64(l ^ r),
358 (_, _) => Dynamic::Null,
359 }
360 }
361}