rune/runtime/vm/
ops.rs

1use core::ops::{
2    Add, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, Mul, Rem, Sub,
3};
4
5use crate::runtime::{InstArithmeticOp, InstBitwiseOp, InstShiftOp, Protocol, VmErrorKind};
6
7pub(super) struct ArithmeticOps {
8    pub(super) protocol: Protocol,
9    pub(super) error: fn() -> VmErrorKind,
10    pub(super) i64: fn(i64, i64) -> Option<i64>,
11    pub(super) u64: fn(u64, u64) -> Option<u64>,
12    pub(super) f64: fn(f64, f64) -> f64,
13}
14
15impl ArithmeticOps {
16    pub(super) fn from_op(op: InstArithmeticOp) -> &'static Self {
17        match op {
18            InstArithmeticOp::Add => &Self {
19                protocol: Protocol::ADD,
20                error: || VmErrorKind::Overflow,
21                i64: i64::checked_add,
22                u64: u64::checked_add,
23                f64: f64::add,
24            },
25            InstArithmeticOp::Sub => &Self {
26                protocol: Protocol::SUB,
27                error: || VmErrorKind::Underflow,
28                i64: i64::checked_sub,
29                u64: u64::checked_sub,
30                f64: f64::sub,
31            },
32            InstArithmeticOp::Mul => &Self {
33                protocol: Protocol::MUL,
34                error: || VmErrorKind::Overflow,
35                i64: i64::checked_mul,
36                u64: u64::checked_mul,
37                f64: f64::mul,
38            },
39            InstArithmeticOp::Div => &Self {
40                protocol: Protocol::DIV,
41                error: || VmErrorKind::DivideByZero,
42                i64: i64::checked_div,
43                u64: u64::checked_div,
44                f64: f64::div,
45            },
46            InstArithmeticOp::Rem => &Self {
47                protocol: Protocol::REM,
48                error: || VmErrorKind::DivideByZero,
49                i64: i64::checked_rem,
50                u64: u64::checked_rem,
51                f64: f64::rem,
52            },
53        }
54    }
55}
56
57pub(super) struct AssignArithmeticOps {
58    pub(super) protocol: Protocol,
59    pub(super) error: fn() -> VmErrorKind,
60    pub(super) i64: fn(i64, i64) -> Option<i64>,
61    pub(super) u64: fn(u64, u64) -> Option<u64>,
62    pub(super) f64: fn(f64, f64) -> f64,
63}
64
65impl AssignArithmeticOps {
66    pub(super) fn from_op(op: InstArithmeticOp) -> &'static AssignArithmeticOps {
67        match op {
68            InstArithmeticOp::Add => &Self {
69                protocol: Protocol::ADD_ASSIGN,
70                error: || VmErrorKind::Overflow,
71                i64: i64::checked_add,
72                u64: u64::checked_add,
73                f64: f64::add,
74            },
75            InstArithmeticOp::Sub => &Self {
76                protocol: Protocol::SUB_ASSIGN,
77                error: || VmErrorKind::Underflow,
78                i64: i64::checked_sub,
79                u64: u64::checked_sub,
80                f64: f64::sub,
81            },
82            InstArithmeticOp::Mul => &Self {
83                protocol: Protocol::MUL_ASSIGN,
84                error: || VmErrorKind::Overflow,
85                i64: i64::checked_mul,
86                u64: u64::checked_mul,
87                f64: f64::mul,
88            },
89            InstArithmeticOp::Div => &Self {
90                protocol: Protocol::DIV_ASSIGN,
91                error: || VmErrorKind::DivideByZero,
92                i64: i64::checked_div,
93                u64: u64::checked_div,
94                f64: f64::div,
95            },
96            InstArithmeticOp::Rem => &Self {
97                protocol: Protocol::REM_ASSIGN,
98                error: || VmErrorKind::DivideByZero,
99                i64: i64::checked_rem,
100                u64: u64::checked_rem,
101                f64: f64::rem,
102            },
103        }
104    }
105}
106
107pub(super) struct AssignBitwiseOps {
108    pub(super) protocol: Protocol,
109    pub(super) i64: fn(&mut i64, i64),
110    pub(super) u64: fn(&mut u64, u64),
111    pub(super) bool: fn(&mut bool, bool),
112}
113
114impl AssignBitwiseOps {
115    pub(super) fn from_ops(op: InstBitwiseOp) -> &'static Self {
116        match op {
117            InstBitwiseOp::BitAnd => &Self {
118                protocol: Protocol::BIT_AND_ASSIGN,
119                i64: i64::bitand_assign,
120                u64: u64::bitand_assign,
121                bool: bool::bitand_assign,
122            },
123            InstBitwiseOp::BitXor => &Self {
124                protocol: Protocol::BIT_XOR_ASSIGN,
125                i64: i64::bitxor_assign,
126                u64: u64::bitxor_assign,
127                bool: bool::bitxor_assign,
128            },
129            InstBitwiseOp::BitOr => &Self {
130                protocol: Protocol::BIT_OR_ASSIGN,
131                i64: i64::bitor_assign,
132                u64: u64::bitor_assign,
133                bool: bool::bitor_assign,
134            },
135        }
136    }
137}
138
139pub(super) struct BitwiseOps {
140    pub(super) protocol: Protocol,
141    pub(super) i64: fn(i64, i64) -> i64,
142    pub(super) u64: fn(u64, u64) -> u64,
143    pub(super) bool: fn(bool, bool) -> bool,
144}
145
146impl BitwiseOps {
147    pub(super) fn from_op(op: InstBitwiseOp) -> &'static BitwiseOps {
148        match op {
149            InstBitwiseOp::BitAnd => &BitwiseOps {
150                protocol: Protocol::BIT_AND,
151                i64: i64::bitand,
152                u64: u64::bitand,
153                bool: bool::bitand,
154            },
155            InstBitwiseOp::BitXor => &BitwiseOps {
156                protocol: Protocol::BIT_XOR,
157                i64: i64::bitxor,
158                u64: u64::bitxor,
159                bool: bool::bitxor,
160            },
161            InstBitwiseOp::BitOr => &BitwiseOps {
162                protocol: Protocol::BIT_OR,
163                i64: i64::bitor,
164                u64: u64::bitor,
165                bool: bool::bitor,
166            },
167        }
168    }
169}
170
171pub(super) struct AssignShiftOps {
172    pub(super) protocol: Protocol,
173    pub(super) error: fn() -> VmErrorKind,
174    pub(super) i64: fn(i64, u32) -> Option<i64>,
175    pub(super) u64: fn(u64, u32) -> Option<u64>,
176}
177
178impl AssignShiftOps {
179    pub(super) fn from_op(op: InstShiftOp) -> &'static AssignShiftOps {
180        match op {
181            InstShiftOp::Shl => &Self {
182                protocol: Protocol::SHL_ASSIGN,
183                error: || VmErrorKind::Overflow,
184                i64: i64::checked_shl,
185                u64: u64::checked_shl,
186            },
187            InstShiftOp::Shr => &Self {
188                protocol: Protocol::SHR_ASSIGN,
189                error: || VmErrorKind::Underflow,
190                i64: i64::checked_shr,
191                u64: u64::checked_shr,
192            },
193        }
194    }
195}
196
197pub(super) struct ShiftOps {
198    pub(super) protocol: Protocol,
199    pub(super) error: fn() -> VmErrorKind,
200    pub(super) i64: fn(i64, u32) -> Option<i64>,
201    pub(super) u64: fn(u64, u32) -> Option<u64>,
202}
203
204impl ShiftOps {
205    pub(super) fn from_op(op: InstShiftOp) -> &'static Self {
206        match op {
207            InstShiftOp::Shl => &Self {
208                protocol: Protocol::SHL,
209                error: || VmErrorKind::Overflow,
210                i64: i64::checked_shl,
211                u64: u64::checked_shl,
212            },
213            InstShiftOp::Shr => &Self {
214                protocol: Protocol::SHR,
215                error: || VmErrorKind::Underflow,
216                i64: i64::checked_shr,
217                u64: u64::checked_shr,
218            },
219        }
220    }
221}