1use super::Val;
2use crate::error;
3use crate::lang::Error;
4use std::convert::TryFrom;
5
6type Result<T> = std::result::Result<T, Error>;
7
8pub struct Operation {}
9
10impl Operation {
11 pub fn negate(val: Val) -> Result<Val> {
12 use Val::*;
13 match val {
14 Integer(n) => Ok(Integer(-n)),
15 Single(n) => Ok(Single(-n)),
16 Double(n) => Ok(Double(-n)),
17 String(_) | Return(_) | Next(_) => Err(error!(TypeMismatch)),
18 }
19 }
20
21 pub fn power(lhs: Val, rhs: Val) -> Result<Val> {
22 use Val::*;
23 match lhs {
24 Integer(l) => match rhs {
25 Integer(r) if r >= 0 => match l.checked_pow(r as u32) {
26 Some(i) => Ok(Integer(i)),
27 None => Err(error!(Overflow)),
28 },
29 Integer(r) => Ok(Single((l as f32).powi(r as i32))),
30 Single(r) => Ok(Single((l as f32).powf(r))),
31 Double(r) => Ok(Double((l as f64).powf(r))),
32 _ => Err(error!(TypeMismatch)),
33 },
34 Single(l) => match rhs {
35 Integer(r) => Ok(Single(l.powi(r as i32))),
36 Single(r) => Ok(Single(l.powf(r))),
37 Double(r) => Ok(Double((l as f64).powf(r))),
38 _ => Err(error!(TypeMismatch)),
39 },
40 Double(l) => match rhs {
41 Integer(r) => Ok(Double(l.powi(r as i32))),
42 Single(r) => Ok(Double(l.powf(r as f64))),
43 Double(r) => Ok(Double(l.powf(r))),
44 _ => Err(error!(TypeMismatch)),
45 },
46 String(_) | Return(_) | Next(_) => Err(error!(TypeMismatch)),
47 }
48 }
49
50 pub fn multiply(lhs: Val, rhs: Val) -> Result<Val> {
51 use Val::*;
52 match lhs {
53 Integer(l) => match rhs {
54 Integer(r) => match l.checked_mul(r) {
55 Some(i) => Ok(Integer(i)),
56 None => Err(error!(Overflow)),
57 },
58 Single(r) => Ok(Single(l as f32 * r)),
59 Double(r) => Ok(Double(l as f64 * r)),
60 _ => Err(error!(TypeMismatch)),
61 },
62 Single(l) => match rhs {
63 Integer(r) => Ok(Single(l * r as f32)),
64 Single(r) => Ok(Single(l * r)),
65 Double(r) => Ok(Double(l as f64 * r)),
66 _ => Err(error!(TypeMismatch)),
67 },
68 Double(l) => match rhs {
69 Integer(r) => Ok(Double(l * r as f64)),
70 Single(r) => Ok(Double(l * r as f64)),
71 Double(r) => Ok(Double(l * r)),
72 _ => Err(error!(TypeMismatch)),
73 },
74 String(_) | Return(_) | Next(_) => Err(error!(TypeMismatch)),
75 }
76 }
77
78 pub fn divide(lhs: Val, rhs: Val) -> Result<Val> {
79 use Val::*;
80 match lhs {
81 Integer(l) => match rhs {
82 Integer(r) => Ok(Single(l as f32 / r as f32)),
83 Single(r) => Ok(Single(l as f32 / r)),
84 Double(r) => Ok(Double(l as f64 / r)),
85 _ => Err(error!(TypeMismatch)),
86 },
87 Single(l) => match rhs {
88 Integer(r) => Ok(Single(l / r as f32)),
89 Single(r) => Ok(Single(l / r)),
90 Double(r) => Ok(Double(l as f64 / r)),
91 _ => Err(error!(TypeMismatch)),
92 },
93 Double(l) => match rhs {
94 Integer(r) => Ok(Double(l / r as f64)),
95 Single(r) => Ok(Double(l / r as f64)),
96 Double(r) => Ok(Double(l / r)),
97 _ => Err(error!(TypeMismatch)),
98 },
99 String(_) | Return(_) | Next(_) => Err(error!(TypeMismatch)),
100 }
101 }
102
103 pub fn divint(lhs: Val, rhs: Val) -> Result<Val> {
104 let lhs = i16::try_from(lhs)?;
105 let rhs = i16::try_from(rhs)?;
106 match lhs.checked_div(rhs) {
107 Some(n) => Ok(Val::Integer(n)),
108 None => Err(error!(DivisionByZero)),
109 }
110 }
111
112 pub fn remainder(lhs: Val, rhs: Val) -> Result<Val> {
113 let lhs = i16::try_from(lhs)?;
114 let rhs = i16::try_from(rhs)?;
115 match lhs.checked_rem(rhs) {
116 Some(n) => Ok(Val::Integer(n)),
117 None => Err(error!(DivisionByZero)),
118 }
119 }
120
121 pub fn sum(lhs: Val, rhs: Val) -> Result<Val> {
122 use Val::*;
123 match lhs {
124 String(l) => match rhs {
125 String(r) => Ok(String((l.to_string() + &r).into())),
126 _ => Err(error!(TypeMismatch)),
127 },
128 Integer(l) => match rhs {
129 Integer(r) => match l.checked_add(r) {
130 Some(i) => Ok(Integer(i)),
131 None => Err(error!(Overflow)),
132 },
133 Single(r) => Ok(Single(l as f32 + r)),
134 Double(r) => Ok(Double(l as f64 + r)),
135 _ => Err(error!(TypeMismatch)),
136 },
137 Single(l) => match rhs {
138 Integer(r) => Ok(Single(l + r as f32)),
139 Single(r) => Ok(Single(l + r)),
140 Double(r) => Ok(Double(l as f64 + r)),
141 _ => Err(error!(TypeMismatch)),
142 },
143 Double(l) => match rhs {
144 Integer(r) => Ok(Double(l + r as f64)),
145 Single(r) => Ok(Double(l + r as f64)),
146 Double(r) => Ok(Double(l + r)),
147 _ => Err(error!(TypeMismatch)),
148 },
149 Return(_) | Next(_) => Err(error!(TypeMismatch)),
150 }
151 }
152
153 pub fn subtract(lhs: Val, rhs: Val) -> Result<Val> {
154 use Val::*;
155 match lhs {
156 Integer(l) => match rhs {
157 Integer(r) => match l.checked_sub(r) {
158 Some(i) => Ok(Integer(i)),
159 None => Err(error!(Overflow)),
160 },
161 Single(r) => Ok(Single(l as f32 - r)),
162 Double(r) => Ok(Double(l as f64 - r)),
163 _ => Err(error!(TypeMismatch)),
164 },
165 Single(l) => match rhs {
166 Integer(r) => Ok(Single(l - r as f32)),
167 Single(r) => Ok(Single(l - r)),
168 Double(r) => Ok(Double(l as f64 - r)),
169 _ => Err(error!(TypeMismatch)),
170 },
171 Double(l) => match rhs {
172 Integer(r) => Ok(Double(l - r as f64)),
173 Single(r) => Ok(Double(l - r as f64)),
174 Double(r) => Ok(Double(l - r)),
175 _ => Err(error!(TypeMismatch)),
176 },
177 String(_) | Return(_) | Next(_) => Err(error!(TypeMismatch)),
178 }
179 }
180
181 pub fn equal(lhs: Val, rhs: Val) -> Result<Val> {
182 if Operation::equal_bool(lhs, rhs)? {
183 Ok(Val::Integer(-1))
184 } else {
185 Ok(Val::Integer(0))
186 }
187 }
188
189 pub fn not_equal(lhs: Val, rhs: Val) -> Result<Val> {
190 if Operation::equal_bool(lhs, rhs)? {
191 Ok(Val::Integer(0))
192 } else {
193 Ok(Val::Integer(-1))
194 }
195 }
196
197 fn equal_bool(lhs: Val, rhs: Val) -> Result<bool> {
198 use Val::*;
199 match lhs {
200 Integer(l) => match rhs {
201 Integer(r) => Ok(l == r),
202 Single(r) => Ok((l as f32 - r).abs() <= std::f32::EPSILON),
203 Double(r) => Ok((l as f64 - r).abs() <= std::f64::EPSILON),
204 _ => Err(error!(TypeMismatch)),
205 },
206 Single(l) => match rhs {
207 Integer(r) => Ok((l - r as f32).abs() <= std::f32::EPSILON),
208 Single(r) => Ok((l - r).abs() <= std::f32::EPSILON),
209 Double(r) => Ok((l as f64 - r).abs() <= std::f64::EPSILON),
210 _ => Err(error!(TypeMismatch)),
211 },
212 Double(l) => match rhs {
213 Integer(r) => Ok((l - r as f64).abs() <= std::f64::EPSILON),
214 Single(r) => Ok((l - r as f64).abs() <= std::f64::EPSILON),
215 Double(r) => Ok((l - r).abs() <= std::f64::EPSILON),
216 _ => Err(error!(TypeMismatch)),
217 },
218 String(l) => match rhs {
219 String(r) => Ok(l == r),
220 _ => Err(error!(TypeMismatch)),
221 },
222 Return(_) | Next(_) => Err(error!(TypeMismatch)),
223 }
224 }
225
226 pub fn greater(lhs: Val, rhs: Val) -> Result<Val> {
227 if Operation::less_bool(rhs, lhs)? {
228 Ok(Val::Integer(-1))
229 } else {
230 Ok(Val::Integer(0))
231 }
232 }
233
234 pub fn less(lhs: Val, rhs: Val) -> Result<Val> {
235 if Operation::less_bool(lhs, rhs)? {
236 Ok(Val::Integer(-1))
237 } else {
238 Ok(Val::Integer(0))
239 }
240 }
241
242 pub fn less_bool(lhs: Val, rhs: Val) -> Result<bool> {
243 use Val::*;
244 match lhs {
245 Integer(l) => match rhs {
246 Integer(r) => Ok(l < r),
247 Single(r) => Ok((l as f32) < r),
248 Double(r) => Ok((l as f64) < r),
249 _ => Err(error!(TypeMismatch)),
250 },
251 Single(l) => match rhs {
252 Integer(r) => Ok(l < r as f32),
253 Single(r) => Ok(l < r),
254 Double(r) => Ok((l as f64) < r),
255 _ => Err(error!(TypeMismatch)),
256 },
257 Double(l) => match rhs {
258 Integer(r) => Ok(l < r as f64),
259 Single(r) => Ok(l < r as f64),
260 Double(r) => Ok(l < r),
261 _ => Err(error!(TypeMismatch)),
262 },
263 String(l) => match rhs {
264 String(r) => Ok(l < r),
265 _ => Err(error!(TypeMismatch)),
266 },
267 Return(_) | Next(_) => Err(error!(TypeMismatch)),
268 }
269 }
270
271 pub fn greater_equal(lhs: Val, rhs: Val) -> Result<Val> {
272 if Operation::less_equal_bool(rhs, lhs)? {
273 Ok(Val::Integer(-1))
274 } else {
275 Ok(Val::Integer(0))
276 }
277 }
278
279 pub fn less_equal(lhs: Val, rhs: Val) -> Result<Val> {
280 if Operation::less_equal_bool(lhs, rhs)? {
281 Ok(Val::Integer(-1))
282 } else {
283 Ok(Val::Integer(0))
284 }
285 }
286
287 pub fn less_equal_bool(lhs: Val, rhs: Val) -> Result<bool> {
288 use Val::*;
289 match lhs {
290 Integer(l) => match rhs {
291 Integer(r) => Ok(l <= r),
292 Single(r) => Ok((l as f32) <= r),
293 Double(r) => Ok((l as f64) <= r),
294 _ => Err(error!(TypeMismatch)),
295 },
296 Single(l) => match rhs {
297 Integer(r) => Ok(l <= r as f32),
298 Single(r) => Ok(l <= r),
299 Double(r) => Ok((l as f64) <= r),
300 _ => Err(error!(TypeMismatch)),
301 },
302 Double(l) => match rhs {
303 Integer(r) => Ok(l <= r as f64),
304 Single(r) => Ok(l <= r as f64),
305 Double(r) => Ok(l <= r),
306 _ => Err(error!(TypeMismatch)),
307 },
308 String(l) => match rhs {
309 String(r) => Ok(l <= r),
310 _ => Err(error!(TypeMismatch)),
311 },
312 Return(_) | Next(_) => Err(error!(TypeMismatch)),
313 }
314 }
315
316 pub fn and(lhs: Val, rhs: Val) -> Result<Val> {
317 let lhs = i16::try_from(lhs)?;
318 let rhs = i16::try_from(rhs)?;
319 Ok(Val::Integer(lhs & rhs))
320 }
321
322 pub fn not(val: Val) -> Result<Val> {
323 Ok(Val::Integer(!i16::try_from(val)?))
324 }
325
326 pub fn or(lhs: Val, rhs: Val) -> Result<Val> {
327 let lhs = i16::try_from(lhs)?;
328 let rhs = i16::try_from(rhs)?;
329 Ok(Val::Integer(lhs | rhs))
330 }
331
332 pub fn xor(lhs: Val, rhs: Val) -> Result<Val> {
333 let lhs = i16::try_from(lhs)?;
334 let rhs = i16::try_from(rhs)?;
335 Ok(Val::Integer(lhs ^ rhs))
336 }
337
338 pub fn imp(lhs: Val, rhs: Val) -> Result<Val> {
339 let lhs = i16::try_from(lhs)?;
340 let rhs = i16::try_from(rhs)?;
341 Ok(Val::Integer(!lhs | rhs))
342 }
343
344 pub fn eqv(lhs: Val, rhs: Val) -> Result<Val> {
345 let lhs = i16::try_from(lhs)?;
346 let rhs = i16::try_from(rhs)?;
347 Ok(Val::Integer(!(lhs ^ rhs)))
348 }
349}