diff --git a/ic10emu/build.rs b/ic10emu/build.rs index d294591..cdfded7 100644 --- a/ic10emu/build.rs +++ b/ic10emu/build.rs @@ -9,19 +9,19 @@ use std::{ str::FromStr, }; -trait PrimitiveRepr {} -impl PrimitiveRepr for u8 {} -impl PrimitiveRepr for u16 {} -impl PrimitiveRepr for u32 {} -impl PrimitiveRepr for u64 {} -impl PrimitiveRepr for u128 {} -impl PrimitiveRepr for usize {} -impl PrimitiveRepr for i8 {} -impl PrimitiveRepr for i16 {} -impl PrimitiveRepr for i32 {} -impl PrimitiveRepr for i64 {} -impl PrimitiveRepr for i128 {} -impl PrimitiveRepr for isize {} +// trait PrimitiveRepr {} +// impl PrimitiveRepr for u8 {} +// impl PrimitiveRepr for u16 {} +// impl PrimitiveRepr for u32 {} +// impl PrimitiveRepr for u64 {} +// impl PrimitiveRepr for u128 {} +// impl PrimitiveRepr for usize {} +// impl PrimitiveRepr for i8 {} +// impl PrimitiveRepr for i16 {} +// impl PrimitiveRepr for i32 {} +// impl PrimitiveRepr for i64 {} +// impl PrimitiveRepr for i128 {} +// impl PrimitiveRepr for isize {} struct EnumVariant

