diff --git a/ic10emu/build.rs b/ic10emu/build.rs index 480398a..ad9659f 100644 --- a/ic10emu/build.rs +++ b/ic10emu/build.rs @@ -44,13 +44,15 @@ fn write_repr_enum<'a, T: std::io::Write, I, P>( .map(|s| format!("serialize = \"{s}\"")) .collect::>() .join(", "); - let deprecated_str = if variant.deprecated { - ", deprecated = \"true\"".to_owned() - } else { - "".to_owned() - }; - let props_str = if let Some(val) = &variant.value { - format!(", props( value = \"{val}\"{deprecated_str})") + let mut props = Vec::new(); + if variant.deprecated { + props.push("deprecated = \"true\"".to_owned()); + } + if let Some(val) = &variant.value { + props.push(format!("value = \"{val}\"")); + } + let props_str = if !props.is_empty() { + format!(", props( {} )", props.join(", ")) } else { "".to_owned() }; @@ -70,7 +72,7 @@ fn write_logictypes() { let output_file = File::create(dest_path).unwrap(); let mut writer = BufWriter::new(&output_file); - let mut logictypes: Vec<(String, EnumVariant)> = Vec::new(); + let mut logictypes: Vec<(String, EnumVariant)> = Vec::new(); let l_infile = Path::new("data/logictypes.txt"); let l_contents = fs::read_to_string(l_infile).unwrap(); @@ -78,7 +80,7 @@ fn write_logictypes() { let mut it = line.splitn(3, ' '); let name = it.next().unwrap(); let val_str = it.next().unwrap(); - let val: Option = val_str.parse().ok(); + let val: Option = val_str.parse().ok(); let docs = it.next(); let deprecated = docs .map(|docs| docs.trim().to_uppercase() == "DEPRECATED") diff --git a/ic10emu/data/logictypes.txt b/ic10emu/data/logictypes.txt index 331a124..e363bdc 100644 --- a/ic10emu/data/logictypes.txt +++ b/ic10emu/data/logictypes.txt @@ -7,18 +7,16 @@ AutoLand 226 Engages the automatic landing algorithm. The rocket will automatica AutoShutOff 218 Turns off all devices in the rocket upon reaching destination Bpm 103 Bpm BurnTimeRemaining 225 Estimated time in seconds until fuel is depleted. Calculated based on current fuel usage. -Bypass None Bypasses some internal behavoiur of the atmospherics device. CelestialHash 242 CelestialParentHash 250 -Channel None Channel on a cable network which should be considered volatile -Channel0 165 Channel on a cable network which should be considered volatile -Channel1 166 Channel on a cable network which should be considered volatile -Channel2 167 Channel on a cable network which should be considered volatile -Channel3 168 Channel on a cable network which should be considered volatile -Channel4 169 Channel on a cable network which should be considered volatile -Channel5 170 Channel on a cable network which should be considered volatile -Channel6 171 Channel on a cable network which should be considered volatile -Channel7 172 Channel on a cable network which should be considered volatile +Channel0 165 Channel 0 on a cable network which should be considered volatile +Channel1 166 Channel 1 on a cable network which should be considered volatile +Channel2 167 Channel 2 on a cable network which should be considered volatile +Channel3 168 Channel 3 on a cable network which should be considered volatile +Channel4 169 Channel 4 on a cable network which should be considered volatile +Channel5 170 Channel 5 on a cable network which should be considered volatile +Channel6 171 Channel 6 on a cable network which should be considered volatile +Channel7 172 Channel 7 on a cable network which should be considered volatile Charge 11 The current charge the device has Chart 256 ChartedNavPoints 259 @@ -92,7 +90,6 @@ OperationalTemperatureEfficiency 150 How the input pipe's temperature effects th OrbitPeriod 245 Orientation 230 Output 70 The output operation for a sort handling device, such as a stacker or sorter, when in logic mode the device will only action one repetition when set zero or above and then back to -1 and await further instructions -OverShootTarget None How far is the landing rocket going to overshoot its landing target at its current thrust. Expressed as a negative value in meters. ensure this is at zero by the time a rocket lands or risk total loss of rocket. PassedMoles 234 Plant 68 Performs the planting action for any plant based machinery PlantEfficiency1 52 DEPRECATED @@ -228,7 +225,6 @@ SizeX 160 Size on the X (right) axis of the object in largeGrids (a largeGrid is SizeY 161 Size on the Y(Up) axis of the object in largeGrids (a largeGrid is 2meters) SizeZ 162 Size on the Z(Forward) axis of the object in largeGrids (a largeGrid is 2meters) SolarAngle 22 Solar angle of the device -SolarConstant None Solar constant of the world SolarIrradiance 176 SoundAlert 175 Plays a sound alert on the devices speaker Stress 156 Machines get stressed when working hard. When Stress reaches 100 the machine will automatically shut down @@ -257,7 +253,6 @@ TotalMolesOutput 135 Returns the total moles of the device's Output Network TotalMolesOutput2 145 Returns the total moles of the device's Output2 Network TotalQuantity 265 TrueAnomaly 251 -Unknown None No description available VelocityMagnitude 79 The current magnitude of the velocity vector VelocityRelativeX 80 The current velocity X relative to the forward vector of this VelocityRelativeY 81 The current velocity Y relative to the forward vector of this diff --git a/ic10emu/generate_data.py b/ic10emu/generate_data.py index 785be14..79373e3 100644 --- a/ic10emu/generate_data.py +++ b/ic10emu/generate_data.py @@ -8,7 +8,7 @@ import xml.etree.ElementTree as ET from collections import defaultdict from itertools import chain from pathlib import Path - +from typing import Any # type:ignore[reportAny] def intOrNone(val: str): try: @@ -219,23 +219,28 @@ def extract_data(install_path: Path, data_path: Path, language: str): logic_types_path = Path("data") / "logictypes.txt" with logic_types_path.open(mode="w") as f: for t, (v, help) in sorted(logictypes.items()): - _ = f.write(f"{t} {v} {help.replace("\r", "").replace("\n", "\\n")}\n") + if v is not None: + _ = f.write(f"{t} {v} {help.replace("\r", "").replace("\n", "\\n")}\n") slot_logic_types_path = Path("data") / "slotlogictypes.txt" with slot_logic_types_path.open(mode="w") as f: for t, (v, help) in sorted(slotlogictypes.items()): - _ = f.write(f"{t} {v} {help.replace("\r", "").replace("\n", "\\n")}\n") + if v is not None: + _ = f.write(f"{t} {v} {help.replace("\r", "").replace("\n", "\\n")}\n") batch_modes_path = Path("data") / "batchmodes.txt" with batch_modes_path.open(mode="w") as f: for t, (v, help) in sorted(batchmodes.items()): - _ = f.write(f"{t} {v} {help.replace("\r", "").replace("\n", "\\n")}\n") + if v is not None: + _ = f.write(f"{t} {v} {help.replace("\r", "").replace("\n", "\\n")}\n") reagent_modes_path = Path("data") / "reagentmodes.txt" with reagent_modes_path.open(mode="w") as f: for t, (v, help) in sorted(reagentmodes.items()): - _ = f.write(f"{t} {v} {help.replace("\r", "").replace("\n", "\\n")}\n") + if v is not None: + _ = f.write(f"{t} {v} {help.replace("\r", "").replace("\n", "\\n")}\n") enums_path = Path("data") / "enums.txt" with enums_path.open(mode="w") as f: for name, (val, help) in sorted(enums.items()): - _ = f.write(f"{name} {val} {help.replace("\r", "").replace("\n", "\\n")}\n") + if val is not None: + _ = f.write(f"{name} {val} {help.replace("\r", "").replace("\n", "\\n")}\n") if __name__ == "__main__": main() diff --git a/ic10emu/src/grammar.rs b/ic10emu/src/grammar.rs index a0d5568..1902822 100644 --- a/ic10emu/src/grammar.rs +++ b/ic10emu/src/grammar.rs @@ -347,11 +347,13 @@ pub enum Operand { RegisterSpec(RegisterSpec), DeviceSpec(DeviceSpec), Number(Number), - LogicType(LogicType), - SlotLogicType(SlotLogicType), - LogicOrSlotLogicType(LogicType, SlotLogicType), - BatchMode(BatchMode), - ReagentMode(ReagentMode), + Type { + logic_type: Option, + slot_logic_type: Option, + batch_mode: Option, + reagent_mode: Option, + identifier: Identifier, + }, Identifier(Identifier), } @@ -368,27 +370,49 @@ impl Operand { target, }) => ic.get_register(indirection, target), Operand::Number(num) => Ok(num.value()), - Operand::LogicType(lt) => lt - .get_str("value") - .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) - .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") - .map(|val| val.parse::().unwrap() as f64) - .ok_or(interpreter::ICError::TypeValueNotKnown), - Operand::ReagentMode(rm) => rm - .get_str("value") - .map(|val| val.parse::().unwrap() as f64) - .ok_or(interpreter::ICError::TypeValueNotKnown), + Operand::Type { + logic_type, + slot_logic_type, + batch_mode, + reagent_mode, + identifier: _, + } => { + if let Some(lt) = logic_type { + Ok(lt + .get_str("value") + .ok_or_else(|| ICError::NoGeneratedValue(lt.to_string()))? + .parse::() + .map_err(|_| { + ICError::BadGeneratedValueParse(lt.to_string(), "u16".to_owned()) + })? as f64) + } else if let Some(slt) = slot_logic_type { + Ok(slt + .get_str("value") + .ok_or_else(|| ICError::NoGeneratedValue(slt.to_string()))? + .parse::() + .map_err(|_| { + ICError::BadGeneratedValueParse(slt.to_string(), "u8".to_owned()) + })? as f64) + } else if let Some(bm) = batch_mode { + Ok(bm + .get_str("value") + .ok_or_else(|| ICError::NoGeneratedValue(bm.to_string()))? + .parse::() + .map_err(|_| { + ICError::BadGeneratedValueParse(bm.to_string(), "u8".to_owned()) + })? as f64) + } else if let Some(rm) = reagent_mode { + Ok(rm + .get_str("value") + .ok_or_else(|| ICError::NoGeneratedValue(rm.to_string()))? + .parse::() + .map_err(|_| { + ICError::BadGeneratedValueParse(rm.to_string(), "u8".to_owned()) + })? as f64) + } else { + Err(interpreter::ICError::TypeValueNotKnown) + } + } Operand::Identifier(id) => { Err(interpreter::ICError::UnknownIdentifier(id.name.to_string())) } @@ -400,6 +424,49 @@ impl Operand { } } + pub fn as_value_i64( + &self, + ic: &interpreter::IC, + signed: bool, + inst: InstructionOp, + index: u32, + ) -> Result { + match self { + Self::Number(num) => Ok(num.value_i64()), + _ => { + 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 { + Ok(interpreter::f64_to_i64(val, signed)) + } else { + Err(interpreter::ICError::ShiftOverflowI64) + } + } + } + } + + pub fn as_value_i32( + &self, + ic: &interpreter::IC, + inst: InstructionOp, + index: u32, + ) -> Result { + match self { + Self::Number(num) => Ok(num.value_i64() as i32), + _ => { + let val = self.as_value(ic, inst, index)?; + if val < -2147483648.0 { + Err(interpreter::ICError::ShiftUnderflowI32) + } else if val <= 2147483647.0 { + Ok(val as i32) + } else { + Err(interpreter::ICError::ShiftOverflowI32) + } + } + } + } + pub fn as_register( &self, ic: &interpreter::IC, @@ -462,39 +529,6 @@ impl Operand { } } - pub fn as_value_i64( - &self, - ic: &interpreter::IC, - signed: bool, - inst: InstructionOp, - index: u32, - ) -> Result { - 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 { - Ok(interpreter::f64_to_i64(val, signed)) - } else { - Err(interpreter::ICError::ShiftOverflowI64) - } - } - - 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 { - Ok(val as i32) - } else { - Err(interpreter::ICError::ShiftOverflowI32) - } - } - pub fn as_logic_type( &self, ic: &interpreter::IC, @@ -502,8 +536,10 @@ impl Operand { index: u32, ) -> Result { match &self { - Operand::LogicType(lt) => Ok(*lt), - Operand::LogicOrSlotLogicType(lt, _slt) => Ok(*lt), + Operand::Type { + logic_type: Some(lt), + .. + } => Ok(*lt), _ => LogicType::try_from(self.as_value(ic, inst, index)?), } } @@ -515,15 +551,47 @@ impl Operand { index: u32, ) -> Result { match &self { - Operand::SlotLogicType(slt) => Ok(*slt), - Operand::LogicOrSlotLogicType(_lt, slt) => Ok(*slt), + Operand::Type { + slot_logic_type: Some(slt), + .. + } => Ok(*slt), _ => SlotLogicType::try_from(self.as_value(ic, inst, index)?), } } + pub fn as_batch_mode( + &self, + ic: &interpreter::IC, + inst: InstructionOp, + index: u32, + ) -> Result { + match &self { + Operand::Type { + batch_mode: Some(bm), + .. + } => Ok(*bm), + _ => BatchMode::try_from(self.as_value(ic, inst, index)?), + } + } + + pub fn as_reagent_mode( + &self, + ic: &interpreter::IC, + inst: InstructionOp, + index: u32, + ) -> Result { + match &self { + Operand::Type { + reagent_mode: Some(rm), + .. + } => Ok(*rm), + _ => ReagentMode::try_from(self.as_value(ic, inst, index)?), + } + } + pub fn translate_alias(&self, ic: &interpreter::IC) -> Self { match &self { - Operand::Identifier(id) => { + Operand::Identifier(id) | Operand::Type { identifier: id, .. } => { if let Some(alias) = ic.aliases.borrow().get(&id.name) { alias.clone() } else if let Some(define) = ic.defines.borrow().get(&id.name) { @@ -723,7 +791,7 @@ impl FromStr for Operand { let num_str = rest_iter .take_while_ref(|c| c.is_ascii_hexdigit()) .collect::(); - let num = i64::from_str_radix(&num_str, 16).unwrap() as f64; + let num = i64::from_str_radix(&num_str, 16).unwrap(); if rest_iter.next().is_none() { Ok(Operand::Number(Number::Hexadecimal(num))) } else { @@ -740,7 +808,7 @@ impl FromStr for Operand { let num_str = rest_iter .take_while_ref(|c| c.is_digit(2)) .collect::(); - let num = i64::from_str_radix(&num_str, 2).unwrap() as f64; + let num = i64::from_str_radix(&num_str, 2).unwrap(); if rest_iter.next().is_none() { Ok(Operand::Number(Number::Binary(num))) } else { @@ -798,24 +866,23 @@ impl FromStr for Operand { Ok(Operand::Number(Number::Enum( val.get_str("value").unwrap().parse().unwrap(), ))) - } else if let Ok(lt) = LogicType::from_str(s) { - 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) { - 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) { - Ok(Operand::ReagentMode(rm)) } else { - Ok(Operand::Identifier(s.parse::()?)) + let lt = LogicType::from_str(s).ok(); + let slt = SlotLogicType::from_str(s).ok(); + let bm = BatchMode::from_str(s).ok(); + let rm = ReagentMode::from_str(s).ok(); + let identifier = Identifier::from_str(s)?; + if lt.is_some() || slt.is_some() || bm.is_some() || rm.is_some() { + Ok(Operand::Type { + logic_type: lt, + slot_logic_type: slt, + batch_mode: bm, + reagent_mode: rm, + identifier, + }) + } else { + Ok(Operand::Identifier(identifier)) + } } } } @@ -865,12 +932,10 @@ impl Display for Operand { Operand::Number(number) => match number { Number::Float(_) => Display::fmt(&number.value(), f), Number::Hexadecimal(n) => { - // FIXME: precision loss here, maybe we should track the source i64? - write!(f, "${:x}", *n as i64) + write!(f, "${:x}", *n) } Number::Binary(n) => { - // FIXME: precision loss here, maybe we should track the source i64? - write!(f, "%{:b}", *n as i64) + write!(f, "%{:b}", *n) } Number::Constant(c) => { dbg!(c); @@ -895,11 +960,7 @@ impl Display for Operand { Display::fmt(&number.value(), f) } }, - 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::Type { identifier, .. } => Display::fmt(&identifier, f), Operand::Identifier(ident) => Display::fmt(&ident, f), } } @@ -987,8 +1048,8 @@ impl Display for Identifier { #[derive(PartialEq, Debug, Clone, Serialize, Deserialize)] pub enum Number { Float(f64), - Binary(f64), - Hexadecimal(f64), + Binary(i64), + Hexadecimal(i64), Constant(f64), String(String), Enum(f64), @@ -997,14 +1058,19 @@ pub enum Number { impl Number { pub fn value(&self) -> f64 { match self { - Number::Enum(val) - | Number::Float(val) - | Number::Binary(val) - | Number::Constant(val) - | Number::Hexadecimal(val) => *val, + Number::Enum(val) | Number::Float(val) | Number::Constant(val) => *val, + + Number::Binary(val) | Number::Hexadecimal(val) => *val as f64, Number::String(s) => const_crc32::crc32(s.as_bytes()) as i32 as f64, } } + pub fn value_i64(&self) -> i64 { + match self { + Number::Enum(val) | Number::Float(val) | Number::Constant(val) => *val as i64, + Number::Binary(val) | Number::Hexadecimal(val) => *val, + Number::String(s) => const_crc32::crc32(s.as_bytes()) as i32 as i64, + } + } } #[cfg(test)] @@ -1036,7 +1102,15 @@ mod tests { device: Device::Numbered(0), connection: None, }), - Operand::LogicType(LogicType::Setting), + Operand::Type { + logic_type: Some(LogicType::Setting), + slot_logic_type: None, + batch_mode: None, + reagent_mode: None, + identifier: Identifier { + name: "Setting".to_owned(), + }, + }, Operand::Number(Number::Float(0.0)), ], },),), @@ -1057,7 +1131,7 @@ mod tests { indirection: 0, target: 0, }), - Operand::Number(Number::Hexadecimal(4095.0)), + Operand::Number(Number::Hexadecimal(4095)), ], },),), comment: None, @@ -1159,7 +1233,15 @@ mod tests { device: Device::Numbered(0), connection: None }), - Operand::LogicOrSlotLogicType(LogicType::On, SlotLogicType::On), + Operand::Type { + logic_type: Some(LogicType::On), + slot_logic_type: Some(SlotLogicType::On), + batch_mode: None, + reagent_mode: None, + identifier: Identifier { + name: "On".to_owned(), + }, + }, Operand::Number(Number::Float(1.0)) ] })), @@ -1232,7 +1314,15 @@ mod tests { }, connection: None, }), - Operand::LogicType(LogicType::RatioWater), + Operand::Type { + logic_type: Some(LogicType::RatioWater), + slot_logic_type: None, + batch_mode: None, + reagent_mode: None, + identifier: Identifier { + name: "RatioWater".to_owned(), + }, + }, ], },),), comment: None, @@ -1271,7 +1361,7 @@ mod tests { indirection: 0, target: 1, }), - Operand::Number(Number::Hexadecimal(255.0)), + Operand::Number(Number::Hexadecimal(255)), ], },),), comment: None, @@ -1284,7 +1374,7 @@ mod tests { indirection: 0, target: 1, }), - Operand::Number(Number::Binary(8.0)), + Operand::Number(Number::Binary(8)), ], },),), comment: None, @@ -1365,4 +1455,34 @@ mod tests { test_roundtrip("$abcd"); test_roundtrip("%1001"); } + + + #[test] + fn all_generated_enums_have_value() { + use strum::IntoEnumIterator; + for lt in LogicType::iter() { + println!("testing LogicType.{lt}"); + let value = lt.get_str("value"); + assert!(value.is_some()); + assert!(value.unwrap().parse::().is_ok()); + } + for slt in SlotLogicType::iter() { + println!("testing SlotLogicType.{slt}"); + let value = slt.get_str("value"); + assert!(value.is_some()); + assert!(value.unwrap().parse::().is_ok()); + } + for bm in BatchMode::iter() { + println!("testing BatchMode.{bm}"); + let value = bm.get_str("value"); + assert!(value.is_some()); + assert!(value.unwrap().parse::().is_ok()); + } + for rm in ReagentMode::iter() { + println!("testing ReagentMode.{rm}"); + let value = rm.get_str("value"); + assert!(value.is_some()); + assert!(value.unwrap().parse::().is_ok()); + } + } } diff --git a/ic10emu/src/interpreter.rs b/ic10emu/src/interpreter.rs index 81bc0ec..c0a1f65 100644 --- a/ic10emu/src/interpreter.rs +++ b/ic10emu/src/interpreter.rs @@ -119,6 +119,10 @@ pub enum ICError { ChannelIndexOutOfRange(usize), #[error("slot has no occupant")] SlotNotOccupied, + #[error("generated Enum {0} has no value attached. Report this error.")] + NoGeneratedValue(String), + #[error("generated Enum {0}'s value does not parse as {1} . Report this error.")] + BadGeneratedValueParse(String, String), } impl ICError { @@ -2458,7 +2462,7 @@ impl IC { let device = vm.get_device_same_network(this.device, device_id); match device { Some(device) => { - let rm = ReagentMode::try_from(rm.as_value(this, inst, 3)?)?; + let rm = rm.as_reagent_mode(this, inst, 3)?; let name = name.as_value(this, inst, 4)?; let val = device.borrow().get_reagent(&rm, name); this.set_register(indirection, target, val)?; @@ -2477,7 +2481,7 @@ impl IC { } = reg.as_register(this, inst, 1)?; let prefab = prefab.as_value(this, inst, 2)?; let lt = lt.as_logic_type(this, inst, 3)?; - let bm = BatchMode::try_from(bm.as_value(this, inst, 4)?)?; + let bm = bm.as_batch_mode(this, inst, 4)?; let val = vm.get_batch_device_field(this.device, prefab, lt, bm)?; this.set_register(indirection, target, val)?; Ok(()) @@ -2493,7 +2497,7 @@ impl IC { let prefab = prefab.as_value(this, inst, 2)?; let name = name.as_value(this, inst, 3)?; let lt = lt.as_logic_type(this, inst, 4)?; - let bm = BatchMode::try_from(bm.as_value(this, inst, 5)?)?; + let bm = bm.as_batch_mode(this, inst, 5)?; let val = vm.get_batch_name_device_field(this.device, prefab, name, lt, bm)?; this.set_register(indirection, target, val)?; @@ -2511,7 +2515,7 @@ impl IC { let name = name.as_value(this, inst, 3)?; let index = index.as_value(this, inst, 4)?; let slt = slt.as_slot_logic_type(this, inst, 5)?; - let bm = BatchMode::try_from(bm.as_value(this, inst, 6)?)?; + let bm = bm.as_batch_mode(this, inst, 6)?; let val = vm.get_batch_name_device_slot_field( this.device, prefab, @@ -2534,7 +2538,7 @@ impl IC { let prefab = prefab.as_value(this, inst, 2)?; let index = index.as_value(this, inst, 3)?; let slt = slt.as_slot_logic_type(this, inst, 4)?; - let bm = BatchMode::try_from(bm.as_value(this, inst, 5)?)?; + let bm = bm.as_batch_mode(this, inst, 5)?; let val = vm.get_batch_device_slot_field(this.device, prefab, index, slt, bm)?; this.set_register(indirection, target, val)?; @@ -2620,15 +2624,15 @@ mod tests { vm.set_code( ic, r#"lb r0 HASH("ItemActiveVent") On Sum - #lb r1 HASH("ItemActiveVent") On Maximum + lb r1 HASH("ItemActiveVent") On Maximum lb r2 HASH("ItemActiveVent") On Minimum"#, )?; vm.step_ic(ic, false)?; let r0 = ic_chip.get_register(0, 0).unwrap(); assert_eq!(r0, 0.0); vm.step_ic(ic, false)?; - // let r1 = ic_chip.get_register(0, 1).unwrap(); - // assert_eq!(r1, f64::NEG_INFINITY); + let r1 = ic_chip.get_register(0, 1).unwrap(); + assert_eq!(r1, f64::NEG_INFINITY); vm.step_ic(ic, false)?; let r2 = ic_chip.get_register(0, 2).unwrap(); assert_eq!(r2, f64::INFINITY); diff --git a/ic10emu/src/vm.rs b/ic10emu/src/vm.rs index 813e6d2..00b7825 100644 --- a/ic10emu/src/vm.rs +++ b/ic10emu/src/vm.rs @@ -377,7 +377,7 @@ impl VM { ic.borrow().ic.replace(0); self.set_modified(id); for _i in 0..128 { - if let Err(err) = ic.borrow_mut().step(self, ignore_errors) { + if let Err(err) = ic.borrow().step(self, ignore_errors) { if !ignore_errors { return Err(err.into()); } diff --git a/ic10emu_wasm/src/types.ts b/ic10emu_wasm/src/types.ts index db87feb..12c659b 100644 --- a/ic10emu_wasm/src/types.ts +++ b/ic10emu_wasm/src/types.ts @@ -59,8 +59,8 @@ export type OperandReagentMode = { readonly ReagentMode: string }; export type Identifier = { readonly Identifier: { name: string } }; export type NumberFloat = { readonly Float: number }; -export type NumberBinary = { readonly Binary: number }; -export type NumberHexadecimal = { readonly Hexadecimal: number }; +export type NumberBinary = { readonly Binary: BigInt }; +export type NumberHexadecimal = { readonly Hexadecimal: BigInt }; export type NumberConstant = { readonly Constant: number }; export type NumberString = { readonly String: string }; export type NumberEnum = { readonly Enum: number };