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")]