diff --git a/ic10emu/Cargo.lock b/ic10emu/Cargo.lock index 68150b7..f08f6e9 100644 --- a/ic10emu/Cargo.lock +++ b/ic10emu/Cargo.lock @@ -11,6 +11,18 @@ dependencies = [ "memchr", ] +[[package]] +name = "bumpalo" +version = "3.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + [[package]] name = "const-crc32" version = "1.3.0" @@ -32,6 +44,19 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" +[[package]] +name = "getrandom" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + [[package]] name = "heck" version = "0.4.1" @@ -44,12 +69,15 @@ version = "0.1.0" dependencies = [ "const-crc32", "convert_case", + "getrandom", "itertools", "phf", "phf_codegen", + "rand", "regex", "strum_macros", "thiserror", + "web-time", ] [[package]] @@ -61,12 +89,39 @@ dependencies = [ "either", ] +[[package]] +name = "js-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "libc" +version = "0.2.153" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" + [[package]] name = "memchr" version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + [[package]] name = "phf" version = "0.11.2" @@ -105,6 +160,12 @@ dependencies = [ "siphasher", ] +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + [[package]] name = "proc-macro2" version = "1.0.79" @@ -129,6 +190,18 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", "rand_core", ] @@ -137,6 +210,9 @@ name = "rand_core" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] [[package]] name = "regex" @@ -234,3 +310,73 @@ name = "unicode-segmentation" version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] diff --git a/ic10emu/Cargo.toml b/ic10emu/Cargo.toml index 28dface..9243a13 100644 --- a/ic10emu/Cargo.toml +++ b/ic10emu/Cargo.toml @@ -9,19 +9,23 @@ edition = "2021" crate-type = ["lib"] + + [dependencies] const-crc32 = "1.3.0" itertools = "0.12.1" phf = "0.11.2" +rand = "0.8.5" regex = "1.10.3" -# rust-sitter = "0.4.1" strum_macros = "0.26.2" thiserror = "1.0.58" +[target.'cfg(target_arch = "wasm32")'.dependencies] +web-time = "1.1.0" +getrandom = { version = "0.2", features = ["js"] } + [build-dependencies] convert_case = "0.6.0" phf_codegen = "0.11.2" regex = "1.10.3" -# rust-sitter-tool = "0.4.1" - diff --git a/ic10emu/src/grammar.rs b/ic10emu/src/grammar.rs index 7341d53..a27bce7 100644 --- a/ic10emu/src/grammar.rs +++ b/ic10emu/src/grammar.rs @@ -223,6 +223,30 @@ impl Operand { &Operand::DeviceSpec { .. } => Err(interpreter::ICError::DeviceNotValue), } } + + + pub fn get_value_i64(&self, ic: &interpreter::IC, signed: bool) -> Result { + let val = self.get_value(ic)?; + if val < -9.223372036854776E+18 { + Err(interpreter::ICError::ShiftUnderflowI64) + } else if val <= 9.223372036854776E+18 { + Ok(interpreter::f64_to_i64(val, signed)) + } else { + Err(interpreter::ICError::ShiftOverflowI64) + } + } + + pub fn get_value_i32(&self, ic: &interpreter::IC) -> Result { + let val = self.get_value(ic)?; + if val < -2147483648.0 { + Err(interpreter::ICError::ShiftUnderflowI32) + } else if val <= 2147483647.0 { + Ok(val as i32) + } else { + Err(interpreter::ICError::ShiftOverflowI32) + } + } + pub fn get_device_id( &self, ic: &interpreter::IC, diff --git a/ic10emu/src/interpreter.rs b/ic10emu/src/interpreter.rs index 8fe3b48..3139b23 100644 --- a/ic10emu/src/interpreter.rs +++ b/ic10emu/src/interpreter.rs @@ -1,12 +1,26 @@ use core::f64; -use std::{collections::HashMap, u32}; +use std::{ + collections::{HashMap, HashSet}, + u32, +}; -use crate::grammar; +use itertools::Itertools; +#[cfg(target_arch = "wasm32")] +use web_time as time; + +#[cfg(not(target_arch = "wasm32"))] +use std::time; + +use crate::grammar::{self, ParseError}; use thiserror::Error; #[derive(Debug, Error)] pub enum ICError { + #[error("Error Compileing Code: {0}")] + ParseError(#[from] ParseError), + #[error("")] + DuplicateLabel(String), #[error("")] InstructionPointerOutOfRange(u32), #[error("")] @@ -33,6 +47,28 @@ pub enum ICError { DeviceNotSet, #[error("")] OperandNotRegister, + #[error("")] + ShiftUnderflowI64, + #[error("")] + ShiftOverflowI64, + #[error("")] + ShiftUnderflowI32, + #[error("")] + ShiftOverflowI32, + #[error("")] + StackUnderflow, + #[error("")] + StackOverflow, + #[error("")] + DuplicateDefine(String), +} + +#[derive(Debug)] +pub enum ICState { + Running, + Yield, + Sleep(time::SystemTime, f64), + HasCaughtFire, } #[derive(Debug)] @@ -40,18 +76,20 @@ pub struct IC { pub id: u16, pub registers: [f64; 18], pub ip: u32, + pub ic: u16, pub stack: [f64; 512], pub aliases: HashMap, - pub labels: HashMap, + pub defines: HashMap, pub pins: [Option; 6], pub code: String, pub program: Program, - should_yield: bool, + pub state: ICState, } #[derive(Debug)] pub struct Program { - pub instructions: Vec, + pub instructions: Vec, + pub labels: HashMap, } impl Default for Program { @@ -64,15 +102,44 @@ impl Program { pub fn new() -> Self { Program { instructions: Vec::new(), + labels: HashMap::new(), } } - pub fn try_from_code(input: &str) -> Result { - let parse_tree = grammar::parse(&input)?; + pub fn try_from_code(code: &str) -> Result { + let parse_tree = grammar::parse(&code)?; + let mut labels_set = HashSet::new(); + let mut labels = HashMap::new(); + let instructions = parse_tree + .into_iter() + .enumerate() + .map(|(line_number, line)| match line.code { + None => Ok(grammar::Instruction { + instruction: grammar::InstructionOp::Nop, + operands: vec![], + }), + Some(code) => match code { + grammar::Code::Label(label) => { + if labels_set.contains(&label.id.name) { + Err(ICError::DuplicateLabel(label.id.name.clone())) + } else { + labels_set.insert(label.id.name.clone()); + labels.insert(label.id.name.clone(), line_number as u32); + Ok(grammar::Instruction { + instruction: grammar::InstructionOp::Nop, + operands: vec![], + }) + } + } + grammar::Code::Instruction(instruction) => Ok(instruction), + }, + }) + .try_collect()?; Ok(Program { - instructions: parse_tree, + instructions, + labels, }) } - pub fn get_line(&self, line: u32) -> Result<&grammar::Line, ICError> { + pub fn get_line(&self, line: u32) -> Result<&grammar::Instruction, ICError> { self.instructions .get(line as usize) .ok_or(ICError::InstructionPointerOutOfRange(line)) @@ -84,17 +151,39 @@ impl IC { IC { id, ip: 0, + ic: 0, registers: [0.0; 18], stack: [0.0; 512], pins: [None; 6], program: Program::new(), code: String::new(), aliases: HashMap::new(), - labels: HashMap::new(), - should_yield: false, + defines: HashMap::new(), + state: ICState::Running, } } + pub fn reset(&mut self) { + self.ip = 0; + self.ic = 0; + self.registers = [0.0; 18]; + self.stack = [0.0; 512]; + self.aliases = HashMap::new(); + self.defines = HashMap::new(); + self.state = ICState::Running; + } + + pub fn set_code(&mut self, code: &str) -> Result<(), ICError> { + let prog = Program::try_from_code(code)?; + self.ip = 0; + self.ic = 0; + self.aliases = HashMap::new(); + self.defines = HashMap::new(); + self.program = prog; + self.code = code.to_string(); + Ok(()) + } + pub fn get_real_target(&self, indirection: u32, target: u32) -> Result { let mut i = indirection; let mut t = target as f64; @@ -137,6 +226,10 @@ impl IC { pub fn get_ident_value(&self, ident: &str) -> Result { if let Some(operand) = self.aliases.get(ident) { operand.get_value(self) + } else if let Some(val) = self.defines.get(ident) { + Ok(*val) + } else if let Some(label) = self.program.labels.get(ident) { + Ok(*label as f64) } else { Err(ICError::UnknownIdentifier(ident.to_string())) } @@ -155,1900 +248,2625 @@ impl IC { self.registers[17] = self.ip as f64; } + fn push(&mut self, val: f64) -> Result { + let sp = (self.registers[16]) as i32; + if sp < 0 { + Err(ICError::StackUnderflow) + } else if sp >= 512 { + Err(ICError::StackOverflow) + } else { + let last = self.stack[sp as usize]; + self.stack[sp as usize] = val; + self.registers[16] += 1.0; + Ok(last) + } + } + + fn pop(&mut self) -> Result { + let sp = (self.registers[16]) as i32; + if sp < 0 { + Err(ICError::StackUnderflow) + } else if sp >= 512 { + Err(ICError::StackOverflow) + } else { + let last = self.stack[sp as usize]; + self.registers[16] -= 1.0; + Ok(last) + } + } + + fn poke(&mut self, address: f64, val: f64) -> Result { + let sp = address as i32; + if sp < 0 || sp >= 512 { + Err(ICError::StackIndexOutOfRange(address)) + } else { + let last = self.stack[sp as usize]; + self.stack[sp as usize] = val; + Ok(last) + } + } + + fn peek(&mut self) -> Result { + let sp = (self.registers[16]) as i32; + if sp < 0 { + Err(ICError::StackUnderflow) + } else if sp >= 512 { + Err(ICError::StackOverflow) + } else { + let last = self.stack[sp as usize]; + Ok(last) + } + } + /// processes one line of the contained program - pub fn step(&mut self, _housing: &mut crate::Device, _vm: &mut crate::VM) -> Result<(), ICError> { - use grammar::InstructionOp::*; + pub fn step( + &mut self, + _housing: &mut crate::Device, + vm: &mut crate::VM, + ) -> Result<(), ICError> { use grammar::*; use ICError::*; let line = self.program.get_line(self.ip)?; let mut next_ip = self.ip + 1; - let result: Result<(), ICError> = if let Some(code) = &line.code { - match code { - Code::Label(label) => { - self.labels.insert(label.id.name.clone(), self.ip); - Ok(()) - } - Code::Instruction(inst) => 'inst: { - match inst.instruction { - Nop => Ok(()), // not used, empty line - Label => Ok(()), // Not used - Sleep => Ok(()), // TODO - Yield => { - if inst.operands.len() != 0 { - Err(TooManyOperands { - provided: inst.operands.len() as u32, - desired: 0, - }) - } else { - self.should_yield = true; - Ok(()) - } - } - Define => match &inst.operands[..] { - [_op1] => Err(ToFewOperands { - provided: 1, - desired: 2, - }), - [name, number] => { - let &Operand::Identifier(ident) = &name else { - break 'inst Err(IncorrectOperandType { - index: 1, - desired: "Name".to_string(), - }); - }; - let &Operand::Number(num) = &number else { - break 'inst Err(IncorrectOperandType { - index: 2, - desired: "Number".to_string(), - }); - }; - self.aliases.insert( - ident.name.clone(), - Operand::Number(Number::Float(num.value())), - ); - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 3, - }), - }, - Alias => match &inst.operands[..] { - [_op1] => Err(ToFewOperands { - provided: 1, - desired: 2, - }), - [name, device_reg] => { - let &Operand::Identifier(ident) = &name else { - break 'inst Err(IncorrectOperandType { - index: 1, - desired: "Name".to_string(), - }); - }; - let alias = match &device_reg { - &Operand::RegisterSpec { - indirection, - target, - } => Operand::RegisterSpec { - indirection: *indirection, - target: *target, - }, - &Operand::DeviceSpec { device, channel } => { - Operand::DeviceSpec { - device: *device, - channel: *channel, - } - } - _ => { - break 'inst Err(IncorrectOperandType { - index: 2, - desired: "Device Or Register".to_string(), - }) - } - }; - self.aliases.insert(ident.name.clone(), alias); - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 2, - }), - }, - Move => match &inst.operands[..] { - [_op1] => Err(ToFewOperands { - provided: 1, - desired: 2, - }), - [reg, val] => { - let &Operand::RegisterSpec { - indirection, - target, - } = ® - else { - break 'inst Err(IncorrectOperandType { - index: 1, - desired: "Register".to_string(), - }); - }; - - let val = val.get_value(self)?; - self.set_register(*indirection, *target, val)?; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 2, - }), - }, - - Beq => match &inst.operands[..] { - oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 3, - }), - [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; - next_ip = if a == b { c as u32 } else { next_ip }; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 3, - }), - }, - Beqal => match &inst.operands[..] { - oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 3, - }), - [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; - next_ip = if a == b { c as u32 } else { next_ip }; - self.al(); - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 3, - }), - }, - Breq => match &inst.operands[..] { - oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 3, - }), - [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; - next_ip = if a == b { - (self.ip as f64 + c) as u32 - } else { - next_ip - }; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 3, - }), - }, - Beqz => match &inst.operands[..] { - oprs @ [_] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 2, - }), - [a, b] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - next_ip = if a == 0.0 { b as u32 } else { next_ip }; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 2, - }), - }, - Beqzal => match &inst.operands[..] { - oprs @ [_] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 2, - }), - [a, b] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - next_ip = if a == 0.0 { b as u32 } else { next_ip }; - self.al(); - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 2, - }), - }, - Breqz => match &inst.operands[..] { - oprs @ [_] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 2, - }), - [a, b] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - next_ip = if a == 0.0 { - (self.ip as f64 + b) as u32 - } else { - next_ip - }; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 2, - }), - }, - Bne => match &inst.operands[..] { - oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 3, - }), - [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; - next_ip = if a != b { c as u32 } else { next_ip }; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 3, - }), - }, - Bneal => match &inst.operands[..] { - oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 3, - }), - [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; - next_ip = if a != b { c as u32 } else { next_ip }; - self.al(); - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 3, - }), - }, - Brne => match &inst.operands[..] { - oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 3, - }), - [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; - next_ip = if a != b { - (self.ip as f64 + c) as u32 - } else { - next_ip - }; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 3, - }), - }, - Bnez => match &inst.operands[..] { - oprs @ [_] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 2, - }), - [a, b] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - next_ip = if a != 0.0 { b as u32 } else { next_ip }; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 2, - }), - }, - Bnezal => match &inst.operands[..] { - oprs @ [_] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 2, - }), - [a, b] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - next_ip = if a != 0.0 { b as u32 } else { next_ip }; - self.al(); - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 2, - }), - }, - Brnez => match &inst.operands[..] { - oprs @ [_] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 2, - }), - [a, b] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - next_ip = if a != 0.0 { - (self.ip as f64 + b) as u32 - } else { - next_ip - }; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 2, - }), - }, - Blt => match &inst.operands[..] { - oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 3, - }), - [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; - next_ip = if a < b { c as u32 } else { next_ip }; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 3, - }), - }, - Bltal => match &inst.operands[..] { - oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 3, - }), - [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; - next_ip = if a < b { c as u32 } else { next_ip }; - self.al(); - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 3, - }), - }, - Brlt => match &inst.operands[..] { - oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 3, - }), - [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; - next_ip = if a < b { - (self.ip as f64 + c) as u32 - } else { - next_ip - }; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 3, - }), - }, - Ble => match &inst.operands[..] { - oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 3, - }), - [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; - next_ip = if a <= b { c as u32 } else { next_ip }; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 3, - }), - }, - Bleal => match &inst.operands[..] { - oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 3, - }), - [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; - next_ip = if a <= b { c as u32 } else { next_ip }; - self.al(); - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 3, - }), - }, - Brle => match &inst.operands[..] { - oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 3, - }), - [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; - next_ip = if a <= b { - (self.ip as f64 + c) as u32 - } else { - next_ip - }; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 3, - }), - }, - Blez => match &inst.operands[..] { - oprs @ [_] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 2, - }), - [a, b] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - next_ip = if a <= 0.0 { b as u32 } else { next_ip }; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 2, - }), - }, - Blezal => match &inst.operands[..] { - oprs @ [_] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 2, - }), - [a, b] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - next_ip = if a <= 0.0 { b as u32 } else { next_ip }; - self.al(); - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 2, - }), - }, - Brlez => match &inst.operands[..] { - oprs @ [_] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 2, - }), - [a, b] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - next_ip = if a <= 0.0 { - (self.ip as f64 + b) as u32 - } else { - next_ip - }; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 2, - }), - }, - Bltz => match &inst.operands[..] { - oprs @ [_] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 2, - }), - [a, b] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - next_ip = if a < 0.0 { b as u32 } else { next_ip }; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 2, - }), - }, - Bltzal => match &inst.operands[..] { - oprs @ [_] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 2, - }), - [a, b] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - next_ip = if a < 0.0 { b as u32 } else { next_ip }; - self.al(); - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 2, - }), - }, - Brltz => match &inst.operands[..] { - oprs @ [_] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 2, - }), - [a, b] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - next_ip = if a < 0.0 { - (self.ip as f64 + b) as u32 - } else { - next_ip - }; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 2, - }), - }, - Bgt => match &inst.operands[..] { - oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 3, - }), - [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; - next_ip = if a > b { c as u32 } else { next_ip }; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 3, - }), - }, - Bgtal => match &inst.operands[..] { - oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 3, - }), - [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; - next_ip = if a > b { c as u32 } else { next_ip }; - self.al(); - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 3, - }), - }, - Brgt => match &inst.operands[..] { - oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 3, - }), - [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; - next_ip = if a > b { - (self.ip as f64 + c) as u32 - } else { - next_ip - }; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 3, - }), - }, - Bgtz => match &inst.operands[..] { - oprs @ [_] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 2, - }), - [a, b] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - next_ip = if a > 0.0 { b as u32 } else { next_ip }; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 2, - }), - }, - Bgtzal => match &inst.operands[..] { - oprs @ [_] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 2, - }), - [a, b] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - next_ip = if a > 0.0 { b as u32 } else { next_ip }; - self.al(); - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 2, - }), - }, - Brgtz => match &inst.operands[..] { - oprs @ [_] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 2, - }), - [a, b] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - next_ip = if a > 0.0 { - (self.ip as f64 + b) as u32 - } else { - next_ip - }; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 2, - }), - }, - Bge => match &inst.operands[..] { - oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 3, - }), - [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; - next_ip = if a >= b { c as u32 } else { next_ip }; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 3, - }), - }, - Bgeal => match &inst.operands[..] { - oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 3, - }), - [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; - next_ip = if a >= b { c as u32 } else { next_ip }; - self.al(); - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 3, - }), - }, - Brge => match &inst.operands[..] { - oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 3, - }), - [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; - next_ip = if a >= b { - (self.ip as f64 + c) as u32 - } else { - next_ip - }; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 3, - }), - }, - Bgez => match &inst.operands[..] { - oprs @ [_] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 2, - }), - [a, b] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - next_ip = if a >= 0.0 { b as u32 } else { next_ip }; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 2, - }), - }, - Bgezal => match &inst.operands[..] { - oprs @ [_] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 2, - }), - [a, b] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - next_ip = if a >= 0.0 { b as u32 } else { next_ip }; - self.al(); - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 2, - }), - }, - Brgez => match &inst.operands[..] { - oprs @ [_] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 2, - }), - [a, b] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - next_ip = if a >= 0.0 { - (self.ip as f64 + b) as u32 - } else { - next_ip - }; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 2, - }), - }, - Bap => match &inst.operands[..] { - oprs @ [_] | oprs @ [_, _] | oprs @ [_, _, _] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 4, - }), - [a, b, c, d] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; - let d = d.get_value(self)?; - next_ip = if f64::abs(a - b) - <= f64::max(c * f64::max(a.abs(), b.abs()), f64::EPSILON * 8.0) - { - d as u32 - } else { - next_ip - }; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 4, - }), - }, - Bapal => match &inst.operands[..] { - oprs @ [_] | oprs @ [_, _] | oprs @ [_, _, _] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 4, - }), - [a, b, c, d] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; - let d = d.get_value(self)?; - next_ip = if f64::abs(a - b) - <= f64::max(c * f64::max(a.abs(), b.abs()), f64::EPSILON * 8.0) - { - d as u32 - } else { - next_ip - }; - self.al(); - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 4, - }), - }, - Brap => match &inst.operands[..] { - oprs @ [_] | oprs @ [_, _] | oprs @ [_, _, _] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 4, - }), - [a, b, c, d] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; - let d = d.get_value(self)?; - next_ip = if f64::abs(a - b) - <= f64::max(c * f64::max(a.abs(), b.abs()), f64::EPSILON * 8.0) - { - (self.ip as f64 + d) as u32 - } else { - next_ip - }; - self.al(); - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 4, - }), - }, - Bapz => match &inst.operands[..] { - oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 3, - }), - [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; - next_ip = if a.abs() <= f64::max(b * a.abs(), f64::EPSILON * 8.0) { - c as u32 - } else { - next_ip - }; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 3, - }), - }, - Bapzal => match &inst.operands[..] { - oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 3, - }), - [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; - next_ip = if a.abs() <= f64::max(b * a.abs(), f64::EPSILON * 8.0) { - c as u32 - } else { - next_ip - }; - self.al(); - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 3, - }), - }, - Brapz => match &inst.operands[..] { - oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 3, - }), - [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; - next_ip = if a.abs() <= f64::max(b * a.abs(), f64::EPSILON * 8.0) { - (self.ip as f64 + c) as u32 - } else { - next_ip - }; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 3, - }), - }, - Bna => match &inst.operands[..] { - oprs @ [_] | oprs @ [_, _] | oprs @ [_, _, _] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 4, - }), - [a, b, c, d] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; - let d = d.get_value(self)?; - next_ip = if f64::abs(a - b) - > f64::max(c * f64::max(a.abs(), b.abs()), f64::EPSILON * 8.0) - { - d as u32 - } else { - next_ip - }; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 4, - }), - }, - Bnaal => match &inst.operands[..] { - oprs @ [_] | oprs @ [_, _] | oprs @ [_, _, _] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 4, - }), - [a, b, c, d] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; - let d = d.get_value(self)?; - next_ip = if f64::abs(a - b) - > f64::max(c * f64::max(a.abs(), b.abs()), f64::EPSILON * 8.0) - { - d as u32 - } else { - next_ip - }; - self.al(); - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 4, - }), - }, - Brna => match &inst.operands[..] { - oprs @ [_] | oprs @ [_, _] | oprs @ [_, _, _] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 4, - }), - [a, b, c, d] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; - let d = d.get_value(self)?; - next_ip = if f64::abs(a - b) - > f64::max(c * f64::max(a.abs(), b.abs()), f64::EPSILON * 8.0) - { - (self.ip as f64 + d) as u32 - } else { - next_ip - }; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 4, - }), - }, - Bnaz => match &inst.operands[..] { - oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 3, - }), - [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; - next_ip = if a.abs() > f64::max(b * a.abs(), f64::EPSILON * 8.0) { - c as u32 - } else { - next_ip - }; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 3, - }), - }, - Bnazal => match &inst.operands[..] { - oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 3, - }), - [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; - next_ip = if a.abs() > f64::max(b * a.abs(), f64::EPSILON * 8.0) { - c as u32 - } else { - next_ip - }; - self.al(); - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 3, - }), - }, - Brnaz => match &inst.operands[..] { - oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 3, - }), - [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; - next_ip = if a.abs() > f64::max(b * a.abs(), f64::EPSILON * 8.0) { - (self.ip as f64 + c) as u32 - } else { - next_ip - }; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 3, - }), - }, - Bdse => match &inst.operands[..] { - [_] => Err(ToFewOperands { - provided: 1, - desired: 2, - }), - [d, a] => { - let (device, _channel) = d.get_device_id(self)?; - let a = a.get_value(self)?; - next_ip = if device.is_some() { a as u32 } else { next_ip }; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 2, - }), - }, - Bdseal => match &inst.operands[..] { - [_] => Err(ToFewOperands { - provided: 1, - desired: 2, - }), - [d, a] => { - let (device, _channel) = d.get_device_id(self)?; - let a = a.get_value(self)?; - next_ip = if device.is_some() { a as u32 } else { next_ip }; - self.al(); - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 2, - }), - }, - Brdse => match &inst.operands[..] { - [_] => Err(ToFewOperands { - provided: 1, - desired: 2, - }), - [d, a] => { - let (device, _channel) = d.get_device_id(self)?; - let a = a.get_value(self)?; - next_ip = if device.is_some() { - (self.ip as f64 + a) as u32 - } else { - next_ip - }; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 2, - }), - }, - Bdns => match &inst.operands[..] { - [_] => Err(ToFewOperands { - provided: 1, - desired: 2, - }), - [d, a] => { - let (device, _channel) = d.get_device_id(self)?; - let a = a.get_value(self)?; - next_ip = if device.is_none() { a as u32 } else { next_ip }; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 2, - }), - }, - Bdnsal => match &inst.operands[..] { - [_] => Err(ToFewOperands { - provided: 1, - desired: 2, - }), - [d, a] => { - let (device, _channel) = d.get_device_id(self)?; - let a = a.get_value(self)?; - next_ip = if device.is_none() { a as u32 } else { next_ip }; - self.al(); - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 2, - }), - }, - Brdns => match &inst.operands[..] { - [_] => Err(ToFewOperands { - provided: 1, - desired: 2, - }), - [d, a] => { - let (device, _channel) = d.get_device_id(self)?; - let a = a.get_value(self)?; - next_ip = if device.is_none() { - (self.ip as f64 + a) as u32 - } else { - next_ip - }; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 2, - }), - }, - Bnan => match &inst.operands[..] { - oprs @ [_] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 2, - }), - [a, b] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - next_ip = if a.is_nan() { b as u32 } else { next_ip }; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 2, - }), - }, - Brnan => match &inst.operands[..] { - oprs @ [_] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 2, - }), - [a, b] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - next_ip = if a.is_nan() { - (self.ip as f64 + b) as u32 - } else { - next_ip - }; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 2, - }), - }, - - J => match &inst.operands[..] { - [a] => { - let a = a.get_value(self)?; - next_ip = a as u32; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 1, - }), - }, - Jal => match &inst.operands[..] { - [a] => { - let a = a.get_value(self)?; - next_ip = a as u32; - self.al(); - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 1, - }), - }, - Jr => match &inst.operands[..] { - [a] => { - let a = a.get_value(self)?; - next_ip = (self.ip as f64 + a) as u32; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 1, - }), - }, - - Seq => match &inst.operands[..] { - oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 3, - }), - [reg, a, b] => { - let &Operand::RegisterSpec { - indirection, - target, - } = reg - else { - break 'inst Err(OperandNotRegister); - }; - let a = a.get_value(self)?; - let b = b.get_value(self)?; - self.set_register( - indirection, - target, - if a == b { 1.0 } else { 0.0 }, - )?; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 3, - }), - }, - Seqz => match &inst.operands[..] { - oprs @ [_] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 3, - }), - [reg, a] => { - let &Operand::RegisterSpec { - indirection, - target, - } = reg - else { - break 'inst Err(OperandNotRegister); - }; - let a = a.get_value(self)?; - self.set_register( - indirection, - target, - if a == 0.0 { 1.0 } else { 0.0 }, - )?; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 3, - }), - }, - Sne => match &inst.operands[..] { - oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 3, - }), - [reg, a, b] => { - let &Operand::RegisterSpec { - indirection, - target, - } = reg - else { - break 'inst Err(OperandNotRegister); - }; - let a = a.get_value(self)?; - let b = b.get_value(self)?; - self.set_register( - indirection, - target, - if a != b { 1.0 } else { 0.0 }, - )?; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 3, - }), - }, - Snez => match &inst.operands[..] { - oprs @ [_] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 3, - }), - [reg, a] => { - let &Operand::RegisterSpec { - indirection, - target, - } = reg - else { - break 'inst Err(OperandNotRegister); - }; - let a = a.get_value(self)?; - self.set_register( - indirection, - target, - if a != 0.0 { 1.0 } else { 0.0 }, - )?; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 3, - }), - }, - Slt => match &inst.operands[..] { - oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 3, - }), - [reg, a, b] => { - let &Operand::RegisterSpec { - indirection, - target, - } = reg - else { - break 'inst Err(OperandNotRegister); - }; - let a = a.get_value(self)?; - let b = b.get_value(self)?; - self.set_register( - indirection, - target, - if a < b { 1.0 } else { 0.0 }, - )?; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 3, - }), - }, - Sltz => match &inst.operands[..] { - oprs @ [_] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 3, - }), - [reg, a] => { - let &Operand::RegisterSpec { - indirection, - target, - } = reg - else { - break 'inst Err(OperandNotRegister); - }; - let a = a.get_value(self)?; - self.set_register( - indirection, - target, - if a < 0.0 { 1.0 } else { 0.0 }, - )?; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 3, - }), - }, - Sle => match &inst.operands[..] { - oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 3, - }), - [reg, a, b] => { - let &Operand::RegisterSpec { - indirection, - target, - } = reg - else { - break 'inst Err(OperandNotRegister); - }; - let a = a.get_value(self)?; - let b = b.get_value(self)?; - self.set_register( - indirection, - target, - if a <= b { 1.0 } else { 0.0 }, - )?; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 3, - }), - }, - Slez => match &inst.operands[..] { - oprs @ [_] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 3, - }), - [reg, a] => { - let &Operand::RegisterSpec { - indirection, - target, - } = reg - else { - break 'inst Err(OperandNotRegister); - }; - let a = a.get_value(self)?; - self.set_register( - indirection, - target, - if a <= 0.0 { 1.0 } else { 0.0 }, - )?; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 3, - }), - }, - Sgt => match &inst.operands[..] { - oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 3, - }), - [reg, a, b] => { - let &Operand::RegisterSpec { - indirection, - target, - } = reg - else { - break 'inst Err(OperandNotRegister); - }; - let a = a.get_value(self)?; - let b = b.get_value(self)?; - self.set_register( - indirection, - target, - if a > b { 1.0 } else { 0.0 }, - )?; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 3, - }), - }, - Sgtz => match &inst.operands[..] { - oprs @ [_] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 3, - }), - [reg, a] => { - let &Operand::RegisterSpec { - indirection, - target, - } = reg - else { - break 'inst Err(OperandNotRegister); - }; - let a = a.get_value(self)?; - self.set_register( - indirection, - target, - if a > 0.0 { 1.0 } else { 0.0 }, - )?; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 3, - }), - }, - Sge => match &inst.operands[..] { - oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 3, - }), - [reg, a, b] => { - let &Operand::RegisterSpec { - indirection, - target, - } = reg - else { - break 'inst Err(OperandNotRegister); - }; - let a = a.get_value(self)?; - let b = b.get_value(self)?; - self.set_register( - indirection, - target, - if a >= b { 1.0 } else { 0.0 }, - )?; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 3, - }), - }, - Sgez => match &inst.operands[..] { - oprs @ [_] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 3, - }), - [reg, a] => { - let &Operand::RegisterSpec { - indirection, - target, - } = reg - else { - break 'inst Err(OperandNotRegister); - }; - let a = a.get_value(self)?; - self.set_register( - indirection, - target, - if a >= 0.0 { 1.0 } else { 0.0 }, - )?; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 3, - }), - }, - Sap => match &inst.operands[..] { - oprs @ [_] | oprs @ [_, _] | oprs @ [_, _, _] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 3, - }), - [reg, a, b, c] => { - let &Operand::RegisterSpec { - indirection, - target, - } = reg - else { - break 'inst Err(OperandNotRegister); - }; - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; - self.set_register( - indirection, - target, - if f64::abs(a - b) - <= f64::max( - c * f64::max(a.abs(), b.abs()), - f64::EPSILON * 8.0, - ) - { - 1.0 - } else { - 0.0 - }, - )?; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 3, - }), - }, - Sapz => match &inst.operands[..] { - oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 3, - }), - [reg, a, b] => { - let &Operand::RegisterSpec { - indirection, - target, - } = reg - else { - break 'inst Err(OperandNotRegister); - }; - let a = a.get_value(self)?; - let b = b.get_value(self)?; - self.set_register( - indirection, - target, - if a.abs() <= f64::max(b * a.abs(), f64::EPSILON * 8.0) { - 1.0 - } else { - 0.0 - }, - )?; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 3, - }), - }, - Sna => match &inst.operands[..] { - oprs @ [_] | oprs @ [_, _] | oprs @ [_, _, _] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 4, - }), - [reg, a, b, c] => { - let &Operand::RegisterSpec { - indirection, - target, - } = reg - else { - break 'inst Err(OperandNotRegister); - }; - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; - self.set_register( - indirection, - target, - if f64::abs(a - b) - > f64::max( - c * f64::max(a.abs(), b.abs()), - f64::EPSILON * 8.0, - ) - { - 1.0 - } else { - 0.0 - }, - )?; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 4, - }), - }, - Snaz => match &inst.operands[..] { - oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 3, - }), - [reg, a, b] => { - let &Operand::RegisterSpec { - indirection, - target, - } = reg - else { - break 'inst Err(OperandNotRegister); - }; - let a = a.get_value(self)?; - let b = b.get_value(self)?; - self.set_register( - indirection, - target, - if a.abs() > f64::max(b * a.abs(), f64::EPSILON * 8.0) { - 1.0 - } else { - 0.0 - }, - )?; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 3, - }), - }, - Sdse => match &inst.operands[..] { - oprs @ [_] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 2, - }), - [reg, device] => { - let &Operand::RegisterSpec { - indirection, - target, - } = reg - else { - break 'inst Err(OperandNotRegister); - }; - let (device, _channel) = device.get_device_id(self)?; - self.set_register( - indirection, - target, - if device.is_some() { 1.0 } else { 0.0 }, - )?; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 2, - }), - }, - Sdns => match &inst.operands[..] { - oprs @ [_] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 2, - }), - [reg, device] => { - let &Operand::RegisterSpec { - indirection, - target, - } = reg - else { - break 'inst Err(OperandNotRegister); - }; - let (device, _channel) = device.get_device_id(self)?; - self.set_register( - indirection, - target, - if device.is_none() { 1.0 } else { 0.0 }, - )?; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 2, - }), - }, - Snan => match &inst.operands[..] { - oprs @ [_] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 2, - }), - [reg, a] => { - let &Operand::RegisterSpec { - indirection, - target, - } = reg - else { - break 'inst Err(OperandNotRegister); - }; - let a = a.get_value(self)?; - self.set_register( - indirection, - target, - if a.is_nan() { 1.0 } else { 0.0 }, - )?; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 2, - }), - }, - Snanz => match &inst.operands[..] { - oprs @ [_] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 2, - }), - [reg, a] => { - let &Operand::RegisterSpec { - indirection, - target, - } = reg - else { - break 'inst Err(OperandNotRegister); - }; - let a = a.get_value(self)?; - self.set_register( - indirection, - target, - if a.is_nan() { 0.0 } else { 1.0 }, - )?; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 2, - }), - }, - - Select => match &inst.operands[..] { - oprs @ [_] | oprs @ [_, _] | oprs @ [_, _, _] => Err(ToFewOperands { - provided: oprs.len() as u32, - desired: 4, - }), - [reg, a, b, c] => { - let &Operand::RegisterSpec { - indirection, - target, - } = reg - else { - break 'inst Err(OperandNotRegister); - }; - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; - self.set_register( - indirection, - target, - if a != 0.0 { b } else { c }, - )?; - Ok(()) - } - oprs => Err(TooManyOperands { - provided: oprs.len() as u32, - desired: 4, - }), - }, - - - Push => Ok(()), - Pop => Ok(()), - Poke => Ok(()), - Peek => Ok(()), - Get => Ok(()), - Getd => Ok(()), - Put => Ok(()), - Putd => Ok(()), - - Sll => Ok(()), - Srl => Ok(()), - Sla => Ok(()), - Sra => Ok(()), - - And => Ok(()), - Or => Ok(()), - Xor => Ok(()), - Nor => Ok(()), - Not => Ok(()), - - Add => Ok(()), - Sub => Ok(()), - Mul => Ok(()), - Div => Ok(()), - Mod => Ok(()), - Exp => Ok(()), - Log => Ok(()), - Sqrt => Ok(()), - - Max => Ok(()), - Min => Ok(()), - Ceil => Ok(()), - Floor => Ok(()), - Abs => Ok(()), - Round => Ok(()), - Trunc => Ok(()), - - Rand => Ok(()), - - Sin => Ok(()), - Cos => Ok(()), - Tan => Ok(()), - Asin => Ok(()), - Acos => Ok(()), - Atan => Ok(()), - Atan2 => Ok(()), - - S => Ok(()), - Sd => Ok(()), - Ss => Ok(()), - Sb => Ok(()), - Sbs => Ok(()), - Sbn => Ok(()), - - L => Ok(()), - Ld => Ok(()), - Ls => Ok(()), - Lr => Ok(()), - Lb => Ok(()), - Lbn => Ok(()), - Lbns => Ok(()), - Lbs => Ok(()), - - Hcf => Ok(()), + let result: Result<(), ICError> = 'inst: { + use grammar::InstructionOp::*; + let operands = &line.operands; + match line.instruction { + Nop => Ok(()), + Label => Ok(()), // Not used + Hcf => Ok(()), // TODO + Sleep => match &operands[..] { + [a] => { + let a = a.get_value(self)?; + let now = time::SystemTime::now(); + self.state = ICState::Sleep(now, a); + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 1, + }), + }, // TODO + Yield => { + if operands.len() != 0 { + Err(TooManyOperands { + provided: operands.len() as u32, + desired: 0, + }) + } else { + self.state = ICState::Yield; + Ok(()) } } + Define => match &operands[..] { + [_op1] => Err(ToFewOperands { + provided: 1, + desired: 2, + }), + [name, number] => { + let &Operand::Identifier(ident) = &name else { + break 'inst Err(IncorrectOperandType { + index: 1, + desired: "Name".to_string(), + }); + }; + let &Operand::Number(num) = &number else { + break 'inst Err(IncorrectOperandType { + index: 2, + desired: "Number".to_string(), + }); + }; + if self.defines.contains_key(&ident.name) { + Err(DuplicateDefine(ident.name.clone())) + } else { + self.defines.insert(ident.name.clone(), num.value()); + Ok(()) + } + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Alias => match &operands[..] { + [_op1] => Err(ToFewOperands { + provided: 1, + desired: 2, + }), + [name, device_reg] => { + let &Operand::Identifier(ident) = &name else { + break 'inst Err(IncorrectOperandType { + index: 1, + desired: "Name".to_string(), + }); + }; + let alias = match &device_reg { + &Operand::RegisterSpec { + indirection, + target, + } => Operand::RegisterSpec { + indirection: *indirection, + target: *target, + }, + &Operand::DeviceSpec { device, channel } => Operand::DeviceSpec { + device: *device, + channel: *channel, + }, + _ => { + break 'inst Err(IncorrectOperandType { + index: 2, + desired: "Device Or Register".to_string(), + }) + } + }; + self.aliases.insert(ident.name.clone(), alias); + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + Move => match &operands[..] { + [_op1] => Err(ToFewOperands { + provided: 1, + desired: 2, + }), + [reg, val] => { + let &Operand::RegisterSpec { + indirection, + target, + } = ® + else { + break 'inst Err(IncorrectOperandType { + index: 1, + desired: "Register".to_string(), + }); + }; + + let val = val.get_value(self)?; + self.set_register(*indirection, *target, val)?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + + Beq => match &operands[..] { + oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [a, b, c] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + let c = c.get_value(self)?; + next_ip = if a == b { c as u32 } else { next_ip }; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Beqal => match &operands[..] { + oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [a, b, c] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + let c = c.get_value(self)?; + next_ip = if a == b { c as u32 } else { next_ip }; + self.al(); + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Breq => match &operands[..] { + oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [a, b, c] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + let c = c.get_value(self)?; + next_ip = if a == b { + (self.ip as f64 + c) as u32 + } else { + next_ip + }; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Beqz => match &operands[..] { + oprs @ [_] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 2, + }), + [a, b] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + next_ip = if a == 0.0 { b as u32 } else { next_ip }; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + Beqzal => match &operands[..] { + oprs @ [_] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 2, + }), + [a, b] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + next_ip = if a == 0.0 { b as u32 } else { next_ip }; + self.al(); + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + Breqz => match &operands[..] { + oprs @ [_] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 2, + }), + [a, b] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + next_ip = if a == 0.0 { + (self.ip as f64 + b) as u32 + } else { + next_ip + }; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + Bne => match &operands[..] { + oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [a, b, c] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + let c = c.get_value(self)?; + next_ip = if a != b { c as u32 } else { next_ip }; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Bneal => match &operands[..] { + oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [a, b, c] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + let c = c.get_value(self)?; + next_ip = if a != b { c as u32 } else { next_ip }; + self.al(); + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Brne => match &operands[..] { + oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [a, b, c] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + let c = c.get_value(self)?; + next_ip = if a != b { + (self.ip as f64 + c) as u32 + } else { + next_ip + }; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Bnez => match &operands[..] { + oprs @ [_] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 2, + }), + [a, b] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + next_ip = if a != 0.0 { b as u32 } else { next_ip }; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + Bnezal => match &operands[..] { + oprs @ [_] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 2, + }), + [a, b] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + next_ip = if a != 0.0 { b as u32 } else { next_ip }; + self.al(); + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + Brnez => match &operands[..] { + oprs @ [_] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 2, + }), + [a, b] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + next_ip = if a != 0.0 { + (self.ip as f64 + b) as u32 + } else { + next_ip + }; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + Blt => match &operands[..] { + oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [a, b, c] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + let c = c.get_value(self)?; + next_ip = if a < b { c as u32 } else { next_ip }; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Bltal => match &operands[..] { + oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [a, b, c] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + let c = c.get_value(self)?; + next_ip = if a < b { c as u32 } else { next_ip }; + self.al(); + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Brlt => match &operands[..] { + oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [a, b, c] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + let c = c.get_value(self)?; + next_ip = if a < b { + (self.ip as f64 + c) as u32 + } else { + next_ip + }; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Ble => match &operands[..] { + oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [a, b, c] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + let c = c.get_value(self)?; + next_ip = if a <= b { c as u32 } else { next_ip }; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Bleal => match &operands[..] { + oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [a, b, c] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + let c = c.get_value(self)?; + next_ip = if a <= b { c as u32 } else { next_ip }; + self.al(); + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Brle => match &operands[..] { + oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [a, b, c] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + let c = c.get_value(self)?; + next_ip = if a <= b { + (self.ip as f64 + c) as u32 + } else { + next_ip + }; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Blez => match &operands[..] { + oprs @ [_] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 2, + }), + [a, b] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + next_ip = if a <= 0.0 { b as u32 } else { next_ip }; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + Blezal => match &operands[..] { + oprs @ [_] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 2, + }), + [a, b] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + next_ip = if a <= 0.0 { b as u32 } else { next_ip }; + self.al(); + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + Brlez => match &operands[..] { + oprs @ [_] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 2, + }), + [a, b] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + next_ip = if a <= 0.0 { + (self.ip as f64 + b) as u32 + } else { + next_ip + }; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + Bltz => match &operands[..] { + oprs @ [_] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 2, + }), + [a, b] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + next_ip = if a < 0.0 { b as u32 } else { next_ip }; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + Bltzal => match &operands[..] { + oprs @ [_] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 2, + }), + [a, b] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + next_ip = if a < 0.0 { b as u32 } else { next_ip }; + self.al(); + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + Brltz => match &operands[..] { + oprs @ [_] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 2, + }), + [a, b] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + next_ip = if a < 0.0 { + (self.ip as f64 + b) as u32 + } else { + next_ip + }; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + Bgt => match &operands[..] { + oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [a, b, c] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + let c = c.get_value(self)?; + next_ip = if a > b { c as u32 } else { next_ip }; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Bgtal => match &operands[..] { + oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [a, b, c] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + let c = c.get_value(self)?; + next_ip = if a > b { c as u32 } else { next_ip }; + self.al(); + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Brgt => match &operands[..] { + oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [a, b, c] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + let c = c.get_value(self)?; + next_ip = if a > b { + (self.ip as f64 + c) as u32 + } else { + next_ip + }; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Bgtz => match &operands[..] { + oprs @ [_] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 2, + }), + [a, b] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + next_ip = if a > 0.0 { b as u32 } else { next_ip }; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + Bgtzal => match &operands[..] { + oprs @ [_] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 2, + }), + [a, b] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + next_ip = if a > 0.0 { b as u32 } else { next_ip }; + self.al(); + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + Brgtz => match &operands[..] { + oprs @ [_] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 2, + }), + [a, b] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + next_ip = if a > 0.0 { + (self.ip as f64 + b) as u32 + } else { + next_ip + }; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + Bge => match &operands[..] { + oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [a, b, c] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + let c = c.get_value(self)?; + next_ip = if a >= b { c as u32 } else { next_ip }; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Bgeal => match &operands[..] { + oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [a, b, c] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + let c = c.get_value(self)?; + next_ip = if a >= b { c as u32 } else { next_ip }; + self.al(); + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Brge => match &operands[..] { + oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [a, b, c] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + let c = c.get_value(self)?; + next_ip = if a >= b { + (self.ip as f64 + c) as u32 + } else { + next_ip + }; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Bgez => match &operands[..] { + oprs @ [_] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 2, + }), + [a, b] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + next_ip = if a >= 0.0 { b as u32 } else { next_ip }; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + Bgezal => match &operands[..] { + oprs @ [_] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 2, + }), + [a, b] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + next_ip = if a >= 0.0 { b as u32 } else { next_ip }; + self.al(); + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + Brgez => match &operands[..] { + oprs @ [_] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 2, + }), + [a, b] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + next_ip = if a >= 0.0 { + (self.ip as f64 + b) as u32 + } else { + next_ip + }; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + Bap => match &operands[..] { + oprs @ [_] | oprs @ [_, _] | oprs @ [_, _, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 4, + }), + [a, b, c, d] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + let c = c.get_value(self)?; + let d = d.get_value(self)?; + next_ip = if f64::abs(a - b) + <= f64::max(c * f64::max(a.abs(), b.abs()), f64::EPSILON * 8.0) + { + d as u32 + } else { + next_ip + }; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 4, + }), + }, + Bapal => match &operands[..] { + oprs @ [_] | oprs @ [_, _] | oprs @ [_, _, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 4, + }), + [a, b, c, d] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + let c = c.get_value(self)?; + let d = d.get_value(self)?; + next_ip = if f64::abs(a - b) + <= f64::max(c * f64::max(a.abs(), b.abs()), f64::EPSILON * 8.0) + { + d as u32 + } else { + next_ip + }; + self.al(); + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 4, + }), + }, + Brap => match &operands[..] { + oprs @ [_] | oprs @ [_, _] | oprs @ [_, _, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 4, + }), + [a, b, c, d] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + let c = c.get_value(self)?; + let d = d.get_value(self)?; + next_ip = if f64::abs(a - b) + <= f64::max(c * f64::max(a.abs(), b.abs()), f64::EPSILON * 8.0) + { + (self.ip as f64 + d) as u32 + } else { + next_ip + }; + self.al(); + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 4, + }), + }, + Bapz => match &operands[..] { + oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [a, b, c] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + let c = c.get_value(self)?; + next_ip = if a.abs() <= f64::max(b * a.abs(), f64::EPSILON * 8.0) { + c as u32 + } else { + next_ip + }; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Bapzal => match &operands[..] { + oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [a, b, c] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + let c = c.get_value(self)?; + next_ip = if a.abs() <= f64::max(b * a.abs(), f64::EPSILON * 8.0) { + c as u32 + } else { + next_ip + }; + self.al(); + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Brapz => match &operands[..] { + oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [a, b, c] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + let c = c.get_value(self)?; + next_ip = if a.abs() <= f64::max(b * a.abs(), f64::EPSILON * 8.0) { + (self.ip as f64 + c) as u32 + } else { + next_ip + }; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Bna => match &operands[..] { + oprs @ [_] | oprs @ [_, _] | oprs @ [_, _, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 4, + }), + [a, b, c, d] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + let c = c.get_value(self)?; + let d = d.get_value(self)?; + next_ip = if f64::abs(a - b) + > f64::max(c * f64::max(a.abs(), b.abs()), f64::EPSILON * 8.0) + { + d as u32 + } else { + next_ip + }; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 4, + }), + }, + Bnaal => match &operands[..] { + oprs @ [_] | oprs @ [_, _] | oprs @ [_, _, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 4, + }), + [a, b, c, d] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + let c = c.get_value(self)?; + let d = d.get_value(self)?; + next_ip = if f64::abs(a - b) + > f64::max(c * f64::max(a.abs(), b.abs()), f64::EPSILON * 8.0) + { + d as u32 + } else { + next_ip + }; + self.al(); + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 4, + }), + }, + Brna => match &operands[..] { + oprs @ [_] | oprs @ [_, _] | oprs @ [_, _, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 4, + }), + [a, b, c, d] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + let c = c.get_value(self)?; + let d = d.get_value(self)?; + next_ip = if f64::abs(a - b) + > f64::max(c * f64::max(a.abs(), b.abs()), f64::EPSILON * 8.0) + { + (self.ip as f64 + d) as u32 + } else { + next_ip + }; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 4, + }), + }, + Bnaz => match &operands[..] { + oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [a, b, c] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + let c = c.get_value(self)?; + next_ip = if a.abs() > f64::max(b * a.abs(), f64::EPSILON * 8.0) { + c as u32 + } else { + next_ip + }; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Bnazal => match &operands[..] { + oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [a, b, c] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + let c = c.get_value(self)?; + next_ip = if a.abs() > f64::max(b * a.abs(), f64::EPSILON * 8.0) { + c as u32 + } else { + next_ip + }; + self.al(); + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Brnaz => match &operands[..] { + oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [a, b, c] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + let c = c.get_value(self)?; + next_ip = if a.abs() > f64::max(b * a.abs(), f64::EPSILON * 8.0) { + (self.ip as f64 + c) as u32 + } else { + next_ip + }; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Bdse => match &operands[..] { + [_] => Err(ToFewOperands { + provided: 1, + desired: 2, + }), + [d, a] => { + let (device, _channel) = d.get_device_id(self)?; + let a = a.get_value(self)?; + next_ip = if device.is_some() { a as u32 } else { next_ip }; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + Bdseal => match &operands[..] { + [_] => Err(ToFewOperands { + provided: 1, + desired: 2, + }), + [d, a] => { + let (device, _channel) = d.get_device_id(self)?; + let a = a.get_value(self)?; + next_ip = if device.is_some() { a as u32 } else { next_ip }; + self.al(); + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + Brdse => match &operands[..] { + [_] => Err(ToFewOperands { + provided: 1, + desired: 2, + }), + [d, a] => { + let (device, _channel) = d.get_device_id(self)?; + let a = a.get_value(self)?; + next_ip = if device.is_some() { + (self.ip as f64 + a) as u32 + } else { + next_ip + }; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + Bdns => match &operands[..] { + [_] => Err(ToFewOperands { + provided: 1, + desired: 2, + }), + [d, a] => { + let (device, _channel) = d.get_device_id(self)?; + let a = a.get_value(self)?; + next_ip = if device.is_none() { a as u32 } else { next_ip }; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + Bdnsal => match &operands[..] { + [_] => Err(ToFewOperands { + provided: 1, + desired: 2, + }), + [d, a] => { + let (device, _channel) = d.get_device_id(self)?; + let a = a.get_value(self)?; + next_ip = if device.is_none() { a as u32 } else { next_ip }; + self.al(); + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + Brdns => match &operands[..] { + [_] => Err(ToFewOperands { + provided: 1, + desired: 2, + }), + [d, a] => { + let (device, _channel) = d.get_device_id(self)?; + let a = a.get_value(self)?; + next_ip = if device.is_none() { + (self.ip as f64 + a) as u32 + } else { + next_ip + }; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + Bnan => match &operands[..] { + oprs @ [_] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 2, + }), + [a, b] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + next_ip = if a.is_nan() { b as u32 } else { next_ip }; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + Brnan => match &operands[..] { + oprs @ [_] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 2, + }), + [a, b] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + next_ip = if a.is_nan() { + (self.ip as f64 + b) as u32 + } else { + next_ip + }; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + + J => match &operands[..] { + [a] => { + let a = a.get_value(self)?; + next_ip = a as u32; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 1, + }), + }, + Jal => match &operands[..] { + [a] => { + let a = a.get_value(self)?; + next_ip = a as u32; + self.al(); + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 1, + }), + }, + Jr => match &operands[..] { + [a] => { + let a = a.get_value(self)?; + next_ip = (self.ip as f64 + a) as u32; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 1, + }), + }, + + Seq => match &operands[..] { + oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [reg, a, b] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value(self)?; + let b = b.get_value(self)?; + self.set_register(indirection, target, if a == b { 1.0 } else { 0.0 })?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Seqz => match &operands[..] { + oprs @ [_] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [reg, a] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value(self)?; + self.set_register(indirection, target, if a == 0.0 { 1.0 } else { 0.0 })?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Sne => match &operands[..] { + oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [reg, a, b] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value(self)?; + let b = b.get_value(self)?; + self.set_register(indirection, target, if a != b { 1.0 } else { 0.0 })?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Snez => match &operands[..] { + oprs @ [_] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [reg, a] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value(self)?; + self.set_register(indirection, target, if a != 0.0 { 1.0 } else { 0.0 })?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Slt => match &operands[..] { + oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [reg, a, b] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value(self)?; + let b = b.get_value(self)?; + self.set_register(indirection, target, if a < b { 1.0 } else { 0.0 })?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Sltz => match &operands[..] { + oprs @ [_] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [reg, a] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value(self)?; + self.set_register(indirection, target, if a < 0.0 { 1.0 } else { 0.0 })?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Sle => match &operands[..] { + oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [reg, a, b] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value(self)?; + let b = b.get_value(self)?; + self.set_register(indirection, target, if a <= b { 1.0 } else { 0.0 })?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Slez => match &operands[..] { + oprs @ [_] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [reg, a] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value(self)?; + self.set_register(indirection, target, if a <= 0.0 { 1.0 } else { 0.0 })?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Sgt => match &operands[..] { + oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [reg, a, b] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value(self)?; + let b = b.get_value(self)?; + self.set_register(indirection, target, if a > b { 1.0 } else { 0.0 })?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Sgtz => match &operands[..] { + oprs @ [_] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [reg, a] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value(self)?; + self.set_register(indirection, target, if a > 0.0 { 1.0 } else { 0.0 })?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Sge => match &operands[..] { + oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [reg, a, b] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value(self)?; + let b = b.get_value(self)?; + self.set_register(indirection, target, if a >= b { 1.0 } else { 0.0 })?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Sgez => match &operands[..] { + oprs @ [_] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [reg, a] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value(self)?; + self.set_register(indirection, target, if a >= 0.0 { 1.0 } else { 0.0 })?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Sap => match &operands[..] { + oprs @ [_] | oprs @ [_, _] | oprs @ [_, _, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [reg, a, b, c] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value(self)?; + let b = b.get_value(self)?; + let c = c.get_value(self)?; + self.set_register( + indirection, + target, + if f64::abs(a - b) + <= f64::max(c * f64::max(a.abs(), b.abs()), f64::EPSILON * 8.0) + { + 1.0 + } else { + 0.0 + }, + )?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Sapz => match &operands[..] { + oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [reg, a, b] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value(self)?; + let b = b.get_value(self)?; + self.set_register( + indirection, + target, + if a.abs() <= f64::max(b * a.abs(), f64::EPSILON * 8.0) { + 1.0 + } else { + 0.0 + }, + )?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Sna => match &operands[..] { + oprs @ [_] | oprs @ [_, _] | oprs @ [_, _, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 4, + }), + [reg, a, b, c] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value(self)?; + let b = b.get_value(self)?; + let c = c.get_value(self)?; + self.set_register( + indirection, + target, + if f64::abs(a - b) + > f64::max(c * f64::max(a.abs(), b.abs()), f64::EPSILON * 8.0) + { + 1.0 + } else { + 0.0 + }, + )?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 4, + }), + }, + Snaz => match &operands[..] { + oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [reg, a, b] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value(self)?; + let b = b.get_value(self)?; + self.set_register( + indirection, + target, + if a.abs() > f64::max(b * a.abs(), f64::EPSILON * 8.0) { + 1.0 + } else { + 0.0 + }, + )?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Sdse => match &operands[..] { + oprs @ [_] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 2, + }), + [reg, device] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let (device, _channel) = device.get_device_id(self)?; + self.set_register( + indirection, + target, + if device.is_some() { 1.0 } else { 0.0 }, + )?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + Sdns => match &operands[..] { + oprs @ [_] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 2, + }), + [reg, device] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let (device, _channel) = device.get_device_id(self)?; + self.set_register( + indirection, + target, + if device.is_none() { 1.0 } else { 0.0 }, + )?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + Snan => match &operands[..] { + oprs @ [_] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 2, + }), + [reg, a] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value(self)?; + self.set_register(indirection, target, if a.is_nan() { 1.0 } else { 0.0 })?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + Snanz => match &operands[..] { + oprs @ [_] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 2, + }), + [reg, a] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value(self)?; + self.set_register(indirection, target, if a.is_nan() { 0.0 } else { 1.0 })?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + + Select => match &operands[..] { + oprs @ [_] | oprs @ [_, _] | oprs @ [_, _, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 4, + }), + [reg, a, b, c] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value(self)?; + let b = b.get_value(self)?; + let c = c.get_value(self)?; + self.set_register(indirection, target, if a != 0.0 { b } else { c })?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 4, + }), + }, + + Add => match &operands[..] { + oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [reg, a, b] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value(self)?; + let b = b.get_value(self)?; + self.set_register(indirection, target, a + b)?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Sub => match &operands[..] { + oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [reg, a, b] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value(self)?; + let b = b.get_value(self)?; + self.set_register(indirection, target, a - b)?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Mul => match &operands[..] { + oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [reg, a, b] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value(self)?; + let b = b.get_value(self)?; + self.set_register(indirection, target, a * b)?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Div => match &operands[..] { + oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [reg, a, b] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value(self)?; + let b = b.get_value(self)?; + self.set_register(indirection, target, a / b)?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Mod => match &operands[..] { + oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [reg, a, b] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value(self)?; + let b = b.get_value(self)?; + self.set_register(indirection, target, ((a % b) + b) % b)?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Exp => match &operands[..] { + oprs @ [_] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 2, + }), + [reg, a] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value(self)?; + self.set_register(indirection, target, f64::exp(a))?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + Log => match &operands[..] { + oprs @ [_] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 2, + }), + [reg, a] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value(self)?; + self.set_register(indirection, target, f64::ln(a))?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + Sqrt => match &operands[..] { + oprs @ [_] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 2, + }), + [reg, a] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value(self)?; + self.set_register(indirection, target, f64::sqrt(a))?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + + Max => match &operands[..] { + oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [reg, a, b] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value(self)?; + let b = b.get_value(self)?; + self.set_register(indirection, target, f64::max(a, b))?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Min => match &operands[..] { + oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [reg, a, b] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value(self)?; + let b = b.get_value(self)?; + self.set_register(indirection, target, f64::min(a, b))?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Ceil => match &operands[..] { + oprs @ [_] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 2, + }), + [reg, a] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value(self)?; + self.set_register(indirection, target, f64::ceil(a))?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + Floor => match &operands[..] { + oprs @ [_] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 2, + }), + [reg, a] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value(self)?; + self.set_register(indirection, target, f64::floor(a))?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + Abs => match &operands[..] { + oprs @ [_] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 2, + }), + [reg, a] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value(self)?; + self.set_register(indirection, target, f64::abs(a))?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + Round => match &operands[..] { + oprs @ [_] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 2, + }), + [reg, a] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value(self)?; + self.set_register(indirection, target, f64::round(a))?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + Trunc => match &operands[..] { + oprs @ [_] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 2, + }), + [reg, a] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value(self)?; + self.set_register(indirection, target, f64::trunc(a))?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + + Rand => match &operands[..] { + [reg] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let val = vm.random.next_f64(); + self.set_register(indirection, target, val)?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 1, + }), + }, + + Sin => match &operands[..] { + oprs @ [_] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 2, + }), + [reg, a] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value(self)?; + self.set_register(indirection, target, f64::sin(a))?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + Cos => match &operands[..] { + oprs @ [_] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 2, + }), + [reg, a] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value(self)?; + self.set_register(indirection, target, f64::cos(a))?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + Tan => match &operands[..] { + oprs @ [_] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 2, + }), + [reg, a] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value(self)?; + self.set_register(indirection, target, f64::tan(a))?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + Asin => match &operands[..] { + oprs @ [_] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 2, + }), + [reg, a] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value(self)?; + self.set_register(indirection, target, f64::asin(a))?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + Acos => match &operands[..] { + oprs @ [_] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 2, + }), + [reg, a] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value(self)?; + self.set_register(indirection, target, f64::acos(a))?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + Atan => match &operands[..] { + oprs @ [_] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 2, + }), + [reg, a] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value(self)?; + self.set_register(indirection, target, f64::atan(a))?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + Atan2 => match &operands[..] { + oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [reg, a, b] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value(self)?; + let b = b.get_value(self)?; + self.set_register(indirection, target, f64::atan2(a, b))?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + + Sll | Sla => match &operands[..] { + oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [reg, a, b] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value_i64(self, true)?; + let b = b.get_value_i32(self)?; + self.set_register(indirection, target, i64_to_f64(a << b))?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Srl => match &operands[..] { + oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [reg, a, b] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value_i64(self, false)?; + let b = b.get_value_i32(self)?; + self.set_register(indirection, target, i64_to_f64((a as u64 >> b) as i64))?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Sra => match &operands[..] { + oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [reg, a, b] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value_i64(self, true)?; + let b = b.get_value_i32(self)?; + self.set_register(indirection, target, i64_to_f64(a >> b))?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + + And => match &operands[..] { + oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [reg, a, b] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value_i64(self, true)?; + let b = b.get_value_i64(self, true)?; + self.set_register(indirection, target, i64_to_f64(a & b))?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Or => match &operands[..] { + oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [reg, a, b] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value_i64(self, true)?; + let b = b.get_value_i64(self, true)?; + self.set_register(indirection, target, i64_to_f64(a | b))?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Xor => match &operands[..] { + oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [reg, a, b] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value_i64(self, true)?; + let b = b.get_value_i64(self, true)?; + self.set_register(indirection, target, i64_to_f64(a ^ b))?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Nor => match &operands[..] { + oprs @ [_] | oprs @ [_, _] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 3, + }), + [reg, a, b] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value_i64(self, true)?; + let b = b.get_value_i64(self, true)?; + self.set_register(indirection, target, i64_to_f64(!(a | b)))?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 3, + }), + }, + Not => match &operands[..] { + oprs @ [_] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 2, + }), + [reg, a] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let a = a.get_value_i64(self, true)?; + self.set_register(indirection, target, i64_to_f64(!a))?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + + Push => match &operands[..] { + [a] => { + let a = a.get_value(self)?; + self.push(a)?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 1, + }), + }, + Pop => match &operands[..] { + [reg] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let val = self.pop()?; + self.set_register(indirection, target, val)?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 1, + }), + }, + Poke => match &operands[..] { + oprs @ [_] => Err(ToFewOperands { + provided: oprs.len() as u32, + desired: 2, + }), + [a, b] => { + let a = a.get_value(self)?; + let b = b.get_value(self)?; + self.poke(a, b)?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 2, + }), + }, + Peek => match &operands[..] { + [reg] => { + let &Operand::RegisterSpec { + indirection, + target, + } = reg + else { + break 'inst Err(OperandNotRegister); + }; + let val = self.peek()?; + self.set_register(indirection, target, val)?; + Ok(()) + } + oprs => Err(TooManyOperands { + provided: oprs.len() as u32, + desired: 1, + }), + }, + + Get => Ok(()), + Getd => Ok(()), + Put => Ok(()), + Putd => Ok(()), + + S => Ok(()), + Sd => Ok(()), + Ss => Ok(()), + Sb => Ok(()), + Sbs => Ok(()), + Sbn => Ok(()), + + L => Ok(()), + Ld => Ok(()), + Ls => Ok(()), + Lr => Ok(()), + Lb => Ok(()), + Lbn => Ok(()), + Lbns => Ok(()), + Lbs => Ok(()), } - } else { - Ok(()) }; self.ip = next_ip; result } } + +pub fn f64_to_i64(f: f64, signed: bool) -> i64 { + let mut num: i64 = (f % 9007199254740992.0) as i64; + if !signed { + num &= 18014398509481983_i64 + } + num +} + +pub fn i64_to_f64(i: i64) -> f64 { + let flag: bool = (i & 9007199254740992_i64) != 0; + let mut i = i & 9007199254740991_i64; + if flag { + i &= -9007199254740992_i64 + } + i as f64 +} diff --git a/ic10emu/src/lib.rs b/ic10emu/src/lib.rs index 429bd99..ea51beb 100644 --- a/ic10emu/src/lib.rs +++ b/ic10emu/src/lib.rs @@ -5,6 +5,7 @@ use std::collections::{HashMap, HashSet}; mod tokens; mod grammar; mod interpreter; +mod rand_mscorlib; use thiserror::Error; @@ -14,8 +15,8 @@ pub enum VMError { UnknownId(u16), #[error("Device with id '{0}' does not have a IC Slot")] NoIC(u16), - #[error("Code did not compile")] - ParseError(#[from] grammar::ParseError) + #[error("IC encoutered an error: {0}")] + ICError(#[from] interpreter::ICError) } @@ -71,6 +72,7 @@ pub struct VM { pub devices: HashMap, pub networks: Vec, id_gen: IdSequenceGenerator, + random: crate::rand_mscorlib::Random, } impl Default for Network { @@ -104,6 +106,7 @@ impl VM { devices: HashMap::new(), networks: vec![default_network], id_gen, + random: crate::rand_mscorlib::Random::new(), }; vm.add_ic(); vm diff --git a/ic10emu/src/rand_mscorlib.rs b/ic10emu/src/rand_mscorlib.rs new file mode 100644 index 0000000..6d8e145 --- /dev/null +++ b/ic10emu/src/rand_mscorlib.rs @@ -0,0 +1,108 @@ +use std::usize; + +const MSEED: i32 = 161803398; +// const MZ: i32 = 0; + +#[derive(Debug)] +pub struct Random { + inext: i32, + inextp: i32, + seed_array: [i32; 56], +} + + +/// Partial implementation of mscorlib System.Random +/// https://github.com/microsoft/referencesource/blob/master/mscorlib/system/random.cs#L94 +impl Random { + pub fn new() -> Self { + Self::with_seed(rand::random::()) + } + + pub fn with_seed(seed: i32) -> Self { + let subtraction: i32 = if seed == i32::MIN { + i32::MAX + } else { + seed.abs() + }; + let mut mj = MSEED - subtraction; + let mut seed_array: [i32; 56] = [0; 56]; + seed_array[55] = mj; + let mut mk: i32 = 1; + + for i in 1_usize..55 { + let ii = (21 * i) % 55; + seed_array[ii] = mk; + mk = mj - mk; + if mk < 0 { + mk += i32::MAX; + } + mj = seed_array[ii]; + } + for _k in 1_usize..5 { + for i in 1_usize..56 { + seed_array[i] -= seed_array[1 + (i + 30) % 55]; + if seed_array[i] < 0 { + seed_array[i] += i32::MAX; + } + } + } + let inext = 0; + let inextp = 21; + // seed = 1; + Random { + inext, + inextp, + seed_array, + } + } + + pub fn sample(&mut self) -> f64 { + (self.internal_sample() as f64) * (1.0 / (i32::MAX as f64)) + } + + fn internal_sample(&mut self) -> i32 { + let mut inext = self.inext; + let mut inextp = self.inextp; + + if { + inext += 1; + inext + } >= 56 + { + inext = 1; + } + if { + inextp += 1; + inextp + } >= 56 + { + inextp = 1; + } + + let mut retval = self.seed_array[inext as usize] - self.seed_array[inextp as usize]; + + if retval == i32::MAX { + retval -= 1; + } + if retval < 0 { + retval += i32::MAX; + } + self.seed_array[inext as usize] = retval; + + self.inext = inext; + self.inextp = inextp; + + retval + } + + #[allow(dead_code)] + pub fn next(&mut self) -> i32 { + self.internal_sample() + } + + pub fn next_f64(&mut self) -> f64 { + self.sample() + } + + +} diff --git a/ic10emu_wasm/Cargo.lock b/ic10emu_wasm/Cargo.lock index 99f2654..fffd9ce 100644 --- a/ic10emu_wasm/Cargo.lock +++ b/ic10emu_wasm/Cargo.lock @@ -112,6 +112,19 @@ dependencies = [ "slab", ] +[[package]] +name = "getrandom" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + [[package]] name = "heck" version = "0.4.1" @@ -124,12 +137,15 @@ version = "0.1.0" dependencies = [ "const-crc32", "convert_case", + "getrandom", "itertools", "phf", "phf_codegen", + "rand", "regex", "strum_macros", "thiserror", + "web-time", ] [[package]] @@ -163,6 +179,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "libc" +version = "0.2.153" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + [[package]] name = "log" version = "0.4.21" @@ -231,6 +253,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + [[package]] name = "proc-macro2" version = "1.0.79" @@ -255,6 +283,18 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", "rand_core", ] @@ -263,6 +303,9 @@ name = "rand_core" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] [[package]] name = "regex" @@ -370,6 +413,12 @@ version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + [[package]] name = "wasm-bindgen" version = "0.2.92" @@ -459,3 +508,13 @@ dependencies = [ "js-sys", "wasm-bindgen", ] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] diff --git a/www/pnpm-lock.yaml b/www/pnpm-lock.yaml index 123cce5..9e0b77a 100644 --- a/www/pnpm-lock.yaml +++ b/www/pnpm-lock.yaml @@ -17,6 +17,15 @@ dependencies: bootstrap: specifier: ^5.3.3 version: 5.3.3(@popperjs/core@2.11.8) + bson: + specifier: ^6.5.0 + version: 6.5.0 + buffer: + specifier: ^6.0.3 + version: 6.0.3 + crypto-browserify: + specifier: ^3.12.0 + version: 3.12.0 ic10emu_wasm: specifier: file:../ic10emu_wasm/pkg version: file:../ic10emu_wasm/pkg @@ -29,11 +38,20 @@ dependencies: lzma-web: specifier: ^3.0.1 version: 3.0.1 + stream-browserify: + specifier: ^3.0.0 + version: 3.0.0 uuid: specifier: ^9.0.1 version: 9.0.1 + vm-browserify: + specifier: ^1.1.2 + version: 1.1.2 devDependencies: + '@oneidentity/zstd-js': + specifier: ^1.0.3 + version: 1.0.3 autoprefixer: specifier: ^10.4.19 version: 10.4.19(postcss@8.4.38) @@ -184,6 +202,12 @@ packages: fastq: 1.17.1 dev: true + /@oneidentity/zstd-js@1.0.3: + resolution: {integrity: sha512-Jm6sawqxLzBrjC4sg2BeXToa33yPzUmq20CKsehKY2++D/gHb/oSwVjNgT+RH4vys+r8FynrgcNzGwhZWMLzfQ==} + dependencies: + '@types/emscripten': 1.39.10 + dev: true + /@pkgjs/parseargs@0.11.0: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} @@ -226,6 +250,10 @@ packages: '@types/node': 20.11.28 dev: true + /@types/emscripten@1.39.10: + resolution: {integrity: sha512-TB/6hBkYQJxsZHSqyeuO1Jt0AB/bW6G7rHt9g7lML7SOF6lbgcHvw/Lr+69iqN0qxgXLhWKScAon73JNnptuDw==} + dev: true + /@types/eslint-scope@3.7.7: resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==} dependencies: @@ -696,6 +724,14 @@ packages: resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} dev: true + /asn1.js@4.10.1: + resolution: {integrity: sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==} + dependencies: + bn.js: 4.12.0 + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + dev: false + /async@3.2.3: resolution: {integrity: sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==} dev: false @@ -719,6 +755,10 @@ packages: /balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + /base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + dev: false + /batch@0.6.1: resolution: {integrity: sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==} dev: true @@ -729,6 +769,14 @@ packages: requiresBuild: true dev: true + /bn.js@4.12.0: + resolution: {integrity: sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==} + dev: false + + /bn.js@5.2.1: + resolution: {integrity: sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==} + dev: false + /body-parser@1.20.2: resolution: {integrity: sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} @@ -789,6 +837,61 @@ packages: fill-range: 7.0.1 dev: true + /brorand@1.1.0: + resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==} + dev: false + + /browserify-aes@1.2.0: + resolution: {integrity: sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==} + dependencies: + buffer-xor: 1.0.3 + cipher-base: 1.0.4 + create-hash: 1.2.0 + evp_bytestokey: 1.0.3 + inherits: 2.0.4 + safe-buffer: 5.2.1 + dev: false + + /browserify-cipher@1.0.1: + resolution: {integrity: sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==} + dependencies: + browserify-aes: 1.2.0 + browserify-des: 1.0.2 + evp_bytestokey: 1.0.3 + dev: false + + /browserify-des@1.0.2: + resolution: {integrity: sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==} + dependencies: + cipher-base: 1.0.4 + des.js: 1.1.0 + inherits: 2.0.4 + safe-buffer: 5.2.1 + dev: false + + /browserify-rsa@4.1.0: + resolution: {integrity: sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==} + dependencies: + bn.js: 5.2.1 + randombytes: 2.1.0 + dev: false + + /browserify-sign@4.2.3: + resolution: {integrity: sha512-JWCZW6SKhfhjJxO8Tyiiy+XYB7cqd2S5/+WeYHsKdNKFlCBhKbblba1A/HN/90YwtxKc8tCErjffZl++UNmGiw==} + engines: {node: '>= 0.12'} + dependencies: + bn.js: 5.2.1 + browserify-rsa: 4.1.0 + create-hash: 1.2.0 + create-hmac: 1.1.7 + elliptic: 6.5.5 + hash-base: 3.0.4 + inherits: 2.0.4 + parse-asn1: 5.1.7 + readable-stream: 2.3.8 + safe-buffer: 5.2.1 + dev: false + /browserslist@4.23.0: resolution: {integrity: sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} @@ -800,10 +903,26 @@ packages: update-browserslist-db: 1.0.13(browserslist@4.23.0) dev: true + /bson@6.5.0: + resolution: {integrity: sha512-DXf1BTAS8vKyR90BO4x5v3rKVarmkdkzwOrnYDFdjAY694ILNDkmA3uRh1xXJEl+C1DAh8XCvAQ+Gh3kzubtpg==} + engines: {node: '>=16.20.1'} + dev: false + /buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} dev: true + /buffer-xor@1.0.3: + resolution: {integrity: sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==} + dev: false + + /buffer@6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + dev: false + /bundle-name@4.1.0: resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} engines: {node: '>=18'} @@ -895,6 +1014,13 @@ packages: engines: {node: '>=6.0'} dev: true + /cipher-base@1.0.4: + resolution: {integrity: sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==} + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + dev: false + /clean-css@5.3.3: resolution: {integrity: sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==} engines: {node: '>= 10.0'} @@ -1022,7 +1148,6 @@ packages: /core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} - dev: true /cosmiconfig@9.0.0(typescript@5.4.2): resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==} @@ -1040,6 +1165,34 @@ packages: typescript: 5.4.2 dev: true + /create-ecdh@4.0.4: + resolution: {integrity: sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==} + dependencies: + bn.js: 4.12.0 + elliptic: 6.5.5 + dev: false + + /create-hash@1.2.0: + resolution: {integrity: sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==} + dependencies: + cipher-base: 1.0.4 + inherits: 2.0.4 + md5.js: 1.3.5 + ripemd160: 2.0.2 + sha.js: 2.4.11 + dev: false + + /create-hmac@1.1.7: + resolution: {integrity: sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==} + dependencies: + cipher-base: 1.0.4 + create-hash: 1.2.0 + inherits: 2.0.4 + ripemd160: 2.0.2 + safe-buffer: 5.2.1 + sha.js: 2.4.11 + dev: false + /cross-spawn@7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} @@ -1049,6 +1202,22 @@ packages: which: 2.0.2 dev: true + /crypto-browserify@3.12.0: + resolution: {integrity: sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==} + dependencies: + browserify-cipher: 1.0.1 + browserify-sign: 4.2.3 + create-ecdh: 4.0.4 + create-hash: 1.2.0 + create-hmac: 1.1.7 + diffie-hellman: 5.0.3 + inherits: 2.0.4 + pbkdf2: 3.1.2 + public-encrypt: 4.0.3 + randombytes: 2.1.0 + randomfill: 1.0.4 + dev: false + /css-loader@6.10.0(webpack@5.90.3): resolution: {integrity: sha512-LTSA/jWbwdMlk+rhmElbDR2vbtQoTBPr7fkJE+mxrHj+7ru0hUmHafDRzWIjIHTwpitWVaqY2/UWGRca3yUgRw==} engines: {node: '>= 12.13.0'} @@ -1160,6 +1329,13 @@ packages: engines: {node: '>= 0.8'} dev: true + /des.js@1.1.0: + resolution: {integrity: sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==} + dependencies: + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + dev: false + /destroy@1.2.0: resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} @@ -1169,6 +1345,14 @@ packages: resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==} dev: true + /diffie-hellman@5.0.3: + resolution: {integrity: sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==} + dependencies: + bn.js: 4.12.0 + miller-rabin: 4.0.1 + randombytes: 2.1.0 + dev: false + /dns-packet@5.6.1: resolution: {integrity: sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==} engines: {node: '>=6'} @@ -1228,6 +1412,18 @@ packages: resolution: {integrity: sha512-iWgEEvREL4GTXXHKohhh33+6Y8XkPI5eHihDmm8zUk5Zo7HICEW+wI/j5kJ2tbuNUCXJ/sNXa03ajW635DiJXA==} dev: true + /elliptic@6.5.5: + resolution: {integrity: sha512-7EjbcmUm17NQFu4Pmgmq2olYMj8nwMnpcddByChSUjArp8F5DQWcIcpriwO4ZToLNAJig0yiyjswfyGNje/ixw==} + dependencies: + bn.js: 4.12.0 + brorand: 1.1.0 + hash.js: 1.1.7 + hmac-drbg: 1.0.1 + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + minimalistic-crypto-utils: 1.0.1 + dev: false + /emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} dev: true @@ -1339,6 +1535,13 @@ packages: engines: {node: '>=0.8.x'} dev: true + /evp_bytestokey@1.0.3: + resolution: {integrity: sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==} + dependencies: + md5.js: 1.3.5 + safe-buffer: 5.2.1 + dev: false + /execa@5.1.1: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} engines: {node: '>=10'} @@ -1623,6 +1826,30 @@ packages: engines: {node: '>= 0.4'} dev: true + /hash-base@3.0.4: + resolution: {integrity: sha512-EeeoJKjTyt868liAlVmcv2ZsUfGHlE3Q+BICOXcZiwN3osr5Q/zFGYmTJpoIzuaSTAwndFy+GqhEwlU4L3j4Ow==} + engines: {node: '>=4'} + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + dev: false + + /hash-base@3.1.0: + resolution: {integrity: sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==} + engines: {node: '>=4'} + dependencies: + inherits: 2.0.4 + readable-stream: 3.6.2 + safe-buffer: 5.2.1 + dev: false + + /hash.js@1.1.7: + resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==} + dependencies: + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + dev: false + /hasown@2.0.2: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} @@ -1639,6 +1866,14 @@ packages: resolution: {integrity: sha512-3hx0GDkDLf/a9ThCMV2qG4mwza8N/MCtm8aeFFc/cdBCL2zMJ1kW1wjNl7xPqD1lz8Yl5+uhnc/cpui4dLwz/w==} dev: true + /hmac-drbg@1.0.1: + resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==} + dependencies: + hash.js: 1.1.7 + minimalistic-assert: 1.0.1 + minimalistic-crypto-utils: 1.0.1 + dev: false + /hpack.js@2.1.6: resolution: {integrity: sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==} dependencies: @@ -1791,6 +2026,10 @@ packages: postcss: 8.4.38 dev: true + /ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + dev: false + /ignore@5.3.1: resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} engines: {node: '>= 4'} @@ -1930,7 +2169,6 @@ packages: /isarray@1.0.0: resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} - dev: true /isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} @@ -2053,6 +2291,14 @@ packages: resolution: {integrity: sha512-sb5cdfd+PLNljK/HUgYzvnz4G7r0GFK8sonyGrqJS0FVyUQjFYcnmU2LqTWFi6r48lH1ZBstnxyLWepKM/t7QA==} dev: false + /md5.js@1.3.5: + resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==} + dependencies: + hash-base: 3.1.0 + inherits: 2.0.4 + safe-buffer: 5.2.1 + dev: false + /media-typer@0.3.0: resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} engines: {node: '>= 0.6'} @@ -2091,6 +2337,14 @@ packages: picomatch: 2.3.1 dev: true + /miller-rabin@4.0.1: + resolution: {integrity: sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==} + hasBin: true + dependencies: + bn.js: 4.12.0 + brorand: 1.1.0 + dev: false + /mime-db@1.52.0: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} engines: {node: '>= 0.6'} @@ -2127,7 +2381,10 @@ packages: /minimalistic-assert@1.0.1: resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} - dev: true + + /minimalistic-crypto-utils@1.0.1: + resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==} + dev: false /minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} @@ -2318,6 +2575,18 @@ packages: callsites: 3.1.0 dev: true + /parse-asn1@5.1.7: + resolution: {integrity: sha512-CTM5kuWR3sx9IFamcl5ErfPl6ea/N8IYwiJ+vpeB2g+1iknv7zBl5uPwbMbRVznRVbrNY6lGuDoE5b30grmbqg==} + engines: {node: '>= 0.10'} + dependencies: + asn1.js: 4.10.1 + browserify-aes: 1.2.0 + evp_bytestokey: 1.0.3 + hash-base: 3.0.4 + pbkdf2: 3.1.2 + safe-buffer: 5.2.1 + dev: false + /parse-json@5.2.0: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} @@ -2376,6 +2645,17 @@ packages: engines: {node: '>=12'} dev: true + /pbkdf2@3.1.2: + resolution: {integrity: sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==} + engines: {node: '>=0.12'} + dependencies: + create-hash: 1.2.0 + create-hmac: 1.1.7 + ripemd160: 2.0.2 + safe-buffer: 5.2.1 + sha.js: 2.4.11 + dev: false + /picocolors@1.0.0: resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} dev: true @@ -2486,7 +2766,6 @@ packages: /process-nextick-args@2.0.1: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} - dev: true /proxy-addr@2.0.7: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} @@ -2496,6 +2775,17 @@ packages: ipaddr.js: 1.9.1 dev: true + /public-encrypt@4.0.3: + resolution: {integrity: sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==} + dependencies: + bn.js: 4.12.0 + browserify-rsa: 4.1.0 + create-hash: 1.2.0 + parse-asn1: 5.1.7 + randombytes: 2.1.0 + safe-buffer: 5.2.1 + dev: false + /punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -2516,7 +2806,13 @@ packages: resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} dependencies: safe-buffer: 5.2.1 - dev: true + + /randomfill@1.0.4: + resolution: {integrity: sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==} + dependencies: + randombytes: 2.1.0 + safe-buffer: 5.2.1 + dev: false /range-parser@1.2.1: resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} @@ -2543,7 +2839,6 @@ packages: safe-buffer: 5.1.2 string_decoder: 1.1.1 util-deprecate: 1.0.2 - dev: true /readable-stream@3.6.2: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} @@ -2552,7 +2847,6 @@ packages: inherits: 2.0.4 string_decoder: 1.3.0 util-deprecate: 1.0.2 - dev: true /readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} @@ -2641,6 +2935,13 @@ packages: glob: 10.3.10 dev: true + /ripemd160@2.0.2: + resolution: {integrity: sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==} + dependencies: + hash-base: 3.1.0 + inherits: 2.0.4 + dev: false + /run-applescript@7.0.0: resolution: {integrity: sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==} engines: {node: '>=18'} @@ -2654,11 +2955,9 @@ packages: /safe-buffer@5.1.2: resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} - dev: true /safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - dev: true /safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} @@ -2813,6 +3112,14 @@ packages: resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} dev: true + /sha.js@2.4.11: + resolution: {integrity: sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==} + hasBin: true + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + dev: false + /shallow-clone@3.0.1: resolution: {integrity: sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==} engines: {node: '>=8'} @@ -2933,6 +3240,13 @@ packages: engines: {node: '>= 0.8'} dev: true + /stream-browserify@3.0.0: + resolution: {integrity: sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==} + dependencies: + inherits: 2.0.4 + readable-stream: 3.6.2 + dev: false + /string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -2955,13 +3269,11 @@ packages: resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} dependencies: safe-buffer: 5.1.2 - dev: true /string_decoder@1.3.0: resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} dependencies: safe-buffer: 5.2.1 - dev: true /strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} @@ -3149,7 +3461,6 @@ packages: /util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - dev: true /utila@0.4.0: resolution: {integrity: sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==} @@ -3175,6 +3486,10 @@ packages: engines: {node: '>= 0.8'} dev: true + /vm-browserify@1.1.2: + resolution: {integrity: sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==} + dev: false + /vscode-css-languageservice@6.2.12: resolution: {integrity: sha512-PS9r7HgNjqzRl3v91sXpCyZPc8UDotNo6gntFNtGCKPhGA9Frk7g/VjX1Mbv3F00pn56D+rxrFzR9ep4cawOgA==} dependencies: