1use crate::{
2 frame_map,
3 result::{RoarError, RoarResult},
4};
5use noise::{Fbm, MultiFractal, Perlin, RidgedMulti, Value};
6use std::{collections::VecDeque, sync::Arc};
7
8use crate::bc::Op;
9
10use super::{value::RuntimeValue, FRAME_SIZE};
11pub struct ExecutionFrame {
12 code_pos: usize,
13 code: Arc<[Op]>,
14 stack: VecDeque<RuntimeValue>,
15 input_pos: usize,
16 input_section: Arc<[RuntimeValue]>,
17 buf_pos: usize,
18 input_buffer: Arc<[RuntimeValue]>,
19 memory: Vec<RuntimeValue>,
20 ctx: ExecutionContext,
21}
22
23impl ExecutionFrame {
24 pub(super) fn new(
25 code: Arc<[Op]>,
26 input_section: Arc<[RuntimeValue]>,
27 input_buffer: Arc<[RuntimeValue]>,
28 ctx: ExecutionContext,
29 ) -> Self {
30 Self {
31 code_pos: 0,
32 code,
33 stack: VecDeque::new(),
34 input_pos: 0,
35 input_section,
36 buf_pos: 0,
37 input_buffer,
38 memory: Vec::with_capacity(256),
39 ctx,
40 }
41 }
42
43 fn pull_op(&mut self) -> RoarResult<Op> {
44 if self.code_pos < self.code.len() {
45 self.code_pos += 1;
46 Ok(self.code[self.code_pos - 1])
47 } else {
48 Err(RoarError::RuntimeNoOpsLeft)
49 }
50 }
51 fn pull_const(&mut self) -> RoarResult<RuntimeValue> {
52 if self.input_pos < self.input_section.len() {
53 self.input_pos += 1;
54 Ok(self.input_section[self.input_pos - 1])
55 } else {
56 Err(RoarError::RuntimeNoConstsLeft)
57 }
58 }
59 fn pull_var(&mut self) -> RoarResult<RuntimeValue> {
60 if self.buf_pos < self.input_buffer.len() {
61 self.buf_pos += 1;
62 Ok(self.input_buffer[self.buf_pos - 1])
63 } else {
64 Err(RoarError::RuntimeNoVarsLeft)
65 }
66 }
67 fn pull_stack(&mut self) -> RoarResult<RuntimeValue> {
68 if let Some(pulled) = self.stack.pop_front() {
69 Ok(pulled)
70 } else {
71 Err(RoarError::RuntimeStackEmpty)
72 }
73 }
74 fn push_stack(&mut self, value: RuntimeValue) {
75 self.stack.push_front(value);
76 }
77 fn step(&mut self) -> RoarResult<()> {
78 match self.pull_op()? {
79 Op::Load => {
80 let value = self.pull_var()?;
81 self.push_stack(value);
82 }
83 Op::LoadConst => {
84 let value = self.pull_const()?;
85 self.push_stack(value);
86 }
87 Op::Set => {
88 let id = self.pull_stack()?.as_i64()?;
89 let val = self.pull_stack()?;
90 self.memory.insert(id[0] as usize, val);
91 }
92 Op::Get => {
93 let id = self.pull_stack()?.as_i64()?;
94 if let Some(val) = self.memory.get(id[0] as usize) {
95 self.push_stack(*val);
96 } else {
97 return Err(RoarError::IndexNotInMemory);
98 }
99 }
100 Op::Swap => {
101 self.stack.swap(0, 1);
102 }
103 Op::Perlin => {
104 let seed = self.pull_stack()?.as_i64()?.unanymous_val()?;
105 let noise = Perlin::new(seed as u32);
106 let noise_map = frame_map!(self.ctx, noise);
107 self.push_stack(RuntimeValue::f64_new(noise_map));
108 }
109 Op::Fbm => {
110 let persistence = self.pull_stack()?.as_f64()?.unanymous_val()?;
111 let lacunarity = self.pull_stack()?.as_f64()?.unanymous_val()?;
112 let freq = self.pull_stack()?.as_f64()?.unanymous_val()?;
113 let octaves = self.pull_stack()?.as_i64()?.unanymous_val()?;
114 let seed = self.pull_stack()?.as_i64()?.unanymous_val()?;
115 let noise = Fbm::<Perlin>::new(seed as u32)
116 .set_persistence(persistence)
117 .set_lacunarity(lacunarity)
118 .set_frequency(freq)
119 .set_octaves(octaves as usize);
120 let noise_map = frame_map!(self.ctx, noise);
121 self.push_stack(RuntimeValue::f64_new(noise_map));
122 }
123 Op::RidgedMulti => {
124 let persistence = self.pull_stack()?.as_f64()?.unanymous_val()?;
125 let lacunarity = self.pull_stack()?.as_f64()?.unanymous_val()?;
126 let freq = self.pull_stack()?.as_f64()?.unanymous_val()?;
127 let octaves = self.pull_stack()?.as_i64()?.unanymous_val()?;
128 let seed = self.pull_stack()?.as_i64()?.unanymous_val()?;
129 let noise = RidgedMulti::<Perlin>::new(seed as u32)
130 .set_persistence(persistence)
131 .set_lacunarity(lacunarity)
132 .set_frequency(freq)
133 .set_octaves(octaves as usize);
134 let noise_map = frame_map!(self.ctx, noise);
135 self.push_stack(RuntimeValue::f64_new(noise_map));
136 }
137 Op::Value => {
138 let seed = self.pull_stack()?.as_i64()?.unanymous_val()?;
139 let noise = Value::new(seed as u32);
140 let noise_map = frame_map!(self.ctx, noise);
141 self.push_stack(RuntimeValue::f64_new(noise_map));
142 }
143 Op::Add => {
144 let rhs = self.pull_stack()?;
145 let out = match rhs {
146 RuntimeValue::F64(rhs) => RuntimeValue::F64(rhs + self.pull_stack()?.as_f64()?),
147 RuntimeValue::I64(rhs) => RuntimeValue::I64(rhs + self.pull_stack()?.as_i64()?),
148 };
149 self.push_stack(out);
150 }
151 Op::Sub => {
152 let rhs = self.pull_stack()?;
153 let out = match rhs {
154 RuntimeValue::F64(rhs) => RuntimeValue::F64(rhs - self.pull_stack()?.as_f64()?),
155 RuntimeValue::I64(rhs) => RuntimeValue::I64(rhs - self.pull_stack()?.as_i64()?),
156 };
157 self.push_stack(out);
158 }
159 Op::Mul => {
160 let rhs = self.pull_stack()?;
161 let out = match rhs {
162 RuntimeValue::F64(rhs) => RuntimeValue::F64(rhs * self.pull_stack()?.as_f64()?),
163 RuntimeValue::I64(rhs) => RuntimeValue::I64(rhs * self.pull_stack()?.as_i64()?),
164 };
165 self.push_stack(out);
166 }
167 Op::Div => {
168 let rhs = self.pull_stack()?;
169 let out = match rhs {
170 RuntimeValue::F64(rhs) => RuntimeValue::F64(rhs / self.pull_stack()?.as_f64()?),
171 RuntimeValue::I64(rhs) => RuntimeValue::I64(rhs / self.pull_stack()?.as_i64()?),
172 };
173 self.push_stack(out);
174 }
175 Op::Neg => {
176 let out = match self.pull_stack()? {
177 RuntimeValue::I64(runtime_i64_value) => RuntimeValue::I64(-runtime_i64_value),
178 RuntimeValue::F64(runtime_f64_value) => RuntimeValue::F64(-runtime_f64_value),
179 };
180 self.push_stack(out);
181 }
182 Op::Max => {
183 let other = self.pull_stack()?;
184 let out = match other {
185 RuntimeValue::F64(other) => {
186 RuntimeValue::F64(other.max(self.pull_stack()?.as_f64()?))
187 }
188 RuntimeValue::I64(other) => {
189 RuntimeValue::I64(other.max(self.pull_stack()?.as_i64()?))
190 }
191 };
192 self.push_stack(out);
193 }
194 Op::Min => {
195 let other = self.pull_stack()?;
196 let out = match other {
197 RuntimeValue::F64(other) => {
198 RuntimeValue::F64(other.min(self.pull_stack()?.as_f64()?))
199 }
200 RuntimeValue::I64(other) => {
201 RuntimeValue::I64(other.min(self.pull_stack()?.as_i64()?))
202 }
203 };
204 self.push_stack(out);
205 }
206 Op::Pwr => {
207 let pow = self.pull_stack()?;
208 let out = match self.pull_stack()? {
209 RuntimeValue::I64(runtime_i64_value) => {
210 RuntimeValue::I64(runtime_i64_value.pow(pow.as_i64()?))
211 }
212 RuntimeValue::F64(runtime_f64_value) => match pow {
213 RuntimeValue::I64(pow_i64) => {
214 RuntimeValue::F64(runtime_f64_value.powi(pow_i64))
215 }
216 RuntimeValue::F64(pow_f64) => {
217 RuntimeValue::F64(runtime_f64_value.powf(pow_f64))
218 }
219 },
220 };
221 self.push_stack(out);
222 }
223 Op::LeftShift => {
224 let rhs = self.pull_stack()?.as_i64()?;
225 let lhs = self.pull_stack()?.as_i64()?;
226 self.push_stack(RuntimeValue::I64(lhs << rhs));
227 }
228 Op::RightShift => {
229 let rhs = self.pull_stack()?.as_i64()?;
230 let lhs = self.pull_stack()?.as_i64()?;
231 self.push_stack(RuntimeValue::I64(lhs >> rhs));
232 }
233 Op::GetCtx1 => self.push_stack(RuntimeValue::f64_splat(self.ctx.x)),
234 Op::GetCtx2 => self.push_stack(RuntimeValue::f64_splat(self.ctx.y)),
235 Op::SetCtx4 => self.ctx.scale_x = self.pull_stack()?.as_f64()?.unanymous_val()?,
236 Op::SetCtx5 => self.ctx.scale_y = self.pull_stack()?.as_f64()?.unanymous_val()?,
237 Op::PutOnCurve => {
238 let end_y = self.pull_stack()?.as_f64()?;
239 let end_x = self.pull_stack()?.as_f64()?;
240 let start_y = self.pull_stack()?.as_f64()?;
241 let start_x = self.pull_stack()?.as_f64()?;
242 let mem_idx = self.pull_stack()?.as_i64()?.unanymous_val()? as usize;
243 let value = self.pull_stack()?.as_f64()?;
244 if self.memory.get(mem_idx).is_none() {
245 self.memory.insert(mem_idx, RuntimeValue::f64_splat(0.0));
246 }
247 let mem = &mut self.memory[mem_idx];
248 match mem {
249 RuntimeValue::I64(_) => return Err(RoarError::UnmatchedTypeUnwrap),
250 RuntimeValue::F64(mem) => {
251 for i in 0..FRAME_SIZE {
252 let v = value[i];
253 let end_y = end_y[i];
254 let end_x = end_x[i];
255 let start_y = start_y[i];
256 let start_x = start_x[i];
257 if start_x <= v && v <= end_x {
258 let t = (v - start_x) / (end_x - start_x);
259 mem[i] = (1.0 - t) * start_y + t * end_y;
260 }
261 }
262 },
263 }
264 self.push_stack(RuntimeValue::F64(value));
265 },
266 }
267 Ok(())
268 }
269 pub fn run(&mut self) -> RoarResult<RuntimeValue> {
270 while self.code_pos < self.code.len() {
271 self.step()?;
272 }
273 if let Some(out) = self.stack.pop_front() {
274 Ok(out)
275 } else {
276 Err(RoarError::RuntimeFinishedWithoutReturnValue)
277 }
278 }
279}
280#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Default)]
281pub struct ExecutionContext {
282 pub(super) x: f64,
283 pub(super) y: f64,
284 pub(super) scale_x: f64,
285 pub(super) scale_y: f64,
286}
287
288#[macro_export]
289macro_rules! frame_map {
290 ($ctx:expr, $noise: expr) => {{
291 use super::{FRAME_SIZE, FRAME_WIDTH};
292 use noise::NoiseFn;
293 let map = noise::utils::PlaneMapBuilder::new_fn(move |[x, y]| $noise.get([x, y]))
294 .set_size(FRAME_WIDTH, FRAME_WIDTH)
295 .set_x_bounds(
296 $ctx.x * 16.0 * $ctx.scale_x,
297 ($ctx.x + 1.0) * 16.0 * $ctx.scale_x,
298 )
299 .set_y_bounds(
300 $ctx.y * 16.0 * $ctx.scale_y,
301 ($ctx.y + 1.0) * 16.0 * $ctx.scale_y,
302 )
303 .build();
304 let mut arr = [0.0; FRAME_SIZE];
305 let mut i = 0;
306 for v in map.iter() {
307 arr[i] = *v;
308 i += 1;
309 }
310 arr
311 }};
312}