Skip to main content

roar/runtime/
value.rs

1use super::{FRAME_SIZE, FRAME_WIDTH};
2use crate::{
3    bc::BytecodeValue,
4    result::{RoarError, RoarResult},
5    runtime_value_impl,
6};
7
8#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
9pub enum RuntimeValue {
10    I64(RuntimeI64Value),
11    F64(RuntimeF64Value),
12}
13
14impl RuntimeValue {
15    pub fn f64_splat(value: f64) -> RuntimeValue {
16        RuntimeValue::F64(RuntimeF64Value::splat(value))
17    }
18    pub fn i64_splat(value: i64) -> RuntimeValue {
19        RuntimeValue::I64(RuntimeI64Value::splat(value))
20    }
21    pub fn f64_new(value: [f64; FRAME_SIZE]) -> RuntimeValue {
22        RuntimeValue::F64(RuntimeF64Value::new(value))
23    }
24    pub fn i64_new(value: [i64; FRAME_SIZE]) -> RuntimeValue {
25        RuntimeValue::I64(RuntimeI64Value::new(value))
26    }
27}
28
29impl From<BytecodeValue> for RuntimeValue {
30    fn from(value: BytecodeValue) -> Self {
31        match value {
32            BytecodeValue::F64(v) => RuntimeValue::F64(RuntimeF64Value::splat(v)),
33            BytecodeValue::I64(v) => RuntimeValue::I64(RuntimeI64Value::splat(v)),
34        }
35    }
36}
37
38impl From<RuntimeI64Value> for RuntimeValue {
39    fn from(value: RuntimeI64Value) -> Self {
40        Self::I64(value)
41    }
42}
43impl RuntimeValue {
44    pub fn as_i64(self) -> RoarResult<RuntimeI64Value> {
45        match self {
46            RuntimeValue::F64(_) => Err(RoarError::UnmatchedTypeUnwrap),
47            RuntimeValue::I64(runtime_i64_value) => Ok(runtime_i64_value),
48        }
49    }
50}
51
52impl From<RuntimeF64Value> for RuntimeValue {
53    fn from(value: RuntimeF64Value) -> Self {
54        Self::F64(value)
55    }
56}
57impl RuntimeValue {
58    pub fn as_f64(self) -> RoarResult<RuntimeF64Value> {
59        match self {
60            RuntimeValue::I64(_) => Err(RoarError::UnmatchedTypeUnwrap),
61            RuntimeValue::F64(runtime_f64_value) => Ok(runtime_f64_value),
62        }
63    }
64}
65
66impl std::ops::Shl for RuntimeI64Value {
67    type Output = RuntimeI64Value;
68
69    fn shl(mut self, rhs: Self) -> Self::Output {
70        for i in 0..FRAME_SIZE {
71            self[i] <<= rhs[i]
72        }
73        self
74    }
75}
76impl std::ops::ShlAssign for RuntimeI64Value {
77    fn shl_assign(&mut self, rhs: Self) {
78        *self = *self << rhs;
79    }
80}
81
82impl std::ops::Shr for RuntimeI64Value {
83    type Output = RuntimeI64Value;
84
85    fn shr(mut self, rhs: Self) -> Self::Output {
86        for i in 0..FRAME_SIZE {
87            self[i] >>= rhs[i]
88        }
89        self
90    }
91}
92impl std::ops::ShrAssign for RuntimeI64Value {
93    fn shr_assign(&mut self, rhs: Self) {
94        *self = *self >> rhs;
95    }
96}
97
98impl RuntimeF64Value {
99    pub fn powi(mut self, pow: RuntimeI64Value) -> Self {
100        for i in 0..FRAME_SIZE {
101            self[i] = self[i].powi(pow[i] as i32)
102        }
103        self
104    }
105    pub fn powf(mut self, pow: RuntimeF64Value) -> Self {
106        for i in 0..FRAME_SIZE {
107            self[i] = self[i].powf(pow[i])
108        }
109        self
110    }
111}
112
113impl RuntimeI64Value {
114    pub fn pow(mut self, pow: Self) -> Self {
115        for i in 0..FRAME_SIZE {
116            self[i] = self[i].pow(pow[i] as u32)
117        }
118        self
119    }
120}
121
122runtime_value_impl!(RuntimeI64Value, i64);
123runtime_value_impl!(RuntimeF64Value, f64);
124
125#[macro_export]
126macro_rules! runtime_value_impl {
127    ($name:ident, $t:ty) => {
128        #[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
129        pub struct $name([$t; FRAME_SIZE]);
130        impl $name {
131            pub fn new(value: [$t; FRAME_SIZE]) -> Self {
132                Self(value)
133            }
134            pub fn splat(value: $t) -> Self {
135                Self([value; FRAME_SIZE])
136            }
137        }
138
139        impl std::ops::Index<usize> for $name {
140            type Output = $t;
141
142            fn index(&self, index: usize) -> &Self::Output {
143                &self.0[index]
144            }
145        }
146
147        impl std::ops::IndexMut<usize> for $name {
148            fn index_mut(&mut self, index: usize) -> &mut Self::Output {
149                &mut self.0[index]
150            }
151        }
152
153        impl std::ops::Add for $name {
154            type Output = $name;
155
156            fn add(mut self, rhs: Self) -> Self::Output {
157                for i in 0..FRAME_SIZE {
158                    self[i] += rhs[i]
159                }
160                self
161            }
162        }
163        impl std::ops::AddAssign for $name {
164            fn add_assign(&mut self, rhs: Self) {
165                *self = *self + rhs;
166            }
167        }
168
169        impl std::ops::Mul for $name {
170            type Output = $name;
171
172            fn mul(mut self, rhs: Self) -> Self::Output {
173                for i in 0..FRAME_SIZE {
174                    self[i] *= rhs[i]
175                }
176                self
177            }
178        }
179        impl std::ops::MulAssign for $name {
180            fn mul_assign(&mut self, rhs: Self) {
181                *self = *self * rhs;
182            }
183        }
184
185        impl std::ops::Sub for $name {
186            type Output = $name;
187
188            fn sub(mut self, rhs: Self) -> Self::Output {
189                for i in 0..FRAME_SIZE {
190                    self[i] -= rhs[i]
191                }
192                self
193            }
194        }
195        impl std::ops::SubAssign for $name {
196            fn sub_assign(&mut self, rhs: Self) {
197                *self = *self - rhs;
198            }
199        }
200
201        impl std::ops::Div for $name {
202            type Output = $name;
203
204            fn div(mut self, rhs: Self) -> Self::Output {
205                for i in 0..FRAME_SIZE {
206                    self[i] /= rhs[i]
207                }
208                self
209            }
210        }
211        impl std::ops::DivAssign for $name {
212            fn div_assign(&mut self, rhs: Self) {
213                *self = *self / rhs;
214            }
215        }
216
217        impl std::ops::Neg for $name {
218            type Output = $name;
219
220            fn neg(mut self) -> Self::Output {
221                for i in 0..FRAME_SIZE {
222                    self[i] = -self[i];
223                }
224                self
225            }
226        }
227
228        impl Default for $name {
229            fn default() -> Self {
230                Self([Default::default(); FRAME_SIZE])
231            }
232        }
233
234        impl $name {
235            pub fn new_with_fn(mut f: impl FnMut(usize, usize) -> $t) -> Self {
236                let mut value = [Default::default(); FRAME_SIZE];
237                for y in 0..FRAME_WIDTH {
238                    for x in 0..FRAME_WIDTH {
239                        value[y * FRAME_WIDTH + x] = f(x, y);
240                    }
241                }
242                Self(value)
243            }
244            pub fn unanymous_val(&self) -> crate::result::RoarResult<$t> {
245                let val = self[0];
246                for i in 0..FRAME_SIZE {
247                    if self[i] != val {
248                        return Err(crate::result::RoarError::ValueNotUnanymous);
249                    }
250                }
251                Ok(val)
252            }
253            pub fn arr(&self) -> [$t; FRAME_SIZE] {
254                self.0
255            }
256        }
257
258        impl $name {
259            pub fn min(mut self, other: Self) -> Self {
260                for i in 0..FRAME_SIZE {
261                    self[i] = self[i].min(other[i]);
262                }
263                self
264            }
265            pub fn max(mut self, other: Self) -> Self {
266                for i in 0..FRAME_SIZE {
267                    self[i] = self[i].max(other[i]);
268                }
269                self
270            }
271        }
272    };
273}