Skip to main content

vihaco_cpu/execute/values/
arithmetic.rs

1// SPDX-FileCopyrightText: 2026 The vihaco Authors
2// SPDX-License-Identifier: MIT
3
4use crate::{CPU, cpu};
5use vihaco_runtime::{Execute, PopFromStack, PushToStack};
6
7impl Execute<cpu::AddI32> for CPU {
8    type Message = PopFromStack<(i32, i32)>;
9    type Effect = PushToStack<(i32,)>;
10    type Error = eyre::Report;
11
12    fn execute(
13        &mut self,
14        _: &cpu::AddI32,
15        PopFromStack((lhs, rhs)): Self::Message,
16    ) -> eyre::Result<Self::Effect> {
17        Ok(PushToStack((lhs.wrapping_add(rhs),)))
18    }
19}
20
21impl Execute<cpu::AddF32> for CPU {
22    type Message = PopFromStack<(f32, f32)>;
23    type Effect = PushToStack<(f32,)>;
24    type Error = eyre::Report;
25
26    fn execute(
27        &mut self,
28        _: &cpu::AddF32,
29        PopFromStack((lhs, rhs)): Self::Message,
30    ) -> eyre::Result<Self::Effect> {
31        Ok(PushToStack((lhs + rhs,)))
32    }
33}
34
35impl Execute<cpu::AddI64> for CPU {
36    type Message = PopFromStack<(i64, i64)>;
37    type Effect = PushToStack<(i64,)>;
38    type Error = eyre::Report;
39
40    fn execute(
41        &mut self,
42        _: &cpu::AddI64,
43        PopFromStack((lhs, rhs)): Self::Message,
44    ) -> eyre::Result<Self::Effect> {
45        Ok(PushToStack((lhs.wrapping_add(rhs),)))
46    }
47}
48
49impl Execute<cpu::AddU32> for CPU {
50    type Message = PopFromStack<(u32, u32)>;
51    type Effect = PushToStack<(u32,)>;
52    type Error = eyre::Report;
53
54    fn execute(
55        &mut self,
56        _: &cpu::AddU32,
57        PopFromStack((lhs, rhs)): Self::Message,
58    ) -> eyre::Result<Self::Effect> {
59        Ok(PushToStack((lhs.wrapping_add(rhs),)))
60    }
61}
62
63impl Execute<cpu::AddU64> for CPU {
64    type Message = PopFromStack<(u64, u64)>;
65    type Effect = PushToStack<(u64,)>;
66    type Error = eyre::Report;
67
68    fn execute(
69        &mut self,
70        _: &cpu::AddU64,
71        PopFromStack((lhs, rhs)): Self::Message,
72    ) -> eyre::Result<Self::Effect> {
73        Ok(PushToStack((lhs.wrapping_add(rhs),)))
74    }
75}
76
77impl Execute<cpu::AddF64> for CPU {
78    type Message = PopFromStack<(f64, f64)>;
79    type Effect = PushToStack<(f64,)>;
80    type Error = eyre::Report;
81
82    fn execute(
83        &mut self,
84        _: &cpu::AddF64,
85        PopFromStack((lhs, rhs)): Self::Message,
86    ) -> eyre::Result<Self::Effect> {
87        Ok(PushToStack((lhs + rhs,)))
88    }
89}
90
91impl Execute<cpu::SubI32> for CPU {
92    type Message = PopFromStack<(i32, i32)>;
93    type Effect = PushToStack<(i32,)>;
94    type Error = eyre::Report;
95
96    fn execute(
97        &mut self,
98        _: &cpu::SubI32,
99        PopFromStack((lhs, rhs)): Self::Message,
100    ) -> eyre::Result<Self::Effect> {
101        Ok(PushToStack((lhs.wrapping_sub(rhs),)))
102    }
103}
104
105impl Execute<cpu::SubI64> for CPU {
106    type Message = PopFromStack<(i64, i64)>;
107    type Effect = PushToStack<(i64,)>;
108    type Error = eyre::Report;
109
110    fn execute(
111        &mut self,
112        _: &cpu::SubI64,
113        PopFromStack((lhs, rhs)): Self::Message,
114    ) -> eyre::Result<Self::Effect> {
115        Ok(PushToStack((lhs.wrapping_sub(rhs),)))
116    }
117}
118
119impl Execute<cpu::SubU32> for CPU {
120    type Message = PopFromStack<(u32, u32)>;
121    type Effect = PushToStack<(u32,)>;
122    type Error = eyre::Report;
123
124    fn execute(
125        &mut self,
126        _: &cpu::SubU32,
127        PopFromStack((lhs, rhs)): Self::Message,
128    ) -> eyre::Result<Self::Effect> {
129        Ok(PushToStack((lhs.wrapping_sub(rhs),)))
130    }
131}
132
133impl Execute<cpu::SubU64> for CPU {
134    type Message = PopFromStack<(u64, u64)>;
135    type Effect = PushToStack<(u64,)>;
136    type Error = eyre::Report;
137
138    fn execute(
139        &mut self,
140        _: &cpu::SubU64,
141        PopFromStack((lhs, rhs)): Self::Message,
142    ) -> eyre::Result<Self::Effect> {
143        Ok(PushToStack((lhs.wrapping_sub(rhs),)))
144    }
145}
146
147impl Execute<cpu::SubF32> for CPU {
148    type Message = PopFromStack<(f32, f32)>;
149    type Effect = PushToStack<(f32,)>;
150    type Error = eyre::Report;
151
152    fn execute(
153        &mut self,
154        _: &cpu::SubF32,
155        PopFromStack((lhs, rhs)): Self::Message,
156    ) -> eyre::Result<Self::Effect> {
157        Ok(PushToStack((lhs - rhs,)))
158    }
159}
160
161impl Execute<cpu::SubF64> for CPU {
162    type Message = PopFromStack<(f64, f64)>;
163    type Effect = PushToStack<(f64,)>;
164    type Error = eyre::Report;
165
166    fn execute(
167        &mut self,
168        _: &cpu::SubF64,
169        PopFromStack((lhs, rhs)): Self::Message,
170    ) -> eyre::Result<Self::Effect> {
171        Ok(PushToStack((lhs - rhs,)))
172    }
173}
174
175impl Execute<cpu::MulI32> for CPU {
176    type Message = PopFromStack<(i32, i32)>;
177    type Effect = PushToStack<(i32,)>;
178    type Error = eyre::Report;
179
180    fn execute(
181        &mut self,
182        _: &cpu::MulI32,
183        PopFromStack((lhs, rhs)): Self::Message,
184    ) -> eyre::Result<Self::Effect> {
185        Ok(PushToStack((lhs.wrapping_mul(rhs),)))
186    }
187}
188
189impl Execute<cpu::MulI64> for CPU {
190    type Message = PopFromStack<(i64, i64)>;
191    type Effect = PushToStack<(i64,)>;
192    type Error = eyre::Report;
193
194    fn execute(
195        &mut self,
196        _: &cpu::MulI64,
197        PopFromStack((lhs, rhs)): Self::Message,
198    ) -> eyre::Result<Self::Effect> {
199        Ok(PushToStack((lhs.wrapping_mul(rhs),)))
200    }
201}
202
203impl Execute<cpu::MulU32> for CPU {
204    type Message = PopFromStack<(u32, u32)>;
205    type Effect = PushToStack<(u32,)>;
206    type Error = eyre::Report;
207
208    fn execute(
209        &mut self,
210        _: &cpu::MulU32,
211        PopFromStack((lhs, rhs)): Self::Message,
212    ) -> eyre::Result<Self::Effect> {
213        Ok(PushToStack((lhs.wrapping_mul(rhs),)))
214    }
215}
216
217impl Execute<cpu::MulU64> for CPU {
218    type Message = PopFromStack<(u64, u64)>;
219    type Effect = PushToStack<(u64,)>;
220    type Error = eyre::Report;
221
222    fn execute(
223        &mut self,
224        _: &cpu::MulU64,
225        PopFromStack((lhs, rhs)): Self::Message,
226    ) -> eyre::Result<Self::Effect> {
227        Ok(PushToStack((lhs.wrapping_mul(rhs),)))
228    }
229}
230
231impl Execute<cpu::MulF32> for CPU {
232    type Message = PopFromStack<(f32, f32)>;
233    type Effect = PushToStack<(f32,)>;
234    type Error = eyre::Report;
235
236    fn execute(
237        &mut self,
238        _: &cpu::MulF32,
239        PopFromStack((lhs, rhs)): Self::Message,
240    ) -> eyre::Result<Self::Effect> {
241        Ok(PushToStack((lhs * rhs,)))
242    }
243}
244
245impl Execute<cpu::MulF64> for CPU {
246    type Message = PopFromStack<(f64, f64)>;
247    type Effect = PushToStack<(f64,)>;
248    type Error = eyre::Report;
249
250    fn execute(
251        &mut self,
252        _: &cpu::MulF64,
253        PopFromStack((lhs, rhs)): Self::Message,
254    ) -> eyre::Result<Self::Effect> {
255        Ok(PushToStack((lhs * rhs,)))
256    }
257}
258
259impl Execute<cpu::DivI32> for CPU {
260    type Message = PopFromStack<(i32, i32)>;
261    type Effect = PushToStack<(i32,)>;
262    type Error = eyre::Report;
263
264    fn execute(
265        &mut self,
266        _: &cpu::DivI32,
267        PopFromStack((lhs, rhs)): Self::Message,
268    ) -> eyre::Result<Self::Effect> {
269        let value = lhs
270            .checked_div(rhs)
271            .ok_or_else(|| eyre::eyre!("integer division error"))?;
272        Ok(PushToStack((value,)))
273    }
274}
275
276impl Execute<cpu::DivI64> for CPU {
277    type Message = PopFromStack<(i64, i64)>;
278    type Effect = PushToStack<(i64,)>;
279    type Error = eyre::Report;
280
281    fn execute(
282        &mut self,
283        _: &cpu::DivI64,
284        PopFromStack((lhs, rhs)): Self::Message,
285    ) -> eyre::Result<Self::Effect> {
286        let value = lhs
287            .checked_div(rhs)
288            .ok_or_else(|| eyre::eyre!("integer division error"))?;
289        Ok(PushToStack((value,)))
290    }
291}
292
293impl Execute<cpu::DivU32> for CPU {
294    type Message = PopFromStack<(u32, u32)>;
295    type Effect = PushToStack<(u32,)>;
296    type Error = eyre::Report;
297
298    fn execute(
299        &mut self,
300        _: &cpu::DivU32,
301        PopFromStack((lhs, rhs)): Self::Message,
302    ) -> eyre::Result<Self::Effect> {
303        let value = lhs
304            .checked_div(rhs)
305            .ok_or_else(|| eyre::eyre!("integer division error"))?;
306        Ok(PushToStack((value,)))
307    }
308}
309
310impl Execute<cpu::DivU64> for CPU {
311    type Message = PopFromStack<(u64, u64)>;
312    type Effect = PushToStack<(u64,)>;
313    type Error = eyre::Report;
314
315    fn execute(
316        &mut self,
317        _: &cpu::DivU64,
318        PopFromStack((lhs, rhs)): Self::Message,
319    ) -> eyre::Result<Self::Effect> {
320        let value = lhs
321            .checked_div(rhs)
322            .ok_or_else(|| eyre::eyre!("integer division error"))?;
323        Ok(PushToStack((value,)))
324    }
325}
326
327impl Execute<cpu::DivF32> for CPU {
328    type Message = PopFromStack<(f32, f32)>;
329    type Effect = PushToStack<(f32,)>;
330    type Error = eyre::Report;
331
332    fn execute(
333        &mut self,
334        _: &cpu::DivF32,
335        PopFromStack((lhs, rhs)): Self::Message,
336    ) -> eyre::Result<Self::Effect> {
337        Ok(PushToStack((lhs / rhs,)))
338    }
339}
340
341impl Execute<cpu::DivF64> for CPU {
342    type Message = PopFromStack<(f64, f64)>;
343    type Effect = PushToStack<(f64,)>;
344    type Error = eyre::Report;
345
346    fn execute(
347        &mut self,
348        _: &cpu::DivF64,
349        PopFromStack((lhs, rhs)): Self::Message,
350    ) -> eyre::Result<Self::Effect> {
351        Ok(PushToStack((lhs / rhs,)))
352    }
353}
354
355impl Execute<cpu::RemI32> for CPU {
356    type Message = PopFromStack<(i32, i32)>;
357    type Effect = PushToStack<(i32,)>;
358    type Error = eyre::Report;
359
360    fn execute(
361        &mut self,
362        _: &cpu::RemI32,
363        PopFromStack((lhs, rhs)): Self::Message,
364    ) -> eyre::Result<Self::Effect> {
365        let value = lhs
366            .checked_rem(rhs)
367            .ok_or_else(|| eyre::eyre!("integer remainder error"))?;
368        Ok(PushToStack((value,)))
369    }
370}
371
372impl Execute<cpu::RemI64> for CPU {
373    type Message = PopFromStack<(i64, i64)>;
374    type Effect = PushToStack<(i64,)>;
375    type Error = eyre::Report;
376
377    fn execute(
378        &mut self,
379        _: &cpu::RemI64,
380        PopFromStack((lhs, rhs)): Self::Message,
381    ) -> eyre::Result<Self::Effect> {
382        let value = lhs
383            .checked_rem(rhs)
384            .ok_or_else(|| eyre::eyre!("integer remainder error"))?;
385        Ok(PushToStack((value,)))
386    }
387}
388
389impl Execute<cpu::RemU32> for CPU {
390    type Message = PopFromStack<(u32, u32)>;
391    type Effect = PushToStack<(u32,)>;
392    type Error = eyre::Report;
393
394    fn execute(
395        &mut self,
396        _: &cpu::RemU32,
397        PopFromStack((lhs, rhs)): Self::Message,
398    ) -> eyre::Result<Self::Effect> {
399        let value = lhs
400            .checked_rem(rhs)
401            .ok_or_else(|| eyre::eyre!("integer remainder error"))?;
402        Ok(PushToStack((value,)))
403    }
404}
405
406impl Execute<cpu::RemU64> for CPU {
407    type Message = PopFromStack<(u64, u64)>;
408    type Effect = PushToStack<(u64,)>;
409    type Error = eyre::Report;
410
411    fn execute(
412        &mut self,
413        _: &cpu::RemU64,
414        PopFromStack((lhs, rhs)): Self::Message,
415    ) -> eyre::Result<Self::Effect> {
416        let value = lhs
417            .checked_rem(rhs)
418            .ok_or_else(|| eyre::eyre!("integer remainder error"))?;
419        Ok(PushToStack((value,)))
420    }
421}
422
423impl Execute<cpu::RemF32> for CPU {
424    type Message = PopFromStack<(f32, f32)>;
425    type Effect = PushToStack<(f32,)>;
426    type Error = eyre::Report;
427
428    fn execute(
429        &mut self,
430        _: &cpu::RemF32,
431        PopFromStack((lhs, rhs)): Self::Message,
432    ) -> eyre::Result<Self::Effect> {
433        Ok(PushToStack((lhs % rhs,)))
434    }
435}
436
437impl Execute<cpu::RemF64> for CPU {
438    type Message = PopFromStack<(f64, f64)>;
439    type Effect = PushToStack<(f64,)>;
440    type Error = eyre::Report;
441
442    fn execute(
443        &mut self,
444        _: &cpu::RemF64,
445        PopFromStack((lhs, rhs)): Self::Message,
446    ) -> eyre::Result<Self::Effect> {
447        Ok(PushToStack((lhs % rhs,)))
448    }
449}