rush_interpreter_vm/
value.rs

1use std::fmt::{self, Display, Formatter};
2
3use crate::{
4    instruction::Type,
5    vm::{RuntimeError, RuntimeErrorKind},
6};
7
8#[derive(Clone, Copy, Debug, PartialEq)]
9pub enum Value {
10    Int(i64),
11    Bool(bool),
12    Char(u8),
13    Float(f64),
14    Ptr(Pointer),
15}
16
17#[derive(Clone, Copy, Debug, PartialEq, Eq)]
18pub enum Pointer {
19    Rel(isize),
20    Abs(usize),
21}
22
23impl Display for Pointer {
24    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
25        match self {
26            Pointer::Rel(offset) => write!(f, "*rel[{offset}]"),
27            Pointer::Abs(addr) => write!(f, "*abs[{addr}]"),
28        }
29    }
30}
31
32impl Value {
33    pub(crate) fn unwrap_int(self) -> i64 {
34        match self {
35            Value::Int(value) => value,
36            _ => panic!("called `Value::unwrap_int` on a non-int value"),
37        }
38    }
39
40    pub(crate) fn unwrap_bool(self) -> bool {
41        match self {
42            Value::Bool(value) => value,
43            _ => panic!("called `Value::unwrap_bool` on a non-bool value"),
44        }
45    }
46
47    pub(crate) fn unwrap_ptr(self) -> Pointer {
48        match self {
49            Value::Ptr(ptr) => ptr,
50            _ => panic!("called `Value::unwrap_ptr` on a non-ptr value"),
51        }
52    }
53
54    pub(crate) fn neg(&self) -> Value {
55        match self {
56            Value::Int(val) => Value::Int(-val),
57            Value::Float(val) => Value::Float(-val),
58            _ => unreachable!("never called this way"),
59        }
60    }
61
62    pub(crate) fn not(&self) -> Value {
63        match self {
64            Value::Int(val) => Value::Int(!val),
65            Value::Bool(value) => Value::Bool(!value),
66            _ => unreachable!("never called this way"),
67        }
68    }
69
70    pub(crate) fn add(&self, rhs: Value) -> Value {
71        match (self, rhs) {
72            (Value::Int(lhs), Value::Int(rhs)) => Value::Int(lhs.wrapping_add(rhs)),
73            (Value::Char(lhs), Value::Char(rhs)) => Value::Char(lhs.wrapping_add(rhs) & 0x7f),
74            (Value::Float(lhs), Value::Float(rhs)) => Value::Float(lhs + rhs),
75            _ => unreachable!("other types do not support this operation: {self} + {rhs}"),
76        }
77    }
78
79    pub(crate) fn sub(&self, rhs: Value) -> Value {
80        match (self, rhs) {
81            (Value::Int(lhs), Value::Int(rhs)) => Value::Int(lhs.wrapping_sub(rhs)),
82            (Value::Char(lhs), Value::Char(rhs)) => Value::Char(lhs.wrapping_sub(rhs) & 0x7f),
83            (Value::Float(lhs), Value::Float(rhs)) => Value::Float(lhs - rhs),
84            _ => unreachable!("other types do not support this operation: {self} - {rhs}"),
85        }
86    }
87
88    pub(crate) fn mul(&self, rhs: Value) -> Value {
89        match (self, rhs) {
90            (Value::Int(lhs), Value::Int(rhs)) => Value::Int(lhs.wrapping_mul(rhs)),
91            (Value::Float(lhs), Value::Float(rhs)) => Value::Float(lhs * rhs),
92            _ => unreachable!("other types do not support this operation: {self} * {rhs}"),
93        }
94    }
95
96    pub(crate) fn pow(&self, rhs: Value) -> Value {
97        Value::Int(self.unwrap_int().wrapping_pow(rhs.unwrap_int() as u32))
98    }
99
100    pub(crate) fn div(&self, rhs: Value) -> Result<Value, RuntimeError> {
101        match (self, rhs) {
102            (_, Value::Int(0)) => Err(RuntimeError::new(
103                RuntimeErrorKind::Arithmetic,
104                format!("{self} / {rhs} is illegal"),
105            )),
106            (Value::Int(lhs), Value::Int(rhs)) => Ok(Value::Int(lhs.wrapping_div(rhs))),
107            (Value::Float(lhs), Value::Float(rhs)) => Ok(Value::Float(lhs / rhs)),
108            _ => unreachable!("other types do not support this operation: {self} / {rhs}"),
109        }
110    }
111
112    pub(crate) fn rem(&self, rhs: Value) -> Result<Value, RuntimeError> {
113        match (self, rhs) {
114            (_, Value::Int(0)) => Err(RuntimeError::new(
115                RuntimeErrorKind::Arithmetic,
116                format!("{self} % {rhs} is illegal"),
117            )),
118            (Value::Int(lhs), Value::Int(rhs)) => Ok(Value::Int(lhs.wrapping_rem(rhs))),
119            _ => unreachable!("other types do not support this operation: {self} % {rhs}"),
120        }
121    }
122
123    pub(crate) fn eq(&self, rhs: Value) -> Value {
124        Value::Bool(*self == rhs)
125    }
126
127    pub(crate) fn ne(&self, rhs: Value) -> Value {
128        Value::Bool(*self != rhs)
129    }
130
131    pub(crate) fn lt(&self, rhs: Value) -> Value {
132        let res = match (self, rhs) {
133            (Value::Int(lhs), Value::Int(rhs)) => *lhs < rhs,
134            (Value::Float(lhs), Value::Float(rhs)) => *lhs < rhs,
135            (Value::Char(lhs), Value::Char(rhs)) => *lhs < rhs,
136            _ => unreachable!("other types cannot be compared: {self} < {rhs}"),
137        };
138        Value::Bool(res)
139    }
140
141    pub(crate) fn le(&self, rhs: Value) -> Value {
142        let res = match (self, rhs) {
143            (Value::Int(lhs), Value::Int(rhs)) => *lhs <= rhs,
144            (Value::Float(lhs), Value::Float(rhs)) => *lhs <= rhs,
145            (Value::Char(lhs), Value::Char(rhs)) => *lhs <= rhs,
146            _ => unreachable!("other types cannot be compared: {self} <= {rhs}"),
147        };
148        Value::Bool(res)
149    }
150
151    pub(crate) fn gt(&self, rhs: Value) -> Value {
152        let res = match (self, rhs) {
153            (Value::Int(lhs), Value::Int(rhs)) => *lhs > rhs,
154            (Value::Float(lhs), Value::Float(rhs)) => *lhs > rhs,
155            (Value::Char(lhs), Value::Char(rhs)) => *lhs > rhs,
156            _ => unreachable!("other types cannot be compared: {self} > {rhs}"),
157        };
158        Value::Bool(res)
159    }
160
161    pub(crate) fn ge(&self, rhs: Value) -> Value {
162        let res = match (self, rhs) {
163            (Value::Int(lhs), Value::Int(rhs)) => *lhs >= rhs,
164            (Value::Float(lhs), Value::Float(rhs)) => *lhs >= rhs,
165            (Value::Char(lhs), Value::Char(rhs)) => *lhs >= rhs,
166            _ => unreachable!("other types cannot be compared: {self} >= {rhs}"),
167        };
168        Value::Bool(res)
169    }
170
171    pub(crate) fn shl(&self, rhs: Value) -> Result<Value, RuntimeError> {
172        let (Value::Int(lhs), Value::Int(rhs)) = (self, rhs) else {
173            unreachable!("other types cannot be shifted: {self} << {rhs}");
174        };
175        if !(0..=63).contains(&rhs) {
176            return Err(RuntimeError::new(
177                RuntimeErrorKind::Arithmetic,
178                "rhs is not in range `0..=63`".to_string(),
179            ));
180        }
181        Ok(Value::Int(lhs << rhs as u32))
182    }
183
184    pub(crate) fn shr(&self, rhs: Value) -> Result<Value, RuntimeError> {
185        let (Value::Int(lhs), Value::Int(rhs)) = (self, rhs) else {
186            unreachable!("other types cannot be shifted: {self} >> {rhs}");
187        };
188        if !(0..=63).contains(&rhs) {
189            return Err(RuntimeError::new(
190                RuntimeErrorKind::Arithmetic,
191                "rhs is not in range `0..=63`".to_string(),
192            ));
193        }
194        Ok(Value::Int(lhs >> rhs as u32))
195    }
196
197    pub(crate) fn bit_or(&self, rhs: Value) -> Value {
198        match (self, rhs) {
199            (Value::Int(lhs), Value::Int(rhs)) => Value::Int(lhs | rhs),
200            (Value::Bool(lhs), Value::Bool(rhs)) => Value::Bool(lhs | rhs),
201            _ => unreachable!("other types are illegal: {self} | {rhs}"),
202        }
203    }
204
205    pub(crate) fn bit_and(&self, rhs: Value) -> Value {
206        match (self, rhs) {
207            (Value::Int(lhs), Value::Int(rhs)) => Value::Int(lhs & rhs),
208            (Value::Bool(lhs), Value::Bool(rhs)) => Value::Bool(lhs & rhs),
209            _ => unreachable!("other types are illegal: {self} & {rhs}"),
210        }
211    }
212
213    pub(crate) fn bit_xor(&self, rhs: Value) -> Value {
214        match (self, rhs) {
215            (Value::Int(lhs), Value::Int(rhs)) => Value::Int(lhs ^ rhs),
216            (Value::Bool(lhs), Value::Bool(rhs)) => Value::Bool(lhs ^ rhs),
217            _ => unreachable!("other types are illegal: {self} ^ {rhs}"),
218        }
219    }
220
221    pub(crate) fn cast(self, to: Type) -> Value {
222        match to {
223            Type::Int => self.cast_int(),
224            Type::Bool => self.cast_bool(),
225            Type::Char => self.cast_char(),
226            Type::Float => self.cast_float(),
227        }
228    }
229
230    fn cast_int(self) -> Value {
231        let res = match self {
232            Value::Bool(val) => val as i64,
233            Value::Char(val) => val as i64,
234            Value::Float(val) => val as i64,
235            _ => unreachable!("other combinations are impossible: {self} as int"),
236        };
237        Value::Int(res)
238    }
239
240    fn cast_bool(self) -> Value {
241        let res = match self {
242            Value::Int(val) => val != 0,
243            Value::Char(val) => val != 0,
244            Value::Float(val) => val != 0.0,
245            _ => unreachable!("other combinations are impossible: {self} as bool"),
246        };
247        Value::Bool(res)
248    }
249
250    fn cast_char(self) -> Value {
251        let res = match self {
252            Value::Int(i64::MIN..=0) => 0,
253            Value::Int(127..=i64::MAX) => 127,
254            Value::Int(val) => val as u8,
255            Value::Bool(val) => val as u8,
256            Value::Float(val) if val < 0.0 => 0,
257            Value::Float(val) if val > 127.0 => 127,
258            Value::Float(val) => val as u8,
259            _ => unreachable!("other combinations are impossible: {self} as char"),
260        };
261        Value::Char(res)
262    }
263
264    fn cast_float(self) -> Value {
265        let res = match self {
266            Value::Int(val) => val as f64,
267            Value::Bool(val) => val as u8 as f64,
268            Value::Char(val) => val as f64,
269            _ => unreachable!("other combinations are impossible: {self} as float"),
270        };
271        Value::Float(res)
272    }
273}
274
275impl Display for Value {
276    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
277        match self {
278            Value::Int(val) => write!(f, "{val}"),
279            Value::Bool(val) => write!(f, "{val}"),
280            Value::Char(val) => write!(f, "{val}"),
281            Value::Float(val) => write!(
282                f,
283                "{val}{zero}",
284                zero = if val.fract() == 0.0 { ".0" } else { "" }
285            ),
286            Value::Ptr(ptr) => match ptr {
287                Pointer::Rel(offset) => write!(f, "*rel[{offset}]"),
288                Pointer::Abs(addr) => write!(f, "*abs[{addr}]"),
289            },
290        }
291    }
292}