From 6b790cea16992a73d90bebed83e7a364a6716b9f Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Thu, 11 Apr 2024 17:07:28 -0700 Subject: [PATCH] Logic and SlotLogic types are sometimes the same name - idealy this would be parsed to the corect varient based on the instrution but runtime switching works too. Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- ic10emu/src/grammar.rs | 74 +++++++++++++++++++++++++++++++++----- ic10emu/src/interpreter.rs | 38 ++++++++++---------- ic10emu/src/lib.rs | 8 ++--- 3 files changed, 88 insertions(+), 32 deletions(-) diff --git a/ic10emu/src/grammar.rs b/ic10emu/src/grammar.rs index d66c9ed..6b7a015 100644 --- a/ic10emu/src/grammar.rs +++ b/ic10emu/src/grammar.rs @@ -1,4 +1,4 @@ -use crate::interpreter; +use crate::interpreter::{self, ICError}; use crate::tokens::{SplitConsecutiveIndicesExt, SplitConsecutiveWithIndices}; use itertools::Itertools; use std::error::Error; @@ -349,6 +349,7 @@ pub enum Operand { Number(Number), LogicType(LogicType), SlotLogicType(SlotLogicType), + LogicOrSlotLogicType(LogicType, SlotLogicType), BatchMode(BatchMode), ReagentMode(ReagentMode), Identifier(Identifier), @@ -369,11 +370,16 @@ impl Operand { Operand::Number(num) => Ok(num.value()), Operand::LogicType(lt) => lt .get_str("value") - .map(|val| val.parse::().unwrap() as f64) + .map(|val| val.parse::().unwrap() as f64) .ok_or(interpreter::ICError::TypeValueNotKnown), Operand::SlotLogicType(slt) => slt .get_str("value") - .map(|val| val.parse::().unwrap() as f64) + .map(|val| val.parse::().unwrap() as f64) + .ok_or(interpreter::ICError::TypeValueNotKnown), + // default to using LogicType when converting to value + Operand::LogicOrSlotLogicType(lt, _) => lt + .get_str("value") + .map(|val| val.parse::().unwrap() as f64) .ok_or(interpreter::ICError::TypeValueNotKnown), Operand::BatchMode(bm) => bm .get_str("value") @@ -487,6 +493,32 @@ impl Operand { } } + pub fn as_logic_type( + &self, + ic: &interpreter::IC, + inst: InstructionOp, + index: u32, + ) -> Result { + match &self { + Operand::LogicType(lt) => Ok(*lt), + Operand::LogicOrSlotLogicType(lt, _slt) => Ok(*lt), + _ => LogicType::try_from(self.as_value(ic, inst, index)?), + } + } + + pub fn as_slot_logic_type( + &self, + ic: &interpreter::IC, + inst: InstructionOp, + index: u32, + ) -> Result { + match &self { + Operand::SlotLogicType(slt) => Ok(*slt), + Operand::LogicOrSlotLogicType(_lt, slt) => Ok(*slt), + _ => SlotLogicType::try_from(self.as_value(ic, inst, index)?), + } + } + pub fn translate_alias(&self, ic: &interpreter::IC) -> Self { match &self { Operand::Identifier(id) => { @@ -765,9 +797,17 @@ impl FromStr for Operand { val.get_str("value").unwrap().parse().unwrap(), ))) } else if let Ok(lt) = LogicType::from_str(s) { - Ok(Operand::LogicType(lt)) + if let Ok(slt) = SlotLogicType::from_str(s) { + Ok(Operand::LogicOrSlotLogicType(lt, slt)) + } else { + Ok(Operand::LogicType(lt)) + } } else if let Ok(slt) = SlotLogicType::from_str(s) { - Ok(Operand::SlotLogicType(slt)) + if let Ok(lt) = LogicType::from_str(s) { + Ok(Operand::LogicOrSlotLogicType(lt, slt)) + } else { + Ok(Operand::SlotLogicType(slt)) + } } else if let Ok(bm) = BatchMode::from_str(s) { Ok(Operand::BatchMode(bm)) } else if let Ok(rm) = ReagentMode::from_str(s) { @@ -855,6 +895,7 @@ impl Display for Operand { }, Operand::LogicType(logic) => Display::fmt(logic, f), Operand::SlotLogicType(slot_logic) => Display::fmt(slot_logic, f), + Operand::LogicOrSlotLogicType(logic, _) => Display::fmt(logic, f), Operand::BatchMode(batch_mode) => Display::fmt(batch_mode, f), Operand::ReagentMode(reagent_mode) => Display::fmt(reagent_mode, f), Operand::Identifier(ident) => Display::fmt(&ident, f), @@ -1029,6 +1070,7 @@ mod tests { define a_hash HASH(\"This is a String\")\n\ alias a_var r0\n\ alias a_device d0\n\ + s d0 On 1\n\ s d0 12 0 \n\ move r2 LogicType.Temperature\n\ move r3 pinf\n\ @@ -1107,6 +1149,20 @@ mod tests { },),), comment: None, }, + Line { + code: Some(Code::Instruction(Instruction { + instruction: InstructionOp::S, + operands: vec![ + Operand::DeviceSpec(DeviceSpec { + device: Device::Numbered(0), + connection: None + }), + Operand::LogicOrSlotLogicType(LogicType::On, SlotLogicType::On), + Operand::Number(Number::Float(1.0)) + ] + })), + comment: None, + }, Line { code: Some(Code::Instruction(Instruction { instruction: InstructionOp::S, @@ -1295,10 +1351,10 @@ mod tests { test_roundtrip("42"); test_roundtrip("1.2345"); test_roundtrip("-1.2345"); - test_roundtrip(&LogicType::Pressure.to_string()); - test_roundtrip(&SlotLogicType::Occupied.to_string()); - test_roundtrip(&BatchMode::Average.to_string()); - test_roundtrip(&ReagentMode::Recipe.to_string()); + test_roundtrip(LogicType::Pressure.as_ref()); + test_roundtrip(SlotLogicType::Occupied.as_ref()); + test_roundtrip(BatchMode::Average.as_ref()); + test_roundtrip(ReagentMode::Recipe.as_ref()); test_roundtrip("pi"); test_roundtrip("pinf"); test_roundtrip("ninf"); diff --git a/ic10emu/src/interpreter.rs b/ic10emu/src/interpreter.rs index 8e9a6c0..a31b15e 100644 --- a/ic10emu/src/interpreter.rs +++ b/ic10emu/src/interpreter.rs @@ -2135,7 +2135,7 @@ impl IC { let (Some(device_id), connection) = dev.as_device(this, inst, 1)? else { return Err(DeviceNotSet); }; - let lt = LogicType::try_from(lt.as_value(this, inst, 2)?)?; + let lt = lt.as_logic_type(this, inst, 2)?; if CHANNEL_LOGIC_TYPES.contains(<) { let channel = lt.as_channel().unwrap(); let Some(connection) = connection else { @@ -2171,7 +2171,7 @@ impl IC { let device = vm.get_device_same_network(this.device, device_id as u16); match device { Some(device) => { - let lt = LogicType::try_from(lt.as_value(this, inst, 2)?)?; + let lt = lt.as_logic_type(this, inst, 2)?; let val = val.as_value(this, inst, 3)?; device.borrow_mut().set_field(lt, val)?; vm.set_modified(device_id as u16); @@ -2183,7 +2183,7 @@ impl IC { oprs => Err(ICError::mismatch_operands(oprs.len(), 3)), }, Ss => match &operands[..] { - [dev, index, lt, val] => { + [dev, index, slt, val] => { let (Some(device_id), _connection) = dev.as_device(this, inst, 1)? else { return Err(DeviceNotSet); }; @@ -2191,9 +2191,9 @@ impl IC { match device { Some(device) => { let index = index.as_value(this, inst, 2)?; - let lt = SlotLogicType::try_from(lt.as_value(this, inst, 3)?)?; + let slt = slt.as_slot_logic_type(this, inst, 3)?; let val = val.as_value(this, inst, 4)?; - device.borrow_mut().set_slot_field(index, lt, val)?; + device.borrow_mut().set_slot_field(index, slt, val)?; vm.set_modified(device_id); Ok(()) } @@ -2205,7 +2205,7 @@ impl IC { Sb => match &operands[..] { [prefab, lt, val] => { let prefab = prefab.as_value(this, inst, 1)?; - let lt = LogicType::try_from(lt.as_value(this, inst, 2)?)?; + let lt = lt.as_logic_type(this, inst, 2)?; let val = val.as_value(this, inst, 3)?; vm.set_batch_device_field(this.device, prefab, lt, val)?; Ok(()) @@ -2213,12 +2213,12 @@ impl IC { oprs => Err(ICError::mismatch_operands(oprs.len(), 3)), }, Sbs => match &operands[..] { - [prefab, index, lt, val] => { + [prefab, index, slt, 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 slt = slt.as_slot_logic_type(this, inst, 3)?; let val = val.as_value(this, inst, 4)?; - vm.set_batch_device_slot_field(this.device, prefab, index, lt, val)?; + vm.set_batch_device_slot_field(this.device, prefab, index, slt, val)?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 4)), @@ -2227,7 +2227,7 @@ impl IC { [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 lt = lt.as_logic_type(this, inst, 3)?; let val = val.as_value(this, inst, 4)?; vm.set_batch_name_device_field(this.device, prefab, name, lt, val)?; Ok(()) @@ -2244,7 +2244,7 @@ impl IC { let (Some(device_id), connection) = dev.as_device(this, inst, 2)? else { return Err(DeviceNotSet); }; - let lt = LogicType::try_from(lt.as_value(this, inst, 3)?)?; + let lt = lt.as_logic_type(this, inst, 3)?; if CHANNEL_LOGIC_TYPES.contains(<) { let channel = lt.as_channel().unwrap(); let Some(connection) = connection else { @@ -2283,7 +2283,7 @@ impl IC { let device = vm.get_device_same_network(this.device, device_id as u16); match device { Some(device) => { - let lt = LogicType::try_from(lt.as_value(this, inst, 3)?)?; + let lt = lt.as_logic_type(this, inst, 3)?; let val = device.borrow().get_field(lt)?; this.set_register(indirection, target, val)?; Ok(()) @@ -2294,7 +2294,7 @@ impl IC { oprs => Err(ICError::mismatch_operands(oprs.len(), 3)), }, Ls => match &operands[..] { - [reg, dev, index, lt] => { + [reg, dev, index, slt] => { let RegisterSpec { indirection, target, @@ -2306,8 +2306,8 @@ impl IC { match device { Some(device) => { 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)?; + let slt = slt.as_slot_logic_type(this, inst, 4)?; + let val = device.borrow().get_slot_field(index, slt)?; this.set_register(indirection, target, val)?; Ok(()) } @@ -2346,7 +2346,7 @@ impl IC { target, } = 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 lt = lt.as_logic_type(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)?; @@ -2362,7 +2362,7 @@ impl IC { } = 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 lt = lt.as_logic_type(this, inst, 4)?; let bm = BatchMode::try_from(bm.as_value(this, inst, 5)?)?; let val = vm.get_batch_name_device_field(this.device, prefab, name, lt, bm)?; @@ -2380,7 +2380,7 @@ impl IC { 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 slt = slt.as_slot_logic_type(this, inst, 5)?; let bm = BatchMode::try_from(bm.as_value(this, inst, 6)?)?; let val = vm.get_batch_name_device_slot_field( this.device, @@ -2403,7 +2403,7 @@ impl IC { } = 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 slt = slt.as_slot_logic_type(this, inst, 4)?; let bm = BatchMode::try_from(bm.as_value(this, inst, 5)?)?; let val = vm.get_batch_device_slot_field(this.device, prefab, index, slt, bm)?; diff --git a/ic10emu/src/lib.rs b/ic10emu/src/lib.rs index 51fb3ba..e44a9bc 100644 --- a/ic10emu/src/lib.rs +++ b/ic10emu/src/lib.rs @@ -538,8 +538,8 @@ impl VM { .iter() .enumerate() .find_map(|(index, conn)| match conn { - &Connection::CableNetwork(_) => Some(index), - &Connection::Other => None, + Connection::CableNetwork(_) => Some(index), + Connection::Other => None, }); self.devices.insert(id, Rc::new(RefCell::new(device))); if let Some(first_data_network) = first_data_network { @@ -583,8 +583,8 @@ impl VM { .iter() .enumerate() .find_map(|(index, conn)| match conn { - &Connection::CableNetwork(_) => Some(index), - &Connection::Other => None, + Connection::CableNetwork(_) => Some(index), + Connection::Other => None, }); self.devices.insert(id, Rc::new(RefCell::new(device))); self.ics.insert(ic_id, Rc::new(RefCell::new(ic)));