From d6ebbcf7e0a6778950d704d448b0e1d17f8f8cab Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Tue, 14 May 2024 00:10:48 -0700 Subject: [PATCH] refactor(vm): use From in freeze object --- ic10emu/src/errors.rs | 6 +- ic10emu/src/network.rs | 8 +- ic10emu/src/vm.rs | 249 +-- ic10emu/src/vm/object.rs | 41 +- ic10emu/src/vm/object/generic/structs.rs | 2 +- ic10emu/src/vm/object/generic/traits.rs | 2 +- ic10emu/src/vm/object/macros.rs | 44 +- ic10emu/src/vm/object/stationpedia.rs | 12 +- .../structs/integrated_circuit.rs | 1294 ++++++------ ic10emu/src/vm/object/templates.rs | 1814 ++++++++--------- ic10emu/src/vm/object/traits.rs | 16 +- 11 files changed, 1709 insertions(+), 1779 deletions(-) diff --git a/ic10emu/src/errors.rs b/ic10emu/src/errors.rs index ea4f240..e0faacf 100644 --- a/ic10emu/src/errors.rs +++ b/ic10emu/src/errors.rs @@ -41,8 +41,10 @@ pub enum VMError { #[derive(Error, Debug, Serialize, Deserialize)] pub enum TemplateError { - #[error("")] - NonConformingObject(ObjectID) + #[error("object id {0} has a non conforming set of interfaces")] + NonConformingObject(ObjectID), + #[error("ObjectID {0} is missing fomr the VM")] + MissingVMObject(ObjectID), } #[derive(Debug, Clone, Serialize, Deserialize)] diff --git a/ic10emu/src/network.rs b/ic10emu/src/network.rs index 47fb45b..58fa0ef 100644 --- a/ic10emu/src/network.rs +++ b/ic10emu/src/network.rs @@ -105,21 +105,21 @@ pub enum ConnectionRole { impl Connection { #[allow(dead_code)] - pub fn from_info(typ: ConnectionType, role: ConnectionRole) -> Self { + pub fn from_info(typ: ConnectionType, role: ConnectionRole, net: Option) -> Self { match typ { ConnectionType::None => Self::None, ConnectionType::Data => Self::CableNetwork { - net: None, + net, typ: CableConnectionType::Data, role, }, ConnectionType::Power => Self::CableNetwork { - net: None, + net, typ: CableConnectionType::Power, role, }, ConnectionType::PowerAndData => Self::CableNetwork { - net: None, + net, typ: CableConnectionType::PowerAndData, role, }, diff --git a/ic10emu/src/vm.rs b/ic10emu/src/vm.rs index c196402..631628c 100644 --- a/ic10emu/src/vm.rs +++ b/ic10emu/src/vm.rs @@ -3,16 +3,16 @@ pub mod instructions; pub mod object; use crate::{ - device::{Device, DeviceTemplate, SlotOccupant, SlotOccupantTemplate}, + device::Device, errors::{ICError, VMError}, - interpreter::{self, FrozenIC, ICState, IC}, - network::{CableConnectionType, CableNetwork, Connection, FrozenNetwork}, + interpreter::ICState, + network::{CableConnectionType, CableNetwork, Connection, ConnectionRole, FrozenNetwork}, vm::{ - enums::script_enums::{LogicBatchMethod as BatchMode, LogicSlotType, LogicType}, + enums::script_enums::{LogicBatchMethod, LogicSlotType, LogicType}, object::{ templates::ObjectTemplate, traits::{Object, ParentSlotInfo}, - BoxedObject, ObjectID, VMObject, + ObjectID, VMObject, }, }, }; @@ -27,15 +27,15 @@ use serde_derive::{Deserialize, Serialize}; #[derive(Debug)] pub struct VM { - pub objects: BTreeMap, + pub objects: RefCell>, pub circuit_holders: RefCell>, pub program_holders: RefCell>, - pub networks: BTreeMap, - pub default_network_key: ObjectID, + pub networks: RefCell>, + pub default_network_key: RefCell, pub wireless_transmitters: RefCell>, pub wireless_receivers: RefCell>, - id_space: IdSpace, - network_id_space: IdSpace, + id_space: RefCell, + network_id_space: RefCell, random: Rc>, /// list of object id's touched on the last operation @@ -60,48 +60,48 @@ pub struct VMTransation { pub wireless_receivers: Vec, pub id_space: IdSpace, pub networks: BTreeMap, -} - -impl Default for VM { - fn default() -> Self { - Self::new() - } + vm: Rc, } impl VM { - pub fn new() -> Self { + pub fn new() -> Rc { let id_space = IdSpace::default(); let mut network_id_space = IdSpace::default(); let default_network_key = network_id_space.next(); - let default_network = VMObject::new(CableNetwork::new(default_network_key)); - let mut networks = BTreeMap::new(); - networks.insert(default_network_key, default_network); + let networks = BTreeMap::new(); - let mut vm = VM { - objects: BTreeMap::new(), + let mut vm = Rc::new(VM { + objects: RefCell::new(BTreeMap::new()), circuit_holders: RefCell::new(Vec::new()), program_holders: RefCell::new(Vec::new()), - networks, - default_network_key, + networks: RefCell::new(networks), + default_network_key: RefCell::new(default_network_key), wireless_transmitters: RefCell::new(Vec::new()), wireless_receivers: RefCell::new(Vec::new()), - id_space, - network_id_space, + id_space: RefCell::new(id_space), + network_id_space: RefCell::new(network_id_space), random: Rc::new(RefCell::new(crate::rand_mscorlib::Random::new())), operation_modified: RefCell::new(Vec::new()), - }; + }); + + let default_network = VMObject::new(CableNetwork::new(default_network_key), vm.clone()); + vm.networks.borrow_mut().insert(default_network_key, default_network); + vm } - pub fn add_device_from_template(&mut self, template: ObjectTemplate) -> Result { + pub fn add_device_from_template( + self: &Rc, + template: ObjectTemplate, + ) -> Result { let mut transaction = VMTransation::new(self); let obj_id = transaction.add_device_from_template(template)?; let transation_ids = transaction.id_space.in_use_ids(); - self.id_space.use_new_ids(&transation_ids); + self.id_space.borrow_mut().use_new_ids(&transation_ids); - self.objects.extend(transaction.objects); + self.objects.borrow_mut().extend(transaction.objects); self.wireless_transmitters .borrow_mut() .extend(transaction.wireless_transmitters); @@ -117,6 +117,7 @@ impl VM { for (net_id, trans_net) in transaction.networks.into_iter() { let net = self .networks + .borrow() .get(&net_id) .expect(&format!( "desync between vm and transation networks: {net_id}" @@ -135,39 +136,43 @@ impl VM { Ok(obj_id) } - pub fn add_network(&mut self) -> u32 { - let next_id = self.network_id_space.next(); + pub fn add_network(self: &Rc) -> u32 { + let next_id = self.network_id_space.borrow_mut().next(); self.networks - .insert(next_id, VMObject::new(CableNetwork::new(next_id))); + .borrow_mut() + .insert(next_id, VMObject::new(CableNetwork::new(next_id), self.clone())); next_id } - pub fn get_default_network(&self) -> VMObject { + pub fn get_default_network(self: &Rc) -> VMObject { self.networks - .get(&self.default_network_key) + .borrow() + .get(&*self.default_network_key.borrow()) .cloned() .expect("default network not present") } - pub fn get_network(&self, id: u32) -> Option { - self.networks.get(&id).cloned() + pub fn get_network(self: &Rc, id: u32) -> Option { + self.networks.borrow().get(&id).cloned() } /// iterate over all object borrowing them mutably, never call unless VM is not currently /// stepping - pub fn change_device_id(&mut self, old_id: u32, new_id: u32) -> Result<(), VMError> { - if self.id_space.has_id(&new_id) { + pub fn change_device_id(self: &Rc, old_id: u32, new_id: u32) -> Result<(), VMError> { + if self.id_space.borrow().has_id(&new_id) { return Err(VMError::IdInUse(new_id)); } let obj = self .objects + .borrow_mut() .remove(&old_id) .ok_or(VMError::UnknownId(old_id))?; - self.id_space.use_id(new_id)?; + self.id_space.borrow_mut().use_id(new_id)?; obj.borrow_mut().set_id(new_id); - self.objects.insert(new_id, obj); + self.objects.borrow_mut().insert(new_id, obj); self.objects + .borrow_mut() .iter_mut() .filter_map(|(_obj_id, obj)| obj.borrow_mut().as_mut_device()) .for_each(|device| { @@ -194,7 +199,7 @@ impl VM { *id = new_id } }); - self.networks.iter().for_each(|(_net_id, net)| { + self.networks.borrow().iter().for_each(|(_net_id, net)| { let net_ref = net .borrow_mut() .as_mut_network() @@ -206,14 +211,15 @@ impl VM { net_ref.add_power(new_id); } }); - self.id_space.free_id(old_id); + self.id_space.borrow_mut().free_id(old_id); Ok(()) } /// Set program code if it's valid - pub fn set_code(&self, id: u32, code: &str) -> Result { + pub fn set_code(self: &Rc, id: u32, code: &str) -> Result { let programmable = self .objects + .borrow() .get(&id) .ok_or(VMError::UnknownId(id))? .borrow_mut() @@ -224,9 +230,10 @@ impl VM { } /// Set program code and translate invalid lines to Nop, collecting errors - pub fn set_code_invalid(&self, id: u32, code: &str) -> Result { + pub fn set_code_invalid(self: &Rc, id: u32, code: &str) -> Result { let programmable = self .objects + .borrow() .get(&id) .ok_or(VMError::UnknownId(id))? .borrow_mut() @@ -237,13 +244,14 @@ impl VM { } /// returns a list of device ids modified in the last operations - pub fn last_operation_modified(&self) -> Vec { + pub fn last_operation_modified(self: &Rc) -> Vec { self.operation_modified.borrow().clone() } - pub fn step_programmable(&self, id: u32, advance_ip_on_err: bool) -> Result<(), VMError> { + pub fn step_programmable(self: &Rc, id: u32, advance_ip_on_err: bool) -> Result<(), VMError> { let programmable = self .objects + .borrow() .get(&id) .ok_or(VMError::UnknownId(id))? .borrow_mut() @@ -256,9 +264,10 @@ impl VM { } /// returns true if executed 128 lines, false if returned early. - pub fn run_programmable(&self, id: u32, ignore_errors: bool) -> Result { + pub fn run_programmable(self: &Rc, id: u32, ignore_errors: bool) -> Result { let programmable = self .objects + .borrow() .get(&id) .ok_or(VMError::UnknownId(id))? .borrow_mut() @@ -284,13 +293,14 @@ impl VM { Ok(true) } - pub fn set_modified(&self, id: ObjectID) { + pub fn set_modified(self: &Rc, id: ObjectID) { self.operation_modified.borrow_mut().push(id); } - pub fn reset_programmable(&self, id: ObjectID) -> Result { + pub fn reset_programmable(self: &Rc, id: ObjectID) -> Result { let programmable = self .objects + .borrow() .get(&id) .ok_or(VMError::UnknownId(id))? .borrow_mut() @@ -300,17 +310,18 @@ impl VM { Ok(true) } - pub fn get_object(&self, id: ObjectID) -> Option { - self.objects.get(&id).cloned() + pub fn get_object(self: &Rc, id: ObjectID) -> Option { + self.objects.borrow().get(&id).cloned() } pub fn batch_device( - &self, + self: &Rc, source: ObjectID, prefab_hash: f64, name: Option, - ) -> impl Iterator { + ) -> impl Iterator { self.objects + .borrow() .iter() .filter(move |(id, device)| { device.borrow().as_device().is_some_and(|device| { @@ -322,9 +333,12 @@ impl VM { && self.devices_on_same_network(&[source, **id]) }) .map(|(_, d)| d) + .cloned() + .collect::>() + .into_iter() } - pub fn get_device_same_network(&self, source: ObjectID, other: ObjectID) -> Option { + pub fn get_device_same_network(self: &Rc, source: ObjectID, other: ObjectID) -> Option { if self.devices_on_same_network(&[source, other]) { self.get_object(other) } else { @@ -332,8 +346,8 @@ impl VM { } } - pub fn get_network_channel(&self, id: u32, channel: usize) -> Result { - let network = self.networks.get(&id).ok_or(ICError::BadNetworkId(id))?; + pub fn get_network_channel(self: &Rc, id: u32, channel: usize) -> Result { + let network = self.networks.borrow().get(&id).ok_or(ICError::BadNetworkId(id))?; if !(0..8).contains(&channel) { Err(ICError::ChannelIndexOutOfRange(channel)) } else { @@ -349,12 +363,12 @@ impl VM { } pub fn set_network_channel( - &self, + self: &Rc, id: ObjectID, channel: usize, val: f64, ) -> Result<(), ICError> { - let network = self.networks.get(&(id)).ok_or(ICError::BadNetworkId(id))?; + let network = self.networks.borrow().get(&(id)).ok_or(ICError::BadNetworkId(id))?; if !(0..8).contains(&channel) { Err(ICError::ChannelIndexOutOfRange(channel)) } else { @@ -369,8 +383,8 @@ impl VM { } } - pub fn devices_on_same_network(&self, ids: &[ObjectID]) -> bool { - for net in self.networks.values() { + pub fn devices_on_same_network(self: &Rc, ids: &[ObjectID]) -> bool { + for net in self.networks.borrow().values() { if net .borrow() .as_network() @@ -384,8 +398,8 @@ impl VM { } /// return a vector with the device ids the source id can see via it's connected networks - pub fn visible_devices(&self, source: ObjectID) -> Vec { - self.networks + pub fn visible_devices(self: &Rc, source: ObjectID) -> Vec { + self.networks.borrow() .values() .filter_map(|net| { let net_ref = net.borrow().as_network().expect("non-network network"); @@ -398,12 +412,12 @@ impl VM { .concat() } - pub fn set_pin(&self, id: u32, pin: usize, val: Option) -> Result { - let Some(obj) = self.objects.get(&id) else { + pub fn set_pin(self: &Rc, id: u32, pin: usize, val: Option) -> Result { + let Some(obj) = self.objects.borrow().get(&id) else { return Err(VMError::UnknownId(id)); }; if let Some(other_device) = val { - if !self.objects.contains_key(&other_device) { + if !self.objects.borrow().contains_key(&other_device) { return Err(VMError::UnknownId(other_device)); } if !self.devices_on_same_network(&[id, other_device]) { @@ -425,12 +439,12 @@ impl VM { } pub fn set_device_connection( - &self, + self: &Rc, id: ObjectID, connection: usize, target_net: Option, ) -> Result { - let Some(obj) = self.objects.get(&id) else { + let Some(obj) = self.objects.borrow().get(&id) else { return Err(VMError::UnknownId(id)); }; let Some(device) = obj.borrow_mut().as_mut_device() else { @@ -443,19 +457,20 @@ impl VM { } // scope this borrow - let Connection::CableNetwork { net, typ } = &connections[connection] else { + let Connection::CableNetwork { net, typ, .. } = &connections[connection] else { return Err(ICError::NotACableConnection(connection).into()); }; // remove from current network if let Some(net) = net { - if let Some(network) = self.networks.get(net) { + if let Some(network) = self.networks.borrow().get(net) { // if there is no other connection to this network if connections .iter() .filter(|conn| { matches!(conn, Connection::CableNetwork { net: Some(other_net), - typ: other_typ + typ: other_typ, + .. } if other_net == net && ( !matches!(typ, CableConnectionType::Power) || matches!(other_typ, CableConnectionType::Data | CableConnectionType::PowerAndData)) @@ -487,12 +502,13 @@ impl VM { let Connection::CableNetwork { ref mut net, ref typ, + .. } = connections[connection] else { return Err(ICError::NotACableConnection(connection).into()); }; if let Some(target_net) = target_net { - if let Some(network) = self.networks.get(&target_net) { + if let Some(network) = self.networks.borrow().get(&target_net) { match typ { CableConnectionType::Power => { network @@ -518,12 +534,12 @@ impl VM { } pub fn remove_device_from_network( - &self, + self: &Rc, id: ObjectID, network_id: ObjectID, ) -> Result { - if let Some(network) = self.networks.get(&network_id) { - let Some(obj) = self.objects.get(&id) else { + if let Some(network) = self.networks.borrow().get(&network_id) { + let Some(obj) = self.objects.borrow().get(&id) else { return Err(VMError::UnknownId(id)); }; let Some(device) = obj.borrow_mut().as_mut_device() else { @@ -549,7 +565,7 @@ impl VM { } pub fn set_batch_device_field( - &self, + self: &Rc, source: ObjectID, prefab: f64, typ: LogicType, @@ -558,7 +574,7 @@ impl VM { ) -> Result<(), ICError> { self.batch_device(source, prefab, None) .map(|device| { - self.set_modified(*device.borrow().get_id()); + self.set_modified(device.borrow().get_id()); device .borrow_mut() .as_mut_device() @@ -570,7 +586,7 @@ impl VM { } pub fn set_batch_device_slot_field( - &self, + self: &Rc, source: ObjectID, prefab: f64, index: f64, @@ -580,7 +596,7 @@ impl VM { ) -> Result<(), ICError> { self.batch_device(source, prefab, None) .map(|device| { - self.set_modified(*device.borrow().get_id()); + self.set_modified(device.borrow().get_id()); device .borrow_mut() .as_mut_device() @@ -592,7 +608,7 @@ impl VM { } pub fn set_batch_name_device_field( - &self, + self: &Rc, source: ObjectID, prefab: f64, name: f64, @@ -602,7 +618,7 @@ impl VM { ) -> Result<(), ICError> { self.batch_device(source, prefab, Some(name)) .map(|device| { - self.set_modified(*device.borrow().get_id()); + self.set_modified(device.borrow().get_id()); device .borrow_mut() .as_mut_device() @@ -614,11 +630,11 @@ impl VM { } pub fn get_batch_device_field( - &self, + self: &Rc, source: ObjectID, prefab: f64, typ: LogicType, - mode: BatchMode, + mode: LogicBatchMethod, ) -> Result { let samples = self .batch_device(source, prefab, None) @@ -636,12 +652,12 @@ impl VM { } pub fn get_batch_name_device_field( - &self, + self: &Rc, source: ObjectID, prefab: f64, name: f64, typ: LogicType, - mode: BatchMode, + mode: LogicBatchMethod, ) -> Result { let samples = self .batch_device(source, prefab, Some(name)) @@ -659,13 +675,13 @@ impl VM { } pub fn get_batch_name_device_slot_field( - &self, + self: &Rc, source: ObjectID, prefab: f64, name: f64, index: f64, typ: LogicSlotType, - mode: BatchMode, + mode: LogicBatchMethod, ) -> Result { let samples = self .batch_device(source, prefab, Some(name)) @@ -683,12 +699,12 @@ impl VM { } pub fn get_batch_device_slot_field( - &self, + self: &Rc, source: ObjectID, prefab: f64, index: f64, typ: LogicSlotType, - mode: BatchMode, + mode: LogicBatchMethod, ) -> Result { let samples = self .batch_device(source, prefab, None) @@ -705,15 +721,15 @@ impl VM { Ok(mode.apply(&samples)) } - pub fn remove_object(&mut self, id: ObjectID) -> Result<(), VMError> { - let Some(obj) = self.objects.remove(&id) else { + pub fn remove_object(self: &Rc, id: ObjectID) -> Result<(), VMError> { + let Some(obj) = self.objects.borrow_mut().remove(&id) else { return Err(VMError::UnknownId(id)); }; if let Some(device) = obj.borrow().as_device() { for conn in device.connection_list().iter() { if let Connection::CableNetwork { net: Some(net), .. } = conn { - if let Some(network) = self.networks.get(&net) { + if let Some(network) = self.networks.borrow().get(&net) { network .borrow_mut() .as_mut_network() @@ -726,7 +742,7 @@ impl VM { self.circuit_holders.borrow_mut().retain(|a| *a != id); } } - self.id_space.free_id(id); + self.id_space.borrow_mut().free_id(id); Ok(()) } @@ -735,13 +751,13 @@ impl VM { /// does not clean up previous object /// returns the id of any former occupant pub fn set_slot_occupant( - &mut self, + self: &Rc, id: ObjectID, index: usize, target: Option, quantity: u32, ) -> Result, VMError> { - let Some(obj) = self.objects.get(&id) else { + let Some(obj) = self.objects.borrow().get(&id) else { return Err(VMError::UnknownId(id)); }; let Some(storage) = obj.borrow_mut().as_mut_storage() else { @@ -751,7 +767,7 @@ impl VM { .get_slot_mut(index) .ok_or(ICError::SlotIndexOutOfRange(index as f64))?; if let Some(target) = target { - let Some(item_obj) = self.objects.get(&target) else { + let Some(item_obj) = self.objects.borrow().get(&target) else { return Err(VMError::UnknownId(id)); }; let Some(item) = item_obj.borrow_mut().as_mut_item() else { @@ -776,11 +792,11 @@ impl VM { /// returns former occupant id if any pub fn remove_slot_occupant( - &mut self, + self: &Rc, id: ObjectID, index: usize, ) -> Result, VMError> { - let Some(obj) = self.objects.get(&id) else { + let Some(obj) = self.objects.borrow().get(&id) else { return Err(VMError::UnknownId(id)); }; let Some(storage) = obj.borrow_mut().as_mut_storage() else { @@ -795,7 +811,7 @@ impl VM { Ok(last) } - pub fn save_vm_state(&self) -> FrozenVM { + pub fn save_vm_state(self: &Rc) -> FrozenVM { FrozenVM { ics: self .circuit_holders @@ -816,7 +832,7 @@ impl VM { } } - pub fn restore_vm_state(&mut self, state: FrozenVM) -> Result<(), VMError> { + pub fn restore_vm_state(self: &Rc, state: FrozenVM) -> Result<(), VMError> { self.circuit_holders.clear(); self.devices.clear(); self.networks.clear(); @@ -868,20 +884,22 @@ impl VM { } impl VMTransation { - pub fn new(vm: &VM) -> Self { + pub fn new(vm: &Rc) -> Self { VMTransation { objects: BTreeMap::new(), circuit_holders: Vec::new(), program_holders: Vec::new(), - default_network_key: vm.default_network_key, + default_network_key: *vm.default_network_key.borrow(), wireless_transmitters: Vec::new(), wireless_receivers: Vec::new(), - id_space: vm.id_space.clone(), + id_space: vm.id_space.borrow().clone(), networks: vm .networks + .borrow() .keys() .map(|net_id| (*net_id, VMTransationNetwork::default())) .collect(), + vm: vm.clone() } } @@ -902,7 +920,7 @@ impl VMTransation { self.id_space.next() }; - let obj = template.build(obj_id); + let obj = template.build(obj_id, self.vm); if let Some(storage) = obj.borrow_mut().as_mut_storage() { for (slot_index, occupant_template) in @@ -935,15 +953,16 @@ impl VMTransation { if let Connection::CableNetwork { net: Some(net_id), typ, + role: ConnectionRole::None, } = conn { - if let Some(net) = self.networks.get_mut(net_id) { + if let Some(net) = self.networks.get_mut(&net_id) { match typ { CableConnectionType::Power => net.power_only.push(obj_id), _ => net.objects.push(obj_id), } } else { - return Err(VMError::InvalidNetwork(*net_id)); + return Err(VMError::InvalidNetwork(net_id)); } } } @@ -955,19 +974,21 @@ impl VMTransation { } } -impl BatchMode { +impl LogicBatchMethod { pub fn apply(&self, samples: &[f64]) -> f64 { match self { - BatchMode::Sum => samples.iter().sum(), + LogicBatchMethod::Sum => samples.iter().sum(), // Both c-charp and rust return NaN for 0.0/0.0 so we're good here - BatchMode::Average => samples.iter().copied().sum::() / samples.len() as f64, + LogicBatchMethod::Average => { + samples.iter().copied().sum::() / samples.len() as f64 + } // Game uses a default of Positive INFINITY for Minimum - BatchMode::Minimum => *samples + LogicBatchMethod::Minimum => *samples .iter() .min_by(|a, b| a.partial_cmp(b).unwrap()) .unwrap_or(&f64::INFINITY), // Game uses default of NEG_INFINITY for Maximum - BatchMode::Maximum => *samples + LogicBatchMethod::Maximum => *samples .iter() .max_by(|a, b| a.partial_cmp(b).unwrap()) .unwrap_or(&f64::NEG_INFINITY), @@ -1063,10 +1084,9 @@ impl IdSpace { } } - #[derive(Debug, Clone, Serialize, Deserialize)] pub struct FrozenVM { - pub objects Vec, + pub objects: Vec, pub circuit_holders: Vec, pub program_holders: Vec, pub default_network_key: ObjectID, @@ -1077,7 +1097,6 @@ pub struct FrozenVM { impl FrozenVM { pub fn from_vm(vm: &VM) -> Self { - let objects = vm.objects.iter().map() - + let objects = vm.objects.iter().map(); } } diff --git a/ic10emu/src/vm/object.rs b/ic10emu/src/vm/object.rs index d49ae72..c0b3831 100644 --- a/ic10emu/src/vm/object.rs +++ b/ic10emu/src/vm/object.rs @@ -1,4 +1,9 @@ -use std::{cell::RefCell, ops::{Deref, DerefMut}, rc::Rc, str::FromStr}; +use std::{ + cell::RefCell, + ops::{Deref, DerefMut}, + rc::Rc, + str::FromStr, +}; use macro_rules_attribute::derive; use serde_derive::{Deserialize, Serialize}; @@ -12,39 +17,55 @@ pub mod traits; use traits::Object; -use crate::vm::enums::{basic_enums::Class as SlotClass, script_enums::LogicSlotType}; +use crate::vm::{ + enums::{basic_enums::Class as SlotClass, script_enums::LogicSlotType}, + VM, +}; use super::enums::prefabs::StationpediaPrefab; pub type ObjectID = u32; -pub type BoxedObject = Rc>>; +pub type BoxedObject = Rc>; #[derive(Debug, Clone)] -pub struct VMObject(BoxedObject); +pub struct VMObject { + obj: BoxedObject, + vm: Rc, +} impl Deref for VMObject { type Target = BoxedObject; #[inline(always)] fn deref(&self) -> &Self::Target { - &self.0 + &self.obj } } impl DerefMut for VMObject { - #[inline(always)] fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 + &mut self.obj } } impl VMObject { - pub fn new(val: T) -> Self + pub fn new(val: T, vm: Rc) -> Self where - T: Object + 'static, + T: Object + 'static, { - VMObject(Rc::new(RefCell::new(val))) + VMObject { + obj: Rc::new(RefCell::new(val)), + vm, + } + } + + pub fn set_vm(&mut self, vm: Rc) { + self.vm = vm; + } + + pub fn get_vm(&self) -> &Rc { + &self.vm } } diff --git a/ic10emu/src/vm/object/generic/structs.rs b/ic10emu/src/vm/object/generic/structs.rs index d97f703..9a5260c 100644 --- a/ic10emu/src/vm/object/generic/structs.rs +++ b/ic10emu/src/vm/object/generic/structs.rs @@ -76,7 +76,7 @@ pub struct GenericLogicableDeviceMemoryReadable { pub prefab: Name, #[custom(object_name)] pub name: Name, - pub small_grid: bool + pub small_grid: bool, pub slots: Vec, pub fields: BTreeMap, pub modes: Option>, diff --git a/ic10emu/src/vm/object/generic/traits.rs b/ic10emu/src/vm/object/generic/traits.rs index f92763f..84b6789 100644 --- a/ic10emu/src/vm/object/generic/traits.rs +++ b/ic10emu/src/vm/object/generic/traits.rs @@ -21,7 +21,7 @@ pub trait GWStructure { fn small_grid(&self) -> bool; } -impl Structure for T { +impl Structure for T { fn is_small_grid(&self) -> bool { self.small_grid() } diff --git a/ic10emu/src/vm/object/macros.rs b/ic10emu/src/vm/object/macros.rs index c5bf977..ce9a691 100644 --- a/ic10emu/src/vm/object/macros.rs +++ b/ic10emu/src/vm/object/macros.rs @@ -1,33 +1,32 @@ macro_rules! object_trait { - (@intf {$trait_name:ident $trt:ident}) => { + (@intf {$trt:ident}) => { paste::paste! { #[allow(missing_docs, unused)] - pub type [<$trt Ref>]<'a, T> = &'a dyn $trt::ID>; + pub type [<$trt Ref>]<'a> = &'a dyn $trt; #[allow(missing_docs, unused)] - pub type [<$trt RefMut>]<'a, T> = &'a mut dyn $trt::ID>; + pub type [<$trt RefMut>]<'a> = &'a mut dyn $trt; } }; (@body $trait_name:ident { $($trt:ident),* }; ) => { - type ID: std::cmp::Ord + std::cmp::Eq + std::hash::Hash; - fn get_id(&self) -> &Self::ID; - fn set_id(&mut self, id: Self::ID); + fn get_id(&self) -> crate::vm::object::ObjectID; + fn set_id(&mut self, id: crate::vm::object::ObjectID); fn get_prefab(&self) -> &crate::vm::object::Name; fn get_mut_prefab(&mut self) -> &mut crate::vm::object::Name; fn get_name(&self) -> &crate::vm::object::Name; fn get_mut_name(&mut self) -> &mut crate::vm::object::Name; fn type_name(&self) -> &str; - fn as_object(&self) -> &dyn $trait_name; - fn as_mut_object(&mut self) -> &mut dyn $trait_name; + fn as_object(&self) -> &dyn $trait_name; + fn as_mut_object(&mut self) -> &mut dyn $trait_name; paste::paste! { $( #[inline(always)] - fn [](&self) -> Option<[<$trt Ref>]> { + fn [](&self) -> Option<[<$trt Ref>]> { None } #[inline(always)] - fn [](&mut self) -> Option<[<$trt RefMut>]> { + fn [](&mut self) -> Option<[<$trt RefMut>]> { None } )* @@ -35,15 +34,15 @@ macro_rules! object_trait { }; (@intf_struct $trait_name:ident { $($trt:ident),* };) => { paste::paste! { - pub struct [<$trait_name Interfaces>]<'a, T: $trait_name> { + pub struct [<$trait_name Interfaces>]<'a> { $( - pub [<$trt:snake>]: Option<[<$trt Ref>]<'a, T>>, + pub [<$trt:snake>]: Option<[<$trt Ref>]<'a>>, )* } - impl<'a, T: $trait_name> [<$trait_name Interfaces>]<'a, T> { + impl<'a> [<$trait_name Interfaces>]<'a> { - pub fn [](obj: &'a dyn $trait_name) -> [<$trait_name Interfaces>]<'a, T> { + pub fn [](obj: &'a dyn $trait_name) -> [<$trait_name Interfaces>]<'a> { [<$trait_name Interfaces>] { $( [<$trt:snake>]: obj.[](), @@ -56,7 +55,7 @@ macro_rules! object_trait { }; ( $trait_name:ident $(: $($bound:tt)* )? {$($trt:ident),*}) => { $( - $crate::vm::object::macros::object_trait!{@intf {$trait_name $trt}} + $crate::vm::object::macros::object_trait!{@intf {$trt}} )* @@ -82,13 +81,12 @@ macro_rules! ObjectInterface { @name $name_field:ident: $name_typ:ty; } => { impl $trait_name for $struct { - type ID = $id_typ; - fn get_id(&self) -> &Self::ID { - &self.$id_field + fn get_id(&self) -> crate::vm::object::ObjectID { + self.$id_field } - fn set_id(&mut self, id: Self::ID) { + fn set_id(&mut self, id: crate::vm::object::ObjectID) { self.$id_field = id; } @@ -113,23 +111,23 @@ macro_rules! ObjectInterface { } #[inline(always)] - fn as_object(&self) -> &dyn $trait_name { + fn as_object(&self) -> &dyn $trait_name { self } #[inline(always)] - fn as_mut_object(&mut self) -> &mut dyn $trait_name { + fn as_mut_object(&mut self) -> &mut dyn $trait_name { self } paste::paste!{$( #[inline(always)] - fn [](&self) -> Option<[<$trt Ref>]> { + fn [](&self) -> Option<[<$trt Ref>]> { Some(self) } #[inline(always)] - fn [](&mut self) -> Option<[<$trt RefMut>]> { + fn [](&mut self) -> Option<[<$trt RefMut>]> { Some(self) } )*} diff --git a/ic10emu/src/vm/object/stationpedia.rs b/ic10emu/src/vm/object/stationpedia.rs index d6713fb..f6b2b2d 100644 --- a/ic10emu/src/vm/object/stationpedia.rs +++ b/ic10emu/src/vm/object/stationpedia.rs @@ -1,4 +1,6 @@ -use crate::vm::enums::prefabs::StationpediaPrefab; +use std::rc::Rc; + +use crate::vm::{enums::prefabs::StationpediaPrefab, VM}; use crate::vm::object::VMObject; use super::templates::ObjectTemplate; @@ -7,12 +9,12 @@ use super::ObjectID; pub mod structs; #[allow(unused)] -pub fn object_from_prefab_template(template: &ObjectTemplate, id: ObjectID) -> Option { +pub fn object_from_prefab_template(template: &ObjectTemplate, id: ObjectID, vm: &Rc) -> Option { let prefab = StationpediaPrefab::from_repr(template.prefab_info().prefab_hash); match prefab { - Some(StationpediaPrefab::ItemIntegratedCircuit10) => { - Some(VMObject::new(structs::ItemIntegratedCircuit10)) - } + // Some(StationpediaPrefab::ItemIntegratedCircuit10) => { + // Some(VMObject::new(structs::ItemIntegratedCircuit10)) + // } // Some(StationpediaPrefab::StructureCircuitHousing) => Some() // Some(StationpediaPrefab::StructureRocketCircuitHousing) => Some() _ => None, diff --git a/ic10emu/src/vm/object/stationpedia/structs/integrated_circuit.rs b/ic10emu/src/vm/object/stationpedia/structs/integrated_circuit.rs index 9ee4b99..8496eea 100644 --- a/ic10emu/src/vm/object/stationpedia/structs/integrated_circuit.rs +++ b/ic10emu/src/vm/object/stationpedia/structs/integrated_circuit.rs @@ -218,6 +218,12 @@ impl Storage for ItemIntegratedCircuit10 { fn get_slot_mut(&mut self, index: usize) -> Option<&mut Slot> { None } + fn get_slots(&self) -> &[Slot] { + &[] + } + fn get_slots_mut(&mut self) -> &mut[Slot] { + &mut [] + } } impl MemoryReadable for ItemIntegratedCircuit10 { @@ -233,6 +239,9 @@ impl MemoryReadable for ItemIntegratedCircuit10 { Ok(self.memory[index as usize]) } } + fn get_memory_slice(&self) -> &[f64] { + &self.memory + } } impl MemoryWritable for ItemIntegratedCircuit10 { @@ -281,6 +290,9 @@ impl IntegratedCircuit for ItemIntegratedCircuit10 { fn set_next_instruction(&mut self, next_instruction: f64) { self.next_ip = next_instruction as usize; } + fn set_next_instruction_relative(&mut self, offset: f64) { + self.next_ip = (self.ip as f64 + offset) as usize + } fn reset(&mut self) { self.ip = 0; self.ic = 0; @@ -387,6 +399,12 @@ impl IntegratedCircuit for ItemIntegratedCircuit10 { fn get_labels(&self) -> &BTreeMap { &self.program.labels } + fn get_state(&self) -> crate::interpreter::ICState { + self.state + } + fn set_state(&mut self, state: crate::interpreter::ICState) { + self.state = state; + } } impl SleepInstruction for ItemIntegratedCircuit10 { @@ -1306,642 +1324,644 @@ impl BdseInstruction for ItemIntegratedCircuit10 { Ok(()) } } -impl BdsealInstruction for ItemIntegratedCircuit10 { - /// bdseal d? a(r?|num) - fn execute_bdseal(&mut self, vm: &VM, d: &Operand, a: &Operand) -> Result<(), ICError>; -} -impl BrdseInstruction for ItemIntegratedCircuit10 { - /// brdse d? a(r?|num) - fn execute_brdse(&mut self, vm: &VM, d: &Operand, a: &Operand) -> Result<(), ICError>; -} -impl AbsInstruction for ItemIntegratedCircuit10 { - /// abs r? a(r?|num) - fn execute_abs(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>; -} -impl AcosInstruction for ItemIntegratedCircuit10 { - /// acos r? a(r?|num) - fn execute_acos(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>; -} -impl AddInstruction for ItemIntegratedCircuit10 { - /// add r? a(r?|num) b(r?|num) - fn execute_add( - &mut self, - vm: &VM, - r: &Operand, - a: &Operand, - b: &Operand, - ) -> Result<(), ICError>; -} -impl AndInstruction for ItemIntegratedCircuit10 { - /// and r? a(r?|num) b(r?|num) - fn execute_and( - &mut self, - vm: &VM, - r: &Operand, - a: &Operand, - b: &Operand, - ) -> Result<(), ICError>; -} -impl AsinInstruction for ItemIntegratedCircuit10 { - /// asin r? a(r?|num) - fn execute_asin(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>; -} -impl AtanInstruction for ItemIntegratedCircuit10 { - /// atan r? a(r?|num) - fn execute_atan(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>; -} -impl Atan2Instruction for ItemIntegratedCircuit10 { - /// atan2 r? a(r?|num) b(r?|num) - fn execute_atan2( - &mut self, - vm: &VM, - r: &Operand, - a: &Operand, - b: &Operand, - ) -> Result<(), ICError>; -} -impl BdnsInstruction for ItemIntegratedCircuit10 { - /// bdns d? a(r?|num) - fn execute_bdns(&mut self, vm: &VM, d: &Operand, a: &Operand) -> Result<(), ICError>; -} -impl BdnsalInstruction for ItemIntegratedCircuit10 { - /// bdnsal d? a(r?|num) - fn execute_bdnsal(&mut self, vm: &VM, d: &Operand, a: &Operand) -> Result<(), ICError>; -} -impl BnanInstruction for ItemIntegratedCircuit10 { - /// bnan a(r?|num) b(r?|num) - fn execute_bnan(&mut self, vm: &VM, a: &Operand, b: &Operand) -> Result<(), ICError>; -} -impl BrdnsInstruction for ItemIntegratedCircuit10 { - /// brdns d? a(r?|num) - fn execute_brdns(&mut self, vm: &VM, d: &Operand, a: &Operand) -> Result<(), ICError>; -} -impl BrnanInstruction for ItemIntegratedCircuit10 { - /// brnan a(r?|num) b(r?|num) - fn execute_brnan(&mut self, vm: &VM, a: &Operand, b: &Operand) -> Result<(), ICError>; -} -impl CeilInstruction for ItemIntegratedCircuit10 { - /// ceil r? a(r?|num) - fn execute_ceil(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>; -} -impl ClrInstruction for ItemIntegratedCircuit10 { - /// clr d? - fn execute_clr(&mut self, vm: &VM, d: &Operand) -> Result<(), ICError>; -} -impl ClrdInstruction for ItemIntegratedCircuit10 { - /// clrd id(r?|num) - fn execute_clrd(&mut self, vm: &VM, id: &Operand) -> Result<(), ICError>; -} -impl CosInstruction for ItemIntegratedCircuit10 { - /// cos r? a(r?|num) - fn execute_cos(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>; -} -impl DivInstruction for ItemIntegratedCircuit10 { - /// div r? a(r?|num) b(r?|num) - fn execute_div( - &mut self, - vm: &VM, - r: &Operand, - a: &Operand, - b: &Operand, - ) -> Result<(), ICError>; -} -impl ExpInstruction for ItemIntegratedCircuit10 { - /// exp r? a(r?|num) - fn execute_exp(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>; -} -impl FloorInstruction for ItemIntegratedCircuit10 { - /// floor r? a(r?|num) - fn execute_floor(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>; -} -impl GetInstruction for ItemIntegratedCircuit10 { - /// get r? d? address(r?|num) - fn execute_get( - &mut self, - vm: &VM, - r: &Operand, - d: &Operand, - address: &Operand, - ) -> Result<(), ICError>; -} -impl GetdInstruction for ItemIntegratedCircuit10 { - /// getd r? id(r?|num) address(r?|num) - fn execute_getd( - &mut self, - vm: &VM, - r: &Operand, - id: &Operand, - address: &Operand, - ) -> Result<(), ICError>; -} -impl HcfInstruction for ItemIntegratedCircuit10 { - /// hcf - fn execute_hcf(&mut self, vm: &VM) -> Result<(), ICError>; -} -impl JInstruction for ItemIntegratedCircuit10 { - /// j int - fn execute_j(&mut self, vm: &VM, int: &Operand) -> Result<(), ICError>; -} -impl JalInstruction for ItemIntegratedCircuit10 { - /// jal int - fn execute_jal(&mut self, vm: &VM, int: &Operand) -> Result<(), ICError>; -} -impl JrInstruction for ItemIntegratedCircuit10 { - /// jr int - fn execute_jr(&mut self, vm: &VM, int: &Operand) -> Result<(), ICError>; -} -impl LInstruction for ItemIntegratedCircuit10 { - /// l r? d? logicType - fn execute_l( - &mut self, - vm: &VM, - r: &Operand, - d: &Operand, - logic_type: &Operand, - ) -> Result<(), ICError>; -} -impl LabelInstruction for ItemIntegratedCircuit10 { - /// label d? str - fn execute_label(&mut self, vm: &VM, d: &Operand, str: &Operand) -> Result<(), ICError>; -} -impl LbInstruction for ItemIntegratedCircuit10 { - /// lb r? deviceHash logicType batchMode - fn execute_lb( - &mut self, - vm: &VM, - r: &Operand, - device_hash: &Operand, - logic_type: &Operand, - batch_mode: &Operand, - ) -> Result<(), ICError>; -} -impl LbnInstruction for ItemIntegratedCircuit10 { - /// lbn r? deviceHash nameHash logicType batchMode - fn execute_lbn( - &mut self, - vm: &VM, - r: &Operand, - device_hash: &Operand, - name_hash: &Operand, - logic_type: &Operand, - batch_mode: &Operand, - ) -> Result<(), ICError>; -} -impl LbnsInstruction for ItemIntegratedCircuit10 { - /// lbns r? deviceHash nameHash slotIndex logicSlotType batchMode - fn execute_lbns( - &mut self, - vm: &VM, - r: &Operand, - device_hash: &Operand, - name_hash: &Operand, - slot_index: &Operand, - logic_slot_type: &Operand, - batch_mode: &Operand, - ) -> Result<(), ICError>; -} -impl LbsInstruction for ItemIntegratedCircuit10 { - /// lbs r? deviceHash slotIndex logicSlotType batchMode - fn execute_lbs( - &mut self, - vm: &VM, - r: &Operand, - device_hash: &Operand, - slot_index: &Operand, - logic_slot_type: &Operand, - batch_mode: &Operand, - ) -> Result<(), ICError>; -} -impl LdInstruction for ItemIntegratedCircuit10 { - /// ld r? id(r?|num) logicType - fn execute_ld( - &mut self, - vm: &VM, - r: &Operand, - id: &Operand, - logic_type: &Operand, - ) -> Result<(), ICError>; -} -impl LogInstruction for ItemIntegratedCircuit10 { - /// log r? a(r?|num) - fn execute_log(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>; -} -impl LrInstruction for ItemIntegratedCircuit10 { - /// lr r? d? reagentMode int - fn execute_lr( - &mut self, - vm: &VM, - r: &Operand, - d: &Operand, - reagent_mode: &Operand, - int: &Operand, - ) -> Result<(), ICError>; -} -impl LsInstruction for ItemIntegratedCircuit10 { - /// ls r? d? slotIndex logicSlotType - fn execute_ls( - &mut self, - vm: &VM, - r: &Operand, - d: &Operand, - slot_index: &Operand, - logic_slot_type: &Operand, - ) -> Result<(), ICError>; -} -impl MaxInstruction for ItemIntegratedCircuit10 { - /// max r? a(r?|num) b(r?|num) - fn execute_max( - &mut self, - vm: &VM, - r: &Operand, - a: &Operand, - b: &Operand, - ) -> Result<(), ICError>; -} -impl MinInstruction for ItemIntegratedCircuit10 { - /// min r? a(r?|num) b(r?|num) - fn execute_min( - &mut self, - vm: &VM, - r: &Operand, - a: &Operand, - b: &Operand, - ) -> Result<(), ICError>; -} -impl ModInstruction for ItemIntegratedCircuit10 { - /// mod r? a(r?|num) b(r?|num) - fn execute_mod( - &mut self, - vm: &VM, - r: &Operand, - a: &Operand, - b: &Operand, - ) -> Result<(), ICError>; -} -impl MulInstruction for ItemIntegratedCircuit10 { - /// mul r? a(r?|num) b(r?|num) - fn execute_mul( - &mut self, - vm: &VM, - r: &Operand, - a: &Operand, - b: &Operand, - ) -> Result<(), ICError>; -} -impl NorInstruction for ItemIntegratedCircuit10 { - /// nor r? a(r?|num) b(r?|num) - fn execute_nor( - &mut self, - vm: &VM, - r: &Operand, - a: &Operand, - b: &Operand, - ) -> Result<(), ICError>; -} -impl NotInstruction for ItemIntegratedCircuit10 { - /// not r? a(r?|num) - fn execute_not(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>; -} -impl OrInstruction for ItemIntegratedCircuit10 { - /// or r? a(r?|num) b(r?|num) - fn execute_or(&mut self, vm: &VM, r: &Operand, a: &Operand, b: &Operand) - -> Result<(), ICError>; -} -impl PeekInstruction for ItemIntegratedCircuit10 { - /// peek r? - fn execute_peek(&mut self, vm: &VM, r: &Operand) -> Result<(), ICError>; -} -impl PokeInstruction for ItemIntegratedCircuit10 { - /// poke address(r?|num) value(r?|num) - fn execute_poke(&mut self, vm: &VM, address: &Operand, value: &Operand) -> Result<(), ICError>; -} -impl PopInstruction for ItemIntegratedCircuit10 { - /// pop r? - fn execute_pop(&mut self, vm: &VM, r: &Operand) -> Result<(), ICError>; -} -impl PushInstruction for ItemIntegratedCircuit10 { - /// push a(r?|num) - fn execute_push(&mut self, vm: &VM, a: &Operand) -> Result<(), ICError>; -} -impl PutInstruction for ItemIntegratedCircuit10 { - /// put d? address(r?|num) value(r?|num) - fn execute_put( - &mut self, - vm: &VM, - d: &Operand, - address: &Operand, - value: &Operand, - ) -> Result<(), ICError>; -} -impl PutdInstruction for ItemIntegratedCircuit10 { - /// putd id(r?|num) address(r?|num) value(r?|num) - fn execute_putd( - &mut self, - vm: &VM, - id: &Operand, - address: &Operand, - value: &Operand, - ) -> Result<(), ICError>; -} -impl RandInstruction for ItemIntegratedCircuit10 { - /// rand r? - fn execute_rand(&mut self, vm: &VM, r: &Operand) -> Result<(), ICError>; -} -impl RoundInstruction for ItemIntegratedCircuit10 { - /// round r? a(r?|num) - fn execute_round(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>; -} -impl SInstruction for ItemIntegratedCircuit10 { - /// s d? logicType r? - fn execute_s( - &mut self, - vm: &VM, - d: &Operand, - logic_type: &Operand, - r: &Operand, - ) -> Result<(), ICError>; -} -impl SapInstruction for ItemIntegratedCircuit10 { - /// sap r? a(r?|num) b(r?|num) c(r?|num) - fn execute_sap( - &mut self, - vm: &VM, - r: &Operand, - a: &Operand, - b: &Operand, - c: &Operand, - ) -> Result<(), ICError>; -} -impl SapzInstruction for ItemIntegratedCircuit10 { - /// sapz r? a(r?|num) b(r?|num) - fn execute_sapz( - &mut self, - vm: &VM, - r: &Operand, - a: &Operand, - b: &Operand, - ) -> Result<(), ICError>; -} -impl SbInstruction for ItemIntegratedCircuit10 { - /// sb deviceHash logicType r? - fn execute_sb( - &mut self, - vm: &VM, - device_hash: &Operand, - logic_type: &Operand, - r: &Operand, - ) -> Result<(), ICError>; -} -impl SbnInstruction for ItemIntegratedCircuit10 { - /// sbn deviceHash nameHash logicType r? - fn execute_sbn( - &mut self, - vm: &VM, - device_hash: &Operand, - name_hash: &Operand, - logic_type: &Operand, - r: &Operand, - ) -> Result<(), ICError>; -} -impl SbsInstruction for ItemIntegratedCircuit10 { - /// sbs deviceHash slotIndex logicSlotType r? - fn execute_sbs( - &mut self, - vm: &VM, - device_hash: &Operand, - slot_index: &Operand, - logic_slot_type: &Operand, - r: &Operand, - ) -> Result<(), ICError>; -} -impl SdInstruction for ItemIntegratedCircuit10 { - /// sd id(r?|num) logicType r? - fn execute_sd( - &mut self, - vm: &VM, - id: &Operand, - logic_type: &Operand, - r: &Operand, - ) -> Result<(), ICError>; -} -impl SdnsInstruction for ItemIntegratedCircuit10 { - /// sdns r? d? - fn execute_sdns(&mut self, vm: &VM, r: &Operand, d: &Operand) -> Result<(), ICError>; -} -impl SdseInstruction for ItemIntegratedCircuit10 { - /// sdse r? d? - fn execute_sdse(&mut self, vm: &VM, r: &Operand, d: &Operand) -> Result<(), ICError>; -} -impl SelectInstruction for ItemIntegratedCircuit10 { - /// select r? a(r?|num) b(r?|num) c(r?|num) - fn execute_select( - &mut self, - vm: &VM, - r: &Operand, - a: &Operand, - b: &Operand, - c: &Operand, - ) -> Result<(), ICError>; -} -impl SeqInstruction for ItemIntegratedCircuit10 { - /// seq r? a(r?|num) b(r?|num) - fn execute_seq( - &mut self, - vm: &VM, - r: &Operand, - a: &Operand, - b: &Operand, - ) -> Result<(), ICError>; -} -impl SeqzInstruction for ItemIntegratedCircuit10 { - /// seqz r? a(r?|num) - fn execute_seqz(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>; -} -impl SgeInstruction for ItemIntegratedCircuit10 { - /// sge r? a(r?|num) b(r?|num) - fn execute_sge( - &mut self, - vm: &VM, - r: &Operand, - a: &Operand, - b: &Operand, - ) -> Result<(), ICError>; -} -impl SgezInstruction for ItemIntegratedCircuit10 { - /// sgez r? a(r?|num) - fn execute_sgez(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>; -} -impl SgtInstruction for ItemIntegratedCircuit10 { - /// sgt r? a(r?|num) b(r?|num) - fn execute_sgt( - &mut self, - vm: &VM, - r: &Operand, - a: &Operand, - b: &Operand, - ) -> Result<(), ICError>; -} -impl SgtzInstruction for ItemIntegratedCircuit10 { - /// sgtz r? a(r?|num) - fn execute_sgtz(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>; -} -impl SinInstruction for ItemIntegratedCircuit10 { - /// sin r? a(r?|num) - fn execute_sin(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>; -} -impl SlaInstruction for ItemIntegratedCircuit10 { - /// sla r? a(r?|num) b(r?|num) - fn execute_sla( - &mut self, - vm: &VM, - r: &Operand, - a: &Operand, - b: &Operand, - ) -> Result<(), ICError>; -} -impl SleInstruction for ItemIntegratedCircuit10 { - /// sle r? a(r?|num) b(r?|num) - fn execute_sle( - &mut self, - vm: &VM, - r: &Operand, - a: &Operand, - b: &Operand, - ) -> Result<(), ICError>; -} -impl SlezInstruction for ItemIntegratedCircuit10 { - /// slez r? a(r?|num) - fn execute_slez(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>; -} -impl SllInstruction for ItemIntegratedCircuit10 { - /// sll r? a(r?|num) b(r?|num) - fn execute_sll( - &mut self, - vm: &VM, - r: &Operand, - a: &Operand, - b: &Operand, - ) -> Result<(), ICError>; -} -impl SltInstruction for ItemIntegratedCircuit10 { - /// slt r? a(r?|num) b(r?|num) - fn execute_slt( - &mut self, - vm: &VM, - r: &Operand, - a: &Operand, - b: &Operand, - ) -> Result<(), ICError>; -} -impl SltzInstruction for ItemIntegratedCircuit10 { - /// sltz r? a(r?|num) - fn execute_sltz(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>; -} -impl SnaInstruction for ItemIntegratedCircuit10 { - /// sna r? a(r?|num) b(r?|num) c(r?|num) - fn execute_sna( - &mut self, - vm: &VM, - r: &Operand, - a: &Operand, - b: &Operand, - c: &Operand, - ) -> Result<(), ICError>; -} -impl SnanInstruction for ItemIntegratedCircuit10 { - /// snan r? a(r?|num) - fn execute_snan(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>; -} -impl SnanzInstruction for ItemIntegratedCircuit10 { - /// snanz r? a(r?|num) - fn execute_snanz(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>; -} -impl SnazInstruction for ItemIntegratedCircuit10 { - /// snaz r? a(r?|num) b(r?|num) - fn execute_snaz( - &mut self, - vm: &VM, - r: &Operand, - a: &Operand, - b: &Operand, - ) -> Result<(), ICError>; -} -impl SneInstruction for ItemIntegratedCircuit10 { - /// sne r? a(r?|num) b(r?|num) - fn execute_sne( - &mut self, - vm: &VM, - r: &Operand, - a: &Operand, - b: &Operand, - ) -> Result<(), ICError>; -} -impl SnezInstruction for ItemIntegratedCircuit10 { - /// snez r? a(r?|num) - fn execute_snez(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>; -} -impl SqrtInstruction for ItemIntegratedCircuit10 { - /// sqrt r? a(r?|num) - fn execute_sqrt(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>; -} -impl SraInstruction for ItemIntegratedCircuit10 { - /// sra r? a(r?|num) b(r?|num) - fn execute_sra( - &mut self, - vm: &VM, - r: &Operand, - a: &Operand, - b: &Operand, - ) -> Result<(), ICError>; -} -impl SrlInstruction for ItemIntegratedCircuit10 { - /// srl r? a(r?|num) b(r?|num) - fn execute_srl( - &mut self, - vm: &VM, - r: &Operand, - a: &Operand, - b: &Operand, - ) -> Result<(), ICError>; -} -impl SsInstruction for ItemIntegratedCircuit10 { - /// ss d? slotIndex logicSlotType r? - fn execute_ss( - &mut self, - vm: &VM, - d: &Operand, - slot_index: &Operand, - logic_slot_type: &Operand, - r: &Operand, - ) -> Result<(), ICError>; -} -impl SubInstruction for ItemIntegratedCircuit10 { - /// sub r? a(r?|num) b(r?|num) - fn execute_sub( - &mut self, - vm: &VM, - r: &Operand, - a: &Operand, - b: &Operand, - ) -> Result<(), ICError>; -} -impl TanInstruction for ItemIntegratedCircuit10 { - /// tan r? a(r?|num) - fn execute_tan(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>; -} -impl TruncInstruction for ItemIntegratedCircuit10 { - /// trunc r? a(r?|num) - fn execute_trunc(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>; -} -impl XorInstruction for ItemIntegratedCircuit10 { - /// xor r? a(r?|num) b(r?|num) - fn execute_xor( - &mut self, - vm: &VM, - r: &Operand, - a: &Operand, - b: &Operand, - ) -> Result<(), ICError>; -} +// impl BdsealInstruction for ItemIntegratedCircuit10 { +// /// bdseal d? a(r?|num) +// fn execute_bdseal(&mut self, vm: &VM, d: &Operand, a: &Operand) -> Result<(), ICError>; +// } +// impl BrdseInstruction for ItemIntegratedCircuit10 { +// /// brdse d? a(r?|num) +// fn execute_brdse(&mut self, vm: &VM, d: &Operand, a: &Operand) -> Result<(), ICError>; +// } +// +// impl AbsInstruction for ItemIntegratedCircuit10 { +// /// abs r? a(r?|num) +// fn execute_abs(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>; +// } +// +// impl AcosInstruction for ItemIntegratedCircuit10 { +// /// acos r? a(r?|num) +// fn execute_acos(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>; +// } +// impl AddInstruction for ItemIntegratedCircuit10 { +// /// add r? a(r?|num) b(r?|num) +// fn execute_add( +// &mut self, +// vm: &VM, +// r: &Operand, +// a: &Operand, +// b: &Operand, +// ) -> Result<(), ICError>; +// } +// impl AndInstruction for ItemIntegratedCircuit10 { +// /// and r? a(r?|num) b(r?|num) +// fn execute_and( +// &mut self, +// vm: &VM, +// r: &Operand, +// a: &Operand, +// b: &Operand, +// ) -> Result<(), ICError>; +// } +// impl AsinInstruction for ItemIntegratedCircuit10 { +// /// asin r? a(r?|num) +// fn execute_asin(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>; +// } +// impl AtanInstruction for ItemIntegratedCircuit10 { +// /// atan r? a(r?|num) +// fn execute_atan(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>; +// } +// impl Atan2Instruction for ItemIntegratedCircuit10 { +// /// atan2 r? a(r?|num) b(r?|num) +// fn execute_atan2( +// &mut self, +// vm: &VM, +// r: &Operand, +// a: &Operand, +// b: &Operand, +// ) -> Result<(), ICError>; +// } +// impl BdnsInstruction for ItemIntegratedCircuit10 { +// /// bdns d? a(r?|num) +// fn execute_bdns(&mut self, vm: &VM, d: &Operand, a: &Operand) -> Result<(), ICError>; +// } +// impl BdnsalInstruction for ItemIntegratedCircuit10 { +// /// bdnsal d? a(r?|num) +// fn execute_bdnsal(&mut self, vm: &VM, d: &Operand, a: &Operand) -> Result<(), ICError>; +// } +// impl BnanInstruction for ItemIntegratedCircuit10 { +// /// bnan a(r?|num) b(r?|num) +// fn execute_bnan(&mut self, vm: &VM, a: &Operand, b: &Operand) -> Result<(), ICError>; +// } +// impl BrdnsInstruction for ItemIntegratedCircuit10 { +// /// brdns d? a(r?|num) +// fn execute_brdns(&mut self, vm: &VM, d: &Operand, a: &Operand) -> Result<(), ICError>; +// } +// impl BrnanInstruction for ItemIntegratedCircuit10 { +// /// brnan a(r?|num) b(r?|num) +// fn execute_brnan(&mut self, vm: &VM, a: &Operand, b: &Operand) -> Result<(), ICError>; +// } +// impl CeilInstruction for ItemIntegratedCircuit10 { +// /// ceil r? a(r?|num) +// fn execute_ceil(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>; +// } +// impl ClrInstruction for ItemIntegratedCircuit10 { +// /// clr d? +// fn execute_clr(&mut self, vm: &VM, d: &Operand) -> Result<(), ICError>; +// } +// impl ClrdInstruction for ItemIntegratedCircuit10 { +// /// clrd id(r?|num) +// fn execute_clrd(&mut self, vm: &VM, id: &Operand) -> Result<(), ICError>; +// } +// impl CosInstruction for ItemIntegratedCircuit10 { +// /// cos r? a(r?|num) +// fn execute_cos(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>; +// } +// impl DivInstruction for ItemIntegratedCircuit10 { +// /// div r? a(r?|num) b(r?|num) +// fn execute_div( +// &mut self, +// vm: &VM, +// r: &Operand, +// a: &Operand, +// b: &Operand, +// ) -> Result<(), ICError>; +// } +// impl ExpInstruction for ItemIntegratedCircuit10 { +// /// exp r? a(r?|num) +// fn execute_exp(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>; +// } +// impl FloorInstruction for ItemIntegratedCircuit10 { +// /// floor r? a(r?|num) +// fn execute_floor(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>; +// } +// impl GetInstruction for ItemIntegratedCircuit10 { +// /// get r? d? address(r?|num) +// fn execute_get( +// &mut self, +// vm: &VM, +// r: &Operand, +// d: &Operand, +// address: &Operand, +// ) -> Result<(), ICError>; +// } +// impl GetdInstruction for ItemIntegratedCircuit10 { +// /// getd r? id(r?|num) address(r?|num) +// fn execute_getd( +// &mut self, +// vm: &VM, +// r: &Operand, +// id: &Operand, +// address: &Operand, +// ) -> Result<(), ICError>; +// } +// impl HcfInstruction for ItemIntegratedCircuit10 { +// /// hcf +// fn execute_hcf(&mut self, vm: &VM) -> Result<(), ICError>; +// } +// impl JInstruction for ItemIntegratedCircuit10 { +// /// j int +// fn execute_j(&mut self, vm: &VM, int: &Operand) -> Result<(), ICError>; +// } +// impl JalInstruction for ItemIntegratedCircuit10 { +// /// jal int +// fn execute_jal(&mut self, vm: &VM, int: &Operand) -> Result<(), ICError>; +// } +// impl JrInstruction for ItemIntegratedCircuit10 { +// /// jr int +// fn execute_jr(&mut self, vm: &VM, int: &Operand) -> Result<(), ICError>; +// } +// impl LInstruction for ItemIntegratedCircuit10 { +// /// l r? d? logicType +// fn execute_l( +// &mut self, +// vm: &VM, +// r: &Operand, +// d: &Operand, +// logic_type: &Operand, +// ) -> Result<(), ICError>; +// } +// impl LabelInstruction for ItemIntegratedCircuit10 { +// /// label d? str +// fn execute_label(&mut self, vm: &VM, d: &Operand, str: &Operand) -> Result<(), ICError>; +// } +// impl LbInstruction for ItemIntegratedCircuit10 { +// /// lb r? deviceHash logicType batchMode +// fn execute_lb( +// &mut self, +// vm: &VM, +// r: &Operand, +// device_hash: &Operand, +// logic_type: &Operand, +// batch_mode: &Operand, +// ) -> Result<(), ICError>; +// } +// impl LbnInstruction for ItemIntegratedCircuit10 { +// /// lbn r? deviceHash nameHash logicType batchMode +// fn execute_lbn( +// &mut self, +// vm: &VM, +// r: &Operand, +// device_hash: &Operand, +// name_hash: &Operand, +// logic_type: &Operand, +// batch_mode: &Operand, +// ) -> Result<(), ICError>; +// } +// impl LbnsInstruction for ItemIntegratedCircuit10 { +// /// lbns r? deviceHash nameHash slotIndex logicSlotType batchMode +// fn execute_lbns( +// &mut self, +// vm: &VM, +// r: &Operand, +// device_hash: &Operand, +// name_hash: &Operand, +// slot_index: &Operand, +// logic_slot_type: &Operand, +// batch_mode: &Operand, +// ) -> Result<(), ICError>; +// } +// impl LbsInstruction for ItemIntegratedCircuit10 { +// /// lbs r? deviceHash slotIndex logicSlotType batchMode +// fn execute_lbs( +// &mut self, +// vm: &VM, +// r: &Operand, +// device_hash: &Operand, +// slot_index: &Operand, +// logic_slot_type: &Operand, +// batch_mode: &Operand, +// ) -> Result<(), ICError>; +// } +// impl LdInstruction for ItemIntegratedCircuit10 { +// /// ld r? id(r?|num) logicType +// fn execute_ld( +// &mut self, +// vm: &VM, +// r: &Operand, +// id: &Operand, +// logic_type: &Operand, +// ) -> Result<(), ICError>; +// } +// impl LogInstruction for ItemIntegratedCircuit10 { +// /// log r? a(r?|num) +// fn execute_log(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>; +// } +// impl LrInstruction for ItemIntegratedCircuit10 { +// /// lr r? d? reagentMode int +// fn execute_lr( +// &mut self, +// vm: &VM, +// r: &Operand, +// d: &Operand, +// reagent_mode: &Operand, +// int: &Operand, +// ) -> Result<(), ICError>; +// } +// impl LsInstruction for ItemIntegratedCircuit10 { +// /// ls r? d? slotIndex logicSlotType +// fn execute_ls( +// &mut self, +// vm: &VM, +// r: &Operand, +// d: &Operand, +// slot_index: &Operand, +// logic_slot_type: &Operand, +// ) -> Result<(), ICError>; +// } +// impl MaxInstruction for ItemIntegratedCircuit10 { +// /// max r? a(r?|num) b(r?|num) +// fn execute_max( +// &mut self, +// vm: &VM, +// r: &Operand, +// a: &Operand, +// b: &Operand, +// ) -> Result<(), ICError>; +// } +// impl MinInstruction for ItemIntegratedCircuit10 { +// /// min r? a(r?|num) b(r?|num) +// fn execute_min( +// &mut self, +// vm: &VM, +// r: &Operand, +// a: &Operand, +// b: &Operand, +// ) -> Result<(), ICError>; +// } +// impl ModInstruction for ItemIntegratedCircuit10 { +// /// mod r? a(r?|num) b(r?|num) +// fn execute_mod( +// &mut self, +// vm: &VM, +// r: &Operand, +// a: &Operand, +// b: &Operand, +// ) -> Result<(), ICError>; +// } +// impl MulInstruction for ItemIntegratedCircuit10 { +// /// mul r? a(r?|num) b(r?|num) +// fn execute_mul( +// &mut self, +// vm: &VM, +// r: &Operand, +// a: &Operand, +// b: &Operand, +// ) -> Result<(), ICError>; +// } +// impl NorInstruction for ItemIntegratedCircuit10 { +// /// nor r? a(r?|num) b(r?|num) +// fn execute_nor( +// &mut self, +// vm: &VM, +// r: &Operand, +// a: &Operand, +// b: &Operand, +// ) -> Result<(), ICError>; +// } +// impl NotInstruction for ItemIntegratedCircuit10 { +// /// not r? a(r?|num) +// fn execute_not(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>; +// } +// impl OrInstruction for ItemIntegratedCircuit10 { +// /// or r? a(r?|num) b(r?|num) +// fn execute_or(&mut self, vm: &VM, r: &Operand, a: &Operand, b: &Operand) +// -> Result<(), ICError>; +// } +// impl PeekInstruction for ItemIntegratedCircuit10 { +// /// peek r? +// fn execute_peek(&mut self, vm: &VM, r: &Operand) -> Result<(), ICError>; +// } +// impl PokeInstruction for ItemIntegratedCircuit10 { +// /// poke address(r?|num) value(r?|num) +// fn execute_poke(&mut self, vm: &VM, address: &Operand, value: &Operand) -> Result<(), ICError>; +// } +// impl PopInstruction for ItemIntegratedCircuit10 { +// /// pop r? +// fn execute_pop(&mut self, vm: &VM, r: &Operand) -> Result<(), ICError>; +// } +// impl PushInstruction for ItemIntegratedCircuit10 { +// /// push a(r?|num) +// fn execute_push(&mut self, vm: &VM, a: &Operand) -> Result<(), ICError>; +// } +// impl PutInstruction for ItemIntegratedCircuit10 { +// /// put d? address(r?|num) value(r?|num) +// fn execute_put( +// &mut self, +// vm: &VM, +// d: &Operand, +// address: &Operand, +// value: &Operand, +// ) -> Result<(), ICError>; +// } +// impl PutdInstruction for ItemIntegratedCircuit10 { +// /// putd id(r?|num) address(r?|num) value(r?|num) +// fn execute_putd( +// &mut self, +// vm: &VM, +// id: &Operand, +// address: &Operand, +// value: &Operand, +// ) -> Result<(), ICError>; +// } +// impl RandInstruction for ItemIntegratedCircuit10 { +// /// rand r? +// fn execute_rand(&mut self, vm: &VM, r: &Operand) -> Result<(), ICError>; +// } +// impl RoundInstruction for ItemIntegratedCircuit10 { +// /// round r? a(r?|num) +// fn execute_round(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>; +// } +// impl SInstruction for ItemIntegratedCircuit10 { +// /// s d? logicType r? +// fn execute_s( +// &mut self, +// vm: &VM, +// d: &Operand, +// logic_type: &Operand, +// r: &Operand, +// ) -> Result<(), ICError>; +// } +// impl SapInstruction for ItemIntegratedCircuit10 { +// /// sap r? a(r?|num) b(r?|num) c(r?|num) +// fn execute_sap( +// &mut self, +// vm: &VM, +// r: &Operand, +// a: &Operand, +// b: &Operand, +// c: &Operand, +// ) -> Result<(), ICError>; +// } +// impl SapzInstruction for ItemIntegratedCircuit10 { +// /// sapz r? a(r?|num) b(r?|num) +// fn execute_sapz( +// &mut self, +// vm: &VM, +// r: &Operand, +// a: &Operand, +// b: &Operand, +// ) -> Result<(), ICError>; +// } +// impl SbInstruction for ItemIntegratedCircuit10 { +// /// sb deviceHash logicType r? +// fn execute_sb( +// &mut self, +// vm: &VM, +// device_hash: &Operand, +// logic_type: &Operand, +// r: &Operand, +// ) -> Result<(), ICError>; +// } +// impl SbnInstruction for ItemIntegratedCircuit10 { +// /// sbn deviceHash nameHash logicType r? +// fn execute_sbn( +// &mut self, +// vm: &VM, +// device_hash: &Operand, +// name_hash: &Operand, +// logic_type: &Operand, +// r: &Operand, +// ) -> Result<(), ICError>; +// } +// impl SbsInstruction for ItemIntegratedCircuit10 { +// /// sbs deviceHash slotIndex logicSlotType r? +// fn execute_sbs( +// &mut self, +// vm: &VM, +// device_hash: &Operand, +// slot_index: &Operand, +// logic_slot_type: &Operand, +// r: &Operand, +// ) -> Result<(), ICError>; +// } +// impl SdInstruction for ItemIntegratedCircuit10 { +// /// sd id(r?|num) logicType r? +// fn execute_sd( +// &mut self, +// vm: &VM, +// id: &Operand, +// logic_type: &Operand, +// r: &Operand, +// ) -> Result<(), ICError>; +// } +// impl SdnsInstruction for ItemIntegratedCircuit10 { +// /// sdns r? d? +// fn execute_sdns(&mut self, vm: &VM, r: &Operand, d: &Operand) -> Result<(), ICError>; +// } +// impl SdseInstruction for ItemIntegratedCircuit10 { +// /// sdse r? d? +// fn execute_sdse(&mut self, vm: &VM, r: &Operand, d: &Operand) -> Result<(), ICError>; +// } +// impl SelectInstruction for ItemIntegratedCircuit10 { +// /// select r? a(r?|num) b(r?|num) c(r?|num) +// fn execute_select( +// &mut self, +// vm: &VM, +// r: &Operand, +// a: &Operand, +// b: &Operand, +// c: &Operand, +// ) -> Result<(), ICError>; +// } +// impl SeqInstruction for ItemIntegratedCircuit10 { +// /// seq r? a(r?|num) b(r?|num) +// fn execute_seq( +// &mut self, +// vm: &VM, +// r: &Operand, +// a: &Operand, +// b: &Operand, +// ) -> Result<(), ICError>; +// } +// impl SeqzInstruction for ItemIntegratedCircuit10 { +// /// seqz r? a(r?|num) +// fn execute_seqz(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>; +// } +// impl SgeInstruction for ItemIntegratedCircuit10 { +// /// sge r? a(r?|num) b(r?|num) +// fn execute_sge( +// &mut self, +// vm: &VM, +// r: &Operand, +// a: &Operand, +// b: &Operand, +// ) -> Result<(), ICError>; +// } +// impl SgezInstruction for ItemIntegratedCircuit10 { +// /// sgez r? a(r?|num) +// fn execute_sgez(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>; +// } +// impl SgtInstruction for ItemIntegratedCircuit10 { +// /// sgt r? a(r?|num) b(r?|num) +// fn execute_sgt( +// &mut self, +// vm: &VM, +// r: &Operand, +// a: &Operand, +// b: &Operand, +// ) -> Result<(), ICError>; +// } +// impl SgtzInstruction for ItemIntegratedCircuit10 { +// /// sgtz r? a(r?|num) +// fn execute_sgtz(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>; +// } +// impl SinInstruction for ItemIntegratedCircuit10 { +// /// sin r? a(r?|num) +// fn execute_sin(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>; +// } +// impl SlaInstruction for ItemIntegratedCircuit10 { +// /// sla r? a(r?|num) b(r?|num) +// fn execute_sla( +// &mut self, +// vm: &VM, +// r: &Operand, +// a: &Operand, +// b: &Operand, +// ) -> Result<(), ICError>; +// } +// impl SleInstruction for ItemIntegratedCircuit10 { +// /// sle r? a(r?|num) b(r?|num) +// fn execute_sle( +// &mut self, +// vm: &VM, +// r: &Operand, +// a: &Operand, +// b: &Operand, +// ) -> Result<(), ICError>; +// } +// impl SlezInstruction for ItemIntegratedCircuit10 { +// /// slez r? a(r?|num) +// fn execute_slez(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>; +// } +// impl SllInstruction for ItemIntegratedCircuit10 { +// /// sll r? a(r?|num) b(r?|num) +// fn execute_sll( +// &mut self, +// vm: &VM, +// r: &Operand, +// a: &Operand, +// b: &Operand, +// ) -> Result<(), ICError>; +// } +// impl SltInstruction for ItemIntegratedCircuit10 { +// /// slt r? a(r?|num) b(r?|num) +// fn execute_slt( +// &mut self, +// vm: &VM, +// r: &Operand, +// a: &Operand, +// b: &Operand, +// ) -> Result<(), ICError>; +// } +// impl SltzInstruction for ItemIntegratedCircuit10 { +// /// sltz r? a(r?|num) +// fn execute_sltz(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>; +// } +// impl SnaInstruction for ItemIntegratedCircuit10 { +// /// sna r? a(r?|num) b(r?|num) c(r?|num) +// fn execute_sna( +// &mut self, +// vm: &VM, +// r: &Operand, +// a: &Operand, +// b: &Operand, +// c: &Operand, +// ) -> Result<(), ICError>; +// } +// impl SnanInstruction for ItemIntegratedCircuit10 { +// /// snan r? a(r?|num) +// fn execute_snan(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>; +// } +// impl SnanzInstruction for ItemIntegratedCircuit10 { +// /// snanz r? a(r?|num) +// fn execute_snanz(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>; +// } +// impl SnazInstruction for ItemIntegratedCircuit10 { +// /// snaz r? a(r?|num) b(r?|num) +// fn execute_snaz( +// &mut self, +// vm: &VM, +// r: &Operand, +// a: &Operand, +// b: &Operand, +// ) -> Result<(), ICError>; +// } +// impl SneInstruction for ItemIntegratedCircuit10 { +// /// sne r? a(r?|num) b(r?|num) +// fn execute_sne( +// &mut self, +// vm: &VM, +// r: &Operand, +// a: &Operand, +// b: &Operand, +// ) -> Result<(), ICError>; +// } +// impl SnezInstruction for ItemIntegratedCircuit10 { +// /// snez r? a(r?|num) +// fn execute_snez(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>; +// } +// impl SqrtInstruction for ItemIntegratedCircuit10 { +// /// sqrt r? a(r?|num) +// fn execute_sqrt(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>; +// } +// impl SraInstruction for ItemIntegratedCircuit10 { +// /// sra r? a(r?|num) b(r?|num) +// fn execute_sra( +// &mut self, +// vm: &VM, +// r: &Operand, +// a: &Operand, +// b: &Operand, +// ) -> Result<(), ICError>; +// } +// impl SrlInstruction for ItemIntegratedCircuit10 { +// /// srl r? a(r?|num) b(r?|num) +// fn execute_srl( +// &mut self, +// vm: &VM, +// r: &Operand, +// a: &Operand, +// b: &Operand, +// ) -> Result<(), ICError>; +// } +// impl SsInstruction for ItemIntegratedCircuit10 { +// /// ss d? slotIndex logicSlotType r? +// fn execute_ss( +// &mut self, +// vm: &VM, +// d: &Operand, +// slot_index: &Operand, +// logic_slot_type: &Operand, +// r: &Operand, +// ) -> Result<(), ICError>; +// } +// impl SubInstruction for ItemIntegratedCircuit10 { +// /// sub r? a(r?|num) b(r?|num) +// fn execute_sub( +// &mut self, +// vm: &VM, +// r: &Operand, +// a: &Operand, +// b: &Operand, +// ) -> Result<(), ICError>; +// } +// impl TanInstruction for ItemIntegratedCircuit10 { +// /// tan r? a(r?|num) +// fn execute_tan(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>; +// } +// impl TruncInstruction for ItemIntegratedCircuit10 { +// /// trunc r? a(r?|num) +// fn execute_trunc(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>; +// } +// impl XorInstruction for ItemIntegratedCircuit10 { +// /// xor r? a(r?|num) b(r?|num) +// fn execute_xor( +// &mut self, +// vm: &VM, +// r: &Operand, +// a: &Operand, +// b: &Operand, +// ) -> Result<(), ICError>; +// } diff --git a/ic10emu/src/vm/object/templates.rs b/ic10emu/src/vm/object/templates.rs index 32f9bfa..19abf69 100644 --- a/ic10emu/src/vm/object/templates.rs +++ b/ic10emu/src/vm/object/templates.rs @@ -1,4 +1,4 @@ -use std::collections::BTreeMap; +use std::{collections::BTreeMap, rc::Rc}; use crate::{ errors::TemplateError, @@ -20,10 +20,11 @@ use crate::{ traits::*, LogicField, Name, Slot, }, + VM, }, }; use serde_derive::{Deserialize, Serialize}; -use strum::IntoEnumIterator; +use strum::{EnumProperty, IntoEnumIterator}; use super::{stationpedia, MemoryAccess, ObjectID, VMObject}; @@ -72,11 +73,11 @@ impl ObjectTemplate { } } - pub fn build(&self, id: ObjectID) -> VMObject { - if let Some(obj) = stationpedia::object_from_prefab_template(&self, id) { + pub fn build(&self, id: ObjectID, vm: &Rc) -> VMObject { + if let Some(obj) = stationpedia::object_from_prefab_template(&self, id, vm) { obj } else { - self.build_generic(id) + self.build_generic(id, vm) } } @@ -194,182 +195,329 @@ impl ObjectTemplate { } } - fn build_generic(&self, id: ObjectID) -> VMObject { + fn build_generic(&self, id: ObjectID, vm: &Rc) -> VMObject { use ObjectTemplate::*; match self { - Structure(s) => VMObject::new(Generic { - id, - prefab: Name::from_prefab_name(&s.prefab.prefab_name), - name: Name::new(&s.prefab.name), - small_grid: s.structure.small_grid, - }), - StructureSlots(s) => VMObject::new(GenericStorage { - id, - prefab: Name::from_prefab_name(&s.prefab.prefab_name), - name: Name::new(&s.prefab.name), - small_grid: s.structure.small_grid, - slots: s - .slots - .iter() - .enumerate() - .map(|(index, info)| Slot { - parent: id, - index, - name: info.name.clone(), - typ: info.typ, - readable_logic: Vec::new(), - writeable_logic: Vec::new(), - occupant: None, - }) - .collect(), - }), - StructureLogic(s) => VMObject::new(GenericLogicable { - id, - prefab: Name::from_prefab_name(&s.prefab.prefab_name), - name: Name::new(&s.prefab.name), - small_grid: s.structure.small_grid, - slots: s - .slots - .iter() - .enumerate() - .map(|(index, info)| Slot { - parent: id, - index, - name: info.name.clone(), - typ: info.typ, - readable_logic: s - .logic - .logic_slot_types - .get(&(index as u32)) - .map(|s_info| { - s_info - .slot_types - .iter() - .filter_map(|(key, access)| match access { - MemoryAccess::Read | MemoryAccess::ReadWrite => Some(key), - _ => None, - }) - .copied() - .collect::>() - }) - .unwrap_or_else(|| Vec::new()), - writeable_logic: s - .logic - .logic_slot_types - .get(&(index as u32)) - .map(|s_info| { - s_info - .slot_types - .iter() - .filter_map(|(key, access)| match access { - MemoryAccess::Write | MemoryAccess::ReadWrite => Some(key), - _ => None, - }) - .copied() - .collect::>() - }) - .unwrap_or_else(|| Vec::new()), - occupant: None, - }) - .collect(), - fields: s - .logic - .logic_types - .types - .iter() - .map(|(key, access)| { - ( - *key, - LogicField { - field_type: *access, - value: 0.0, - }, - ) - }) - .collect(), - modes: s.logic.modes.clone(), - }), - StructureLogicDevice(s) => VMObject::new(GenericLogicableDevice { - id, - prefab: Name::from_prefab_name(&s.prefab.prefab_name), - name: Name::new(&s.prefab.name), - small_grid: s.structure.small_grid, - slots: s - .slots - .iter() - .enumerate() - .map(|(index, info)| Slot { - parent: id, - index, - name: info.name.clone(), - typ: info.typ, - readable_logic: s - .logic - .logic_slot_types - .get(&(index as u32)) - .map(|s_info| { - s_info - .slot_types - .iter() - .filter_map(|(key, access)| match access { - MemoryAccess::Read | MemoryAccess::ReadWrite => Some(key), - _ => None, - }) - .copied() - .collect::>() - }) - .unwrap_or_else(|| Vec::new()), - writeable_logic: s - .logic - .logic_slot_types - .get(&(index as u32)) - .map(|s_info| { - s_info - .slot_types - .iter() - .filter_map(|(key, access)| match access { - MemoryAccess::Write | MemoryAccess::ReadWrite => Some(key), - _ => None, - }) - .copied() - .collect::>() - }) - .unwrap_or_else(|| Vec::new()), - occupant: None, - }) - .collect(), - fields: s - .logic - .logic_types - .types - .iter() - .map(|(key, access)| { - ( - *key, - LogicField { - field_type: *access, - value: 0.0, - }, - ) - }) - .collect(), - modes: s.logic.modes.clone(), - connections: s - .device - .connection_list - .iter() - .map(|conn_info| Connection::from_info(conn_info.typ, conn_info.role)) - .collect(), - pins: s - .device - .device_pins_length - .map(|pins_len| vec![None; pins_len]), - device_info: s.device.clone(), - }), + Structure(s) => VMObject::new( + Generic { + id, + prefab: Name::from_prefab_name(&s.prefab.prefab_name), + name: Name::new(&s.prefab.name), + small_grid: s.structure.small_grid, + }, + vm.clone(), + ), + StructureSlots(s) => VMObject::new( + GenericStorage { + id, + prefab: Name::from_prefab_name(&s.prefab.prefab_name), + name: Name::new(&s.prefab.name), + small_grid: s.structure.small_grid, + slots: s + .slots + .iter() + .enumerate() + .map(|(index, info)| Slot { + parent: id, + index, + name: info.name.clone(), + typ: info.typ, + readable_logic: Vec::new(), + writeable_logic: Vec::new(), + occupant: None, + }) + .collect(), + }, + vm.clone(), + ), + StructureLogic(s) => VMObject::new( + GenericLogicable { + id, + prefab: Name::from_prefab_name(&s.prefab.prefab_name), + name: Name::new(&s.prefab.name), + small_grid: s.structure.small_grid, + slots: s + .slots + .iter() + .enumerate() + .map(|(index, info)| Slot { + parent: id, + index, + name: info.name.clone(), + typ: info.typ, + readable_logic: s + .logic + .logic_slot_types + .get(&(index as u32)) + .map(|s_info| { + s_info + .slot_types + .iter() + .filter_map(|(key, access)| match access { + MemoryAccess::Read | MemoryAccess::ReadWrite => { + Some(key) + } + _ => None, + }) + .copied() + .collect::>() + }) + .unwrap_or_else(|| Vec::new()), + writeable_logic: s + .logic + .logic_slot_types + .get(&(index as u32)) + .map(|s_info| { + s_info + .slot_types + .iter() + .filter_map(|(key, access)| match access { + MemoryAccess::Write | MemoryAccess::ReadWrite => { + Some(key) + } + _ => None, + }) + .copied() + .collect::>() + }) + .unwrap_or_else(|| Vec::new()), + occupant: None, + }) + .collect(), + fields: s + .logic + .logic_types + .types + .iter() + .map(|(key, access)| { + ( + *key, + LogicField { + field_type: *access, + value: s + .logic + .logic_values + .map(|values| values.get(key)) + .flatten() + .copied() + .unwrap_or(0.0), + }, + ) + }) + .collect(), + modes: s.logic.modes.clone(), + }, + vm.clone(), + ), + StructureLogicDevice(s) => VMObject::new( + GenericLogicableDevice { + id, + prefab: Name::from_prefab_name(&s.prefab.prefab_name), + name: Name::new(&s.prefab.name), + small_grid: s.structure.small_grid, + slots: s + .slots + .iter() + .enumerate() + .map(|(index, info)| Slot { + parent: id, + index, + name: info.name.clone(), + typ: info.typ, + readable_logic: s + .logic + .logic_slot_types + .get(&(index as u32)) + .map(|s_info| { + s_info + .slot_types + .iter() + .filter_map(|(key, access)| match access { + MemoryAccess::Read | MemoryAccess::ReadWrite => { + Some(key) + } + _ => None, + }) + .copied() + .collect::>() + }) + .unwrap_or_else(|| Vec::new()), + writeable_logic: s + .logic + .logic_slot_types + .get(&(index as u32)) + .map(|s_info| { + s_info + .slot_types + .iter() + .filter_map(|(key, access)| match access { + MemoryAccess::Write | MemoryAccess::ReadWrite => { + Some(key) + } + _ => None, + }) + .copied() + .collect::>() + }) + .unwrap_or_else(|| Vec::new()), + occupant: None, + }) + .collect(), + fields: s + .logic + .logic_types + .types + .iter() + .map(|(key, access)| { + ( + *key, + LogicField { + field_type: *access, + value: s + .logic + .logic_values + .map(|values| values.get(key)) + .flatten() + .copied() + .unwrap_or(0.0), + }, + ) + }) + .collect(), + modes: s.logic.modes.clone(), + connections: s + .device + .connection_list + .iter() + .map(|conn_info| { + Connection::from_info(conn_info.typ, conn_info.role, conn_info.network) + }) + .collect(), + pins: s + .device + .device_pins + .map(|pins| Some(pins.clone())) + .unwrap_or_else(|| { + s.device + .device_pins_length + .map(|pins_len| vec![None; pins_len]) + }), + device_info: s.device.clone(), + }, + vm.clone(), + ), StructureLogicDeviceMemory(s) if matches!(s.memory.memory_access, MemoryAccess::Read) => { - VMObject::new(GenericLogicableDeviceMemoryReadable { + VMObject::new( + GenericLogicableDeviceMemoryReadable { + id, + prefab: Name::from_prefab_name(&s.prefab.prefab_name), + name: Name::new(&s.prefab.name), + small_grid: s.structure.small_grid, + slots: s + .slots + .iter() + .enumerate() + .map(|(index, info)| Slot { + parent: id, + index, + name: info.name.clone(), + typ: info.typ, + readable_logic: s + .logic + .logic_slot_types + .get(&(index as u32)) + .map(|s_info| { + s_info + .slot_types + .iter() + .filter_map(|(key, access)| match access { + MemoryAccess::Read | MemoryAccess::ReadWrite => { + Some(key) + } + _ => None, + }) + .copied() + .collect::>() + }) + .unwrap_or_else(|| Vec::new()), + writeable_logic: s + .logic + .logic_slot_types + .get(&(index as u32)) + .map(|s_info| { + s_info + .slot_types + .iter() + .filter_map(|(key, access)| match access { + MemoryAccess::Write | MemoryAccess::ReadWrite => { + Some(key) + } + _ => None, + }) + .copied() + .collect::>() + }) + .unwrap_or_else(|| Vec::new()), + occupant: None, + }) + .collect(), + fields: s + .logic + .logic_types + .types + .iter() + .map(|(key, access)| { + ( + *key, + LogicField { + field_type: *access, + value: s + .logic + .logic_values + .map(|values| values.get(key)) + .flatten() + .copied() + .unwrap_or(0.0), + }, + ) + }) + .collect(), + modes: s.logic.modes.clone(), + connections: s + .device + .connection_list + .iter() + .map(|conn_info| { + Connection::from_info( + conn_info.typ, + conn_info.role, + conn_info.network, + ) + }) + .collect(), + pins: s + .device + .device_pins + .map(|pins| Some(pins.clone())) + .unwrap_or_else(|| { + s.device + .device_pins_length + .map(|pins_len| vec![None; pins_len]) + }), + device_info: s.device.clone(), + memory: s + .memory + .values + .clone() + .unwrap_or_else(|| vec![0.0; s.memory.memory_size as usize]), + }, + vm.clone(), + ) + } + StructureLogicDeviceMemory(s) => VMObject::new( + GenericLogicableDeviceMemoryReadWriteable { id, prefab: Name::from_prefab_name(&s.prefab.prefab_name), name: Name::new(&s.prefab.name), @@ -432,7 +580,13 @@ impl ObjectTemplate { *key, LogicField { field_type: *access, - value: 0.0, + value: s + .logic + .logic_values + .map(|values| values.get(key)) + .flatten() + .copied() + .unwrap_or(0.0), }, ) }) @@ -442,23 +596,46 @@ impl ObjectTemplate { .device .connection_list .iter() - .map(|conn_info| Connection::from_info(conn_info.typ, conn_info.role)) + .map(|conn_info| { + Connection::from_info(conn_info.typ, conn_info.role, conn_info.network) + }) .collect(), pins: s .device - .device_pins_length - .map(|pins_len| vec![None; pins_len]), + .device_pins + .map(|pins| Some(pins.clone())) + .unwrap_or_else(|| { + s.device + .device_pins_length + .map(|pins_len| vec![None; pins_len]) + }), device_info: s.device.clone(), - memory: vec![0.0; s.memory.memory_size as usize], - }) - } - StructureLogicDeviceMemory(s) => { - VMObject::new(GenericLogicableDeviceMemoryReadWriteable { + memory: s + .memory + .values + .clone() + .unwrap_or_else(|| vec![0.0; s.memory.memory_size as usize]), + }, + vm.clone(), + ), + Item(i) => VMObject::new( + GenericItem { id, - prefab: Name::from_prefab_name(&s.prefab.prefab_name), - name: Name::new(&s.prefab.name), - small_grid: s.structure.small_grid, - slots: s + prefab: Name::from_prefab_name(&i.prefab.prefab_name), + name: Name::new(&i.prefab.name), + item_info: i.item.clone(), + parent_slot: None, + }, + vm.clone(), + ), + ItemSlots(i) => VMObject::new( + GenericItemStorage { + id, + prefab: Name::from_prefab_name(&i.prefab.prefab_name), + name: Name::new(&i.prefab.name), + item_info: i.item.clone(), + parent_slot: None, + slots: i .slots .iter() .enumerate() @@ -467,172 +644,16 @@ impl ObjectTemplate { index, name: info.name.clone(), typ: info.typ, - readable_logic: s - .logic - .logic_slot_types - .get(&(index as u32)) - .map(|s_info| { - s_info - .slot_types - .iter() - .filter_map(|(key, access)| match access { - MemoryAccess::Read | MemoryAccess::ReadWrite => { - Some(key) - } - _ => None, - }) - .copied() - .collect::>() - }) - .unwrap_or_else(|| Vec::new()), - writeable_logic: s - .logic - .logic_slot_types - .get(&(index as u32)) - .map(|s_info| { - s_info - .slot_types - .iter() - .filter_map(|(key, access)| match access { - MemoryAccess::Write | MemoryAccess::ReadWrite => { - Some(key) - } - _ => None, - }) - .copied() - .collect::>() - }) - .unwrap_or_else(|| Vec::new()), + readable_logic: Vec::new(), + writeable_logic: Vec::new(), occupant: None, }) .collect(), - fields: s - .logic - .logic_types - .types - .iter() - .map(|(key, access)| { - ( - *key, - LogicField { - field_type: *access, - value: 0.0, - }, - ) - }) - .collect(), - modes: s.logic.modes.clone(), - connections: s - .device - .connection_list - .iter() - .map(|conn_info| Connection::from_info(conn_info.typ, conn_info.role)) - .collect(), - pins: s - .device - .device_pins_length - .map(|pins_len| vec![None; pins_len]), - device_info: s.device.clone(), - memory: vec![0.0; s.memory.memory_size as usize], - }) - } - Item(i) => VMObject::new(GenericItem { - id, - prefab: Name::from_prefab_name(&i.prefab.prefab_name), - name: Name::new(&i.prefab.name), - item_info: i.item.clone(), - parent_slot: None, - }), - ItemSlots(i) => VMObject::new(GenericItemStorage { - id, - prefab: Name::from_prefab_name(&i.prefab.prefab_name), - name: Name::new(&i.prefab.name), - item_info: i.item.clone(), - parent_slot: None, - slots: i - .slots - .iter() - .enumerate() - .map(|(index, info)| Slot { - parent: id, - index, - name: info.name.clone(), - typ: info.typ, - readable_logic: Vec::new(), - writeable_logic: Vec::new(), - occupant: None, - }) - .collect(), - }), - ItemLogic(i) => VMObject::new(GenericItemLogicable { - id, - prefab: Name::from_prefab_name(&i.prefab.prefab_name), - name: Name::new(&i.prefab.name), - item_info: i.item.clone(), - parent_slot: None, - slots: i - .slots - .iter() - .enumerate() - .map(|(index, info)| Slot { - parent: id, - index, - name: info.name.clone(), - typ: info.typ, - readable_logic: i - .logic - .logic_slot_types - .get(&(index as u32)) - .map(|s_info| { - s_info - .slot_types - .iter() - .filter_map(|(key, access)| match access { - MemoryAccess::Read | MemoryAccess::ReadWrite => Some(key), - _ => None, - }) - .copied() - .collect::>() - }) - .unwrap_or_else(|| Vec::new()), - writeable_logic: i - .logic - .logic_slot_types - .get(&(index as u32)) - .map(|s_info| { - s_info - .slot_types - .iter() - .filter_map(|(key, access)| match access { - MemoryAccess::Write | MemoryAccess::ReadWrite => Some(key), - _ => None, - }) - .copied() - .collect::>() - }) - .unwrap_or_else(|| Vec::new()), - occupant: None, - }) - .collect(), - fields: i - .logic - .logic_types - .types - .iter() - .map(|(key, access)| { - ( - *key, - LogicField { - field_type: *access, - value: 0.0, - }, - ) - }) - .collect(), - modes: i.logic.modes.clone(), - }), - ItemLogicMemory(i) if matches!(i.memory.memory_access, MemoryAccess::Read) => { - VMObject::new(GenericItemLogicableMemoryReadable { + }, + vm.clone(), + ), + ItemLogic(i) => VMObject::new( + GenericItemLogicable { id, prefab: Name::from_prefab_name(&i.prefab.prefab_name), name: Name::new(&i.prefab.name), @@ -696,92 +717,202 @@ impl ObjectTemplate { *key, LogicField { field_type: *access, - value: 0.0, + value: i + .logic + .logic_values + .map(|values| values.get(key)) + .flatten() + .copied() + .unwrap_or(0.0), }, ) }) .collect(), modes: i.logic.modes.clone(), - memory: vec![0.0; i.memory.memory_size as usize], - }) + }, + vm.clone(), + ), + ItemLogicMemory(i) if matches!(i.memory.memory_access, MemoryAccess::Read) => { + VMObject::new( + GenericItemLogicableMemoryReadable { + id, + prefab: Name::from_prefab_name(&i.prefab.prefab_name), + name: Name::new(&i.prefab.name), + item_info: i.item.clone(), + parent_slot: None, + slots: i + .slots + .iter() + .enumerate() + .map(|(index, info)| Slot { + parent: id, + index, + name: info.name.clone(), + typ: info.typ, + readable_logic: i + .logic + .logic_slot_types + .get(&(index as u32)) + .map(|s_info| { + s_info + .slot_types + .iter() + .filter_map(|(key, access)| match access { + MemoryAccess::Read | MemoryAccess::ReadWrite => { + Some(key) + } + _ => None, + }) + .copied() + .collect::>() + }) + .unwrap_or_else(|| Vec::new()), + writeable_logic: i + .logic + .logic_slot_types + .get(&(index as u32)) + .map(|s_info| { + s_info + .slot_types + .iter() + .filter_map(|(key, access)| match access { + MemoryAccess::Write | MemoryAccess::ReadWrite => { + Some(key) + } + _ => None, + }) + .copied() + .collect::>() + }) + .unwrap_or_else(|| Vec::new()), + occupant: None, + }) + .collect(), + fields: i + .logic + .logic_types + .types + .iter() + .map(|(key, access)| { + ( + *key, + LogicField { + field_type: *access, + value: i + .logic + .logic_values + .map(|values| values.get(key)) + .flatten() + .copied() + .unwrap_or(0.0), + }, + ) + }) + .collect(), + modes: i.logic.modes.clone(), + memory: i + .memory + .values + .clone() + .unwrap_or_else(|| vec![0.0; i.memory.memory_size as usize]), + }, + vm.clone(), + ) } - ItemLogicMemory(i) => VMObject::new(GenericItemLogicableMemoryReadWriteable { - id, - prefab: Name::from_prefab_name(&i.prefab.prefab_name), - name: Name::new(&i.prefab.name), - item_info: i.item.clone(), - parent_slot: None, - slots: i - .slots - .iter() - .enumerate() - .map(|(index, info)| Slot { - parent: id, - index, - name: info.name.clone(), - typ: info.typ, - readable_logic: i - .logic - .logic_slot_types - .get(&(index as u32)) - .map(|s_info| { - s_info - .slot_types - .iter() - .filter_map(|(key, access)| match access { - MemoryAccess::Read | MemoryAccess::ReadWrite => Some(key), - _ => None, - }) - .copied() - .collect::>() - }) - .unwrap_or_else(|| Vec::new()), - writeable_logic: i - .logic - .logic_slot_types - .get(&(index as u32)) - .map(|s_info| { - s_info - .slot_types - .iter() - .filter_map(|(key, access)| match access { - MemoryAccess::Write | MemoryAccess::ReadWrite => Some(key), - _ => None, - }) - .copied() - .collect::>() - }) - .unwrap_or_else(|| Vec::new()), - occupant: None, - }) - .collect(), - fields: i - .logic - .logic_types - .types - .iter() - .map(|(key, access)| { - ( - *key, - LogicField { - field_type: *access, - value: 0.0, - }, - ) - }) - .collect(), - modes: i.logic.modes.clone(), - memory: vec![0.0; i.memory.memory_size as usize], - }), + ItemLogicMemory(i) => VMObject::new( + GenericItemLogicableMemoryReadWriteable { + id, + prefab: Name::from_prefab_name(&i.prefab.prefab_name), + name: Name::new(&i.prefab.name), + item_info: i.item.clone(), + parent_slot: None, + slots: i + .slots + .iter() + .enumerate() + .map(|(index, info)| Slot { + parent: id, + index, + name: info.name.clone(), + typ: info.typ, + readable_logic: i + .logic + .logic_slot_types + .get(&(index as u32)) + .map(|s_info| { + s_info + .slot_types + .iter() + .filter_map(|(key, access)| match access { + MemoryAccess::Read | MemoryAccess::ReadWrite => { + Some(key) + } + _ => None, + }) + .copied() + .collect::>() + }) + .unwrap_or_else(|| Vec::new()), + writeable_logic: i + .logic + .logic_slot_types + .get(&(index as u32)) + .map(|s_info| { + s_info + .slot_types + .iter() + .filter_map(|(key, access)| match access { + MemoryAccess::Write | MemoryAccess::ReadWrite => { + Some(key) + } + _ => None, + }) + .copied() + .collect::>() + }) + .unwrap_or_else(|| Vec::new()), + occupant: None, + }) + .collect(), + fields: i + .logic + .logic_types + .types + .iter() + .map(|(key, access)| { + ( + *key, + LogicField { + field_type: *access, + value: i + .logic + .logic_values + .map(|values| values.get(key)) + .flatten() + .copied() + .unwrap_or(0.0), + }, + ) + }) + .collect(), + modes: i.logic.modes.clone(), + memory: i + .memory + .values + .clone() + .unwrap_or_else(|| vec![0.0; i.memory.memory_size as usize]), + }, + vm.clone(), + ), } } - pub fn freeze_object(obj: &VMObject) -> Result { + pub fn freeze_object(obj: &VMObject, vm: &Rc) -> Result { let obj_ref = obj.borrow(); let interfaces = ObjectInterfaces::from_object(&*obj_ref); match interfaces { ObjectInterfaces { - structure: Some(stru), + structure: Some(structure), storage: None, memory_readable: None, memory_writable: None, @@ -798,35 +929,16 @@ impl ObjectTemplate { wireless_receive: None, network: None, } => { - let prefab_lookup = StationpediaPrefab::from_repr(obj_ref.get_prefab().hash); // completely generic structure? not sure how this got created but it technically // valid in the data model Ok(ObjectTemplate::Structure(StructureTemplate { - object: Some(ObjectInfo { - name: Some(obj_ref.get_name().value()), - id: Some(*obj_ref.get_id()), - }), - prefab: PrefabInfo { - prefab_name: obj_ref.get_prefab().value, - prefab_hash: obj_ref.get_prefab().hash, - name: prefab_lookup - .map(|prefab| prefab.get_str("name")) - .flatten() - .unwrap_or("") - .to_string(), - desc: prefab_lookup - .map(|prefab| prefab.get_str("desc")) - .flatten() - .unwrap_or("") - .to_string(), - }, - structure: StructureInfo { - small_grid: stru.is_small_grid(), - }, + object: Some(obj.into()), + prefab: obj.into(), + structure: structure.into(), })) } ObjectInterfaces { - structure: Some(stru), + structure: Some(structure), storage: Some(storage), memory_readable: None, memory_writable: None, @@ -842,435 +954,91 @@ impl ObjectTemplate { wireless_transmit: None, wireless_receive: None, network: None, - } => { - let prefab_lookup = StationpediaPrefab::from_repr(obj_ref.get_prefab().hash); - Ok(ObjectTemplate::StructureSlots(StructureSlotsTemplate { - object: Some(ObjectInfo { - name: Some(obj_ref.get_name().value()), - id: Some(*obj_ref.get_id()), - }), - prefab: PrefabInfo { - prefab_name: obj_ref.get_prefab().value, - prefab_hash: obj_ref.get_prefab().hash, - name: prefab_lookup - .map(|prefab| prefab.get_str("name")) - .flatten() - .unwrap_or("") - .to_string(), - desc: prefab_lookup - .map(|prefab| prefab.get_str("desc")) - .flatten() - .unwrap_or("") - .to_string(), - }, - structure: StructureInfo { - small_grid: stru.is_small_grid(), - }, - slots: storage - .get_slots() - .iter() - .map(|slot| { - Ok(SlotInfo { - name: slot.name.clone(), - typ: slot.typ, - occupant: slot - .occupant - .map(|occupant| ObjectTemplate::freeze_object(occupant)) - .map_or(Ok(None), |v| v.map(Some))?, - }) - }) - .collect::, _>>()?, - })) - } + } => Ok(ObjectTemplate::StructureSlots(StructureSlotsTemplate { + object: Some(obj.into()), + prefab: obj.into(), + structure: structure.into(), + slots: freeze_storage(storage, vm)?, + })), ObjectInterfaces { - structure: Some(stru), + structure: Some(structure), storage: Some(storage), memory_readable: None, memory_writable: None, logicable: Some(logic), source_code: None, - circuit_holder: None, + circuit_holder: _ch, item: None, integrated_circuit: None, programmable: None, instructable: None, logic_stack: None, device: None, - wireless_transmit: None, - wireless_receive: None, + wireless_transmit: _wt, + wireless_receive: _wr, network: None, - } => { - let prefab_lookup = StationpediaPrefab::from_repr(obj_ref.get_prefab().hash); - Ok(ObjectTemplate::StructureLogic(StructureLogicTemplate { - object: Some(ObjectInfo { - name: Some(obj_ref.get_name().value()), - id: Some(*obj_ref.get_id()), - }), - prefab: PrefabInfo { - prefab_name: obj_ref.get_prefab().value, - prefab_hash: obj_ref.get_prefab().hash, - name: prefab_lookup - .map(|prefab| prefab.get_str("name")) - .flatten() - .unwrap_or("") - .to_string(), - desc: prefab_lookup - .map(|prefab| prefab.get_str("desc")) - .flatten() - .unwrap_or("") - .to_string(), - }, - structure: StructureInfo { - small_grid: stru.is_small_grid(), - }, - slots: storage - .get_slots() - .iter() - .map(|slot| { - Ok(SlotInfo { - name: slot.name.clone(), - typ: slot.typ, - occupant: slot - .occupant - .map(|occupant| ObjectTemplate::freeze_object(occupant)) - .map_or(Ok(None), |v| v.map(Some))?, - }) - }) - .collect::, _>>()?, - logic: LogicInfo { - logic_slot_types: storage - .get_slots() - .iter() - .enumerate() - .map(|(index, slot)| { - ( - index as u32, - LogicSlotTypes { - slot_types: LogicSlotType::iter() - .filter_map(|slt| { - let readable = slot.readable_logic.contains(&slt); - let writeable = slot.writeable_logic.contains(&slt); - if readable && writeable { - Some((slt, MemoryAccess::ReadWrite)) - } else if readable { - Some((slt, MemoryAccess::Read)) - } else if writeable { - Some((slt, MemoryAccess::Write)) - } else { - None - } - }) - .collect(), - }, - ) - }) - .collect(), - logic_types: LogicTypes { - types: logic - .valid_logic_types() - .iter() - .filter_map(|lt| { - let readable = logic.can_logic_read(lt); - let writeable = logic.can_logic_write(lt); - if readable && writeable { - Some((lt, MemoryAccess::ReadWrite)) - } else if readable { - Some((lt, MemoryAccess::Read)) - } else if writeable { - Some((lt, MemoryAccess::Write)) - } else { - None - } - }) - .collect(), - }, - modes: logic.known_modes().map(|modes| modes.iter().collect()), - logic_values: logic - .valid_logic_types() - .iter() - .filter_map(|lt| logic.get_logic(lt).ok()), - transmission_receiver: false, - wireless_logic: false, - circuit_holder: false, - }, - })) - } + } => Ok(ObjectTemplate::StructureLogic(StructureLogicTemplate { + object: Some(obj.into()), + prefab: obj.into(), + structure: structure.into(), + slots: freeze_storage(storage, vm)?, + logic: logic.into(), + })), ObjectInterfaces { - structure: Some(stru), + structure: Some(structure), storage: Some(storage), memory_readable: None, memory_writable: None, logicable: Some(logic), source_code: None, - circuit_holder: None, + circuit_holder: _ch, item: None, integrated_circuit: None, programmable: None, instructable: None, logic_stack: None, device: Some(device), - wireless_transmit: None, - wireless_receive: None, + wireless_transmit: _wt, + wireless_receive: _wr, network: None, - } => { - let prefab_lookup = StationpediaPrefab::from_repr(obj_ref.get_prefab().hash); - Ok(ObjectTemplate::StructureLogicDevice( - StructureLogicDeviceTemplate { - object: Some(ObjectInfo { - name: Some(obj_ref.get_name().value()), - id: Some(*obj_ref.get_id()), - }), - prefab: PrefabInfo { - prefab_name: obj_ref.get_prefab().value, - prefab_hash: obj_ref.get_prefab().hash, - name: prefab_lookup - .map(|prefab| prefab.get_str("name")) - .flatten() - .unwrap_or("") - .to_string(), - desc: prefab_lookup - .map(|prefab| prefab.get_str("desc")) - .flatten() - .unwrap_or("") - .to_string(), - }, - structure: StructureInfo { - small_grid: stru.is_small_grid(), - }, - slots: storage - .get_slots() - .iter() - .map(|slot| { - Ok(SlotInfo { - name: slot.name.clone(), - typ: slot.typ, - occupant: slot - .occupant - .map(|occupant| ObjectTemplate::freeze_object(occupant)) - .map_or(Ok(None), |v| v.map(Some))?, - }) - }) - .collect::, _>>()?, - logic: LogicInfo { - logic_slot_types: storage - .get_slots() - .iter() - .enumerate() - .map(|(index, slot)| { - ( - index as u32, - LogicSlotTypes { - slot_types: LogicSlotType::iter() - .filter_map(|slt| { - let readable = - slot.readable_logic.contains(&slt); - let writeable = - slot.writeable_logic.contains(&slt); - if readable && writeable { - Some((slt, MemoryAccess::ReadWrite)) - } else if readable { - Some((slt, MemoryAccess::Read)) - } else if writeable { - Some((slt, MemoryAccess::Write)) - } else { - None - } - }) - .collect(), - }, - ) - }) - .collect(), - logic_types: LogicTypes { - types: logic - .valid_logic_types() - .iter() - .filter_map(|lt| { - let readable = logic.can_logic_read(lt); - let writeable = logic.can_logic_write(lt); - if readable && writeable { - Some((lt, MemoryAccess::ReadWrite)) - } else if readable { - Some((lt, MemoryAccess::Read)) - } else if writeable { - Some((lt, MemoryAccess::Write)) - } else { - None - } - }) - .collect(), - }, - modes: logic.known_modes().map(|modes| modes.iter().collect()), - logic_values: logic - .valid_logic_types() - .iter() - .filter_map(|lt| logic.get_logic(lt).ok()), - transmission_receiver: false, - wireless_logic: false, - circuit_holder: false, - }, - device: DeviceInfo { - connection_list: device - .connection_list() - .iter() - .map(|conn| conn.to_info()), - device_pins_length: device.device_pins().map(|pins| pins.len()), - device_pins: device.device_pins().map(|pins| pins.iter().collect()), - has_reagents: device.has_reagents(), - has_lock_state: device.has_lock_state(), - has_mode_state: device.has_mode_state(), - has_open_state: device.has_mode_state(), - has_on_off_state: device.has_on_off_state(), - has_color_state: device.has_color_state(), - has_atmosphere: device.has_atmosphere(), - has_activate_state: device.has_activate_state(), - }, - }, - )) - } + } => Ok(ObjectTemplate::StructureLogicDevice( + StructureLogicDeviceTemplate { + object: Some(obj.into()), + prefab: obj.into(), + structure: structure.into(), + slots: freeze_storage(storage, vm)?, + logic: logic.into(), + device: device.into(), + }, + )), ObjectInterfaces { - structure: Some(stru), + structure: Some(structure), storage: Some(storage), memory_readable: Some(mem_r), - memory_writable: mem_w, + memory_writable: _mem_w, logicable: Some(logic), source_code: None, - circuit_holder: None, + circuit_holder: _ch, item: None, integrated_circuit: None, programmable: None, - instructable: inst, - logic_stack: None, + instructable: _inst, + logic_stack: _logic_stack, device: Some(device), - wireless_transmit: None, - wireless_receive: None, + wireless_transmit: _wt, + wireless_receive: _wr, network: None, - } => { - let prefab_lookup = StationpediaPrefab::from_repr(obj_ref.get_prefab().hash); - Ok(ObjectTemplate::StructureLogicDeviceMemory( - StructureLogicDeviceMemoryTemplate { - object: Some(ObjectInfo { - name: Some(obj_ref.get_name().value()), - id: Some(*obj_ref.get_id()), - }), - prefab: PrefabInfo { - prefab_name: obj_ref.get_prefab().value, - prefab_hash: obj_ref.get_prefab().hash, - name: prefab_lookup - .map(|prefab| prefab.get_str("name")) - .flatten() - .unwrap_or("") - .to_string(), - desc: prefab_lookup - .map(|prefab| prefab.get_str("desc")) - .flatten() - .unwrap_or("") - .to_string(), - }, - structure: StructureInfo { - small_grid: stru.is_small_grid(), - }, - slots: storage - .get_slots() - .iter() - .map(|slot| { - Ok(SlotInfo { - name: slot.name.clone(), - typ: slot.typ, - occupant: slot - .occupant - .map(|occupant| ObjectTemplate::freeze_object(occupant)) - .map_or(Ok(None), |v| v.map(Some))?, - }) - }) - .collect::, _>>()?, - logic: LogicInfo { - logic_slot_types: storage - .get_slots() - .iter() - .enumerate() - .map(|(index, slot)| { - ( - index as u32, - LogicSlotTypes { - slot_types: LogicSlotType::iter() - .filter_map(|slt| { - let readable = - slot.readable_logic.contains(&slt); - let writeable = - slot.writeable_logic.contains(&slt); - if readable && writeable { - Some((slt, MemoryAccess::ReadWrite)) - } else if readable { - Some((slt, MemoryAccess::Read)) - } else if writeable { - Some((slt, MemoryAccess::Write)) - } else { - None - } - }) - .collect(), - }, - ) - }) - .collect(), - logic_types: LogicTypes { - types: logic - .valid_logic_types() - .iter() - .filter_map(|lt| { - let readable = logic.can_logic_read(lt); - let writeable = logic.can_logic_write(lt); - if readable && writeable { - Some((lt, MemoryAccess::ReadWrite)) - } else if readable { - Some((lt, MemoryAccess::Read)) - } else if writeable { - Some((lt, MemoryAccess::Write)) - } else { - None - } - }) - .collect(), - }, - modes: logic.known_modes().map(|modes| modes.iter().collect()), - logic_values: logic - .valid_logic_types() - .iter() - .filter_map(|lt| logic.get_logic(lt).ok()), - transmission_receiver: false, - wireless_logic: false, - circuit_holder: false, - }, - device: DeviceInfo { - connection_list: device - .connection_list() - .iter() - .map(|conn| conn.to_info()), - device_pins_length: device.device_pins().map(|pins| pins.len()), - device_pins: device.device_pins().map(|pins| pins.iter().collect()), - has_reagents: device.has_reagents(), - has_lock_state: device.has_lock_state(), - has_mode_state: device.has_mode_state(), - has_open_state: device.has_mode_state(), - has_on_off_state: device.has_on_off_state(), - has_color_state: device.has_color_state(), - has_atmosphere: device.has_atmosphere(), - has_activate_state: device.has_activate_state(), - }, - memory: MemoryInfo { - instructions: None, // TODO: map info from `Instructable` trait - memory_access: if mem_w.is_some() { - MemoryAccess::ReadWrite - } else { - MemoryAccess::Read - }, - memory_size: mem_r.memory_size(), - values: Some(mem_r.get_memory_slice().iter().collect()), - }, - }, - )) - } + } => Ok(ObjectTemplate::StructureLogicDeviceMemory( + StructureLogicDeviceMemoryTemplate { + object: Some(obj.into()), + prefab: obj.into(), + structure: structure.into(), + slots: freeze_storage(storage, vm)?, + logic: logic.into(), + device: device.into(), + memory: mem_r.into(), + }, + )), // Item Objects ObjectInterfaces { @@ -1290,38 +1058,11 @@ impl ObjectTemplate { wireless_transmit: None, wireless_receive: None, network: None, - } => { - let prefab_lookup = StationpediaPrefab::from_repr(obj_ref.get_prefab().hash); - Ok(ObjectTemplate::Item(ItemTemplate { - object: Some(ObjectInfo { - name: Some(obj_ref.get_name().value()), - id: Some(*obj_ref.get_id()), - }), - prefab: PrefabInfo { - prefab_name: obj_ref.get_prefab().value, - prefab_hash: obj_ref.get_prefab().hash, - name: prefab_lookup - .map(|prefab| prefab.get_str("name")) - .flatten() - .unwrap_or("") - .to_string(), - desc: prefab_lookup - .map(|prefab| prefab.get_str("desc")) - .flatten() - .unwrap_or("") - .to_string(), - }, - item: ItemInfo { - consumable: item.consumable(), - filter_type: item.filter_type(), - ingredient: item.ingredient(), - max_quantity: item.max_quantity(), - reagents: item.reagents(), - slot_class: item.slot_class(), - sorting_class: item.sorting_class(), - }, - })) - } + } => Ok(ObjectTemplate::Item(ItemTemplate { + object: Some(obj.into()), + prefab: obj.into(), + item: item.into(), + })), ObjectInterfaces { structure: None, storage: Some(storage), @@ -1339,53 +1080,12 @@ impl ObjectTemplate { wireless_transmit: None, wireless_receive: None, network: None, - } => { - let prefab_lookup = StationpediaPrefab::from_repr(obj_ref.get_prefab().hash); - Ok(ObjectTemplate::ItemSlots(ItemSlotsTemplate { - object: Some(ObjectInfo { - name: Some(obj_ref.get_name().value()), - id: Some(*obj_ref.get_id()), - }), - prefab: PrefabInfo { - prefab_name: obj_ref.get_prefab().value, - prefab_hash: obj_ref.get_prefab().hash, - name: prefab_lookup - .map(|prefab| prefab.get_str("name")) - .flatten() - .unwrap_or("") - .to_string(), - desc: prefab_lookup - .map(|prefab| prefab.get_str("desc")) - .flatten() - .unwrap_or("") - .to_string(), - }, - item: ItemInfo { - consumable: item.consumable(), - filter_type: item.filter_type(), - ingredient: item.ingredient(), - max_quantity: item.max_quantity(), - reagents: item.reagents(), - slot_class: item.slot_class(), - sorting_class: item.sorting_class(), - }, - slots: storage - .get_slots() - .iter() - .map(|slot| { - Ok(SlotInfo { - name: slot.name.clone(), - typ: slot.typ, - occupant: slot - .occupant - .map(|occupant| ObjectTemplate::freeze_object(occupant)) - .map_or(Ok(None), |v| v.map(Some))?, - }) - }) - .collect::, _>>()?, - })) - } - + } => Ok(ObjectTemplate::ItemSlots(ItemSlotsTemplate { + object: Some(obj.into()), + prefab: obj.into(), + item: item.into(), + slots: freeze_storage(storage, vm)?, + })), ObjectInterfaces { structure: None, storage: Some(storage), @@ -1393,69 +1093,76 @@ impl ObjectTemplate { memory_writable: None, logicable: Some(logic), source_code: None, - circuit_holder: None, + circuit_holder: _ch, item: Some(item), integrated_circuit: None, programmable: None, instructable: None, logic_stack: None, device: None, - wireless_transmit: wt, - wireless_receive: wr, + wireless_transmit: _wt, + wireless_receive: _wr, network: None, - } => { - let prefab_lookup = StationpediaPrefab::from_repr(obj_ref.get_prefab().hash); - Ok(ObjectTemplate::ItemLogic(ItemLogicTemplate { - object: Some(ObjectInfo { - name: Some(obj_ref.get_name().value()), - id: Some(*obj_ref.get_id()), - }), - prefab: PrefabInfo { - prefab_name: obj_ref.get_prefab().value, - prefab_hash: obj_ref.get_prefab().hash, - name: prefab_lookup - .map(|prefab| prefab.get_str("name")) - .flatten() - .unwrap_or("") - .to_string(), - desc: prefab_lookup - .map(|prefab| prefab.get_str("desc")) - .flatten() - .unwrap_or("") - .to_string(), - }, - item: ItemInfo { - consumable: item.consumable(), - filter_type: item.filter_type(), - ingredient: item.ingredient(), - max_quantity: item.max_quantity(), - reagents: item.reagents(), - slot_class: item.slot_class(), - sorting_class: item.sorting_class(), - }, - slots: storage - .get_slots() - .iter() - .map(|slot| { - Ok(SlotInfo { - name: slot.name.clone(), - typ: slot.typ, - occupant: slot - .occupant - .map(|occupant| ObjectTemplate::freeze_object(occupant)) - .map_or(Ok(None), |v| v.map(Some))?, - }) - }) - .collect::, _>>()?, - })) - } - _ => { - Err(TemplateError::NonConformingObject(obj_ref.get_id())) - } + } => Ok(ObjectTemplate::ItemLogic(ItemLogicTemplate { + object: Some(obj.into()), + prefab: obj.into(), + item: item.into(), + slots: freeze_storage(storage, vm)?, + logic: logic.into(), + })), + ObjectInterfaces { + structure: None, + storage: Some(storage), + memory_readable: Some(mem_r), + memory_writable: _mem_w, + logicable: Some(logic), + source_code: None, + circuit_holder: _ch, + item: Some(item), + integrated_circuit: None, + programmable: None, + instructable: _inst, + logic_stack: _logic_stack, + device: None, + wireless_transmit: _wt, + wireless_receive: _wr, + network: None, + } => Ok(ObjectTemplate::ItemLogicMemory(ItemLogicMemoryTemplate { + object: Some(obj.into()), + prefab: obj.into(), + item: item.into(), + slots: freeze_storage(storage, vm)?, + logic: logic.into(), + memory: mem_r.into(), + })), + _ => Err(TemplateError::NonConformingObject(obj_ref.get_id())), } } } +fn freeze_storage(storage: StorageRef<'_>, vm: &Rc) -> Result, TemplateError> { + let slots = storage + .get_slots() + .iter() + .map(|slot| { + Ok(SlotInfo { + name: slot.name.clone(), + typ: slot.typ, + occupant: slot + .occupant + .map(|occupant| { + let occupant = vm + .get_object(occupant) + .ok_or(TemplateError::MissingVMObject(occupant))?; + ObjectTemplate::freeze_object(&occupant, vm) + }) + .map_or(Ok(None), |v| v.map(Some))?, + }) + }) + .collect::, _>>()?; + Ok(slots) +} + #[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct PrefabInfo { @@ -1465,6 +1172,27 @@ pub struct PrefabInfo { pub name: String, } +impl From<&VMObject> for PrefabInfo { + fn from(obj: &VMObject) -> Self { + let obj_prefab = obj.borrow().get_prefab(); + let prefab_lookup = StationpediaPrefab::from_repr(obj_prefab.hash); + PrefabInfo { + prefab_name: obj_prefab.value.clone(), + prefab_hash: obj_prefab.hash, + name: prefab_lookup + .map(|prefab| prefab.get_str("name")) + .flatten() + .unwrap_or("") + .to_string(), + desc: prefab_lookup + .map(|prefab| prefab.get_str("desc")) + .flatten() + .unwrap_or("") + .to_string(), + } + } +} + #[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ObjectInfo { @@ -1472,6 +1200,16 @@ pub struct ObjectInfo { pub id: Option, } +impl From<&VMObject> for ObjectInfo { + fn from(obj: &VMObject) -> Self { + let obj_ref = obj.borrow(); + ObjectInfo { + name: Some(obj_ref.get_name().value.clone()), + id: Some(obj_ref.get_id()), + } + } +} + #[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct SlotInfo { @@ -1507,6 +1245,80 @@ pub struct LogicInfo { pub circuit_holder: bool, } +impl From> for LogicInfo { + fn from(logic: LogicableRef) -> Self { + // Logicable: Storage -> !None + let storage = logic.as_storage().unwrap(); + let wt = logic.as_wireless_transmit(); + let wr = logic.as_wireless_receive(); + let circuit_holder = logic.as_circuit_holder(); + LogicInfo { + logic_slot_types: storage + .get_slots() + .iter() + .enumerate() + .map(|(index, slot)| { + ( + index as u32, + LogicSlotTypes { + slot_types: LogicSlotType::iter() + .filter_map(|slt| { + let readable = slot.readable_logic.contains(&slt); + let writeable = slot.writeable_logic.contains(&slt); + if readable && writeable { + Some((slt, MemoryAccess::ReadWrite)) + } else if readable { + Some((slt, MemoryAccess::Read)) + } else if writeable { + Some((slt, MemoryAccess::Write)) + } else { + None + } + }) + .collect(), + }, + ) + }) + .collect(), + logic_types: LogicTypes { + types: logic + .valid_logic_types() + .iter() + .filter_map(|lt| { + let readable = logic.can_logic_read(*lt); + let writeable = logic.can_logic_write(*lt); + if readable && writeable { + Some((*lt, MemoryAccess::ReadWrite)) + } else if readable { + Some((*lt, MemoryAccess::Read)) + } else if writeable { + Some((*lt, MemoryAccess::Write)) + } else { + None + } + }) + .collect(), + }, + modes: logic + .known_modes() + .map(|modes| modes.iter().cloned().collect()), + logic_values: Some( + logic + .valid_logic_types() + .iter() + .filter_map(|lt| match logic.get_logic(*lt) { + Ok(val) => Some((*lt, val)), + _ => None + }) + .collect(), + ), + transmission_receiver: wr.is_some(), + wireless_logic: wt.is_some(), + circuit_holder: circuit_holder.is_some(), + } + } +} + #[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ItemInfo { @@ -1521,6 +1333,20 @@ pub struct ItemInfo { pub sorting_class: SortingClass, } +impl From> for ItemInfo { + fn from(item: ItemRef<'_>) -> Self { + ItemInfo { + consumable: item.consumable(), + filter_type: item.filter_type(), + ingredient: item.ingredient(), + max_quantity: item.max_quantity(), + reagents: item.reagents().cloned(), + slot_class: item.slot_class(), + sorting_class: item.sorting_class(), + } + } +} + #[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ConnectionInfo { @@ -1548,12 +1374,38 @@ pub struct DeviceInfo { pub has_reagents: bool, } +impl From> for DeviceInfo { + fn from(device: DeviceRef) -> Self { + DeviceInfo { + connection_list: device.connection_list().iter().map(|conn| conn.to_info()).collect(), + device_pins_length: device.device_pins().map(|pins| pins.len()), + device_pins: device.device_pins().map(|pins| pins.iter().copied().collect()), + has_reagents: device.has_reagents(), + has_lock_state: device.has_lock_state(), + has_mode_state: device.has_mode_state(), + has_open_state: device.has_mode_state(), + has_on_off_state: device.has_on_off_state(), + has_color_state: device.has_color_state(), + has_atmosphere: device.has_atmosphere(), + has_activate_state: device.has_activate_state(), + } + } +} + #[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct StructureInfo { pub small_grid: bool, } +impl From> for StructureInfo { + fn from(value: StructureRef) -> Self { + StructureInfo { + small_grid: value.is_small_grid(), + } + } +} + #[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Instruction { @@ -1562,7 +1414,7 @@ pub struct Instruction { pub value: i64, } -#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct MemoryInfo { #[serde(skip_serializing_if = "Option::is_none")] @@ -1573,6 +1425,22 @@ pub struct MemoryInfo { pub values: Option>, } +impl From> for MemoryInfo { + fn from(mem_r: MemoryReadableRef<'_>) -> Self { + let mem_w = mem_r.as_memory_writable(); + MemoryInfo { + instructions: None, // TODO: map info from `Instructable` and LogicStack traits + memory_access: if mem_w.is_some() { + MemoryAccess::ReadWrite + } else { + MemoryAccess::Read + }, + memory_size: mem_r.memory_size(), + values: Some(mem_r.get_memory_slice().iter().copied().collect()), + } + } +} + #[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct StructureTemplate { diff --git a/ic10emu/src/vm/object/traits.rs b/ic10emu/src/vm/object/traits.rs index 1869611..b209fb1 100644 --- a/ic10emu/src/vm/object/traits.rs +++ b/ic10emu/src/vm/object/traits.rs @@ -75,14 +75,14 @@ tag_object_traits! { pub trait CircuitHolder: Logicable + Storage { fn clear_error(&mut self); fn set_error(&mut self, state: i32); - fn get_logicable_from_index(&self, device: usize, vm: &VM) -> Option>; - fn get_logicable_from_index_mut(&self, device: usize, vm: &VM) -> Option>; - fn get_logicable_from_id(&self, device: ObjectID, vm: &VM) -> Option>; - fn get_logicable_from_id_mut(&self, device: ObjectID, vm: &VM) -> Option>; + fn get_logicable_from_index(&self, device: usize, vm: &VM) -> Option; + fn get_logicable_from_index_mut(&self, device: usize, vm: &VM) -> Option; + fn get_logicable_from_id(&self, device: ObjectID, vm: &VM) -> Option; + fn get_logicable_from_id_mut(&self, device: ObjectID, vm: &VM) -> Option; fn get_source_code(&self) -> String; fn set_source_code(&self, code: String); - fn get_batch(&self) -> Vec>; - fn get_batch_mut(&self) -> Vec>; + fn get_batch(&self) -> Vec; + fn get_batch_mut(&self) -> Vec; fn get_ic(&self) -> Option; } @@ -99,7 +99,7 @@ tag_object_traits! { } pub trait IntegratedCircuit: Logicable + MemoryWritable + SourceCode + Item { - fn get_circuit_holder(&self, vm: &VM) -> Option>; + fn get_circuit_holder(&self, vm: &VM) -> Option; fn get_instruction_pointer(&self) -> f64; fn set_next_instruction(&mut self, next_instruction: f64); fn set_next_instruction_relative(&mut self, offset: f64) { @@ -189,7 +189,7 @@ tag_object_traits! { } -impl Debug for dyn Object { +impl Debug for dyn Object { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!( f,