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}