Skip to main content

dynamic/
ops.rs

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}