where @@ -328,7 +328,7 @@ fn write_constants() { writeln!( &mut writer, - "pub(crate) const CONSTANTS_LOOKUP: phf::Map<&'static str, f64> = {};", + "#[allow(clippy::approx_constant)] pub(crate) const CONSTANTS_LOOKUP: phf::Map<&'static str, f64> = {};", constants_lookup_map_builder.build() ) .unwrap(); diff --git a/ic10emu/data/constants.txt b/ic10emu/data/constants.txt index 4bd6485..3dfa33d 100644 --- a/ic10emu/data/constants.txt +++ b/ic10emu/data/constants.txt @@ -1,7 +1,7 @@ nan f64::NAN A constant representing 'not a number'. This constants technically provides a 'quiet' NaN, a signal NaN from some instructions will result in an exception and halt execution pinf f64::INFINITY A constant representing a positive infinite value ninf f64::NEG_INFINITY A constant representing a negative infinite value -pi 3.14159265358979f64 \nA constant representing the ratio of the circumference of a circle to its diameter, provided in double percision +pi 3.141592653589793f64 \nA constant representing the ratio of the circumference of a circle to its diameter, provided in double percision deg2rad 0.0174532923847437f64 \nDegrees to radians conversion constant rad2deg 57.2957801818848f64 \nRadians to degrees conversion constant epsilon f64::EPSILON A constant representing the smallest value representable in double precision diff --git a/ic10emu/src/grammar.rs b/ic10emu/src/grammar.rs index 06a6b06..5a896c8 100644 --- a/ic10emu/src/grammar.rs +++ b/ic10emu/src/grammar.rs @@ -88,7 +88,7 @@ pub mod generated { pub use generated::*; use serde::{Deserialize, Serialize}; -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] pub struct ParseError { pub line: usize, pub start: usize, @@ -147,6 +147,14 @@ pub fn parse(code: &str) -> Result, ParseError> { .collect() } +/// Like `parse` but can return Code::Invalid for some lines +pub fn parse_with_invlaid(code: &str) -> Vec { + code.lines() + .enumerate() + .map(|(n, l)| Line::from_str_with_invalid(n, l)) + .collect() +} + #[derive(PartialEq, Debug)] pub struct Line { pub code: Option, @@ -168,15 +176,47 @@ impl FromStr for Line { } }) .transpose()?; - let comment = parts.next().map(|s| s.parse()).transpose()?; + let comment = parts + .next() + .map(|s| s.parse()) + .transpose() + .expect("infallible"); Ok(Line { code, comment }) } } +impl Line { + fn from_str_with_invalid(line: usize, s: &str) -> Self { + let mut parts = s.splitn(2, '#'); + let code_part = parts + .next() + .and_then(|s| { + let s = s.trim_end(); + if s.is_empty() { + None + } else { + Some(s.parse::().map_err(|e| e.offset_line(line))) + } + }) + .transpose(); + let code = match code_part { + Ok(c) => c, + Err(e) => Some(Code::Invalid(e)), + }; + let comment = parts + .next() + .map(|s| s.parse()) + .transpose() + .expect("infallible"); + Line { code, comment } + } +} + #[derive(PartialEq, Debug)] pub enum Code { Instruction(Instruction), Label(Label), + Invalid(ParseError), } impl FromStr for Code { @@ -201,7 +241,7 @@ pub struct Comment { } impl FromStr for Comment { - type Err = ParseError; + type Err = std::convert::Infallible; fn from_str(s: &str) -> Result { Ok(Comment { comment: s.to_owned(), @@ -279,16 +319,22 @@ pub enum Device { Indirect { indirection: u32, target: u32 }, } +#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)] +pub struct RegisterSpec { + pub indirection: u32, + pub target: u32, +} + +#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)] +pub struct DeviceSpec { + pub device: Device, + pub connection: Option, +} + #[derive(PartialEq, Debug, Clone, Serialize, Deserialize)] pub enum Operand { - RegisterSpec { - indirection: u32, - target: u32, - }, - DeviceSpec { - device: Device, - connection: Option, - }, + RegisterSpec(RegisterSpec), + DeviceSpec(DeviceSpec), Number(Number), LogicType(LogicType), SlotLogicType(SlotLogicType), @@ -298,12 +344,17 @@ pub enum Operand { } impl Operand { - pub fn get_value(&self, ic: &interpreter::IC) -> Result { + pub fn as_value( + &self, + ic: &interpreter::IC, + inst: InstructionOp, + index: u32, + ) -> Result { match self.translate_alias(ic) { - Operand::RegisterSpec { + Operand::RegisterSpec(RegisterSpec { indirection, target, - } => ic.get_register(indirection, target), + }) => ic.get_register(indirection, target), Operand::Number(num) => Ok(num.value()), Operand::LogicType(lt) => lt .get_str("value") @@ -321,17 +372,85 @@ impl Operand { .get_str("value") .map(|val| val.parse::().unwrap() as f64) .ok_or(interpreter::ICError::TypeValueNotKnown), - Operand::Identifier(ident) => ic.get_ident_value(&ident.name), - Operand::DeviceSpec { .. } => Err(interpreter::ICError::DeviceNotValue), + Operand::Identifier(id) => { + Err(interpreter::ICError::UnknownIdentifier(id.name.to_string())) + } + Operand::DeviceSpec { .. } => Err(interpreter::ICError::IncorrectOperandType { + inst, + index, + desired: "Value".to_owned(), + }), } } - pub fn get_value_i64( + pub fn as_register( + &self, + ic: &interpreter::IC, + inst: InstructionOp, + index: u32, + ) -> Result { + match self.translate_alias(ic) { + Operand::RegisterSpec(reg) => Ok(reg), + Operand::Identifier(id) => { + Err(interpreter::ICError::UnknownIdentifier(id.name.to_string())) + } + _ => Err(interpreter::ICError::IncorrectOperandType { + inst, + index, + desired: "Register".to_owned(), + }), + } + } + + pub fn as_device( + &self, + ic: &interpreter::IC, + inst: InstructionOp, + index: u32, + ) -> Result<(Option, Option), interpreter::ICError> { + match self.translate_alias(ic) { + Operand::DeviceSpec(DeviceSpec { device, connection }) => match device { + Device::Db => Ok((Some(ic.device), connection)), + Device::Numbered(p) => { + let dp = ic + .pins + .get(p as usize) + .ok_or(interpreter::ICError::DeviceIndexOutOfRange(p as f64)) + .copied()?; + Ok((dp, connection)) + } + Device::Indirect { + indirection, + target, + } => { + let val = ic.get_register(indirection, target)?; + let dp = ic + .pins + .get(val as usize) + .ok_or(interpreter::ICError::DeviceIndexOutOfRange(val)) + .copied()?; + Ok((dp, connection)) + } + }, + Operand::Identifier(id) => { + Err(interpreter::ICError::UnknownIdentifier(id.name.to_string())) + } + _ => Err(interpreter::ICError::IncorrectOperandType { + inst, + index, + desired: "Value".to_owned(), + }), + } + } + + pub fn as_value_i64( &self, ic: &interpreter::IC, signed: bool, + inst: InstructionOp, + index: u32, ) -> Result { - let val = self.get_value(ic)?; + let val = self.as_value(ic, inst, index)?; if val < -9.223_372_036_854_776E18 { Err(interpreter::ICError::ShiftUnderflowI64) } else if val <= 9.223_372_036_854_776E18 { @@ -341,8 +460,13 @@ impl Operand { } } - pub fn get_value_i32(&self, ic: &interpreter::IC) -> Result { - let val = self.get_value(ic)?; + pub fn as_value_i32( + &self, + ic: &interpreter::IC, + inst: InstructionOp, + index: u32, + ) -> Result { + let val = self.as_value(ic, inst, index)?; if val < -2147483648.0 { Err(interpreter::ICError::ShiftUnderflowI32) } else if val <= 2147483647.0 { @@ -359,47 +483,15 @@ impl Operand { alias.clone() } else if let Some(define) = ic.defines.get(&id.name) { Operand::Number(Number::Float(*define)) + } else if let Some(label) = ic.program.labels.get(&id.name) { + Operand::Number(Number::Float(*label as f64)) } else { self.clone() } - }, + } _ => self.clone(), } } - - - pub fn get_device_id( - &self, - ic: &interpreter::IC, - ) -> Result<(Option, Option), interpreter::ICError> { - match &self { - Operand::DeviceSpec { device, connection } => match device { - Device::Db => Ok((Some(ic.device), *connection)), - Device::Numbered(p) => { - let dp = ic - .pins - .get(*p as usize) - .ok_or(interpreter::ICError::DeviceIndexOutOfRange(*p as f64)) - .copied()?; - Ok((dp, *connection)) - } - Device::Indirect { - indirection, - target, - } => { - let val = ic.get_register(*indirection, *target)?; - let dp = ic - .pins - .get(val as usize) - .ok_or(interpreter::ICError::DeviceIndexOutOfRange(val)) - .copied()?; - Ok((dp, *connection)) - } - }, - Operand::Identifier(id) => ic.get_ident_device_id(&id.name), - _ => Err(interpreter::ICError::ValueNotDevice), - } - } } impl FromStr for Operand { @@ -408,14 +500,14 @@ impl FromStr for Operand { fn from_str(s: &str) -> Result { let chars = s.chars().collect::>(); match &chars[..] { - ['s', 'p'] => Ok(Operand::RegisterSpec { + ['s', 'p'] => Ok(Operand::RegisterSpec(RegisterSpec { indirection: 0, target: 16, - }), - ['r', 'a'] => Ok(Operand::RegisterSpec { + })), + ['r', 'a'] => Ok(Operand::RegisterSpec(RegisterSpec { indirection: 0, target: 17, - }), + })), ['r', rest @ ..] => { let mut rest_iter = rest.iter(); let indirection = rest_iter.take_while_ref(|c| *c == &'r').count(); @@ -426,10 +518,10 @@ impl FromStr for Operand { let target = target_str.parse::().ok(); if let Some(target) = target { if rest_iter.next().is_none() { - return Ok(Operand::RegisterSpec { + return Ok(Operand::RegisterSpec(RegisterSpec { indirection: indirection as u32, target, - }); + })); } else { return Err(ParseError { line: 0, @@ -443,16 +535,16 @@ impl FromStr for Operand { Ok(Operand::Identifier(s.parse::()?)) } ['d', rest @ ..] => match rest { - ['b'] => Ok(Operand::DeviceSpec { + ['b'] => Ok(Operand::DeviceSpec(DeviceSpec { device: Device::Db, connection: None, - }), + })), ['b', ':', chan @ ..] => { if chan.iter().all(|c| c.is_ascii_digit()) { - Ok(Operand::DeviceSpec { + Ok(Operand::DeviceSpec(DeviceSpec { device: Device::Db, connection: Some(String::from_iter(chan).parse().unwrap()), - }) + })) } else { Err(ParseError { line: 0, @@ -501,13 +593,13 @@ impl FromStr for Operand { } }?; if rest_iter.next().is_none() { - Ok(Operand::DeviceSpec { + Ok(Operand::DeviceSpec(DeviceSpec { device: Device::Indirect { indirection: indirection as u32, target, }, connection, - }) + })) } else { Err(ParseError { line: 0, @@ -552,10 +644,10 @@ impl FromStr for Operand { }?; if let Some(target) = target { if rest_iter.next().is_none() { - Ok(Operand::DeviceSpec { + Ok(Operand::DeviceSpec(DeviceSpec { device: Device::Numbered(target), connection, - }) + })) } else { Err(ParseError { line: 0, @@ -675,12 +767,6 @@ impl FromStr for Operand { } } -// #[derive(PartialEq, Debug)] -// pub struct LogicType { -// pub name: String, -// pub value: f64, -// } - #[derive(PartialEq, Eq, Debug)] pub struct Label { pub id: Identifier, @@ -712,7 +798,6 @@ impl FromStr for Label { #[derive(PartialEq, Eq, Debug, Clone, Serialize, Deserialize)] pub struct Identifier { - // #[rust_sitter::leaf(pattern = r"[a-zA-Z_.][\w\d.]*", transform = |id| id.to_string())] pub name: String, } @@ -803,10 +888,10 @@ mod tests { code: Some(Code::Instruction(Instruction { instruction: InstructionOp::S, operands: vec![ - Operand::DeviceSpec { + Operand::DeviceSpec(DeviceSpec { device: Device::Numbered(0), connection: None, - }, + }), Operand::LogicType(LogicType::Setting), Operand::Number(Number::Float(0.0)), ], @@ -824,10 +909,10 @@ mod tests { code: Some(Code::Instruction(Instruction { instruction: InstructionOp::Move, operands: vec![ - Operand::RegisterSpec { + Operand::RegisterSpec(RegisterSpec { indirection: 0, target: 0, - }, + }), Operand::Number(Number::Hexadecimal(4095.0)), ], },),), @@ -898,10 +983,10 @@ mod tests { Operand::Identifier(Identifier { name: "a_var".to_owned(), },), - Operand::RegisterSpec { + Operand::RegisterSpec(RegisterSpec { indirection: 0, target: 0, - }, + }), ], },),), comment: None, @@ -913,10 +998,10 @@ mod tests { Operand::Identifier(Identifier { name: "a_device".to_owned(), },), - Operand::DeviceSpec { + Operand::DeviceSpec(DeviceSpec { device: Device::Numbered(0), connection: None, - }, + }), ], },),), comment: None, @@ -925,10 +1010,10 @@ mod tests { code: Some(Code::Instruction(Instruction { instruction: InstructionOp::S, operands: vec![ - Operand::DeviceSpec { + Operand::DeviceSpec(DeviceSpec { device: Device::Numbered(0), connection: None, - }, + }), Operand::Number(Number::Float(12.0)), Operand::Number(Number::Float(0.0)), ], @@ -939,10 +1024,10 @@ mod tests { code: Some(Code::Instruction(Instruction { instruction: InstructionOp::Move, operands: vec![ - Operand::RegisterSpec { + Operand::RegisterSpec(RegisterSpec { indirection: 0, target: 2, - }, + }), Operand::Identifier(Identifier { name: "LogicType.Temperature".to_owned() }), @@ -954,10 +1039,10 @@ mod tests { code: Some(Code::Instruction(Instruction { instruction: InstructionOp::Move, operands: vec![ - Operand::RegisterSpec { + Operand::RegisterSpec(RegisterSpec { indirection: 0, target: 3, - }, + }), Operand::Number(Number::Constant(f64::INFINITY)), ], },),), @@ -979,17 +1064,17 @@ mod tests { code: Some(Code::Instruction(Instruction { instruction: InstructionOp::L, operands: vec![ - Operand::RegisterSpec { + Operand::RegisterSpec(RegisterSpec { indirection: 0, target: 1, - }, - Operand::DeviceSpec { + }), + Operand::DeviceSpec(DeviceSpec { device: Device::Indirect { indirection: 0, target: 15, }, connection: None, - }, + }), Operand::LogicType(LogicType::RatioWater), ], },),), @@ -999,10 +1084,10 @@ mod tests { code: Some(Code::Instruction(Instruction { instruction: InstructionOp::Move, operands: vec![ - Operand::RegisterSpec { + Operand::RegisterSpec(RegisterSpec { indirection: 0, target: 0, - }, + }), Operand::Number(Number::String("AccessCardBlack".to_owned()),), ], },),), @@ -1012,10 +1097,10 @@ mod tests { code: Some(Code::Instruction(Instruction { instruction: InstructionOp::Move, operands: vec![ - Operand::RegisterSpec { + Operand::RegisterSpec(RegisterSpec { indirection: 0, target: 1, - }, + }), Operand::Number(Number::Float(-2045627372.0)), ], },),), @@ -1025,10 +1110,10 @@ mod tests { code: Some(Code::Instruction(Instruction { instruction: InstructionOp::Move, operands: vec![ - Operand::RegisterSpec { + Operand::RegisterSpec(RegisterSpec { indirection: 0, target: 1, - }, + }), Operand::Number(Number::Hexadecimal(255.0)), ], },),), @@ -1038,10 +1123,10 @@ mod tests { code: Some(Code::Instruction(Instruction { instruction: InstructionOp::Move, operands: vec![ - Operand::RegisterSpec { + Operand::RegisterSpec(RegisterSpec { indirection: 0, target: 1, - }, + }), Operand::Number(Number::Binary(8.0)), ], },),), @@ -1051,10 +1136,10 @@ mod tests { code: Some(Code::Instruction(Instruction { instruction: InstructionOp::Move, operands: vec![ - Operand::RegisterSpec { + Operand::RegisterSpec(RegisterSpec { indirection: 1, target: 1, - }, + }), Operand::Number(Number::Float(0.0)), ], },),), diff --git a/ic10emu/src/interpreter.rs b/ic10emu/src/interpreter.rs index 16446c5..30dd797 100644 --- a/ic10emu/src/interpreter.rs +++ b/ic10emu/src/interpreter.rs @@ -60,12 +60,6 @@ pub enum ICError { }, #[error("Unknown identifier '{0}")] UnknownIdentifier(String), - #[error("A Device is not a Value")] - DeviceNotValue, - #[error("A Value is not a Device")] - ValueNotDevice, - #[error("A Value is not a Register")] - ValueNotRegister, #[error("Device Not Set")] DeviceNotSet, #[error("Shift Underflow i64(signed long)")] @@ -190,6 +184,7 @@ pub struct IC { #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Program { pub instructions: Vec, + pub errors: Vec, pub labels: HashMap, } @@ -203,6 +198,7 @@ impl Program { pub fn new() -> Self { Program { instructions: Vec::new(), + errors: Vec::new(), labels: HashMap::new(), } } @@ -211,6 +207,7 @@ impl Program { let parse_tree = grammar::parse(code)?; let mut labels_set = HashSet::new(); let mut labels = HashMap::new(); + let errors = Vec::new(); let instructions = parse_tree .into_iter() .enumerate() @@ -233,15 +230,61 @@ impl Program { } } grammar::Code::Instruction(instruction) => Ok(instruction), + grammar::Code::Invalid(err) => Err(err.into()), }, }) .try_collect()?; Ok(Program { instructions, + errors, labels, }) } + pub fn from_code_with_invalid(code: &str) -> Self { + let parse_tree = grammar::parse_with_invlaid(code); + let mut labels_set = HashSet::new(); + let mut labels = HashMap::new(); + let mut errors = Vec::new(); + let instructions = parse_tree + .into_iter() + .enumerate() + .map(|(line_number, line)| match line.code { + None => grammar::Instruction { + instruction: grammar::InstructionOp::Nop, + operands: vec![], + }, + Some(code) => match code { + grammar::Code::Label(label) => { + if labels_set.contains(&label.id.name) { + errors.push(ICError::DuplicateLabel(label.id.name)); + } else { + labels_set.insert(label.id.name.clone()); + labels.insert(label.id.name, line_number as u32); + } + grammar::Instruction { + instruction: grammar::InstructionOp::Nop, + operands: vec![], + } + } + grammar::Code::Instruction(instruction) => instruction, + grammar::Code::Invalid(err) => { + errors.push(err.into()); + grammar::Instruction { + instruction: grammar::InstructionOp::Nop, + operands: vec![], + } + } + }, + }) + .collect_vec(); + Program { + instructions, + errors, + labels, + } + } + pub fn get_line(&self, line: u32) -> Result<&grammar::Instruction, ICError> { self.instructions .get(line as usize) @@ -277,6 +320,7 @@ impl IC { self.state = ICState::Start; } + /// Set program code if it's valid pub fn set_code(&mut self, code: &str) -> Result<(), ICError> { let prog = Program::try_from_code(code)?; self.ip = 0; @@ -288,6 +332,17 @@ impl IC { Ok(()) } + /// Set program code and translate invalid lines to Nop, collecting errors + pub fn set_code_invalid(&mut self, code: &str) { + let prog = Program::from_code_with_invalid(code); + self.ip = 0; + self.ic = 0; + self.aliases = HashMap::new(); + self.defines = HashMap::new(); + self.program = prog; + self.code = code.to_string(); + } + pub fn get_real_target(&self, indirection: u32, target: u32) -> Result { let mut i = indirection; let mut t = target as f64; @@ -327,26 +382,6 @@ impl IC { Ok(old_val) } - 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())) - } - } - - pub fn get_ident_device_id(&self, ident: &str) -> Result<(Option, Option), ICError> { - if let Some(operand) = self.aliases.get(ident) { - operand.get_device_id(self) - } else { - Err(ICError::UnknownIdentifier(ident.to_string())) - } - } - /// save ip to 'ra' or register 18 fn al(&mut self) { self.registers[17] = self.ip as f64 + 1.0; @@ -415,11 +450,11 @@ impl IC { } /// processes one line of the contained program - pub fn step(&mut self, vm: &crate::VM) -> Result { + pub fn step(&mut self, vm: &crate::VM, advance_ip_on_err: bool) -> Result { // TODO: handle sleep self.state = ICState::Running; let line = self.ip; - let result = self.internal_step(vm); + let result = self.internal_step(vm, advance_ip_on_err); if let Err(error) = result { let error = LineError { error, line }; self.state = ICState::Error(error.clone()); @@ -429,31 +464,35 @@ impl IC { } } - fn internal_step(&mut self, vm: &crate::VM) -> Result<(), ICError> { + fn internal_step(&mut self, vm: &crate::VM, advance_ip_on_err: bool) -> 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> = 'inst: { + // XXX: This closure should be replaced with a try block + // https://github.com/rust-lang/rust/issues/31436 + let mut process_op = |this: &mut Self| -> Result<(), ICError> { use grammar::InstructionOp::*; + + let line = this.program.get_line(this.ip)?; let operands = &line.operands; - match line.instruction { + let inst = line.instruction; + match inst { Nop => Ok(()), Hcf => Ok(()), // TODO Sleep => match &operands[..] { [a] => { - let a = a.get_value(self)?; + let a = a.as_value(this, inst, 1)?; let now = time::OffsetDateTime::now_local() .unwrap_or_else(|_| time::OffsetDateTime::now_utc()); - self.state = ICState::Sleep(now, a); + this.state = ICState::Sleep(now, a); Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 1)), }, // TODO Yield => match &operands[..] { [] => { - self.state = ICState::Yield; + this.state = ICState::Yield; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 0)), @@ -461,23 +500,23 @@ impl IC { Define => match &operands[..] { [name, number] => { let &Operand::Identifier(ident) = &name else { - break 'inst Err(IncorrectOperandType { + return Err(IncorrectOperandType { inst: line.instruction, index: 1, desired: "Name".to_owned(), }); }; let &Operand::Number(num) = &number else { - break 'inst Err(IncorrectOperandType { + return Err(IncorrectOperandType { inst: line.instruction, index: 2, desired: "Number".to_owned(), }); }; - if self.defines.contains_key(&ident.name) { + if this.defines.contains_key(&ident.name) { Err(DuplicateDefine(ident.name.clone())) } else { - self.defines.insert(ident.name.clone(), num.value()); + this.defines.insert(ident.name.clone(), num.value()); Ok(()) } } @@ -486,53 +525,48 @@ impl IC { Alias => match &operands[..] { [name, device_reg] => { let &Operand::Identifier(ident) = &name else { - break 'inst Err(IncorrectOperandType { + return Err(IncorrectOperandType { inst: line.instruction, index: 1, desired: "Name".to_owned(), }); }; let alias = match &device_reg { - Operand::RegisterSpec { + Operand::RegisterSpec(RegisterSpec { indirection, target, - } => Operand::RegisterSpec { + }) => Operand::RegisterSpec(RegisterSpec { indirection: *indirection, target: *target, - }, - Operand::DeviceSpec { device, connection } => Operand::DeviceSpec { - device: *device, - connection: *connection, - }, + }), + Operand::DeviceSpec(DeviceSpec { device, connection }) => { + Operand::DeviceSpec(DeviceSpec { + device: *device, + connection: *connection, + }) + } _ => { - break 'inst Err(IncorrectOperandType { + return Err(IncorrectOperandType { inst: line.instruction, index: 2, desired: "Device Or Register".to_owned(), }) } }; - self.aliases.insert(ident.name.clone(), alias); + this.aliases.insert(ident.name.clone(), alias); Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 2)), }, Move => match &operands[..] { [reg, val] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; + } = reg.as_register(this, line.instruction, 1)?; - let val = val.get_value(self)?; - self.set_register(indirection, target, val)?; + let val = val.as_value(this, inst, 2)?; + this.set_register(indirection, target, val)?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 2)), @@ -540,9 +574,9 @@ impl IC { Beq => match &operands[..] { [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; + let c = c.as_value(this, inst, 3)?; next_ip = if a == b { c as u32 } else { next_ip }; Ok(()) } @@ -550,22 +584,22 @@ impl IC { }, Beqal => match &operands[..] { [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; + let c = c.as_value(this, inst, 3)?; next_ip = if a == b { c as u32 } else { next_ip }; - self.al(); + this.al(); Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 3)), }, Breq => match &operands[..] { [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; + let c = c.as_value(this, inst, 3)?; next_ip = if a == b { - (self.ip as f64 + c) as u32 + (this.ip as f64 + c) as u32 } else { next_ip }; @@ -575,8 +609,8 @@ impl IC { }, Beqz => match &operands[..] { [a, b] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; next_ip = if a == 0.0 { b as u32 } else { next_ip }; Ok(()) } @@ -584,20 +618,20 @@ impl IC { }, Beqzal => match &operands[..] { [a, b] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; next_ip = if a == 0.0 { b as u32 } else { next_ip }; - self.al(); + this.al(); Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 2)), }, Breqz => match &operands[..] { [a, b] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; next_ip = if a == 0.0 { - (self.ip as f64 + b) as u32 + (this.ip as f64 + b) as u32 } else { next_ip }; @@ -607,9 +641,9 @@ impl IC { }, Bne => match &operands[..] { [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; + let c = c.as_value(this, inst, 3)?; next_ip = if a != b { c as u32 } else { next_ip }; Ok(()) } @@ -617,22 +651,22 @@ impl IC { }, Bneal => match &operands[..] { [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; + let c = c.as_value(this, inst, 3)?; next_ip = if a != b { c as u32 } else { next_ip }; - self.al(); + this.al(); Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 3)), }, Brne => match &operands[..] { [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; + let c = c.as_value(this, inst, 3)?; next_ip = if a != b { - (self.ip as f64 + c) as u32 + (this.ip as f64 + c) as u32 } else { next_ip }; @@ -642,8 +676,8 @@ impl IC { }, Bnez => match &operands[..] { [a, b] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; next_ip = if a != 0.0 { b as u32 } else { next_ip }; Ok(()) } @@ -651,20 +685,20 @@ impl IC { }, Bnezal => match &operands[..] { [a, b] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; next_ip = if a != 0.0 { b as u32 } else { next_ip }; - self.al(); + this.al(); Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 2)), }, Brnez => match &operands[..] { [a, b] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; next_ip = if a != 0.0 { - (self.ip as f64 + b) as u32 + (this.ip as f64 + b) as u32 } else { next_ip }; @@ -674,9 +708,9 @@ impl IC { }, Blt => match &operands[..] { [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; + let c = c.as_value(this, inst, 3)?; next_ip = if a < b { c as u32 } else { next_ip }; Ok(()) } @@ -684,22 +718,22 @@ impl IC { }, Bltal => match &operands[..] { [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; + let c = c.as_value(this, inst, 3)?; next_ip = if a < b { c as u32 } else { next_ip }; - self.al(); + this.al(); Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 3)), }, Brlt => match &operands[..] { [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; + let c = c.as_value(this, inst, 3)?; next_ip = if a < b { - (self.ip as f64 + c) as u32 + (this.ip as f64 + c) as u32 } else { next_ip }; @@ -709,9 +743,9 @@ impl IC { }, Ble => match &operands[..] { [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; + let c = c.as_value(this, inst, 3)?; next_ip = if a <= b { c as u32 } else { next_ip }; Ok(()) } @@ -719,22 +753,22 @@ impl IC { }, Bleal => match &operands[..] { [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; + let c = c.as_value(this, inst, 3)?; next_ip = if a <= b { c as u32 } else { next_ip }; - self.al(); + this.al(); Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 3)), }, Brle => match &operands[..] { [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; + let c = c.as_value(this, inst, 3)?; next_ip = if a <= b { - (self.ip as f64 + c) as u32 + (this.ip as f64 + c) as u32 } else { next_ip }; @@ -744,8 +778,8 @@ impl IC { }, Blez => match &operands[..] { [a, b] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; next_ip = if a <= 0.0 { b as u32 } else { next_ip }; Ok(()) } @@ -753,20 +787,20 @@ impl IC { }, Blezal => match &operands[..] { [a, b] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; next_ip = if a <= 0.0 { b as u32 } else { next_ip }; - self.al(); + this.al(); Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 2)), }, Brlez => match &operands[..] { [a, b] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; next_ip = if a <= 0.0 { - (self.ip as f64 + b) as u32 + (this.ip as f64 + b) as u32 } else { next_ip }; @@ -776,8 +810,8 @@ impl IC { }, Bltz => match &operands[..] { [a, b] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; next_ip = if a < 0.0 { b as u32 } else { next_ip }; Ok(()) } @@ -785,20 +819,20 @@ impl IC { }, Bltzal => match &operands[..] { [a, b] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; next_ip = if a < 0.0 { b as u32 } else { next_ip }; - self.al(); + this.al(); Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 2)), }, Brltz => match &operands[..] { [a, b] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; next_ip = if a < 0.0 { - (self.ip as f64 + b) as u32 + (this.ip as f64 + b) as u32 } else { next_ip }; @@ -808,9 +842,9 @@ impl IC { }, Bgt => match &operands[..] { [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; + let c = c.as_value(this, inst, 3)?; next_ip = if a > b { c as u32 } else { next_ip }; Ok(()) } @@ -818,22 +852,22 @@ impl IC { }, Bgtal => match &operands[..] { [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; + let c = c.as_value(this, inst, 3)?; next_ip = if a > b { c as u32 } else { next_ip }; - self.al(); + this.al(); Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 3)), }, Brgt => match &operands[..] { [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; + let c = c.as_value(this, inst, 3)?; next_ip = if a > b { - (self.ip as f64 + c) as u32 + (this.ip as f64 + c) as u32 } else { next_ip }; @@ -843,8 +877,8 @@ impl IC { }, Bgtz => match &operands[..] { [a, b] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; next_ip = if a > 0.0 { b as u32 } else { next_ip }; Ok(()) } @@ -852,20 +886,20 @@ impl IC { }, Bgtzal => match &operands[..] { [a, b] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; next_ip = if a > 0.0 { b as u32 } else { next_ip }; - self.al(); + this.al(); Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 2)), }, Brgtz => match &operands[..] { [a, b] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; next_ip = if a > 0.0 { - (self.ip as f64 + b) as u32 + (this.ip as f64 + b) as u32 } else { next_ip }; @@ -875,9 +909,9 @@ impl IC { }, Bge => match &operands[..] { [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; + let c = c.as_value(this, inst, 3)?; next_ip = if a >= b { c as u32 } else { next_ip }; Ok(()) } @@ -885,22 +919,22 @@ impl IC { }, Bgeal => match &operands[..] { [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; + let c = c.as_value(this, inst, 3)?; next_ip = if a >= b { c as u32 } else { next_ip }; - self.al(); + this.al(); Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 3)), }, Brge => match &operands[..] { [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; + let c = c.as_value(this, inst, 3)?; next_ip = if a >= b { - (self.ip as f64 + c) as u32 + (this.ip as f64 + c) as u32 } else { next_ip }; @@ -910,8 +944,8 @@ impl IC { }, Bgez => match &operands[..] { [a, b] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; next_ip = if a >= 0.0 { b as u32 } else { next_ip }; Ok(()) } @@ -919,20 +953,20 @@ impl IC { }, Bgezal => match &operands[..] { [a, b] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; next_ip = if a >= 0.0 { b as u32 } else { next_ip }; - self.al(); + this.al(); Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 2)), }, Brgez => match &operands[..] { [a, b] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; next_ip = if a >= 0.0 { - (self.ip as f64 + b) as u32 + (this.ip as f64 + b) as u32 } else { next_ip }; @@ -942,10 +976,10 @@ impl IC { }, Bap => match &operands[..] { [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)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; + let c = c.as_value(this, inst, 3)?; + let d = d.as_value(this, inst, 4)?; next_ip = if f64::abs(a - b) <= f64::max(c * f64::max(a.abs(), b.abs()), f64::EPSILON * 8.0) { @@ -959,10 +993,10 @@ impl IC { }, Bapal => match &operands[..] { [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)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; + let c = c.as_value(this, inst, 3)?; + let d = d.as_value(this, inst, 4)?; next_ip = if f64::abs(a - b) <= f64::max(c * f64::max(a.abs(), b.abs()), f64::EPSILON * 8.0) { @@ -970,34 +1004,34 @@ impl IC { } else { next_ip }; - self.al(); + this.al(); Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 4)), }, Brap => match &operands[..] { [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)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; + let c = c.as_value(this, inst, 3)?; + let d = d.as_value(this, inst, 4)?; 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 + (this.ip as f64 + d) as u32 } else { next_ip }; - self.al(); + this.al(); Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 4)), }, Bapz => match &operands[..] { [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; + let c = c.as_value(this, inst, 3)?; next_ip = if a.abs() <= f64::max(b * a.abs(), f64::EPSILON * 8.0) { c as u32 } else { @@ -1009,26 +1043,26 @@ impl IC { }, Bapzal => match &operands[..] { [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; + let c = c.as_value(this, inst, 3)?; next_ip = if a.abs() <= f64::max(b * a.abs(), f64::EPSILON * 8.0) { c as u32 } else { next_ip }; - self.al(); + this.al(); Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 3)), }, Brapz => match &operands[..] { [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; + let c = c.as_value(this, inst, 3)?; next_ip = if a.abs() <= f64::max(b * a.abs(), f64::EPSILON * 8.0) { - (self.ip as f64 + c) as u32 + (this.ip as f64 + c) as u32 } else { next_ip }; @@ -1038,10 +1072,10 @@ impl IC { }, Bna => match &operands[..] { [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)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; + let c = c.as_value(this, inst, 3)?; + let d = d.as_value(this, inst, 4)?; next_ip = if f64::abs(a - b) > f64::max(c * f64::max(a.abs(), b.abs()), f64::EPSILON * 8.0) { @@ -1055,10 +1089,10 @@ impl IC { }, Bnaal => match &operands[..] { [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)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; + let c = c.as_value(this, inst, 3)?; + let d = d.as_value(this, inst, 4)?; next_ip = if f64::abs(a - b) > f64::max(c * f64::max(a.abs(), b.abs()), f64::EPSILON * 8.0) { @@ -1066,21 +1100,21 @@ impl IC { } else { next_ip }; - self.al(); + this.al(); Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 4)), }, Brna => match &operands[..] { [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)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; + let c = c.as_value(this, inst, 3)?; + let d = d.as_value(this, inst, 4)?; 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 + (this.ip as f64 + d) as u32 } else { next_ip }; @@ -1090,9 +1124,9 @@ impl IC { }, Bnaz => match &operands[..] { [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; + let c = c.as_value(this, inst, 3)?; next_ip = if a.abs() > f64::max(b * a.abs(), f64::EPSILON * 8.0) { c as u32 } else { @@ -1104,26 +1138,26 @@ impl IC { }, Bnazal => match &operands[..] { [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; + let c = c.as_value(this, inst, 3)?; next_ip = if a.abs() > f64::max(b * a.abs(), f64::EPSILON * 8.0) { c as u32 } else { next_ip }; - self.al(); + this.al(); Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 3)), }, Brnaz => match &operands[..] { [a, b, c] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; + let c = c.as_value(this, inst, 3)?; next_ip = if a.abs() > f64::max(b * a.abs(), f64::EPSILON * 8.0) { - (self.ip as f64 + c) as u32 + (this.ip as f64 + c) as u32 } else { next_ip }; @@ -1133,8 +1167,8 @@ impl IC { }, Bdse => match &operands[..] { [d, a] => { - let (device, _connection) = d.get_device_id(self)?; - let a = a.get_value(self)?; + let (device, _connection) = d.as_device(this, inst, 1)?; + let a = a.as_value(this, inst, 2)?; next_ip = if device.is_some() { a as u32 } else { next_ip }; Ok(()) } @@ -1142,20 +1176,20 @@ impl IC { }, Bdseal => match &operands[..] { [d, a] => { - let (device, _connection) = d.get_device_id(self)?; - let a = a.get_value(self)?; + let (device, _connection) = d.as_device(this, inst, 1)?; + let a = a.as_value(this, inst, 2)?; next_ip = if device.is_some() { a as u32 } else { next_ip }; - self.al(); + this.al(); Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 2)), }, Brdse => match &operands[..] { [d, a] => { - let (device, _connection) = d.get_device_id(self)?; - let a = a.get_value(self)?; + let (device, _connection) = d.as_device(this, inst, 1)?; + let a = a.as_value(this, inst, 2)?; next_ip = if device.is_some() { - (self.ip as f64 + a) as u32 + (this.ip as f64 + a) as u32 } else { next_ip }; @@ -1165,8 +1199,8 @@ impl IC { }, Bdns => match &operands[..] { [d, a] => { - let (device, _connection) = d.get_device_id(self)?; - let a = a.get_value(self)?; + let (device, _connection) = d.as_device(this, inst, 1)?; + let a = a.as_value(this, inst, 2)?; next_ip = if device.is_none() { a as u32 } else { next_ip }; Ok(()) } @@ -1174,20 +1208,20 @@ impl IC { }, Bdnsal => match &operands[..] { [d, a] => { - let (device, _connection) = d.get_device_id(self)?; - let a = a.get_value(self)?; + let (device, _connection) = d.as_device(this, inst, 1)?; + let a = a.as_value(this, inst, 2)?; next_ip = if device.is_none() { a as u32 } else { next_ip }; - self.al(); + this.al(); Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 2)), }, Brdns => match &operands[..] { [d, a] => { - let (device, _connection) = d.get_device_id(self)?; - let a = a.get_value(self)?; + let (device, _connection) = d.as_device(this, inst, 1)?; + let a = a.as_value(this, inst, 2)?; next_ip = if device.is_none() { - (self.ip as f64 + a) as u32 + (this.ip as f64 + a) as u32 } else { next_ip }; @@ -1197,8 +1231,8 @@ impl IC { }, Bnan => match &operands[..] { [a, b] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; next_ip = if a.is_nan() { b as u32 } else { next_ip }; Ok(()) } @@ -1206,10 +1240,10 @@ impl IC { }, Brnan => match &operands[..] { [a, b] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; next_ip = if a.is_nan() { - (self.ip as f64 + b) as u32 + (this.ip as f64 + b) as u32 } else { next_ip }; @@ -1220,7 +1254,7 @@ impl IC { J => match &operands[..] { [a] => { - let a = a.get_value(self)?; + let a = a.as_value(this, inst, 1)?; next_ip = a as u32; Ok(()) } @@ -1228,17 +1262,17 @@ impl IC { }, Jal => match &operands[..] { [a] => { - let a = a.get_value(self)?; + let a = a.as_value(this, inst, 1)?; next_ip = a as u32; - self.al(); + this.al(); Ok(()) } oprs => Err(ICError::too_many_operands(oprs.len(), 1)), }, Jr => match &operands[..] { [a] => { - let a = a.get_value(self)?; - next_ip = (self.ip as f64 + a) as u32; + let a = a.as_value(this, inst, 1)?; + next_ip = (this.ip as f64 + a) as u32; Ok(()) } oprs => Err(ICError::too_many_operands(oprs.len(), 1)), @@ -1246,255 +1280,164 @@ impl IC { Seq => match &operands[..] { [reg, a, b] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - 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 })?; + } = reg.as_register(this, inst, 1)?; + let a = a.as_value(this, inst, 2)?; + let b = b.as_value(this, inst, 3)?; + this.set_register(indirection, target, if a == b { 1.0 } else { 0.0 })?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 3)), }, Seqz => match &operands[..] { [reg, a] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - let a = a.get_value(self)?; - self.set_register(indirection, target, if a == 0.0 { 1.0 } else { 0.0 })?; + } = reg.as_register(this, inst, 1)?; + let a = a.as_value(this, inst, 2)?; + this.set_register(indirection, target, if a == 0.0 { 1.0 } else { 0.0 })?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 3)), }, Sne => match &operands[..] { [reg, a, b] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - 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 })?; + } = reg.as_register(this, inst, 1)?; + let a = a.as_value(this, inst, 2)?; + let b = b.as_value(this, inst, 3)?; + this.set_register(indirection, target, if a != b { 1.0 } else { 0.0 })?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 3)), }, Snez => match &operands[..] { [reg, a] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - let a = a.get_value(self)?; - self.set_register(indirection, target, if a != 0.0 { 1.0 } else { 0.0 })?; + } = reg.as_register(this, inst, 1)?; + let a = a.as_value(this, inst, 2)?; + this.set_register(indirection, target, if a != 0.0 { 1.0 } else { 0.0 })?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 3)), }, Slt => match &operands[..] { [reg, a, b] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - 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 })?; + } = reg.as_register(this, inst, 1)?; + let a = a.as_value(this, inst, 2)?; + let b = b.as_value(this, inst, 3)?; + this.set_register(indirection, target, if a < b { 1.0 } else { 0.0 })?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 3)), }, Sltz => match &operands[..] { [reg, a] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - let a = a.get_value(self)?; - self.set_register(indirection, target, if a < 0.0 { 1.0 } else { 0.0 })?; + } = reg.as_register(this, inst, 1)?; + let a = a.as_value(this, inst, 2)?; + this.set_register(indirection, target, if a < 0.0 { 1.0 } else { 0.0 })?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 3)), }, Sle => match &operands[..] { [reg, a, b] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - 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 })?; + } = reg.as_register(this, inst, 1)?; + let a = a.as_value(this, inst, 2)?; + let b = b.as_value(this, inst, 3)?; + this.set_register(indirection, target, if a <= b { 1.0 } else { 0.0 })?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 3)), }, Slez => match &operands[..] { [reg, a] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - let a = a.get_value(self)?; - self.set_register(indirection, target, if a <= 0.0 { 1.0 } else { 0.0 })?; + } = reg.as_register(this, inst, 1)?; + let a = a.as_value(this, inst, 2)?; + this.set_register(indirection, target, if a <= 0.0 { 1.0 } else { 0.0 })?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 3)), }, Sgt => match &operands[..] { [reg, a, b] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - 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 })?; + } = reg.as_register(this, inst, 1)?; + let a = a.as_value(this, inst, 2)?; + let b = b.as_value(this, inst, 3)?; + this.set_register(indirection, target, if a > b { 1.0 } else { 0.0 })?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 3)), }, Sgtz => match &operands[..] { [reg, a] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - let a = a.get_value(self)?; - self.set_register(indirection, target, if a > 0.0 { 1.0 } else { 0.0 })?; + } = reg.as_register(this, inst, 1)?; + let a = a.as_value(this, inst, 2)?; + this.set_register(indirection, target, if a > 0.0 { 1.0 } else { 0.0 })?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 3)), }, Sge => match &operands[..] { [reg, a, b] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - 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 })?; + } = reg.as_register(this, inst, 1)?; + let a = a.as_value(this, inst, 2)?; + let b = b.as_value(this, inst, 3)?; + this.set_register(indirection, target, if a >= b { 1.0 } else { 0.0 })?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 3)), }, Sgez => match &operands[..] { [reg, a] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - let a = a.get_value(self)?; - self.set_register(indirection, target, if a >= 0.0 { 1.0 } else { 0.0 })?; + } = reg.as_register(this, inst, 1)?; + let a = a.as_value(this, inst, 2)?; + this.set_register(indirection, target, if a >= 0.0 { 1.0 } else { 0.0 })?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 3)), }, Sap => match &operands[..] { [reg, a, b, c] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; - self.set_register( + } = reg.as_register(this, inst, 1)?; + let a = a.as_value(this, inst, 2)?; + let b = b.as_value(this, inst, 3)?; + let c = c.as_value(this, inst, 4)?; + this.set_register( indirection, target, if f64::abs(a - b) @@ -1511,20 +1454,13 @@ impl IC { }, Sapz => match &operands[..] { [reg, a, b] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - let a = a.get_value(self)?; - let b = b.get_value(self)?; - self.set_register( + } = reg.as_register(this, inst, 1)?; + let a = a.as_value(this, inst, 2)?; + let b = b.as_value(this, inst, 3)?; + this.set_register( indirection, target, if a.abs() <= f64::max(b * a.abs(), f64::EPSILON * 8.0) { @@ -1539,21 +1475,14 @@ impl IC { }, Sna => match &operands[..] { [reg, a, b, c] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - let a = a.get_value(self)?; - let b = b.get_value(self)?; - let c = c.get_value(self)?; - self.set_register( + } = reg.as_register(this, inst, 1)?; + let a = a.as_value(this, inst, 2)?; + let b = b.as_value(this, inst, 3)?; + let c = c.as_value(this, inst, 4)?; + this.set_register( indirection, target, if f64::abs(a - b) @@ -1570,20 +1499,13 @@ impl IC { }, Snaz => match &operands[..] { [reg, a, b] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - let a = a.get_value(self)?; - let b = b.get_value(self)?; - self.set_register( + } = reg.as_register(this, inst, 1)?; + let a = a.as_value(this, inst, 2)?; + let b = b.as_value(this, inst, 3)?; + this.set_register( indirection, target, if a.abs() > f64::max(b * a.abs(), f64::EPSILON * 8.0) { @@ -1598,19 +1520,12 @@ impl IC { }, Sdse => match &operands[..] { [reg, device] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - let (device, _connection) = device.get_device_id(self)?; - self.set_register( + } = reg.as_register(this, inst, 1)?; + let (device, _connection) = device.as_device(this, inst, 2)?; + this.set_register( indirection, target, if device.is_some() { 1.0 } else { 0.0 }, @@ -1621,19 +1536,12 @@ impl IC { }, Sdns => match &operands[..] { [reg, device] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - let (device, _connection) = device.get_device_id(self)?; - self.set_register( + } = reg.as_register(this, inst, 1)?; + let (device, _connection) = device.as_device(this, inst, 2)?; + this.set_register( indirection, target, if device.is_none() { 1.0 } else { 0.0 }, @@ -1644,38 +1552,24 @@ impl IC { }, Snan => match &operands[..] { [reg, a] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - let a = a.get_value(self)?; - self.set_register(indirection, target, if a.is_nan() { 1.0 } else { 0.0 })?; + } = reg.as_register(this, inst, 1)?; + let a = a.as_value(this, inst, 2)?; + this.set_register(indirection, target, if a.is_nan() { 1.0 } else { 0.0 })?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 2)), }, Snanz => match &operands[..] { [reg, a] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - let a = a.get_value(self)?; - self.set_register(indirection, target, if a.is_nan() { 0.0 } else { 1.0 })?; + } = reg.as_register(this, inst, 1)?; + let a = a.as_value(this, inst, 2)?; + this.set_register(indirection, target, if a.is_nan() { 0.0 } else { 1.0 })?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 2)), @@ -1683,21 +1577,14 @@ impl IC { Select => match &operands[..] { [reg, a, b, c] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - 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 })?; + } = reg.as_register(this, inst, 1)?; + let a = a.as_value(this, inst, 2)?; + let b = b.as_value(this, inst, 3)?; + let c = c.as_value(this, inst, 4)?; + this.set_register(indirection, target, if a != 0.0 { b } else { c })?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 4)), @@ -1705,157 +1592,101 @@ impl IC { Add => match &operands[..] { [reg, a, b] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - let a = a.get_value(self)?; - let b = b.get_value(self)?; - self.set_register(indirection, target, a + b)?; + } = reg.as_register(this, inst, 1)?; + let a = a.as_value(this, inst, 2)?; + let b = b.as_value(this, inst, 3)?; + this.set_register(indirection, target, a + b)?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 3)), }, Sub => match &operands[..] { [reg, a, b] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - let a = a.get_value(self)?; - let b = b.get_value(self)?; - self.set_register(indirection, target, a - b)?; + } = reg.as_register(this, inst, 1)?; + let a = a.as_value(this, inst, 2)?; + let b = b.as_value(this, inst, 3)?; + this.set_register(indirection, target, a - b)?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 3)), }, Mul => match &operands[..] { [reg, a, b] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - let a = a.get_value(self)?; - let b = b.get_value(self)?; - self.set_register(indirection, target, a * b)?; + } = reg.as_register(this, inst, 1)?; + let a = a.as_value(this, inst, 2)?; + let b = b.as_value(this, inst, 3)?; + this.set_register(indirection, target, a * b)?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 3)), }, Div => match &operands[..] { [reg, a, b] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - let a = a.get_value(self)?; - let b = b.get_value(self)?; - self.set_register(indirection, target, a / b)?; + } = reg.as_register(this, inst, 1)?; + let a = a.as_value(this, inst, 2)?; + let b = b.as_value(this, inst, 3)?; + this.set_register(indirection, target, a / b)?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 3)), }, Mod => match &operands[..] { [reg, a, b] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - let a = a.get_value(self)?; - let b = b.get_value(self)?; - self.set_register(indirection, target, ((a % b) + b) % b)?; + } = reg.as_register(this, inst, 1)?; + let a = a.as_value(this, inst, 2)?; + let b = b.as_value(this, inst, 1)?; + this.set_register(indirection, target, ((a % b) + b) % b)?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 3)), }, Exp => match &operands[..] { [reg, a] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - let a = a.get_value(self)?; - self.set_register(indirection, target, f64::exp(a))?; + } = reg.as_register(this, inst, 1)?; + let a = a.as_value(this, inst, 2)?; + this.set_register(indirection, target, f64::exp(a))?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 2)), }, Log => match &operands[..] { [reg, a] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - let a = a.get_value(self)?; - self.set_register(indirection, target, f64::ln(a))?; + } = reg.as_register(this, inst, 1)?; + let a = a.as_value(this, inst, 2)?; + this.set_register(indirection, target, f64::ln(a))?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 2)), }, Sqrt => match &operands[..] { [reg, a] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - let a = a.get_value(self)?; - self.set_register(indirection, target, f64::sqrt(a))?; + } = reg.as_register(this, inst, 1)?; + let a = a.as_value(this, inst, 2)?; + this.set_register(indirection, target, f64::sqrt(a))?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 2)), @@ -1863,135 +1694,86 @@ impl IC { Max => match &operands[..] { [reg, a, b] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - let a = a.get_value(self)?; - let b = b.get_value(self)?; - self.set_register(indirection, target, f64::max(a, b))?; + } = reg.as_register(this, inst, 1)?; + let a = a.as_value(this, inst, 2)?; + let b = b.as_value(this, inst, 3)?; + this.set_register(indirection, target, f64::max(a, b))?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 3)), }, Min => match &operands[..] { [reg, a, b] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - let a = a.get_value(self)?; - let b = b.get_value(self)?; - self.set_register(indirection, target, f64::min(a, b))?; + } = reg.as_register(this, inst, 1)?; + let a = a.as_value(this, inst, 2)?; + let b = b.as_value(this, inst, 3)?; + this.set_register(indirection, target, f64::min(a, b))?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 3)), }, Ceil => match &operands[..] { [reg, a] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - let a = a.get_value(self)?; - self.set_register(indirection, target, f64::ceil(a))?; + } = reg.as_register(this, inst, 1)?; + let a = a.as_value(this, inst, 2)?; + this.set_register(indirection, target, f64::ceil(a))?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 2)), }, Floor => match &operands[..] { [reg, a] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - let a = a.get_value(self)?; - self.set_register(indirection, target, f64::floor(a))?; + } = reg.as_register(this, inst, 1)?; + let a = a.as_value(this, inst, 2)?; + this.set_register(indirection, target, f64::floor(a))?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 2)), }, Abs => match &operands[..] { [reg, a] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - let a = a.get_value(self)?; - self.set_register(indirection, target, f64::abs(a))?; + } = reg.as_register(this, inst, 1)?; + let a = a.as_value(this, inst, 2)?; + this.set_register(indirection, target, f64::abs(a))?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 2)), }, Round => match &operands[..] { [reg, a] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - let a = a.get_value(self)?; - self.set_register(indirection, target, f64::round(a))?; + } = reg.as_register(this, inst, 1)?; + let a = a.as_value(this, inst, 2)?; + this.set_register(indirection, target, f64::round(a))?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 2)), }, Trunc => match &operands[..] { [reg, a] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - let a = a.get_value(self)?; - self.set_register(indirection, target, f64::trunc(a))?; + } = reg.as_register(this, inst, 1)?; + let a = a.as_value(this, inst, 2)?; + this.set_register(indirection, target, f64::trunc(a))?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 2)), @@ -1999,19 +1781,12 @@ impl IC { Rand => match &operands[..] { [reg] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; + } = reg.as_register(this, inst, 1)?; let val = vm.random.clone().borrow_mut().next_f64(); - self.set_register(indirection, target, val)?; + this.set_register(indirection, target, val)?; Ok(()) } oprs => Err(ICError::too_many_operands(oprs.len(), 1)), @@ -2019,134 +1794,85 @@ impl IC { Sin => match &operands[..] { [reg, a] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - let a = a.get_value(self)?; - self.set_register(indirection, target, f64::sin(a))?; + } = reg.as_register(this, inst, 1)?; + let a = a.as_value(this, inst, 2)?; + this.set_register(indirection, target, f64::sin(a))?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 2)), }, Cos => match &operands[..] { [reg, a] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - let a = a.get_value(self)?; - self.set_register(indirection, target, f64::cos(a))?; + } = reg.as_register(this, inst, 1)?; + let a = a.as_value(this, inst, 2)?; + this.set_register(indirection, target, f64::cos(a))?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 2)), }, Tan => match &operands[..] { [reg, a] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - let a = a.get_value(self)?; - self.set_register(indirection, target, f64::tan(a))?; + } = reg.as_register(this, inst, 1)?; + let a = a.as_value(this, inst, 2)?; + this.set_register(indirection, target, f64::tan(a))?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 2)), }, Asin => match &operands[..] { [reg, a] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - let a = a.get_value(self)?; - self.set_register(indirection, target, f64::asin(a))?; + } = reg.as_register(this, inst, 1)?; + let a = a.as_value(this, inst, 2)?; + this.set_register(indirection, target, f64::asin(a))?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 2)), }, Acos => match &operands[..] { [reg, a] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - let a = a.get_value(self)?; - self.set_register(indirection, target, f64::acos(a))?; + } = reg.as_register(this, inst, 1)?; + let a = a.as_value(this, inst, 2)?; + this.set_register(indirection, target, f64::acos(a))?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 2)), }, Atan => match &operands[..] { [reg, a] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - let a = a.get_value(self)?; - self.set_register(indirection, target, f64::atan(a))?; + } = reg.as_register(this, inst, 1)?; + let a = a.as_value(this, inst, 2)?; + this.set_register(indirection, target, f64::atan(a))?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 2)), }, Atan2 => match &operands[..] { [reg, a, b] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - let a = a.get_value(self)?; - let b = b.get_value(self)?; - self.set_register(indirection, target, f64::atan2(a, b))?; + } = reg.as_register(this, inst, 1)?; + let a = a.as_value(this, inst, 2)?; + let b = b.as_value(this, inst, 3)?; + this.set_register(indirection, target, f64::atan2(a, b))?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 3)), @@ -2154,60 +1880,39 @@ impl IC { Sll | Sla => match &operands[..] { [reg, a, b] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - 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))?; + } = reg.as_register(this, inst, 1)?; + let a = a.as_value_i64(this, true, inst, 2)?; + let b = b.as_value_i32(this, inst, 3)?; + this.set_register(indirection, target, i64_to_f64(a << b))?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 3)), }, Srl => match &operands[..] { [reg, a, b] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - 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))?; + } = reg.as_register(this, inst, 1)?; + let a = a.as_value_i64(this, false, inst, 2)?; + let b = b.as_value_i32(this, inst, 3)?; + this.set_register(indirection, target, i64_to_f64((a as u64 >> b) as i64))?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 3)), }, Sra => match &operands[..] { [reg, a, b] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - 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))?; + } = reg.as_register(this, inst, 1)?; + let a = a.as_value_i64(this, true, inst, 2)?; + let b = b.as_value_i32(this, inst, 3)?; + this.set_register(indirection, target, i64_to_f64(a >> b))?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 3)), @@ -2215,99 +1920,64 @@ impl IC { And => match &operands[..] { [reg, a, b] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - 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))?; + } = reg.as_register(this, inst, 1)?; + let a = a.as_value_i64(this, true, inst, 2)?; + let b = b.as_value_i64(this, true, inst, 3)?; + this.set_register(indirection, target, i64_to_f64(a & b))?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 3)), }, Or => match &operands[..] { [reg, a, b] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - 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))?; + } = reg.as_register(this, inst, 1)?; + let a = a.as_value_i64(this, true, inst, 2)?; + let b = b.as_value_i64(this, true, inst, 3)?; + this.set_register(indirection, target, i64_to_f64(a | b))?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 3)), }, Xor => match &operands[..] { [reg, a, b] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - 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))?; + } = reg.as_register(this, inst, 1)?; + let a = a.as_value_i64(this, true, inst, 2)?; + let b = b.as_value_i64(this, true, inst, 3)?; + this.set_register(indirection, target, i64_to_f64(a ^ b))?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 3)), }, Nor => match &operands[..] { [reg, a, b] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - 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)))?; + } = reg.as_register(this, inst, 1)?; + let a = a.as_value_i64(this, true, inst, 2)?; + let b = b.as_value_i64(this, true, inst, 3)?; + this.set_register(indirection, target, i64_to_f64(!(a | b)))?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 3)), }, Not => match &operands[..] { [reg, a] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - let a = a.get_value_i64(self, true)?; - self.set_register(indirection, target, i64_to_f64(!a))?; + } = reg.as_register(this, inst, 1)?; + let a = a.as_value_i64(this, true, inst, 2)?; + this.set_register(indirection, target, i64_to_f64(!a))?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 2)), @@ -2315,55 +1985,41 @@ impl IC { Push => match &operands[..] { [a] => { - let a = a.get_value(self)?; - self.push(a)?; + let a = a.as_value(this, inst, 1)?; + this.push(a)?; Ok(()) } oprs => Err(ICError::too_many_operands(oprs.len(), 1)), }, Pop => match &operands[..] { [reg] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - let val = self.pop()?; - self.set_register(indirection, target, val)?; + } = reg.as_register(this, inst, 1)?; + let val = this.pop()?; + this.set_register(indirection, target, val)?; Ok(()) } oprs => Err(ICError::too_many_operands(oprs.len(), 1)), }, Poke => match &operands[..] { [a, b] => { - let a = a.get_value(self)?; - let b = b.get_value(self)?; - self.poke(a, b)?; + let a = a.as_value(this, inst, 1)?; + let b = b.as_value(this, inst, 2)?; + this.poke(a, b)?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 2)), }, Peek => match &operands[..] { [reg] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - let val = self.peek()?; - self.set_register(indirection, target, val)?; + } = reg.as_register(this, inst, 1)?; + let val = this.peek()?; + this.set_register(indirection, target, val)?; Ok(()) } oprs => Err(ICError::too_many_operands(oprs.len(), 1)), @@ -2371,28 +2027,22 @@ impl IC { Get => match &operands[..] { [reg, dev_id, addr] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); + + } = reg.as_register(this, inst, 1)?; + let (Some(device_id), _connection) = dev_id.as_device(this, inst, 2)? else { + return Err(DeviceNotSet); }; - let (Some(device_id), _connection) = dev_id.get_device_id(self)? else { - break 'inst Err(DeviceNotSet); - }; - let device = vm.get_device_same_network(self.device, device_id); + let device = vm.get_device_same_network(this.device, device_id); match device { Some(device) => match device.borrow().ic.as_ref() { Some(ic_id) => { - let addr = addr.get_value(self)?; + let addr = addr.as_value(this, inst, 3)?; let ic = vm.ics.get(ic_id).unwrap().borrow(); let val = ic.peek_addr(addr)?; - self.set_register(indirection, target, val)?; + this.set_register(indirection, target, val)?; Ok(()) } None => Err(DeviceHasNoIC), @@ -2404,28 +2054,22 @@ impl IC { }, Getd => match &operands[..] { [reg, dev_id, addr] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); + + } = reg.as_register(this, inst, 1)?; + let (Some(device_id), _connection) = dev_id.as_device(this, inst, 2)? else { + return Err(DeviceNotSet); }; - let (Some(device_id), _connection) = dev_id.get_device_id(self)? else { - break 'inst Err(DeviceNotSet); - }; - let device = vm.get_device_same_network(self.device, device_id); + let device = vm.get_device_same_network(this.device, device_id); match device { Some(device) => match device.borrow().ic.as_ref() { Some(ic_id) => { - let addr = addr.get_value(self)?; + let addr = addr.as_value(this, inst, 3)?; let ic = vm.ics.get(ic_id).unwrap().borrow(); let val = ic.peek_addr(addr)?; - self.set_register(indirection, target, val)?; + this.set_register(indirection, target, val)?; Ok(()) } None => Err(DeviceHasNoIC), @@ -2436,16 +2080,17 @@ impl IC { oprs => Err(ICError::mismatch_operands(oprs.len(), 3)), }, Put => match &operands[..] { + [dev_id, addr, val] => { - let (Some(device_id), _connection) = dev_id.get_device_id(self)? else { - break 'inst Err(DeviceNotSet); + let (Some(device_id), _connection) = dev_id.as_device(this, inst, 1)? else { + return Err(DeviceNotSet); }; - let device = vm.get_device_same_network(self.device, device_id); + let device = vm.get_device_same_network(this.device, device_id); match device { Some(device) => match device.borrow().ic.as_ref() { Some(ic_id) => { - let addr = addr.get_value(self)?; - let val = val.get_value(self)?; + let addr = addr.as_value(this, inst, 2)?; + let val = val.as_value(this, inst, 3)?; let mut ic = vm.ics.get(ic_id).unwrap().borrow_mut(); ic.poke(addr, val)?; Ok(()) @@ -2459,16 +2104,16 @@ impl IC { }, Putd => match &operands[..] { [dev_id, addr, val] => { - let device_id = dev_id.get_value(self)?; + let device_id = dev_id.as_value(this, inst, 1)?; if device_id >= u16::MAX as f64 || device_id < u16::MIN as f64 { - break 'inst Err(DeviceIndexOutOfRange(device_id)); + return Err(DeviceIndexOutOfRange(device_id)); } - let device = vm.get_device_same_network(self.device, device_id as u16); + let device = vm.get_device_same_network(this.device, device_id as u16); match device { Some(device) => match device.borrow().ic.as_ref() { Some(ic_id) => { - let addr = addr.get_value(self)?; - let val = val.get_value(self)?; + let addr = addr.as_value(this, inst, 2)?; + let val = val.as_value(this, inst, 3)?; let mut ic = vm.ics.get(ic_id).unwrap().borrow_mut(); ic.poke(addr, val)?; Ok(()) @@ -2483,27 +2128,27 @@ impl IC { S => match &operands[..] { [dev, lt, val] => { - let (Some(device_id), connection) = dev.get_device_id(self)? else { - break 'inst Err(DeviceNotSet); + let (Some(device_id), connection) = dev.as_device(this, inst, 1)? else { + return Err(DeviceNotSet); }; - let lt = LogicType::try_from(lt.get_value(self)?)?; + let lt = LogicType::try_from(lt.as_value(this, inst, 2)?)?; if CHANNEL_LOGIC_TYPES.contains(<) { let channel = lt.as_channel().unwrap(); let Some(connection) = connection else { - break 'inst Err(MissingConnectionSpecifier); + return Err(MissingConnectionSpecifier); }; let network_id = vm - .get_device_same_network(self.device, device_id) + .get_device_same_network(this.device, device_id) .map(|device| device.borrow().get_network_id(connection as usize)) .unwrap_or(Err(UnknownDeviceID(device_id as f64)))?; - let val = val.get_value(self)?; + let val = val.as_value(this, inst, 3)?; vm.set_network_channel(network_id as usize, channel, val)?; return Ok(()); } - let device = vm.get_device_same_network(self.device, device_id); + let device = vm.get_device_same_network(this.device, device_id); match device { Some(device) => { - let val = val.get_value(self)?; + let val = val.as_value(this, inst, 1)?; device.borrow_mut().set_field(lt, val)?; Ok(()) } @@ -2514,15 +2159,15 @@ impl IC { }, Sd => match &operands[..] { [dev, lt, val] => { - let device_id = dev.get_value(self)?; + let device_id = dev.as_value(this, inst, 1)?; if device_id >= u16::MAX as f64 || device_id < u16::MIN as f64 { - break 'inst Err(DeviceIndexOutOfRange(device_id)); + return Err(DeviceIndexOutOfRange(device_id)); } - let device = vm.get_device_same_network(self.device, device_id as u16); + let device = vm.get_device_same_network(this.device, device_id as u16); match device { Some(device) => { - let lt = LogicType::try_from(lt.get_value(self)?)?; - let val = val.get_value(self)?; + let lt = LogicType::try_from(lt.as_value(this, inst, 2)?)?; + let val = val.as_value(this, inst, 3)?; device.borrow_mut().set_field(lt, val)?; Ok(()) } @@ -2533,15 +2178,15 @@ impl IC { }, Ss => match &operands[..] { [dev, index, lt, val] => { - let (Some(device_id), _connection) = dev.get_device_id(self)? else { - break 'inst Err(DeviceNotSet); + let (Some(device_id), _connection) = dev.as_device(this, inst, 1)? else { + return Err(DeviceNotSet); }; - let device = vm.get_device_same_network(self.device, device_id); + let device = vm.get_device_same_network(this.device, device_id); match device { Some(device) => { - let index = index.get_value(self)?; - let lt = SlotLogicType::try_from(lt.get_value(self)?)?; - let val = val.get_value(self)?; + let index = index.as_value(this, inst, 2)?; + let lt = SlotLogicType::try_from(lt.as_value(this, inst, 3)?)?; + let val = val.as_value(this, inst, 4)?; device.borrow_mut().set_slot_field(index, lt, val)?; Ok(()) } @@ -2552,32 +2197,32 @@ impl IC { }, Sb => match &operands[..] { [prefab, lt, val] => { - let prefab = prefab.get_value(self)?; - let lt = LogicType::try_from(lt.get_value(self)?)?; - let val = val.get_value(self)?; - vm.set_batch_device_field(self.device, prefab, lt, val)?; + let prefab = prefab.as_value(this, inst, 1)?; + let lt = LogicType::try_from(lt.as_value(this, inst, 2)?)?; + let val = val.as_value(this, inst, 3)?; + vm.set_batch_device_field(this.device, prefab, lt, val)?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 3)), }, Sbs => match &operands[..] { [prefab, index, lt, val] => { - let prefab = prefab.get_value(self)?; - let index = index.get_value(self)?; - let lt = SlotLogicType::try_from(lt.get_value(self)?)?; - let val = val.get_value(self)?; - vm.set_batch_device_slot_field(self.device, prefab, index, lt, val)?; + let prefab = prefab.as_value(this, inst, 1)?; + let index = index.as_value(this, inst, 2)?; + let lt = SlotLogicType::try_from(lt.as_value(this, inst, 3)?)?; + let val = val.as_value(this, inst, 4)?; + vm.set_batch_device_slot_field(this.device, prefab, index, lt, val)?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 4)), }, Sbn => match &operands[..] { [prefab, name, lt, val] => { - let prefab = prefab.get_value(self)?; - let name = name.get_value(self)?; - let lt = LogicType::try_from(lt.get_value(self)?)?; - let val = val.get_value(self)?; - vm.set_batch_name_device_field(self.device, prefab, name, lt, val)?; + let prefab = prefab.as_value(this, inst, 1)?; + let name = name.as_value(this, inst, 2)?; + let lt = LogicType::try_from(lt.as_value(this, inst, 3)?)?; + let val = val.as_value(this, inst, 4)?; + vm.set_batch_name_device_field(this.device, prefab, name, lt, val)?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 4)), @@ -2585,39 +2230,32 @@ impl IC { L => match &operands[..] { [reg, dev, lt] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); + } = reg.as_register(this, inst, 1)?; + let (Some(device_id), connection) = dev.as_device(this, inst, 2)? else { + return Err(DeviceNotSet); }; - let (Some(device_id), connection) = dev.get_device_id(self)? else { - break 'inst Err(DeviceNotSet); - }; - let lt = LogicType::try_from(lt.get_value(self)?)?; + let lt = LogicType::try_from(lt.as_value(this, inst, 3)?)?; if CHANNEL_LOGIC_TYPES.contains(<) { let channel = lt.as_channel().unwrap(); let Some(connection) = connection else { - break 'inst Err(MissingConnectionSpecifier); + return Err(MissingConnectionSpecifier); }; let network_id = vm - .get_device_same_network(self.device, device_id) + .get_device_same_network(this.device, device_id) .map(|device| device.borrow().get_network_id(connection as usize)) .unwrap_or(Err(UnknownDeviceID(device_id as f64)))?; let val = vm.get_network_channel(network_id as usize, channel)?; - self.set_register(indirection, target, val)?; + this.set_register(indirection, target, val)?; return Ok(()); } - let device = vm.get_device_same_network(self.device, device_id); + let device = vm.get_device_same_network(this.device, device_id); match device { Some(device) => { let val = device.borrow().get_field(lt)?; - self.set_register(indirection, target, val)?; + this.set_register(indirection, target, val)?; Ok(()) } None => Err(UnknownDeviceID(device_id as f64)), @@ -2627,27 +2265,20 @@ impl IC { }, Ld => match &operands[..] { [reg, dev, lt] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - let device_id = dev.get_value(self)?; + } = reg.as_register(this, inst, 1)?; + let device_id = dev.as_value(this, inst, 2)?; if device_id >= u16::MAX as f64 || device_id < u16::MIN as f64 { - break 'inst Err(DeviceIndexOutOfRange(device_id)); + return Err(DeviceIndexOutOfRange(device_id)); } - let device = vm.get_device_same_network(self.device, device_id as u16); + let device = vm.get_device_same_network(this.device, device_id as u16); match device { Some(device) => { - let lt = LogicType::try_from(lt.get_value(self)?)?; + let lt = LogicType::try_from(lt.as_value(this, inst, 3)?)?; let val = device.borrow().get_field(lt)?; - self.set_register(indirection, target, val)?; + this.set_register(indirection, target, val)?; Ok(()) } None => Err(UnknownDeviceID(device_id)), @@ -2657,27 +2288,20 @@ impl IC { }, Ls => match &operands[..] { [reg, dev, index, lt] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); + } = reg.as_register(this, inst, 1)?; + let (Some(device_id), _connection) = dev.as_device(this, inst, 2)? else { + return Err(DeviceNotSet); }; - let (Some(device_id), _connection) = dev.get_device_id(self)? else { - break 'inst Err(DeviceNotSet); - }; - let device = vm.get_device_same_network(self.device, device_id); + let device = vm.get_device_same_network(this.device, device_id); match device { Some(device) => { - let index = index.get_value(self)?; - let lt = SlotLogicType::try_from(lt.get_value(self)?)?; + let index = index.as_value(this, inst, 3)?; + let lt = SlotLogicType::try_from(lt.as_value(this, inst, 4)?)?; let val = device.borrow().get_slot_field(index, lt)?; - self.set_register(indirection, target, val)?; + this.set_register(indirection, target, val)?; Ok(()) } None => Err(UnknownDeviceID(device_id as f64)), @@ -2687,27 +2311,20 @@ impl IC { }, Lr => match &operands[..] { [reg, dev, rm, name] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); + } = reg.as_register(this, inst, 1)?; + let (Some(device_id), _connection) = dev.as_device(this, inst, 2)? else { + return Err(DeviceNotSet); }; - let (Some(device_id), _connection) = dev.get_device_id(self)? else { - break 'inst Err(DeviceNotSet); - }; - let device = vm.get_device_same_network(self.device, device_id); + let device = vm.get_device_same_network(this.device, device_id); match device { Some(device) => { - let rm = ReagentMode::try_from(rm.get_value(self)?)?; - let name = name.get_value(self)?; + let rm = ReagentMode::try_from(rm.as_value(this, inst, 3)?)?; + let name = name.as_value(this, inst, 4)?; let val = device.borrow().get_reagent(&rm, name); - self.set_register(indirection, target, val)?; + this.set_register(indirection, target, val)?; Ok(()) } None => Err(UnknownDeviceID(device_id as f64)), @@ -2717,108 +2334,83 @@ impl IC { }, Lb => match &operands[..] { [reg, prefab, lt, bm] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - let prefab = prefab.get_value(self)?; - let lt = LogicType::try_from(lt.get_value(self)?)?; - let bm = BatchMode::try_from(bm.get_value(self)?)?; - let val = vm.get_batch_device_field(self.device, prefab, lt, bm)?; - self.set_register(indirection, target, val)?; + } = reg.as_register(this, inst, 1)?; + let prefab = prefab.as_value(this, inst, 2)?; + let lt = LogicType::try_from(lt.as_value(this, inst, 3)?)?; + let bm = BatchMode::try_from(bm.as_value(this, inst, 4)?)?; + let val = vm.get_batch_device_field(this.device, prefab, lt, bm)?; + this.set_register(indirection, target, val)?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 4)), }, Lbn => match &operands[..] { [reg, prefab, name, lt, bm] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - let prefab = prefab.get_value(self)?; - let name = name.get_value(self)?; - let lt = LogicType::try_from(lt.get_value(self)?)?; - let bm = BatchMode::try_from(bm.get_value(self)?)?; + } = reg.as_register(this, inst, 1)?; + let prefab = prefab.as_value(this, inst, 2)?; + let name = name.as_value(this, inst, 3)?; + let lt = LogicType::try_from(lt.as_value(this, inst, 4)?)?; + let bm = BatchMode::try_from(bm.as_value(this, inst, 5)?)?; let val = - vm.get_batch_name_device_field(self.device, prefab, name, lt, bm)?; - self.set_register(indirection, target, val)?; + vm.get_batch_name_device_field(this.device, prefab, name, lt, bm)?; + this.set_register(indirection, target, val)?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 5)), }, Lbns => match &operands[..] { [reg, prefab, name, index, slt, bm] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - let prefab = prefab.get_value(self)?; - let name = name.get_value(self)?; - let index = index.get_value(self)?; - let slt = SlotLogicType::try_from(slt.get_value(self)?)?; - let bm = BatchMode::try_from(bm.get_value(self)?)?; + } = reg.as_register(this, inst, 1)?; + let prefab = prefab.as_value(this, inst, 2)?; + let name = name.as_value(this, inst, 3)?; + let index = index.as_value(this, inst, 4)?; + let slt = SlotLogicType::try_from(slt.as_value(this, inst, 5)?)?; + let bm = BatchMode::try_from(bm.as_value(this, inst, 6)?)?; let val = vm.get_batch_name_device_slot_field( - self.device, + this.device, prefab, name, index, slt, bm, )?; - self.set_register(indirection, target, val)?; + this.set_register(indirection, target, val)?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 6)), }, Lbs => match &operands[..] { [reg, prefab, index, slt, bm] => { - let Operand::RegisterSpec { + let RegisterSpec { indirection, target, - } = reg.translate_alias(self) - else { - break 'inst Err(IncorrectOperandType { - inst: line.instruction, - index: 1, - desired: "Register".to_owned(), - }); - }; - let prefab = prefab.get_value(self)?; - let index = index.get_value(self)?; - let slt = SlotLogicType::try_from(slt.get_value(self)?)?; - let bm = BatchMode::try_from(bm.get_value(self)?)?; + } = reg.as_register(this, inst, 1)?; + let prefab = prefab.as_value(this, inst, 2)?; + let index = index.as_value(this, inst, 3)?; + let slt = SlotLogicType::try_from(slt.as_value(this, inst, 4)?)?; + let bm = BatchMode::try_from(bm.as_value(this, inst, 5)?)?; let val = - vm.get_batch_device_slot_field(self.device, prefab, index, slt, bm)?; - self.set_register(indirection, target, val)?; + vm.get_batch_device_slot_field(this.device, prefab, index, slt, bm)?; + this.set_register(indirection, target, val)?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 5)), }, } }; - self.ic += 1; + let result = process_op(self); + if result.is_ok() || advance_ip_on_err { + self.ic += 1; + } self.ip = next_ip; result } diff --git a/ic10emu/src/lib.rs b/ic10emu/src/lib.rs index cc26a39..819aefb 100644 --- a/ic10emu/src/lib.rs +++ b/ic10emu/src/lib.rs @@ -515,6 +515,7 @@ impl VM { } } + /// Set program code if it's valid pub fn set_code(&self, id: u16, code: &str) -> Result { let device = self .devices @@ -534,7 +535,27 @@ impl VM { Ok(true) } - pub fn step_ic(&self, id: u16) -> Result { + /// Set program code and translate invalid lines to Nop, collecting errors + pub fn set_code_invalid(&self, id: u16, code: &str) -> Result { + let device = self + .devices + .get(&id) + .ok_or(VMError::UnknownId(id))? + .borrow(); + let ic_id = *device.ic.as_ref().ok_or(VMError::NoIC(id))?; + let mut ic = self + .ics + .get(&ic_id) + .ok_or(VMError::UnknownIcId(ic_id))? + .borrow_mut(); + let new_prog = interpreter::Program::from_code_with_invalid(code); + ic.program = new_prog; + ic.ip = 0; + ic.code = code.to_string(); + Ok(true) + } + + pub fn step_ic(&self, id: u16, advance_ip_on_err: bool) -> Result { let device = self.devices.get(&id).ok_or(VMError::UnknownId(id))?.clone(); let ic_id = *device.borrow().ic.as_ref().ok_or(VMError::NoIC(id))?; let ic = self @@ -543,7 +564,7 @@ impl VM { .ok_or(VMError::UnknownIcId(ic_id))? .clone(); ic.borrow_mut().ic = 0; - let result = ic.borrow_mut().step(self)?; + let result = ic.borrow_mut().step(self, advance_ip_on_err)?; Ok(result) } @@ -558,7 +579,7 @@ impl VM { .clone(); ic.borrow_mut().ic = 0; for _i in 0..128 { - if let Err(err) = ic.borrow_mut().step(self) { + if let Err(err) = ic.borrow_mut().step(self, ignore_errors) { if !ignore_errors { return Err(err.into()); } diff --git a/ic10emu_wasm/src/lib.rs b/ic10emu_wasm/src/lib.rs index 716252e..ac86864 100644 --- a/ic10emu_wasm/src/lib.rs +++ b/ic10emu_wasm/src/lib.rs @@ -235,9 +235,9 @@ impl DeviceRef { } #[wasm_bindgen(js_name = "step")] - pub fn step_ic(&self) -> Result { + pub fn step_ic(&self, advance_ip_on_err: bool) -> Result { let id = self.device.borrow().id; - Ok(self.vm.borrow().step_ic(id)?) + Ok(self.vm.borrow().step_ic(id, advance_ip_on_err)?) } #[wasm_bindgen(js_name = "run")] @@ -253,11 +253,19 @@ impl DeviceRef { } #[wasm_bindgen(js_name = "setCode")] + /// Set program code if it's valid pub fn set_code(&self, code: &str) -> Result { let id = self.device.borrow().id; Ok(self.vm.borrow().set_code(id, code)?) } + #[wasm_bindgen(js_name = "setCodeInvalid")] + /// Set program code and translate invalid lines to Nop, collecting errors + pub fn set_code_invlaid(&self, code: &str) -> Result { + let id = self.device.borrow().id; + Ok(self.vm.borrow().set_code_invalid(id, code)?) + } + #[wasm_bindgen(js_name = "setRegister")] pub fn ic_set_register(&self, index: u32, val: f64) -> Result { let ic_id = *self @@ -319,13 +327,20 @@ impl VM { } #[wasm_bindgen(js_name = "setCode")] + /// Set program code if it's valid pub fn set_code(&self, id: u16, code: &str) -> Result { Ok(self.vm.borrow().set_code(id, code)?) } + #[wasm_bindgen(js_name = "setCodeInvalid")] + /// Set program code and translate invalid lines to Nop, collecting errors + pub fn set_code_invalid(&self, id: u16, code: &str) -> Result { + Ok(self.vm.borrow().set_code_invalid(id, code)?) + } + #[wasm_bindgen(js_name = "stepIC")] - pub fn step_ic(&self, id: u16) -> Result { - Ok(self.vm.borrow().step_ic(id)?) + pub fn step_ic(&self, id: u16, advance_ip_on_err: bool) -> Result { + Ok(self.vm.borrow().step_ic(id, advance_ip_on_err)?) } #[wasm_bindgen(js_name = "runIC")]