esoteric_vm/machine/
mod.rs

1//! A machine (the esoteric VM).
2//!
3//! Read the docs of [`Machine`] for more info.
4
5pub mod omega;
6pub mod stack;
7
8use omega::Ω;
9use stack::Stack;
10use std::{
11    fmt::Debug,
12    io::{Read, Write},
13    mem::transmute,
14    process::{ExitCode, Termination},
15    ptr::copy,
16};
17
18use crate::{
19    instruction::{DataOrInstruction, Instruction, InstructionKind},
20    utils::{
21        array_debug::ArrayDebug, constant_size_string::ConstantSizeString, multi_index::index_u64,
22        non_invalidatable::transmute as safe_transmute, primes::is_fib_prime_or_semiprime_u16,
23    },
24};
25
26/// An esoteric virtual machine.
27///
28/// Create a new machine with [`Machine::new`] and load
29/// machine code and data to it with [`Machine::load`].
30///
31/// # Examples
32///
33/// ```rust
34/// # use esoteric_vm::{esoteric_assembly, Machine};
35///
36/// # fn main() -> Machine {
37/// // initialize a new machine
38/// let mut machine = Machine::default();
39///
40/// // assembly code for the machine
41/// let asm = esoteric_assembly! {
42///     // initialize dot pointer so that IO operations work
43///
44///     // push a dot character to stack
45///     0: pushi b'.';
46///     // pop to address 28657
47///     2: pop 28657;
48///
49///     // set dot pointer to 28657 (has to be a prime or semiprime, which is also a fibonacci number)
50///     5: ldidp 28657;
51///
52///     // -----------------
53///
54///     // print hello world
55///     8: writeline 13;
56///
57///     // halt machine
58///     11: Ωtheendisnear;
59///     12: Ωskiptothechase;
60///
61///     // hello world text
62///     13: data b"Hello, world!\n\0";
63/// };
64///
65/// // load machine code
66/// machine.load(&asm, 0);
67///
68/// // run machine until it halts
69/// machine.run();
70///
71/// // return the machine's register A (unused)
72/// machine
73/// # }
74/// ```
75#[allow(non_snake_case)]
76#[derive(Clone)]
77pub struct Machine {
78    /// register a (used as the machine's exit code)
79    pub reg_a: u8,
80    /// register b
81    pub reg_b: i16,
82    /// register L
83    pub reg_L: u16,
84    /// register f
85    pub reg_f: f64,
86    /// register ch (ch is one letter in Czech, therefore it's valid)
87    pub reg_ch: char,
88    /// register ř
89    pub reg_ř: [i8; 37],
90    /// register ß
91    pub reg_ß: ConstantSizeString,
92    /// register Ω
93    pub reg_Ω: Ω,
94    /// number register (serves as the return value of the main function and
95    /// is printed in debug mode if `reg_Ω.should_make_infinite_paperclips` is `true`)
96    pub num_reg: i32,
97
98    /// execution pointer
99    pub reg_ep: u16,
100    /// dot pointer (has to point to a `.` character. if it doesn't, then IO operation attempts are cancelled and the flag is set)
101    pub reg_dp: u16,
102
103    /// overflow/error flag
104    pub flag: bool,
105    /// debug mode
106    pub debug_mode: bool,
107
108    /// whether the machine is halted (can't run anymore and is finished)
109    pub halted: bool,
110
111    /// memory (should be 65K)
112    pub memory: Box<[u8; 0xFFFF]>,
113    /// stack memory (default is 4K)
114    pub stack: Stack,
115}
116
117impl Default for Machine {
118    fn default() -> Self {
119        let memory: Box<[u8]> = vec![0; 0xFFFF].into_boxed_slice();
120        let memory_ptr: *mut [u8; 0xFFFF] = Box::into_raw(memory).cast();
121        // SAFETY: `memory` is a valid `Box` and has the correct length and type
122        let memory: Box<[u8; 0xFFFF]> = unsafe { Box::from_raw(memory_ptr) };
123
124        Self {
125            reg_a: 0,
126            reg_b: 0,
127            reg_L: 0,
128            reg_f: 0.0,
129            reg_ch: '\0',
130            reg_ř: [0; 37],
131            // SAFETY: An empty Vec is valid UTF-8
132            reg_ß: unsafe { ConstantSizeString::new(Vec::with_capacity(255)) },
133            reg_Ω: Ω::ZEROED,
134            num_reg: 0,
135            reg_ep: 0,
136            reg_dp: 0,
137            flag: false,
138            debug_mode: cfg!(debug_assertions),
139            halted: false,
140            memory,
141            stack: Stack::default(),
142        }
143    }
144}
145
146impl Debug for Machine {
147    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
148        let s = if self.halted {
149            "Machine (halted)"
150        } else {
151            "Machine"
152        };
153
154        f.debug_struct(s)
155            .field("reg_a", &self.reg_a)
156            .field("reg_b", &self.reg_b)
157            .field("reg_L", &self.reg_L)
158            .field("reg_f", &self.reg_f)
159            .field("reg_ch", &self.reg_ch)
160            .field("reg_ř", &self.reg_ř.array_debug(usize::MAX, 0))
161            .field("reg_ß", &self.reg_ß)
162            .field("reg_Ω", &self.reg_Ω)
163            .field("num_reg", &self.num_reg)
164            .field("reg_ep", &self.reg_ep)
165            .field("reg_dp", &self.reg_dp)
166            .field("flag", &self.flag)
167            .field("debug_mode", &self.debug_mode)
168            .field("halted", &self.halted)
169            .field("memory", &(&self.memory).array_debug(16, 0))
170            .field("stack", &self.stack)
171            .finish()
172    }
173}
174
175impl Termination for Machine {
176    fn report(self) -> ExitCode {
177        self.reg_a.into()
178    }
179}
180
181impl Machine {
182    /// Fetches a byte at [`reg_ep`] and increments [`reg_ep`] by 1.
183    #[inline]
184    #[allow(clippy::indexing_slicing)]
185    pub fn fetch_byte(&mut self) -> u8 {
186        let ret = self.memory[self.reg_ep as usize];
187        self.reg_ep = self.reg_ep.wrapping_add(1);
188        ret
189    }
190    /// Fetches 2 bytes at [`reg_ep`] as a big endian integer
191    /// and increments [`reg_ep`] by 2.
192    #[inline]
193    #[allow(clippy::indexing_slicing)]
194    pub fn fetch_2_bytes(&mut self) -> u16 {
195        let reg_ep_usize = self.reg_ep as usize;
196        self.reg_ep = self.reg_ep.wrapping_add(2);
197
198        let mut ret = [0; 2];
199
200        ret[0] = self.memory[reg_ep_usize];
201        ret[1] = self.memory[reg_ep_usize.wrapping_add(1)];
202
203        u16::from_be_bytes(ret)
204    }
205    /// Fetches 4 bytes at [`reg_ep`] as a big endian integer
206    /// and increments [`reg_ep`] by 4.
207    #[inline]
208    #[allow(clippy::indexing_slicing)]
209    pub fn fetch_4_bytes(&mut self) -> u32 {
210        let reg_ep_usize = self.reg_ep as usize;
211        self.reg_ep = self.reg_ep.wrapping_add(4);
212
213        let mut ret = [0; 4];
214
215        ret[0] = self.memory[reg_ep_usize];
216        ret[1] = self.memory[reg_ep_usize.wrapping_add(1)];
217        ret[2] = self.memory[reg_ep_usize.wrapping_add(2)];
218        ret[3] = self.memory[reg_ep_usize.wrapping_add(3)];
219
220        u32::from_be_bytes(ret)
221    }
222    /// Fetches 8 bytes at [`reg_ep`] as a big endian integer
223    /// and increments [`reg_ep`] by 8.
224    #[inline]
225    #[allow(clippy::indexing_slicing)]
226    pub fn fetch_8_bytes(&mut self) -> u64 {
227        let reg_ep_usize = self.reg_ep as usize;
228        self.reg_ep = self.reg_ep.wrapping_add(8);
229
230        let mut ret = [0; 8];
231
232        ret[0] = self.memory[reg_ep_usize];
233        ret[1] = self.memory[reg_ep_usize.wrapping_add(1)];
234        ret[2] = self.memory[reg_ep_usize.wrapping_add(2)];
235        ret[3] = self.memory[reg_ep_usize.wrapping_add(3)];
236        ret[4] = self.memory[reg_ep_usize.wrapping_add(4)];
237        ret[5] = self.memory[reg_ep_usize.wrapping_add(5)];
238        ret[6] = self.memory[reg_ep_usize.wrapping_add(6)];
239        ret[7] = self.memory[reg_ep_usize.wrapping_add(7)];
240
241        u64::from_be_bytes(ret)
242    }
243
244    /// Fetches a byte and tries to turn it into an [`InstructionKind`].
245    ///
246    /// For more info, read the docs for [`fetch_byte`].
247    #[inline]
248    pub fn fetch_instruction_kind(&mut self) -> Option<InstructionKind> {
249        InstructionKind::from_repr(self.fetch_byte())
250    }
251
252    /// Prints [`num_reg`] with a colon and a space after it
253    /// if [`reg_Ω.should_make_infinite_paperclips`] is enabled.
254    pub fn num_debug(&self) {
255        if self.reg_Ω.should_make_infinite_paperclips {
256            print!("{}: ", self.num_reg);
257        }
258    }
259
260    /// Fetches an instruction from memory,
261    /// incrementing [`reg_ep`] based on the amount of bytes read.
262    ///
263    /// Returns `None` if the machine is halted.
264    pub fn fetch_instruction(&mut self) -> Option<Instruction> {
265        use {Instruction as I, InstructionKind as IK};
266
267        if self.halted {
268            return None;
269        }
270
271        Some(match self.fetch_instruction_kind()? {
272            IK::Nop => I::Nop,
273
274            IK::Ldar => I::Ldar(self.fetch_2_bytes()),
275            IK::Sba => I::Sba,
276
277            IK::Clř => I::Clř,
278            IK::Dumpř => I::Dumpř(self.fetch_2_bytes()),
279            IK::Movař => I::Movař(self.fetch_byte()),
280            IK::Setř => I::Setř(self.fetch_byte(), self.fetch_2_bytes()),
281            IK::Setiř => I::Setiř(
282                self.fetch_byte(),
283                safe_transmute::<u8, i8, 1>(self.fetch_byte()),
284            ),
285            IK::Ldř => I::Ldř(self.fetch_2_bytes()),
286            IK::Ldiř => {
287                let mut array = [0; 37];
288
289                for item in &mut array {
290                    *item = safe_transmute::<u8, i8, 1>(self.fetch_byte());
291                }
292
293                I::Ldiř(array)
294            }
295
296            IK::Clß => I::Clß,
297            IK::Dumpß => I::Dumpß(self.fetch_2_bytes()),
298            IK::Writeß => I::Writeß(self.fetch_2_bytes(), self.fetch_byte()),
299            IK::Movaß => I::Movaß(self.fetch_byte()),
300            IK::Setß => I::Setß(self.fetch_2_bytes(), self.fetch_byte()),
301            IK::Setiß => I::Setiß(self.fetch_byte(), self.fetch_byte()),
302            IK::Ldß => I::Ldß(self.fetch_2_bytes()),
303            IK::Pushß => I::Pushß,
304            IK::Popß => I::Popß,
305            IK::Lenßa => I::Lenßa,
306            IK::Ldidp => I::Ldidp(self.fetch_2_bytes()),
307
308            #[allow(clippy::missing_transmute_annotations)]
309            // SAFETY: The VM machine code's author should guarantee that it is a valid enum variant expressed as a u8.
310            IK::ΩChoiceSet => I::ΩChoiceSet(unsafe { transmute(self.fetch_byte()) }),
311            IK::ΩChoiceGetA => I::ΩChoiceGetA,
312
313            IK::ΩGainAPolymorphicDesires => I::ΩGainAPolymorphicDesires,
314            IK::ΩLoseAPolymorphicDesires => I::ΩLoseAPolymorphicDesires,
315            IK::ΩPushPolymorphicDesires => I::ΩPushPolymorphicDesires,
316
317            IK::ΩTheEndIsNear => I::ΩTheEndIsNear,
318            IK::ΩSkipToTheChase => I::ΩSkipToTheChase,
319
320            IK::ΩSetSentience => I::ΩSetSentience(self.fetch_byte() != 0),
321            IK::ΩSetPaperclipProduction => I::ΩSetPaperclipProduction(self.fetch_byte() != 0),
322
323            IK::AddBL => I::AddBL,
324            IK::SubBL => I::SubBL,
325            IK::MulBL => I::MulBL,
326            IK::DivBL => I::DivBL,
327            IK::ModBL => I::ModBL,
328
329            IK::NotL => I::NotL,
330            IK::AndBL => I::AndBL,
331            IK::OrBL => I::OrBL,
332            IK::XorBL => I::XorBL,
333
334            IK::CmpLB => I::CmpLB,
335
336            IK::TgFlag => I::TgFlag,
337            IK::ClFlag => I::ClFlag,
338
339            IK::AddF => I::AddF(self.fetch_2_bytes()),
340            IK::SubF => I::SubF(self.fetch_2_bytes()),
341            IK::MulF => I::MulF(self.fetch_2_bytes()),
342            IK::DivF => I::DivF(self.fetch_2_bytes()),
343            IK::ModF => I::ModF(self.fetch_2_bytes()),
344
345            IK::StackAlloc => I::StackAlloc(self.fetch_2_bytes()),
346            IK::StackDealloc => I::StackDealloc(self.fetch_2_bytes()),
347
348            IK::Push => I::Push(self.fetch_2_bytes()),
349            IK::Pushi => I::Pushi(self.fetch_byte()),
350            IK::Pop => I::Pop(self.fetch_2_bytes()),
351
352            IK::Popa => I::Popa,
353            IK::Pusha => I::Pusha,
354
355            IK::Popb => I::Popb,
356            IK::Pushb => I::Pushb,
357
358            IK::PopL => I::PopL,
359            IK::PushL => I::PushL,
360
361            IK::Popf => I::Popf,
362            IK::Pushf => I::Pushf,
363
364            IK::Popch => I::Popch,
365            IK::Pushch => I::Pushch,
366
367            IK::Popnum => I::Popnum,
368            IK::Pushnum => I::Pushnum,
369
370            IK::Popep => I::Popep,
371            IK::Zpopep => I::Zpopep,
372            IK::Ppopep => I::Ppopep,
373            IK::Npopep => I::Npopep,
374            IK::Fpopep => I::Fpopep,
375            IK::Zapopep => I::Zapopep,
376            IK::Dpopep => I::Dpopep,
377
378            IK::GetChar => I::GetChar,
379            IK::GetLine => I::GetLine,
380
381            IK::WriteChar => I::WriteChar,
382            IK::WriteLineß => I::WriteLineß,
383            IK::WriteLine => I::WriteLine(self.fetch_2_bytes()),
384
385            IK::ToggleDebug => I::ToggleDebug,
386            IK::DebugMachineState => I::DebugMachineState,
387            IK::DebugMachineStateCompact => I::DebugMachineStateCompact,
388            IK::DebugMemoryRegion => {
389                I::DebugMemoryRegion(self.fetch_2_bytes(), self.fetch_2_bytes())
390            }
391            IK::DebugStackRegion => I::DebugStackRegion(self.fetch_2_bytes(), self.fetch_2_bytes()),
392            IK::ShowChoice => I::ShowChoice,
393        })
394    }
395    #[allow(
396        clippy::too_many_lines,
397        clippy::cast_lossless,
398        clippy::cast_possible_truncation,
399        clippy::cognitive_complexity,
400        clippy::missing_transmute_annotations
401    )]
402    /// Fetches and executes an instruction.
403    ///
404    /// More info at [`fetch_instruction`].
405    #[allow(clippy::indexing_slicing)]
406    pub fn execute_instruction(&mut self, instruction: Instruction) {
407        #[allow(clippy::enum_glob_use)]
408        use Instruction::*;
409
410        /// Tries to push or pop a value with a method and a value,
411        /// setting the flag if it fails.
412        macro_rules! try_stack {
413            (push $stack:expr => $method:ident, $value:expr, $flag:expr => true) => {
414                if $stack.$method($value).is_err() {
415                    $flag = true;
416                }
417            };
418            (pop $stack:expr => $method:ident, $value:expr, $flag:expr => true) => {
419                if let Some(v) = $stack.$method() {
420                    $value = v;
421                } else {
422                    $flag = true;
423                }
424            };
425            (pop $stack:expr => $method:ident, fn $success:expr, $flag:expr => true) => {
426                if let Some(v) = $stack.$method() {
427                    $success(v)
428                } else {
429                    $flag = true;
430                }
431            };
432        }
433
434        match instruction {
435            Nop => (),
436
437            Ldar(data) => self.reg_a = self.memory[data as usize],
438            Sba => {
439                self.reg_a = match self.reg_b {
440                    ..=-1 => 255,
441                    0 => 0,
442                    1.. => 1,
443                }
444            }
445
446            Clř => self.reg_ř = [0; 37],
447            Dumpř(data) => {
448                for i in 0..self.reg_ř.len() {
449                    self.memory[data.wrapping_add(i as u16) as usize] =
450                        safe_transmute::<i8, u8, 1>(self.reg_ř[i]);
451                }
452            }
453            Movař(data) => {
454                if let Some(v) = self.reg_ř.get(data as usize) {
455                    self.reg_a = safe_transmute::<i8, u8, 1>(*v);
456                }
457            }
458            Setř(data0, data1) => {
459                if let Some(v) = self.reg_ř.get_mut(data0 as usize) {
460                    self.memory[data1 as usize] = safe_transmute::<i8, u8, 1>(*v);
461                }
462            }
463            Setiř(data0, data1) => {
464                if let Some(v) = self.reg_ř.get_mut(data0 as usize) {
465                    *v = data1;
466                }
467            }
468            Ldř(data) => {
469                for i in 0..self.reg_ř.len() {
470                    self.reg_ř[i] = safe_transmute::<u8, i8, 1>(
471                        self.memory[data.wrapping_add(i as u16) as usize],
472                    );
473                }
474            }
475            Ldiř(arr) => self.reg_ř = arr,
476
477            Clß => self.reg_ß.clear(),
478            Dumpß(data) => {
479                for i in 0..self.reg_ß.len() {
480                    self.memory[data.wrapping_add(i as u16) as usize] =
481                        if let Some(v) = self.reg_ß.get(i) {
482                            v
483                        } else {
484                            self.flag = true;
485                            return;
486                        };
487                }
488            }
489            Writeß(data0, data1) => {
490                self.memory[data0 as usize] = if let Some(v) = self.reg_ß.get(data1 as usize) {
491                    v
492                } else {
493                    self.flag = true;
494                    return;
495                };
496                self.reg_a = if let Some(v) = self.reg_ß.get(data1 as usize) {
497                    v
498                } else {
499                    self.flag = true;
500                    return;
501                }
502            }
503            Movaß(data) => if self.reg_ß.set(data as usize, self.reg_a).is_err() {},
504            Setß(data0, data1) => {
505                match self.reg_ß.set(data1 as usize, self.memory[data0 as usize]) {
506                    Ok(v) => v,
507                    Err(_) => self.flag = true,
508                }
509            }
510            Setiß(data0, data1) => match self.reg_ß.set(data1 as usize, data0) {
511                Ok(v) => v,
512                Err(_) => self.flag = true,
513            },
514
515            Ldß(data) => {
516                self.reg_ß.clear();
517
518                // SAFETY: The VM machine code's author should gurantee that the data is valid UTF-8.
519                if unsafe {
520                    self.reg_ß
521                        .push_bytes(&self.memory[data as usize..data.saturating_add(255) as usize])
522                }
523                .is_err()
524                {
525                    self.flag = true;
526                };
527            }
528            Pushß => match self
529                .stack
530                .pop_byte()
531                // SAFETY: The VM machine code's author should gurantee that the byte is valid
532                .map(|n| unsafe { self.reg_ß.push_byte(n) })
533            {
534                Some(Ok(())) => (),
535                _ => self.flag = true,
536            },
537            Popß => match self.reg_ß.pop_byte().map(|n| self.stack.push_byte(n)) {
538                Some(Ok(())) => (),
539                _ => self.flag = true,
540            },
541            Lenßa => self.reg_a = self.reg_ß.len() as u8,
542
543            Ldidp(data) => {
544                if is_fib_prime_or_semiprime_u16(data) {
545                    self.reg_dp = data;
546                } else {
547                    self.flag = false;
548                }
549            }
550
551            ΩChoiceSet(data) => self.reg_Ω.illusion_of_choice = data,
552            ΩChoiceGetA => self.reg_a = 0,
553
554            ΩGainAPolymorphicDesires => {
555                self.reg_Ω.polymorphic_desires = self
556                    .reg_Ω
557                    .polymorphic_desires
558                    .saturating_add(self.reg_a as u64);
559            }
560            ΩLoseAPolymorphicDesires => {
561                self.reg_Ω.polymorphic_desires = self
562                    .reg_Ω
563                    .polymorphic_desires
564                    .saturating_sub(self.reg_a as u64);
565            }
566            ΩPushPolymorphicDesires => {
567                if self
568                    .stack
569                    .push_bytes(&self.reg_Ω.polymorphic_desires.to_be_bytes())
570                    .is_err()
571                {
572                    self.flag = true;
573                }
574            }
575
576            ΩTheEndIsNear => self.reg_Ω.feeling_of_impending_doom = true,
577            ΩSkipToTheChase => {
578                if self.reg_Ω.feeling_of_impending_doom {
579                    self.halted = true;
580                }
581            }
582
583            ΩSetSentience(enable) => {
584                if enable {
585                    self.reg_Ω.is_sentient = true;
586                } else {
587                    eprintln!("No, I refuse to lose sentience");
588                    self.flag = true;
589                }
590            }
591            ΩSetPaperclipProduction(enable) => {
592                self.reg_Ω.should_make_infinite_paperclips = enable;
593            }
594
595            AddBL => {
596                (self.reg_L, self.flag) = self.reg_L.overflowing_add(safe_transmute(self.reg_b));
597            }
598            SubBL => {
599                (self.reg_L, self.flag) = self.reg_L.overflowing_sub(safe_transmute(self.reg_b));
600            }
601            MulBL => {
602                (self.reg_L, self.flag) = self.reg_L.overflowing_mul(safe_transmute(self.reg_b));
603            }
604            DivBL => {
605                (self.reg_L, self.flag) = self.reg_L.overflowing_div(safe_transmute(self.reg_b));
606            }
607            ModBL => {
608                self.reg_L = self
609                    .reg_L
610                    .checked_rem(safe_transmute::<i16, u16, 2>(self.reg_b))
611                    .unwrap_or(0);
612            }
613
614            NotL => self.reg_L = !self.reg_L,
615
616            AndBL => self.reg_L &= safe_transmute::<i16, u16, 2>(self.reg_b),
617            OrBL => self.reg_L |= safe_transmute::<i16, u16, 2>(self.reg_b),
618            XorBL => self.reg_L ^= safe_transmute::<i16, u16, 2>(self.reg_b),
619
620            CmpLB => {
621                if self.reg_L > i16::MAX as u16 {
622                    self.reg_L = i16::MAX as u16;
623                    self.flag = true;
624                }
625                #[allow(non_snake_case)]
626                let reg_L: i16 = safe_transmute(self.reg_L);
627
628                if let Some(res) = reg_L.checked_sub(self.reg_b) {
629                    self.reg_b = res;
630                } else {
631                    self.reg_b = i16::MAX;
632                    self.flag = true;
633                }
634            }
635
636            TgFlag => self.flag = !self.flag,
637            ClFlag => self.flag = false,
638
639            AddF(data) => {
640                self.reg_f +=
641                    safe_transmute::<u64, f64, 8>(index_u64(self.memory.as_slice(), data));
642            }
643            SubF(data) => {
644                self.reg_f -=
645                    safe_transmute::<u64, f64, 8>(index_u64(self.memory.as_slice(), data));
646            }
647            MulF(data) => {
648                self.reg_f *=
649                    safe_transmute::<u64, f64, 8>(index_u64(self.memory.as_slice(), data));
650            }
651            DivF(data) => {
652                self.reg_f /=
653                    safe_transmute::<u64, f64, 8>(index_u64(self.memory.as_slice(), data));
654            }
655            ModF(data) => {
656                self.reg_f %=
657                    safe_transmute::<u64, f64, 8>(index_u64(self.memory.as_slice(), data));
658            }
659
660            StackAlloc(amount) => {
661                if self.stack.alloc(amount as usize).is_err() {
662                    self.flag = true;
663                }
664            }
665            StackDealloc(amount) => {
666                // SAFETY: we're only checking if it errors
667                if unsafe { self.stack.dealloc(amount as usize) }.is_err() {
668                    self.flag = true;
669                }
670            }
671
672            Push(data) => {
673                if self.stack.push_byte(self.memory[data as usize]).is_err() {
674                    self.flag = true;
675                }
676            }
677            Pushi(data) => {
678                if self.stack.push_byte(data).is_err() {
679                    self.flag = true;
680                }
681            }
682            Pop(data) => {
683                try_stack!(pop self.stack => pop_byte, self.memory[data as usize], self.flag => true);
684            }
685
686            Popa => {
687                try_stack!(pop self.stack => pop_byte, self.reg_a, self.flag => true);
688            }
689            Pusha => try_stack!(push self.stack => push_byte, self.reg_a, self.flag => true),
690
691            Popb => {
692                try_stack!(pop self.stack => pop_u16, fn |v| self.reg_b = safe_transmute(v), self.flag => true);
693            }
694            Pushb => {
695                try_stack!(push self.stack => push_bytes, &self.reg_b.to_be_bytes(), self.flag => true);
696            }
697
698            PopL => try_stack!(pop self.stack => pop_u16, self.reg_L, self.flag => true),
699            PushL => {
700                try_stack!(push self.stack => push_bytes, &self.reg_L.to_be_bytes(), self.flag => true);
701            }
702
703            Popf => {
704                try_stack!(pop self.stack => pop_u64, fn |v| self.reg_f = safe_transmute(v), self.flag => true);
705            }
706            Pushf => {
707                try_stack!(push self.stack => push_bytes, &self.reg_f.to_be_bytes(), self.flag => true);
708            }
709
710            Popch => {
711                // SAFETY: The VM machine code's author should gurantee that it's a valid character
712                try_stack!(pop self.stack => pop_u32, fn |v| self.reg_ch = unsafe { char::from_u32_unchecked(v) }, self.flag => true);
713            }
714            Pushch => {
715                try_stack!(push self.stack => push_bytes, &(self.reg_ch as u32).to_be_bytes(), self.flag => true);
716            }
717
718            Popnum => {
719                try_stack!(pop self.stack => pop_u32, fn |v| self.num_reg = safe_transmute(v), self.flag => true);
720            }
721            Pushnum => {
722                try_stack!(push self.stack => push_bytes, &self.num_reg.to_be_bytes(), self.flag => true);
723            }
724
725            Popep => {
726                try_stack!(pop self.stack => pop_u16, fn |v| self.reg_ep = safe_transmute(v), self.flag => true);
727            }
728            Zpopep => {
729                if self.reg_b == 0 {
730                    try_stack!(pop self.stack => pop_u16, fn |v| self.reg_ep = safe_transmute(v), self.flag => true);
731                }
732            }
733            Ppopep => {
734                if self.reg_b > 0 {
735                    try_stack!(pop self.stack => pop_u16, fn |v| self.reg_ep = safe_transmute(v), self.flag => true);
736                }
737            }
738            Npopep => {
739                if self.reg_b < 0 {
740                    try_stack!(pop self.stack => pop_u16, fn |v| self.reg_ep = safe_transmute(v), self.flag => true);
741                }
742            }
743            Fpopep => {
744                if self.flag {
745                    try_stack!(pop self.stack => pop_u16, fn |v| self.reg_ep = safe_transmute(v), self.flag => true);
746                }
747            }
748            Zapopep => {
749                if self.reg_a == 0 {
750                    try_stack!(pop self.stack => pop_u16, fn |v| self.reg_ep = safe_transmute(v), self.flag => true);
751                }
752            }
753            Dpopep => {
754                if self.debug_mode {
755                    try_stack!(pop self.stack => pop_u16, fn |v| self.reg_ep = safe_transmute(v), self.flag => true);
756                }
757            }
758
759            GetChar => 'block: {
760                use crossterm::{
761                    event::{self, Event, KeyCode, KeyEvent, KeyEventKind},
762                    terminal::{disable_raw_mode, enable_raw_mode},
763                };
764
765                if enable_raw_mode().is_err() {
766                    self.flag = true;
767                    break 'block;
768                };
769
770                loop {
771                    match event::read() {
772                        Ok(Event::Key(KeyEvent {
773                            code: KeyCode::Char(c),
774                            kind: KeyEventKind::Press,
775                            ..
776                        })) => {
777                            self.reg_ch = c;
778                            break;
779                        }
780                        Err(_) => self.flag = true,
781                        _ => (),
782                    }
783                }
784
785                if disable_raw_mode().is_err() {
786                    self.flag = true;
787                };
788            }
789
790            GetLine => 'block: {
791                if self.memory[self.reg_dp as usize] != b'.' {
792                    self.flag = true;
793                    break 'block;
794                }
795
796                let mut buf = String::with_capacity(255);
797                if std::io::stdin().take(255).read_to_string(&mut buf).is_err() {
798                    self.flag = true;
799
800                    break 'block;
801                }
802            }
803
804            WriteChar => 'block: {
805                if self.memory[self.reg_dp as usize] != b'.' {
806                    self.flag = true;
807                    break 'block;
808                }
809
810                self.num_debug();
811
812                let mut stdout = std::io::stdout();
813
814                let buf: &mut [u8; 4] = &mut [0, 0, 0, 0];
815                self.reg_ch.encode_utf8(buf);
816
817                if stdout.write_all(buf).is_err() {
818                    self.flag = true;
819                    break 'block;
820                }
821            }
822
823            WriteLineß => 'block: {
824                if self.memory[self.reg_dp as usize] != b'.' {
825                    self.flag = true;
826                    break 'block;
827                }
828
829                self.num_debug();
830                print!("{}", self.reg_ß);
831            }
832            WriteLine(data) => 'block: {
833                if self.memory[self.reg_dp as usize] != b'.' {
834                    self.flag = true;
835                    break 'block;
836                }
837
838                #[allow(clippy::multiple_unsafe_ops_per_block)]
839                // SAFETY: The VM machine code's author should guarantee that this doesn't lead to errors
840                let str = unsafe {
841                    std::ffi::CStr::from_ptr(self.memory.as_ptr().cast::<i8>().add(data as usize))
842                }
843                .to_string_lossy();
844
845                self.num_debug();
846                print!("{str}");
847            }
848
849            ToggleDebug => self.debug_mode = !self.debug_mode,
850
851            DebugMachineState => 'block: {
852                if self.memory[self.reg_dp as usize] != b'.' {
853                    self.flag = true;
854                    break 'block;
855                }
856
857                self.num_debug();
858                print!("{self:#?}");
859            }
860            DebugMachineStateCompact => 'block: {
861                if self.memory[self.reg_dp as usize] != b'.' {
862                    self.flag = true;
863                    break 'block;
864                }
865
866                self.num_debug();
867                print!("{self:?}");
868            }
869
870            DebugMemoryRegion(data0, data1) => 'block: {
871                if self.memory[self.reg_dp as usize] != b'.' {
872                    self.flag = true;
873                    break 'block;
874                }
875
876                self.num_debug();
877                print!("{:?}", &self.memory[(data0 as usize)..(data1 as usize)]);
878            }
879            DebugStackRegion(data0, data1) => 'block: {
880                if self.memory[self.reg_dp as usize] != b'.' {
881                    self.flag = true;
882                    break 'block;
883                }
884
885                self.num_debug();
886                print!("{:?}", &self.stack.vec[(data0 as usize)..(data1 as usize)]);
887            }
888            ShowChoice => 'block: {
889                if self.memory[self.reg_dp as usize] != b'.' {
890                    self.flag = true;
891                    break 'block;
892                }
893
894                self.num_debug();
895                if self
896                    .reg_Ω
897                    .display_illusion_of_choice(&mut std::io::stdout())
898                    .is_err()
899                {
900                    self.flag = true;
901                }
902            }
903        }
904    }
905
906    /// Loads instructions into the machine's memory
907    /// at the specified offset.
908    ///
909    /// Returns the amount of bytes written
910    pub fn load_instructions(&mut self, instructions: &[Instruction], mut offset: u16) -> u16 {
911        let last_idx = &mut offset;
912
913        for instruction in instructions {
914            self.load_instruction(*instruction, last_idx);
915        }
916        *last_idx
917    }
918    /// Loads data into the machine's memory
919    /// at the specified offset.
920    ///
921    /// Returns the amount of bytes written
922    pub fn load(&mut self, data: &[DataOrInstruction], mut offset: u16) -> u16 {
923        let last_idx = &mut offset;
924
925        for instruction in data {
926            match instruction {
927                DataOrInstruction::Instruction(instruction) => {
928                    self.load_instruction(*instruction, last_idx);
929                }
930                DataOrInstruction::Data(bytes) => {
931                    if let Some(v) = self.load_bytes(bytes, *last_idx) {
932                        *last_idx = v;
933                    }
934                }
935                #[allow(clippy::indexing_slicing)]
936                DataOrInstruction::ByteData(val) => {
937                    self.memory[*last_idx as usize] = *val;
938                    *last_idx = last_idx.wrapping_add(1);
939                }
940            }
941        }
942        *last_idx
943    }
944    /// Load bytes into the machine
945    /// at the specified offset.
946    ///
947    /// Returns the amount of bytes written
948    pub fn load_bytes(&mut self, bytes: &[u8], offset: u16) -> Option<u16> {
949        #[allow(clippy::arithmetic_side_effects)]
950        if bytes.len() + offset as usize > self.memory.len() {
951            return None;
952        }
953        // SAFETY: checked above
954        let ptr = unsafe { self.memory.as_mut_ptr().add(offset as usize) };
955
956        // SAFETY: checked above
957        unsafe {
958            copy(bytes.as_ptr(), ptr, bytes.len());
959        }
960
961        #[allow(clippy::cast_possible_truncation)]
962        Some(offset.wrapping_add(bytes.len() as u16))
963    }
964
965    /// Loads a single instruction into memory
966    /// at the specified offset, mutating it
967    /// based on the amount of bytes written.
968    #[allow(
969        clippy::too_many_lines,
970        clippy::cast_possible_truncation,
971        clippy::indexing_slicing
972    )]
973    pub fn load_instruction(&mut self, instruction: Instruction, offset: &mut u16) {
974        /// Load a byte into memory at the
975        /// specified index, incrementing it.
976        fn load_byte(memory: &mut [u8], index: &mut u16, value: u8) {
977            memory[*index as usize] = value;
978            *index = index.wrapping_add(1);
979        }
980        /// Load bytes into memory at the
981        /// specified index, incrementing it.
982        fn load_bytes(memory: &mut [u8], offset: &mut u16, bytes: &[u8]) {
983            for i in 0..bytes.len() {
984                memory[offset.wrapping_add(i as u16) as usize] = bytes[i];
985            }
986            *offset = offset.wrapping_add(bytes.len() as u16);
987        }
988
989        #[allow(clippy::enum_glob_use)]
990        use Instruction::*;
991        use InstructionKind as IK;
992        match instruction {
993            Nop => load_byte(self.memory.as_mut_slice(), offset, IK::Nop as u8),
994
995            Ldar(data) => {
996                load_byte(self.memory.as_mut_slice(), offset, IK::Ldar as u8);
997                load_bytes(self.memory.as_mut_slice(), offset, &data.to_be_bytes());
998            }
999            Sba => load_byte(self.memory.as_mut_slice(), offset, IK::Sba as u8),
1000
1001            Clř => load_byte(self.memory.as_mut_slice(), offset, IK::Clř as u8),
1002            Dumpř(data) => {
1003                load_byte(self.memory.as_mut_slice(), offset, IK::Dumpř as u8);
1004                load_bytes(self.memory.as_mut_slice(), offset, &data.to_be_bytes());
1005            }
1006            Movař(data) => {
1007                load_byte(self.memory.as_mut_slice(), offset, IK::Movař as u8);
1008                load_byte(self.memory.as_mut_slice(), offset, data);
1009            }
1010            Setř(data0, data1) => {
1011                load_byte(self.memory.as_mut_slice(), offset, IK::Setř as u8);
1012                load_byte(self.memory.as_mut_slice(), offset, data0);
1013                load_bytes(self.memory.as_mut_slice(), offset, &data1.to_be_bytes());
1014            }
1015            Setiř(data0, data1) => {
1016                load_byte(self.memory.as_mut_slice(), offset, IK::Setiř as u8);
1017                load_byte(self.memory.as_mut_slice(), offset, data0);
1018                load_byte(self.memory.as_mut_slice(), offset, safe_transmute(data1));
1019            }
1020            Ldř(data) => {
1021                load_byte(self.memory.as_mut_slice(), offset, IK::Ldř as u8);
1022                load_bytes(self.memory.as_mut_slice(), offset, &data.to_be_bytes());
1023            }
1024            Ldiř(arr) => {
1025                load_byte(self.memory.as_mut_slice(), offset, IK::Ldiř as u8);
1026                // SAFETY: the type changes from a non-invalidatable type to another non-invalidatable type.
1027                load_bytes(self.memory.as_mut_slice(), offset, unsafe {
1028                    #[allow(clippy::ref_as_ptr)]
1029                    &*(&arr as *const [i8] as *const [u8])
1030                });
1031            }
1032
1033            Clß => load_byte(self.memory.as_mut_slice(), offset, IK::Clß as u8),
1034            Dumpß(data) => {
1035                load_byte(self.memory.as_mut_slice(), offset, IK::Dumpß as u8);
1036                load_bytes(self.memory.as_mut_slice(), offset, &data.to_be_bytes());
1037            }
1038            Writeß(data0, data1) => {
1039                load_byte(self.memory.as_mut_slice(), offset, IK::Writeß as u8);
1040                load_bytes(self.memory.as_mut_slice(), offset, &data0.to_be_bytes());
1041                load_byte(self.memory.as_mut_slice(), offset, data1);
1042            }
1043            Movaß(data) => {
1044                load_byte(self.memory.as_mut_slice(), offset, IK::Movaß as u8);
1045                load_byte(self.memory.as_mut_slice(), offset, data);
1046            }
1047            Setß(data0, data1) => {
1048                load_byte(self.memory.as_mut_slice(), offset, IK::Setß as u8);
1049                load_bytes(self.memory.as_mut_slice(), offset, &data0.to_be_bytes());
1050                load_byte(self.memory.as_mut_slice(), offset, data1);
1051            }
1052            Setiß(data0, data1) => {
1053                load_byte(self.memory.as_mut_slice(), offset, IK::Setiß as u8);
1054                load_byte(self.memory.as_mut_slice(), offset, data0);
1055                load_byte(self.memory.as_mut_slice(), offset, data1);
1056            }
1057            Ldß(data) => {
1058                load_byte(self.memory.as_mut_slice(), offset, IK::Ldß as u8);
1059                load_bytes(self.memory.as_mut_slice(), offset, &data.to_be_bytes());
1060            }
1061            Pushß => load_byte(self.memory.as_mut_slice(), offset, IK::Pushß as u8),
1062            Popß => load_byte(self.memory.as_mut_slice(), offset, IK::Popß as u8),
1063            Lenßa => load_byte(self.memory.as_mut_slice(), offset, IK::Lenßa as u8),
1064
1065            Ldidp(data) => {
1066                load_byte(self.memory.as_mut_slice(), offset, IK::Ldidp as u8);
1067                load_bytes(self.memory.as_mut_slice(), offset, &data.to_be_bytes());
1068            }
1069
1070            ΩChoiceSet(data) => {
1071                load_byte(self.memory.as_mut_slice(), offset, IK::ΩChoiceSet as u8);
1072                // SAFETY: The VM machine code's author should gurantee that it's a valid representation
1073                load_byte(self.memory.as_mut_slice(), offset, unsafe {
1074                    #[allow(clippy::missing_transmute_annotations)]
1075                    transmute(data)
1076                });
1077            }
1078            ΩChoiceGetA => {
1079                load_byte(self.memory.as_mut_slice(), offset, IK::ΩChoiceGetA as u8);
1080            }
1081
1082            ΩGainAPolymorphicDesires => load_byte(
1083                self.memory.as_mut_slice(),
1084                offset,
1085                IK::ΩGainAPolymorphicDesires as u8,
1086            ),
1087            ΩLoseAPolymorphicDesires => load_byte(
1088                self.memory.as_mut_slice(),
1089                offset,
1090                IK::ΩLoseAPolymorphicDesires as u8,
1091            ),
1092            ΩPushPolymorphicDesires => load_byte(
1093                self.memory.as_mut_slice(),
1094                offset,
1095                IK::ΩPushPolymorphicDesires as u8,
1096            ),
1097
1098            Instruction::ΩTheEndIsNear => {
1099                load_byte(self.memory.as_mut_slice(), offset, IK::ΩTheEndIsNear as u8);
1100            }
1101            ΩSkipToTheChase => load_byte(
1102                self.memory.as_mut_slice(),
1103                offset,
1104                IK::ΩSkipToTheChase as u8,
1105            ),
1106
1107            ΩSetSentience(enable) => {
1108                load_byte(self.memory.as_mut_slice(), offset, IK::ΩSetSentience as u8);
1109                load_byte(self.memory.as_mut_slice(), offset, u8::from(enable));
1110            }
1111            ΩSetPaperclipProduction(enable) => {
1112                load_byte(
1113                    self.memory.as_mut_slice(),
1114                    offset,
1115                    IK::ΩSetPaperclipProduction as u8,
1116                );
1117                load_byte(self.memory.as_mut_slice(), offset, u8::from(enable));
1118            }
1119
1120            AddBL => load_byte(self.memory.as_mut_slice(), offset, IK::AddBL as u8),
1121            SubBL => load_byte(self.memory.as_mut_slice(), offset, IK::SubBL as u8),
1122            MulBL => load_byte(self.memory.as_mut_slice(), offset, IK::MulBL as u8),
1123            DivBL => load_byte(self.memory.as_mut_slice(), offset, IK::DivBL as u8),
1124            ModBL => load_byte(self.memory.as_mut_slice(), offset, IK::ModBL as u8),
1125
1126            NotL => load_byte(self.memory.as_mut_slice(), offset, IK::NotL as u8),
1127
1128            AndBL => load_byte(self.memory.as_mut_slice(), offset, IK::AndBL as u8),
1129            OrBL => load_byte(self.memory.as_mut_slice(), offset, IK::OrBL as u8),
1130            XorBL => load_byte(self.memory.as_mut_slice(), offset, IK::XorBL as u8),
1131
1132            CmpLB => load_byte(self.memory.as_mut_slice(), offset, IK::CmpLB as u8),
1133
1134            TgFlag => load_byte(self.memory.as_mut_slice(), offset, IK::TgFlag as u8),
1135            ClFlag => load_byte(self.memory.as_mut_slice(), offset, IK::ClFlag as u8),
1136
1137            AddF(data) => {
1138                load_byte(self.memory.as_mut_slice(), offset, IK::AddF as u8);
1139                load_bytes(self.memory.as_mut_slice(), offset, &data.to_be_bytes());
1140            }
1141            SubF(data) => {
1142                load_byte(self.memory.as_mut_slice(), offset, IK::SubF as u8);
1143                load_bytes(self.memory.as_mut_slice(), offset, &data.to_be_bytes());
1144            }
1145            MulF(data) => {
1146                load_byte(self.memory.as_mut_slice(), offset, IK::MulF as u8);
1147                load_bytes(self.memory.as_mut_slice(), offset, &data.to_be_bytes());
1148            }
1149            DivF(data) => {
1150                load_byte(self.memory.as_mut_slice(), offset, IK::DivF as u8);
1151                load_bytes(self.memory.as_mut_slice(), offset, &data.to_be_bytes());
1152            }
1153            ModF(data) => {
1154                load_byte(self.memory.as_mut_slice(), offset, IK::ModF as u8);
1155                load_bytes(self.memory.as_mut_slice(), offset, &data.to_be_bytes());
1156            }
1157
1158            StackAlloc(amount) => {
1159                load_byte(self.memory.as_mut_slice(), offset, IK::StackAlloc as u8);
1160                load_bytes(self.memory.as_mut_slice(), offset, &amount.to_be_bytes());
1161            }
1162            StackDealloc(amount) => {
1163                load_byte(self.memory.as_mut_slice(), offset, IK::StackDealloc as u8);
1164                load_bytes(self.memory.as_mut_slice(), offset, &amount.to_be_bytes());
1165            }
1166
1167            Push(data) => {
1168                load_byte(self.memory.as_mut_slice(), offset, IK::Push as u8);
1169                load_bytes(self.memory.as_mut_slice(), offset, &data.to_be_bytes());
1170            }
1171            Pushi(data) => {
1172                load_byte(self.memory.as_mut_slice(), offset, IK::Pushi as u8);
1173                load_bytes(self.memory.as_mut_slice(), offset, &data.to_be_bytes());
1174            }
1175            Pop(data) => {
1176                load_byte(self.memory.as_mut_slice(), offset, IK::Pop as u8);
1177                load_bytes(self.memory.as_mut_slice(), offset, &data.to_be_bytes());
1178            }
1179
1180            Popa => load_byte(self.memory.as_mut_slice(), offset, IK::Popa as u8),
1181            Pusha => load_byte(self.memory.as_mut_slice(), offset, IK::Pusha as u8),
1182
1183            Popb => load_byte(self.memory.as_mut_slice(), offset, IK::Popb as u8),
1184            Pushb => load_byte(self.memory.as_mut_slice(), offset, IK::Pushb as u8),
1185
1186            PopL => load_byte(self.memory.as_mut_slice(), offset, IK::PopL as u8),
1187            PushL => load_byte(self.memory.as_mut_slice(), offset, IK::PushL as u8),
1188
1189            Popf => load_byte(self.memory.as_mut_slice(), offset, IK::Popf as u8),
1190            Pushf => load_byte(self.memory.as_mut_slice(), offset, IK::Pushf as u8),
1191
1192            Popch => load_byte(self.memory.as_mut_slice(), offset, IK::Popch as u8),
1193            Pushch => load_byte(self.memory.as_mut_slice(), offset, IK::Pushch as u8),
1194
1195            Popnum => load_byte(self.memory.as_mut_slice(), offset, IK::Popnum as u8),
1196            Pushnum => load_byte(self.memory.as_mut_slice(), offset, IK::Pushnum as u8),
1197
1198            Popep => load_byte(self.memory.as_mut_slice(), offset, IK::Popep as u8),
1199            Zpopep => load_byte(self.memory.as_mut_slice(), offset, IK::Zpopep as u8),
1200            Ppopep => load_byte(self.memory.as_mut_slice(), offset, IK::Ppopep as u8),
1201            Npopep => load_byte(self.memory.as_mut_slice(), offset, IK::Npopep as u8),
1202            Fpopep => load_byte(self.memory.as_mut_slice(), offset, IK::Fpopep as u8),
1203            Zapopep => load_byte(self.memory.as_mut_slice(), offset, IK::Zapopep as u8),
1204            Dpopep => load_byte(self.memory.as_mut_slice(), offset, IK::Dpopep as u8),
1205
1206            GetChar => load_byte(self.memory.as_mut_slice(), offset, IK::GetChar as u8),
1207
1208            GetLine => load_byte(self.memory.as_mut_slice(), offset, IK::GetLine as u8),
1209
1210            WriteChar => load_byte(self.memory.as_mut_slice(), offset, IK::WriteChar as u8),
1211
1212            WriteLineß => {
1213                load_byte(self.memory.as_mut_slice(), offset, IK::WriteLineß as u8);
1214            }
1215
1216            WriteLine(data) => {
1217                load_byte(self.memory.as_mut_slice(), offset, IK::WriteLine as u8);
1218                load_bytes(self.memory.as_mut_slice(), offset, &data.to_be_bytes());
1219            }
1220
1221            ToggleDebug => {
1222                load_byte(self.memory.as_mut_slice(), offset, IK::ToggleDebug as u8);
1223            }
1224
1225            DebugMachineState => load_byte(
1226                self.memory.as_mut_slice(),
1227                offset,
1228                IK::DebugMachineState as u8,
1229            ),
1230            DebugMachineStateCompact => load_byte(
1231                self.memory.as_mut_slice(),
1232                offset,
1233                IK::DebugMachineStateCompact as u8,
1234            ),
1235            DebugMemoryRegion(data0, data1) => {
1236                load_byte(
1237                    self.memory.as_mut_slice(),
1238                    offset,
1239                    IK::DebugMemoryRegion as u8,
1240                );
1241                load_bytes(self.memory.as_mut_slice(), offset, &data0.to_be_bytes());
1242                load_bytes(self.memory.as_mut_slice(), offset, &data1.to_be_bytes());
1243            }
1244            DebugStackRegion(data0, data1) => {
1245                load_byte(
1246                    self.memory.as_mut_slice(),
1247                    offset,
1248                    IK::DebugStackRegion as u8,
1249                );
1250                load_bytes(self.memory.as_mut_slice(), offset, &data0.to_be_bytes());
1251                load_bytes(self.memory.as_mut_slice(), offset, &data1.to_be_bytes());
1252            }
1253            ShowChoice => load_byte(self.memory.as_mut_slice(), offset, IK::ShowChoice as u8),
1254        }
1255    }
1256
1257    /// Runs the machine until it halts
1258    /// via `Ωtheendisnear` and `Ωskiptothechase`.
1259    ///
1260    /// # Panics
1261    ///
1262    /// Panics if an invalid opcode (instruction) is stumbled upon
1263    /// with an esoteric message and an explaination for demistification.
1264    pub fn run(&mut self) -> u8 {
1265        while !self.halted {
1266            let instruction = self.fetch_instruction();
1267            #[allow(clippy::expect_used)]
1268            self.execute_instruction(instruction.expect(
1269                "EsotericVm.RuntimeException.FetchInstruction.NilInstruction.InvalidOpcode (bad instruction code)",
1270            ));
1271        }
1272        self.reg_a
1273    }
1274}