refactor(vm): impl circuit holder, impl ObjectRef/Mut
This commit is contained in:
@@ -77,6 +77,11 @@ impl Program {
|
|||||||
self.instructions.len()
|
self.instructions.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn is_empty(&self) -> bool {
|
||||||
|
self.len() == 0
|
||||||
|
}
|
||||||
|
|
||||||
pub fn try_from_code(code: &str) -> Result<Self, ICError> {
|
pub fn try_from_code(code: &str) -> Result<Self, ICError> {
|
||||||
let parse_tree = grammar::parse(code)?;
|
let parse_tree = grammar::parse(code)?;
|
||||||
let mut labels_set = HashSet::new();
|
let mut labels_set = HashSet::new();
|
||||||
|
|||||||
@@ -865,10 +865,10 @@ impl<T: IC10Marker> BdseInstruction for T {
|
|||||||
let a = a.as_value(self)?;
|
let a = a.as_value(self)?;
|
||||||
if self
|
if self
|
||||||
.get_circuit_holder()
|
.get_circuit_holder()
|
||||||
.ok_or(ICError::NoCircuitHolder(self.get_id()))?
|
.ok_or(ICError::NoCircuitHolder(*self.get_id()))?
|
||||||
.borrow()
|
.borrow()
|
||||||
.as_circuit_holder()
|
.as_circuit_holder()
|
||||||
.ok_or(ICError::CircuitHolderNotLogicable(self.get_id()))?
|
.ok_or(ICError::CircuitHolderNotLogicable(*self.get_id()))?
|
||||||
.get_logicable_from_index(device, connection)
|
.get_logicable_from_index(device, connection)
|
||||||
.is_some()
|
.is_some()
|
||||||
{
|
{
|
||||||
@@ -885,10 +885,10 @@ impl<T: IC10Marker> BdsealInstruction for T {
|
|||||||
let a = a.as_value(self)?;
|
let a = a.as_value(self)?;
|
||||||
if self
|
if self
|
||||||
.get_circuit_holder()
|
.get_circuit_holder()
|
||||||
.ok_or(ICError::NoCircuitHolder(self.get_id()))?
|
.ok_or(ICError::NoCircuitHolder(*self.get_id()))?
|
||||||
.borrow()
|
.borrow()
|
||||||
.as_circuit_holder()
|
.as_circuit_holder()
|
||||||
.ok_or(ICError::CircuitHolderNotLogicable(self.get_id()))?
|
.ok_or(ICError::CircuitHolderNotLogicable(*self.get_id()))?
|
||||||
.get_logicable_from_index(device, connection)
|
.get_logicable_from_index(device, connection)
|
||||||
.is_some()
|
.is_some()
|
||||||
{
|
{
|
||||||
@@ -906,10 +906,10 @@ impl<T: IC10Marker> BrdseInstruction for T {
|
|||||||
let a = a.as_value(self)?;
|
let a = a.as_value(self)?;
|
||||||
if self
|
if self
|
||||||
.get_circuit_holder()
|
.get_circuit_holder()
|
||||||
.ok_or(ICError::NoCircuitHolder(self.get_id()))?
|
.ok_or(ICError::NoCircuitHolder(*self.get_id()))?
|
||||||
.borrow()
|
.borrow()
|
||||||
.as_circuit_holder()
|
.as_circuit_holder()
|
||||||
.ok_or(ICError::CircuitHolderNotLogicable(self.get_id()))?
|
.ok_or(ICError::CircuitHolderNotLogicable(*self.get_id()))?
|
||||||
.get_logicable_from_index(device, connection)
|
.get_logicable_from_index(device, connection)
|
||||||
.is_some()
|
.is_some()
|
||||||
{
|
{
|
||||||
@@ -926,10 +926,10 @@ impl<T: IC10Marker> BdnsInstruction for T {
|
|||||||
let a = a.as_value(self)?;
|
let a = a.as_value(self)?;
|
||||||
if self
|
if self
|
||||||
.get_circuit_holder()
|
.get_circuit_holder()
|
||||||
.ok_or(ICError::NoCircuitHolder(self.get_id()))?
|
.ok_or(ICError::NoCircuitHolder(*self.get_id()))?
|
||||||
.borrow()
|
.borrow()
|
||||||
.as_circuit_holder()
|
.as_circuit_holder()
|
||||||
.ok_or(ICError::CircuitHolderNotLogicable(self.get_id()))?
|
.ok_or(ICError::CircuitHolderNotLogicable(*self.get_id()))?
|
||||||
.get_logicable_from_index(device, connection)
|
.get_logicable_from_index(device, connection)
|
||||||
.is_none()
|
.is_none()
|
||||||
{
|
{
|
||||||
@@ -946,10 +946,10 @@ impl<T: IC10Marker> BdnsalInstruction for T {
|
|||||||
let a = a.as_value(self)?;
|
let a = a.as_value(self)?;
|
||||||
if self
|
if self
|
||||||
.get_circuit_holder()
|
.get_circuit_holder()
|
||||||
.ok_or(ICError::NoCircuitHolder(self.get_id()))?
|
.ok_or(ICError::NoCircuitHolder(*self.get_id()))?
|
||||||
.borrow()
|
.borrow()
|
||||||
.as_circuit_holder()
|
.as_circuit_holder()
|
||||||
.ok_or(ICError::CircuitHolderNotLogicable(self.get_id()))?
|
.ok_or(ICError::CircuitHolderNotLogicable(*self.get_id()))?
|
||||||
.get_logicable_from_index(device, connection)
|
.get_logicable_from_index(device, connection)
|
||||||
.is_none()
|
.is_none()
|
||||||
{
|
{
|
||||||
@@ -967,10 +967,10 @@ impl<T: IC10Marker> BrdnsInstruction for T {
|
|||||||
let a = a.as_value(self)?;
|
let a = a.as_value(self)?;
|
||||||
if self
|
if self
|
||||||
.get_circuit_holder()
|
.get_circuit_holder()
|
||||||
.ok_or(ICError::NoCircuitHolder(self.get_id()))?
|
.ok_or(ICError::NoCircuitHolder(*self.get_id()))?
|
||||||
.borrow()
|
.borrow()
|
||||||
.as_circuit_holder()
|
.as_circuit_holder()
|
||||||
.ok_or(ICError::CircuitHolderNotLogicable(self.get_id()))?
|
.ok_or(ICError::CircuitHolderNotLogicable(*self.get_id()))?
|
||||||
.get_logicable_from_index(device, connection)
|
.get_logicable_from_index(device, connection)
|
||||||
.is_none()
|
.is_none()
|
||||||
{
|
{
|
||||||
@@ -1341,14 +1341,16 @@ impl<T: IC10Marker> SdseInstruction for T {
|
|||||||
target,
|
target,
|
||||||
} = r.as_register(self)?;
|
} = r.as_register(self)?;
|
||||||
let (device, connection) = d.as_device(self)?;
|
let (device, connection) = d.as_device(self)?;
|
||||||
let obj = self
|
let is_some = {
|
||||||
.get_circuit_holder()
|
self.get_circuit_holder()
|
||||||
.ok_or(ICError::NoCircuitHolder(self.get_id()))?
|
.ok_or(ICError::NoCircuitHolder(*self.get_id()))?
|
||||||
.borrow()
|
.borrow()
|
||||||
.as_circuit_holder()
|
.as_circuit_holder()
|
||||||
.ok_or(ICError::CircuitHolderNotLogicable(self.get_id()))?
|
.ok_or(ICError::CircuitHolderNotLogicable(*self.get_id()))?
|
||||||
.get_logicable_from_index(device, connection);
|
.get_logicable_from_index(device, connection)
|
||||||
self.set_register(indirection, target, if obj.is_some() { 1.0 } else { 0.0 })?;
|
.is_some()
|
||||||
|
};
|
||||||
|
self.set_register(indirection, target, if is_some { 1.0 } else { 0.0 })?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1360,14 +1362,16 @@ impl<T: IC10Marker> SdnsInstruction for T {
|
|||||||
target,
|
target,
|
||||||
} = r.as_register(self)?;
|
} = r.as_register(self)?;
|
||||||
let (device, connection) = d.as_device(self)?;
|
let (device, connection) = d.as_device(self)?;
|
||||||
let obj = self
|
let is_none = {
|
||||||
.get_circuit_holder()
|
self.get_circuit_holder()
|
||||||
.ok_or(ICError::NoCircuitHolder(self.get_id()))?
|
.ok_or(ICError::NoCircuitHolder(*self.get_id()))?
|
||||||
.borrow()
|
.borrow()
|
||||||
.as_circuit_holder()
|
.as_circuit_holder()
|
||||||
.ok_or(ICError::CircuitHolderNotLogicable(self.get_id()))?
|
.ok_or(ICError::CircuitHolderNotLogicable(*self.get_id()))?
|
||||||
.get_logicable_from_index(device, connection);
|
.get_logicable_from_index(device, connection)
|
||||||
self.set_register(indirection, target, if obj.is_none() { 1.0 } else { 0.0 })?;
|
.is_none()
|
||||||
|
};
|
||||||
|
self.set_register(indirection, target, if is_none { 1.0 } else { 0.0 })?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1988,19 +1992,22 @@ impl<T: IC10Marker> GetInstruction for T {
|
|||||||
} = r.as_register(self)?;
|
} = r.as_register(self)?;
|
||||||
let address = address.as_value(self)?;
|
let address = address.as_value(self)?;
|
||||||
let (device, connection) = d.as_device(self)?;
|
let (device, connection) = d.as_device(self)?;
|
||||||
let obj = self
|
self.get_circuit_holder()
|
||||||
.get_circuit_holder()
|
.ok_or(ICError::NoCircuitHolder(*self.get_id()))?
|
||||||
.ok_or(ICError::NoCircuitHolder(self.get_id()))?
|
|
||||||
.borrow()
|
.borrow()
|
||||||
.as_circuit_holder()
|
.as_circuit_holder()
|
||||||
.ok_or(ICError::CircuitHolderNotLogicable(self.get_id()))?
|
.ok_or(ICError::CircuitHolderNotLogicable(*self.get_id()))?
|
||||||
.get_logicable_from_index(device, connection)
|
.get_logicable_from_index(device, connection)
|
||||||
.ok_or(ICError::DeviceNotSet)?;
|
.ok_or(ICError::DeviceNotSet)
|
||||||
let obj_ref = obj.borrow();
|
.and_then(|obj| {
|
||||||
let memory = obj_ref
|
obj.map(|obj_ref| {
|
||||||
.as_memory_readable()
|
let val = obj_ref
|
||||||
.ok_or(MemoryError::NotReadable)?;
|
.as_memory_readable()
|
||||||
self.set_register(indirection, target, memory.get_memory(address as i32)?)?;
|
.ok_or(MemoryError::NotWriteable)?
|
||||||
|
.get_memory(address as i32)?;
|
||||||
|
self.set_register(indirection, target, val)
|
||||||
|
})
|
||||||
|
})?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2019,19 +2026,22 @@ impl<T: IC10Marker> GetdInstruction for T {
|
|||||||
} = r.as_register(self)?;
|
} = r.as_register(self)?;
|
||||||
let id = id.as_value(self)?;
|
let id = id.as_value(self)?;
|
||||||
let address = address.as_value(self)?;
|
let address = address.as_value(self)?;
|
||||||
let obj = self
|
self.get_circuit_holder()
|
||||||
.get_circuit_holder()
|
.ok_or(ICError::NoCircuitHolder(*self.get_id()))?
|
||||||
.ok_or(ICError::NoCircuitHolder(self.get_id()))?
|
|
||||||
.borrow()
|
.borrow()
|
||||||
.as_circuit_holder()
|
.as_circuit_holder()
|
||||||
.ok_or(ICError::CircuitHolderNotLogicable(self.get_id()))?
|
.ok_or(ICError::CircuitHolderNotLogicable(*self.get_id()))?
|
||||||
.get_logicable_from_id(id as ObjectID, None)
|
.get_logicable_from_id(id as ObjectID, None)
|
||||||
.ok_or(ICError::DeviceNotSet)?;
|
.ok_or(ICError::DeviceNotSet)
|
||||||
let obj_ref = obj.borrow();
|
.and_then(|obj| {
|
||||||
let memory = obj_ref
|
obj.map(|obj_ref| {
|
||||||
.as_memory_readable()
|
let val = obj_ref
|
||||||
.ok_or(MemoryError::NotReadable)?;
|
.as_memory_readable()
|
||||||
self.set_register(indirection, target, memory.get_memory(address as i32)?)?;
|
.ok_or(MemoryError::NotWriteable)?
|
||||||
|
.get_memory(address as i32)?;
|
||||||
|
self.set_register(indirection, target, val)
|
||||||
|
})
|
||||||
|
})?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2047,19 +2057,22 @@ impl<T: IC10Marker> PutInstruction for T {
|
|||||||
let (device, connection) = d.as_device(self)?;
|
let (device, connection) = d.as_device(self)?;
|
||||||
let address = address.as_value(self)?;
|
let address = address.as_value(self)?;
|
||||||
let value = value.as_value(self)?;
|
let value = value.as_value(self)?;
|
||||||
let obj = self
|
self.get_circuit_holder()
|
||||||
.get_circuit_holder()
|
.ok_or(ICError::NoCircuitHolder(*self.get_id()))?
|
||||||
.ok_or(ICError::NoCircuitHolder(self.get_id()))?
|
.borrow_mut()
|
||||||
.borrow()
|
.as_mut_circuit_holder()
|
||||||
.as_circuit_holder()
|
.ok_or(ICError::CircuitHolderNotLogicable(*self.get_id()))?
|
||||||
.ok_or(ICError::CircuitHolderNotLogicable(self.get_id()))?
|
.get_logicable_from_index_mut(device, connection)
|
||||||
.get_logicable_from_index(device, connection)
|
.ok_or(ICError::DeviceNotSet)
|
||||||
.ok_or(ICError::DeviceNotSet)?;
|
.and_then(|mut obj| {
|
||||||
let mut obj_ref = obj.borrow_mut();
|
obj.map(|obj_ref| {
|
||||||
let memory = obj_ref
|
obj_ref
|
||||||
.as_mut_memory_writable()
|
.as_mut_memory_writable()
|
||||||
.ok_or(MemoryError::NotWriteable)?;
|
.ok_or(MemoryError::NotWriteable)?
|
||||||
memory.set_memory(address as i32, value)?;
|
.set_memory(address as i32, value)
|
||||||
|
.map_err(Into::into)
|
||||||
|
})
|
||||||
|
})?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2075,19 +2088,22 @@ impl<T: IC10Marker> PutdInstruction for T {
|
|||||||
let id = id.as_value(self)?;
|
let id = id.as_value(self)?;
|
||||||
let address = address.as_value(self)?;
|
let address = address.as_value(self)?;
|
||||||
let value = value.as_value(self)?;
|
let value = value.as_value(self)?;
|
||||||
let obj = self
|
self.get_circuit_holder()
|
||||||
.get_circuit_holder()
|
.ok_or(ICError::NoCircuitHolder(*self.get_id()))?
|
||||||
.ok_or(ICError::NoCircuitHolder(self.get_id()))?
|
.borrow_mut()
|
||||||
.borrow()
|
.as_mut_circuit_holder()
|
||||||
.as_circuit_holder()
|
.ok_or(ICError::CircuitHolderNotLogicable(*self.get_id()))?
|
||||||
.ok_or(ICError::CircuitHolderNotLogicable(self.get_id()))?
|
.get_logicable_from_id_mut(id as ObjectID, None)
|
||||||
.get_logicable_from_id(id as ObjectID, None)
|
.ok_or(ICError::DeviceNotSet)
|
||||||
.ok_or(ICError::DeviceNotSet)?;
|
.and_then(|mut obj| {
|
||||||
let mut obj_ref = obj.borrow_mut();
|
obj.map(|obj_ref| {
|
||||||
let memory = obj_ref
|
obj_ref
|
||||||
.as_mut_memory_writable()
|
.as_mut_memory_writable()
|
||||||
.ok_or(MemoryError::NotWriteable)?;
|
.ok_or(MemoryError::NotWriteable)?
|
||||||
memory.set_memory(address as i32, value)?;
|
.set_memory(address as i32, value)
|
||||||
|
.map_err(Into::into)
|
||||||
|
})
|
||||||
|
})?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2096,19 +2112,22 @@ impl<T: IC10Marker> ClrInstruction for T {
|
|||||||
/// clr d?
|
/// clr d?
|
||||||
fn execute_inner(&mut self, d: &InstOperand) -> Result<(), ICError> {
|
fn execute_inner(&mut self, d: &InstOperand) -> Result<(), ICError> {
|
||||||
let (device, connection) = d.as_device(self)?;
|
let (device, connection) = d.as_device(self)?;
|
||||||
let obj = self
|
self.get_circuit_holder()
|
||||||
.get_circuit_holder()
|
.ok_or(ICError::NoCircuitHolder(*self.get_id()))?
|
||||||
.ok_or(ICError::NoCircuitHolder(self.get_id()))?
|
.borrow_mut()
|
||||||
.borrow()
|
.as_mut_circuit_holder()
|
||||||
.as_circuit_holder()
|
.ok_or(ICError::CircuitHolderNotLogicable(*self.get_id()))?
|
||||||
.ok_or(ICError::CircuitHolderNotLogicable(self.get_id()))?
|
.get_logicable_from_index_mut(device, connection)
|
||||||
.get_logicable_from_index(device, connection)
|
.ok_or(ICError::DeviceNotSet)
|
||||||
.ok_or(ICError::DeviceNotSet)?;
|
.and_then(|mut obj| {
|
||||||
let mut obj_ref = obj.borrow_mut();
|
obj.map(|obj_ref| {
|
||||||
let memory = obj_ref
|
obj_ref
|
||||||
.as_mut_memory_writable()
|
.as_mut_memory_writable()
|
||||||
.ok_or(MemoryError::NotWriteable)?;
|
.ok_or(MemoryError::NotWriteable)?
|
||||||
memory.clear_memory()?;
|
.clear_memory()
|
||||||
|
.map_err(Into::into)
|
||||||
|
})
|
||||||
|
})?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2116,19 +2135,22 @@ impl<T: IC10Marker> ClrdInstruction for T {
|
|||||||
/// clrd id(r?|num)
|
/// clrd id(r?|num)
|
||||||
fn execute_inner(&mut self, id: &InstOperand) -> Result<(), ICError> {
|
fn execute_inner(&mut self, id: &InstOperand) -> Result<(), ICError> {
|
||||||
let id = id.as_value(self)?;
|
let id = id.as_value(self)?;
|
||||||
let obj = self
|
self.get_circuit_holder()
|
||||||
.get_circuit_holder()
|
.ok_or(ICError::NoCircuitHolder(*self.get_id()))?
|
||||||
.ok_or(ICError::NoCircuitHolder(self.get_id()))?
|
.borrow_mut()
|
||||||
.borrow()
|
.as_mut_circuit_holder()
|
||||||
.as_circuit_holder()
|
.ok_or(ICError::CircuitHolderNotLogicable(*self.get_id()))?
|
||||||
.ok_or(ICError::CircuitHolderNotLogicable(self.get_id()))?
|
.get_logicable_from_id_mut(id as ObjectID, None)
|
||||||
.get_logicable_from_id(id as ObjectID, None)
|
.ok_or(ICError::DeviceNotSet)
|
||||||
.ok_or(ICError::DeviceNotSet)?;
|
.and_then(|mut obj| {
|
||||||
let mut obj_ref = obj.borrow_mut();
|
obj.map(|obj_ref| {
|
||||||
let memory = obj_ref
|
obj_ref
|
||||||
.as_mut_memory_writable()
|
.as_mut_memory_writable()
|
||||||
.ok_or(MemoryError::NotWriteable)?;
|
.ok_or(MemoryError::NotWriteable)?
|
||||||
memory.clear_memory()?;
|
.clear_memory()
|
||||||
|
.map_err(Into::into)
|
||||||
|
})
|
||||||
|
})?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2144,23 +2166,30 @@ impl<T: IC10Marker> SInstruction for T {
|
|||||||
let (device, connection) = d.as_device(self)?;
|
let (device, connection) = d.as_device(self)?;
|
||||||
let logic_type = logic_type.as_logic_type(self)?;
|
let logic_type = logic_type.as_logic_type(self)?;
|
||||||
let val = r.as_value(self)?;
|
let val = r.as_value(self)?;
|
||||||
let obj = self
|
self.get_circuit_holder()
|
||||||
.get_circuit_holder()
|
.ok_or(ICError::NoCircuitHolder(*self.get_id()))?
|
||||||
.ok_or(ICError::NoCircuitHolder(self.get_id()))?
|
.borrow_mut()
|
||||||
.borrow()
|
.as_mut_circuit_holder()
|
||||||
.as_circuit_holder()
|
.ok_or(ICError::CircuitHolderNotLogicable(*self.get_id()))?
|
||||||
.ok_or(ICError::CircuitHolderNotLogicable(self.get_id()))?
|
.get_logicable_from_index_mut(device, connection)
|
||||||
.get_logicable_from_index(device, connection)
|
.ok_or(ICError::DeviceNotSet)
|
||||||
.ok_or(ICError::DeviceNotSet)?;
|
.and_then(|mut obj| {
|
||||||
let mut obj_ref = obj.borrow_mut();
|
let obj_id = obj.get_id();
|
||||||
let device_id = obj_ref.get_id();
|
obj.map(|obj_ref| {
|
||||||
let logicable = obj_ref
|
obj_ref
|
||||||
.as_mut_logicable()
|
.as_mut_logicable()
|
||||||
.ok_or(ICError::NotLogicable(device_id))?;
|
.ok_or(ICError::NotLogicable(obj_id))
|
||||||
if !logicable.can_logic_write(logic_type) {
|
.and_then(|logicable| {
|
||||||
return Err(LogicError::CantWrite(logic_type).into());
|
if !logicable.can_logic_write(logic_type) {
|
||||||
}
|
Err(LogicError::CantWrite(logic_type).into())
|
||||||
logicable.set_logic(logic_type, val, false)?;
|
} else {
|
||||||
|
logicable
|
||||||
|
.set_logic(logic_type, val, false)
|
||||||
|
.map_err(Into::into)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2176,23 +2205,30 @@ impl<T: IC10Marker> SdInstruction for T {
|
|||||||
let id = id.as_value(self)?;
|
let id = id.as_value(self)?;
|
||||||
let logic_type = logic_type.as_logic_type(self)?;
|
let logic_type = logic_type.as_logic_type(self)?;
|
||||||
let val = r.as_value(self)?;
|
let val = r.as_value(self)?;
|
||||||
let obj = self
|
self.get_circuit_holder()
|
||||||
.get_circuit_holder()
|
.ok_or(ICError::NoCircuitHolder(*self.get_id()))?
|
||||||
.ok_or(ICError::NoCircuitHolder(self.get_id()))?
|
.borrow_mut()
|
||||||
.borrow()
|
.as_mut_circuit_holder()
|
||||||
.as_circuit_holder()
|
.ok_or(ICError::CircuitHolderNotLogicable(*self.get_id()))?
|
||||||
.ok_or(ICError::CircuitHolderNotLogicable(self.get_id()))?
|
.get_logicable_from_id_mut(id as ObjectID, None)
|
||||||
.get_logicable_from_id(id as ObjectID, None)
|
.ok_or(ICError::DeviceNotSet)
|
||||||
.ok_or(ICError::DeviceNotSet)?;
|
.and_then(|mut obj| {
|
||||||
let mut obj_ref = obj.borrow_mut();
|
let obj_id = obj.get_id();
|
||||||
let device_id = obj_ref.get_id();
|
obj.map(|obj_ref| {
|
||||||
let logicable = obj_ref
|
obj_ref
|
||||||
.as_mut_logicable()
|
.as_mut_logicable()
|
||||||
.ok_or(ICError::NotLogicable(device_id))?;
|
.ok_or(ICError::NotLogicable(obj_id))
|
||||||
if !logicable.can_logic_write(logic_type) {
|
.and_then(|logicable| {
|
||||||
return Err(LogicError::CantWrite(logic_type).into());
|
if !logicable.can_logic_write(logic_type) {
|
||||||
}
|
Err(LogicError::CantWrite(logic_type).into())
|
||||||
logicable.set_logic(logic_type, val, false)?;
|
} else {
|
||||||
|
logicable
|
||||||
|
.set_logic(logic_type, val, false)
|
||||||
|
.map_err(Into::into)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2210,27 +2246,30 @@ impl<T: IC10Marker> SsInstruction for T {
|
|||||||
let slot_index = slot_index.as_value(self)?;
|
let slot_index = slot_index.as_value(self)?;
|
||||||
let logic_slot_type = logic_slot_type.as_slot_logic_type(self)?;
|
let logic_slot_type = logic_slot_type.as_slot_logic_type(self)?;
|
||||||
let val = r.as_value(self)?;
|
let val = r.as_value(self)?;
|
||||||
let obj = self
|
self.get_circuit_holder()
|
||||||
.get_circuit_holder()
|
.ok_or(ICError::NoCircuitHolder(*self.get_id()))?
|
||||||
.ok_or(ICError::NoCircuitHolder(self.get_id()))?
|
.borrow_mut()
|
||||||
.borrow()
|
.as_mut_circuit_holder()
|
||||||
.as_circuit_holder()
|
.ok_or(ICError::CircuitHolderNotLogicable(*self.get_id()))?
|
||||||
.ok_or(ICError::CircuitHolderNotLogicable(self.get_id()))?
|
.get_logicable_from_index_mut(device, connection)
|
||||||
.get_logicable_from_index(device, connection)
|
.ok_or(ICError::DeviceNotSet)
|
||||||
.ok_or(ICError::DeviceNotSet)?;
|
.and_then(|mut obj| {
|
||||||
let mut obj_ref = obj.borrow_mut();
|
let obj_id = obj.get_id();
|
||||||
let device_id = obj_ref.get_id();
|
obj.map(|obj_ref| {
|
||||||
let logicable = obj_ref
|
obj_ref
|
||||||
.as_mut_logicable()
|
.as_mut_device()
|
||||||
.ok_or(ICError::NotLogicable(device_id))?;
|
.ok_or(ICError::NotLogicable(obj_id))
|
||||||
let device_id = logicable.get_id();
|
.and_then(|logicable| {
|
||||||
let device = logicable
|
if !logicable.can_slot_logic_write(logic_slot_type, slot_index) {
|
||||||
.as_mut_device()
|
Err(LogicError::CantSlotWrite(logic_slot_type, slot_index).into())
|
||||||
.ok_or(ICError::NotSlotWriteable(device_id))?;
|
} else {
|
||||||
if !device.can_slot_logic_write(logic_slot_type, slot_index) {
|
logicable
|
||||||
return Err(LogicError::CantSlotWrite(logic_slot_type, slot_index).into());
|
.set_slot_logic(logic_slot_type, slot_index, val, false)
|
||||||
}
|
.map_err(Into::into)
|
||||||
device.set_slot_logic(logic_slot_type, slot_index, val, false)?;
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2248,7 +2287,7 @@ impl<T: IC10Marker> SbInstruction for T {
|
|||||||
let logic_type = logic_type.as_logic_type(self)?;
|
let logic_type = logic_type.as_logic_type(self)?;
|
||||||
let val = r.as_value(self)?;
|
let val = r.as_value(self)?;
|
||||||
self.get_vm()
|
self.get_vm()
|
||||||
.set_batch_device_field(self.get_id(), prefab, logic_type, val, false)?;
|
.set_batch_device_field(*self.get_id(), prefab, logic_type, val, false)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2268,7 +2307,7 @@ impl<T: IC10Marker> SbsInstruction for T {
|
|||||||
let logic_slot_type = logic_slot_type.as_slot_logic_type(self)?;
|
let logic_slot_type = logic_slot_type.as_slot_logic_type(self)?;
|
||||||
let val = r.as_value(self)?;
|
let val = r.as_value(self)?;
|
||||||
self.get_vm().set_batch_device_slot_field(
|
self.get_vm().set_batch_device_slot_field(
|
||||||
self.get_id(),
|
*self.get_id(),
|
||||||
prefab,
|
prefab,
|
||||||
slot_index,
|
slot_index,
|
||||||
logic_slot_type,
|
logic_slot_type,
|
||||||
@@ -2294,7 +2333,7 @@ impl<T: IC10Marker> SbnInstruction for T {
|
|||||||
let logic_type = logic_type.as_logic_type(self)?;
|
let logic_type = logic_type.as_logic_type(self)?;
|
||||||
let val = r.as_value(self)?;
|
let val = r.as_value(self)?;
|
||||||
self.get_vm().set_batch_name_device_field(
|
self.get_vm().set_batch_name_device_field(
|
||||||
self.get_id(),
|
*self.get_id(),
|
||||||
prefab,
|
prefab,
|
||||||
name,
|
name,
|
||||||
logic_type,
|
logic_type,
|
||||||
@@ -2320,22 +2359,29 @@ impl<T: IC10Marker> LInstruction for T {
|
|||||||
} = r.as_register(self)?;
|
} = r.as_register(self)?;
|
||||||
let (device, connection) = d.as_device(self)?;
|
let (device, connection) = d.as_device(self)?;
|
||||||
let logic_type = logic_type.as_logic_type(self)?;
|
let logic_type = logic_type.as_logic_type(self)?;
|
||||||
let obj = self
|
let val = self
|
||||||
.get_circuit_holder()
|
.get_circuit_holder()
|
||||||
.ok_or(ICError::NoCircuitHolder(self.get_id()))?
|
.ok_or(ICError::NoCircuitHolder(*self.get_id()))?
|
||||||
.borrow()
|
.borrow()
|
||||||
.as_circuit_holder()
|
.as_circuit_holder()
|
||||||
.ok_or(ICError::CircuitHolderNotLogicable(self.get_id()))?
|
.ok_or(ICError::CircuitHolderNotLogicable(*self.get_id()))?
|
||||||
.get_logicable_from_index(device, connection)
|
.get_logicable_from_index(device, connection)
|
||||||
.ok_or(ICError::DeviceNotSet)?;
|
.ok_or(ICError::DeviceNotSet)
|
||||||
let obj_ref = obj.borrow();
|
.and_then(|obj| {
|
||||||
let logicable = obj_ref
|
obj.map(|obj_ref| {
|
||||||
.as_logicable()
|
obj_ref
|
||||||
.ok_or(ICError::NotLogicable(obj_ref.get_id()))?;
|
.as_logicable()
|
||||||
if !logicable.can_logic_read(logic_type) {
|
.ok_or(ICError::NotLogicable(*obj_ref.get_id()))
|
||||||
return Err(LogicError::CantRead(logic_type).into());
|
.and_then(|logicable| {
|
||||||
}
|
if !logicable.can_logic_read(logic_type) {
|
||||||
self.set_register(indirection, target, logicable.get_logic(logic_type)?)?;
|
Err(LogicError::CantRead(logic_type).into())
|
||||||
|
} else {
|
||||||
|
logicable.get_logic(logic_type).map_err(Into::into)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})?;
|
||||||
|
self.set_register(indirection, target, val)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2354,22 +2400,29 @@ impl<T: IC10Marker> LdInstruction for T {
|
|||||||
} = r.as_register(self)?;
|
} = r.as_register(self)?;
|
||||||
let id = id.as_value(self)?;
|
let id = id.as_value(self)?;
|
||||||
let logic_type = logic_type.as_logic_type(self)?;
|
let logic_type = logic_type.as_logic_type(self)?;
|
||||||
let obj = self
|
let val = self
|
||||||
.get_circuit_holder()
|
.get_circuit_holder()
|
||||||
.ok_or(ICError::NoCircuitHolder(self.get_id()))?
|
.ok_or(ICError::NoCircuitHolder(*self.get_id()))?
|
||||||
.borrow()
|
.borrow()
|
||||||
.as_circuit_holder()
|
.as_circuit_holder()
|
||||||
.ok_or(ICError::CircuitHolderNotLogicable(self.get_id()))?
|
.ok_or(ICError::CircuitHolderNotLogicable(*self.get_id()))?
|
||||||
.get_logicable_from_id(id as ObjectID, None)
|
.get_logicable_from_id(id as ObjectID, None)
|
||||||
.ok_or(ICError::DeviceNotSet)?;
|
.ok_or(ICError::DeviceNotSet)
|
||||||
let obj_ref = obj.borrow();
|
.and_then(|obj| {
|
||||||
let logicable = obj_ref
|
obj.map(|obj_ref| {
|
||||||
.as_logicable()
|
obj_ref
|
||||||
.ok_or(ICError::NotLogicable(obj_ref.get_id()))?;
|
.as_logicable()
|
||||||
if !logicable.can_logic_read(logic_type) {
|
.ok_or(ICError::NotLogicable(*obj_ref.get_id()))
|
||||||
return Err(LogicError::CantRead(logic_type).into());
|
.and_then(|logicable| {
|
||||||
}
|
if !logicable.can_logic_read(logic_type) {
|
||||||
self.set_register(indirection, target, logicable.get_logic(logic_type)?)?;
|
Err(LogicError::CantRead(logic_type).into())
|
||||||
|
} else {
|
||||||
|
logicable.get_logic(logic_type).map_err(Into::into)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})?;
|
||||||
|
self.set_register(indirection, target, val)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2390,26 +2443,31 @@ impl<T: IC10Marker> LsInstruction for T {
|
|||||||
let (device, connection) = d.as_device(self)?;
|
let (device, connection) = d.as_device(self)?;
|
||||||
let slot_index = slot_index.as_value(self)?;
|
let slot_index = slot_index.as_value(self)?;
|
||||||
let logic_slot_type = logic_slot_type.as_slot_logic_type(self)?;
|
let logic_slot_type = logic_slot_type.as_slot_logic_type(self)?;
|
||||||
let obj = self
|
let val = self
|
||||||
.get_circuit_holder()
|
.get_circuit_holder()
|
||||||
.ok_or(ICError::NoCircuitHolder(self.get_id()))?
|
.ok_or(ICError::NoCircuitHolder(*self.get_id()))?
|
||||||
.borrow()
|
.borrow()
|
||||||
.as_circuit_holder()
|
.as_circuit_holder()
|
||||||
.ok_or(ICError::CircuitHolderNotLogicable(self.get_id()))?
|
.ok_or(ICError::CircuitHolderNotLogicable(*self.get_id()))?
|
||||||
.get_logicable_from_index(device, connection)
|
.get_logicable_from_index(device, connection)
|
||||||
.ok_or(ICError::DeviceNotSet)?;
|
.ok_or(ICError::DeviceNotSet)
|
||||||
let obj_ref = obj.borrow();
|
.and_then(|obj| {
|
||||||
let logicable = obj_ref
|
obj.map(|obj_ref| {
|
||||||
.as_logicable()
|
obj_ref
|
||||||
.ok_or(ICError::NotLogicable(obj_ref.get_id()))?;
|
.as_logicable()
|
||||||
if !logicable.can_slot_logic_read(logic_slot_type, slot_index) {
|
.ok_or(ICError::NotLogicable(*obj_ref.get_id()))
|
||||||
return Err(LogicError::CantSlotRead(logic_slot_type, slot_index).into());
|
.and_then(|logicable| {
|
||||||
}
|
if !logicable.can_slot_logic_read(logic_slot_type, slot_index) {
|
||||||
self.set_register(
|
Err(LogicError::CantSlotRead(logic_slot_type, slot_index).into())
|
||||||
indirection,
|
} else {
|
||||||
target,
|
logicable
|
||||||
logicable.get_slot_logic(logic_slot_type, slot_index)?,
|
.get_slot_logic(logic_slot_type, slot_index)
|
||||||
)?;
|
.map_err(Into::into)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})?;
|
||||||
|
self.set_register(indirection, target, val)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2430,66 +2488,70 @@ impl<T: IC10Marker> LrInstruction for T {
|
|||||||
let (device, connection) = d.as_device(self)?;
|
let (device, connection) = d.as_device(self)?;
|
||||||
let reagent_mode = reagent_mode.as_reagent_mode(self)?;
|
let reagent_mode = reagent_mode.as_reagent_mode(self)?;
|
||||||
let int = int.as_value(self)?;
|
let int = int.as_value(self)?;
|
||||||
let obj = self
|
let val = self
|
||||||
.get_circuit_holder()
|
.get_circuit_holder()
|
||||||
.ok_or(ICError::NoCircuitHolder(self.get_id()))?
|
.ok_or(ICError::NoCircuitHolder(*self.get_id()))?
|
||||||
.borrow()
|
.borrow()
|
||||||
.as_circuit_holder()
|
.as_circuit_holder()
|
||||||
.ok_or(ICError::CircuitHolderNotLogicable(self.get_id()))?
|
.ok_or(ICError::CircuitHolderNotLogicable(*self.get_id()))?
|
||||||
.get_logicable_from_index(device, connection)
|
.get_logicable_from_index(device, connection)
|
||||||
.ok_or(ICError::DeviceNotSet)?;
|
.ok_or(ICError::DeviceNotSet)
|
||||||
let obj_ref = obj.borrow();
|
.and_then(|obj| {
|
||||||
let logicable = obj_ref
|
obj.map(|obj_ref| {
|
||||||
.as_logicable()
|
obj_ref
|
||||||
.ok_or(ICError::NotLogicable(obj_ref.get_id()))?;
|
.as_logicable()
|
||||||
|
.ok_or(ICError::NotLogicable(*obj_ref.get_id()))
|
||||||
let result = match reagent_mode {
|
.and_then(|logicable| {
|
||||||
LogicReagentMode::Contents => {
|
let result = match reagent_mode {
|
||||||
let device = logicable
|
LogicReagentMode::Contents => {
|
||||||
.as_device()
|
let device = logicable
|
||||||
.ok_or(ICError::NotReagentReadable(logicable.get_id()))?;
|
.as_device()
|
||||||
device
|
.ok_or(ICError::NotReagentReadable(*logicable.get_id()))?;
|
||||||
.get_reagents()
|
device
|
||||||
.iter()
|
.get_reagents()
|
||||||
.find(|(hash, _)| *hash as f64 == int)
|
.iter()
|
||||||
.map(|(_, quantity)| *quantity)
|
.find(|(hash, _)| *hash as f64 == int)
|
||||||
.unwrap_or(0.0)
|
.map(|(_, quantity)| *quantity)
|
||||||
}
|
.unwrap_or(0.0)
|
||||||
LogicReagentMode::TotalContents => {
|
}
|
||||||
let device = logicable
|
LogicReagentMode::TotalContents => {
|
||||||
.as_device()
|
let device = logicable
|
||||||
.ok_or(ICError::NotReagentReadable(logicable.get_id()))?;
|
.as_device()
|
||||||
device
|
.ok_or(ICError::NotReagentReadable(*logicable.get_id()))?;
|
||||||
.get_reagents()
|
device
|
||||||
.iter()
|
.get_reagents()
|
||||||
.map(|(_, quantity)| quantity)
|
.iter()
|
||||||
.sum()
|
.map(|(_, quantity)| quantity)
|
||||||
}
|
.sum()
|
||||||
LogicReagentMode::Required => {
|
}
|
||||||
let reagent_interface = logicable
|
LogicReagentMode::Required => {
|
||||||
.as_reagent_interface()
|
let reagent_interface = logicable
|
||||||
.ok_or(ICError::NotReagentReadable(logicable.get_id()))?;
|
.as_reagent_interface()
|
||||||
reagent_interface
|
.ok_or(ICError::NotReagentReadable(*logicable.get_id()))?;
|
||||||
.get_current_required()
|
reagent_interface
|
||||||
.iter()
|
.get_current_required()
|
||||||
.find(|(hash, _)| *hash as f64 == int)
|
.iter()
|
||||||
.map(|(_, quantity)| *quantity)
|
.find(|(hash, _)| *hash as f64 == int)
|
||||||
.unwrap_or(0.0)
|
.map(|(_, quantity)| *quantity)
|
||||||
}
|
.unwrap_or(0.0)
|
||||||
LogicReagentMode::Recipe => {
|
}
|
||||||
let reagent_interface = logicable
|
LogicReagentMode::Recipe => {
|
||||||
.as_reagent_interface()
|
let reagent_interface = logicable
|
||||||
.ok_or(ICError::NotReagentReadable(logicable.get_id()))?;
|
.as_reagent_interface()
|
||||||
reagent_interface
|
.ok_or(ICError::NotReagentReadable(*logicable.get_id()))?;
|
||||||
.get_current_recipie()
|
reagent_interface
|
||||||
.iter()
|
.get_current_recipie()
|
||||||
.find(|(hash, _)| *hash as f64 == int)
|
.iter()
|
||||||
.map(|(_, quantity)| *quantity)
|
.find(|(hash, _)| *hash as f64 == int)
|
||||||
.unwrap_or(0.0)
|
.map(|(_, quantity)| *quantity)
|
||||||
}
|
.unwrap_or(0.0)
|
||||||
};
|
}
|
||||||
|
};
|
||||||
self.set_register(indirection, target, result)?;
|
Ok(result)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})?;
|
||||||
|
self.set_register(indirection, target, val)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2513,7 +2575,7 @@ impl<T: IC10Marker> LbInstruction for T {
|
|||||||
let batch_mode = batch_mode.as_batch_mode(self)?;
|
let batch_mode = batch_mode.as_batch_mode(self)?;
|
||||||
let val =
|
let val =
|
||||||
self.get_vm()
|
self.get_vm()
|
||||||
.get_batch_device_field(self.get_id(), prefab, logic_type, batch_mode)?;
|
.get_batch_device_field(*self.get_id(), prefab, logic_type, batch_mode)?;
|
||||||
self.set_register(indirection, target, val)?;
|
self.set_register(indirection, target, val)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -2539,7 +2601,7 @@ impl<T: IC10Marker> LbnInstruction for T {
|
|||||||
let logic_type = logic_type.as_logic_type(self)?;
|
let logic_type = logic_type.as_logic_type(self)?;
|
||||||
let batch_mode = batch_mode.as_batch_mode(self)?;
|
let batch_mode = batch_mode.as_batch_mode(self)?;
|
||||||
let val = self.get_vm().get_batch_name_device_field(
|
let val = self.get_vm().get_batch_name_device_field(
|
||||||
self.get_id(),
|
*self.get_id(),
|
||||||
prefab,
|
prefab,
|
||||||
name,
|
name,
|
||||||
logic_type,
|
logic_type,
|
||||||
@@ -2572,7 +2634,7 @@ impl<T: IC10Marker> LbnsInstruction for T {
|
|||||||
let logic_slot_type = logic_slot_type.as_slot_logic_type(self)?;
|
let logic_slot_type = logic_slot_type.as_slot_logic_type(self)?;
|
||||||
let batch_mode = batch_mode.as_batch_mode(self)?;
|
let batch_mode = batch_mode.as_batch_mode(self)?;
|
||||||
let val = self.get_vm().get_batch_name_device_slot_field(
|
let val = self.get_vm().get_batch_name_device_slot_field(
|
||||||
self.get_id(),
|
*self.get_id(),
|
||||||
prefab,
|
prefab,
|
||||||
name,
|
name,
|
||||||
slot_index,
|
slot_index,
|
||||||
@@ -2604,7 +2666,7 @@ impl<T: IC10Marker> LbsInstruction for T {
|
|||||||
let logic_slot_type = logic_slot_type.as_slot_logic_type(self)?;
|
let logic_slot_type = logic_slot_type.as_slot_logic_type(self)?;
|
||||||
let batch_mode = batch_mode.as_batch_mode(self)?;
|
let batch_mode = batch_mode.as_batch_mode(self)?;
|
||||||
let val = self.get_vm().get_batch_device_slot_field(
|
let val = self.get_vm().get_batch_device_slot_field(
|
||||||
self.get_id(),
|
*self.get_id(),
|
||||||
prefab,
|
prefab,
|
||||||
slot_index,
|
slot_index,
|
||||||
logic_slot_type,
|
logic_slot_type,
|
||||||
@@ -2618,12 +2680,14 @@ impl<T: IC10Marker> LbsInstruction for T {
|
|||||||
impl<T: IC10Marker> HcfInstruction for T {
|
impl<T: IC10Marker> HcfInstruction for T {
|
||||||
/// hcf
|
/// hcf
|
||||||
fn execute_inner(&mut self) -> Result<(), ICError> {
|
fn execute_inner(&mut self) -> Result<(), ICError> {
|
||||||
self.get_circuit_holder()
|
{
|
||||||
.ok_or(ICError::NoCircuitHolder(self.get_id()))?
|
self.get_circuit_holder()
|
||||||
.borrow_mut()
|
.ok_or(ICError::NoCircuitHolder(*self.get_id()))?
|
||||||
.as_mut_circuit_holder()
|
.borrow_mut()
|
||||||
.ok_or(ICError::CircuitHolderNotLogicable(self.get_id()))?
|
.as_mut_circuit_holder()
|
||||||
.hault_and_catch_fire();
|
.ok_or(ICError::CircuitHolderNotLogicable(*self.get_id()))?
|
||||||
|
.hault_and_catch_fire();
|
||||||
|
}
|
||||||
self.set_state(ICState::HasCaughtFire);
|
self.set_state(ICState::HasCaughtFire);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -235,11 +235,11 @@ impl Storage for CableNetwork {
|
|||||||
fn get_slot_mut(&mut self, _index: usize) -> Option<&mut crate::vm::object::Slot> {
|
fn get_slot_mut(&mut self, _index: usize) -> Option<&mut crate::vm::object::Slot> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
fn get_slots(&self) -> &[crate::vm::object::Slot] {
|
fn get_slots(&self) -> Vec<&crate::vm::object::Slot> {
|
||||||
&[]
|
vec![]
|
||||||
}
|
}
|
||||||
fn get_slots_mut(&mut self) -> &mut [crate::vm::object::Slot] {
|
fn get_slots_mut(&mut self) -> Vec<&mut crate::vm::object::Slot> {
|
||||||
&mut []
|
vec![]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -422,7 +422,7 @@ where
|
|||||||
impl From<NetworkRef<'_>> for FrozenCableNetwork {
|
impl From<NetworkRef<'_>> for FrozenCableNetwork {
|
||||||
fn from(value: NetworkRef) -> Self {
|
fn from(value: NetworkRef) -> Self {
|
||||||
FrozenCableNetwork {
|
FrozenCableNetwork {
|
||||||
id: value.get_id(),
|
id: *value.get_id(),
|
||||||
devices: value.get_devices(),
|
devices: value.get_devices(),
|
||||||
power_only: value.get_power_only(),
|
power_only: value.get_power_only(),
|
||||||
channels: *value.get_channel_data(),
|
channels: *value.get_channel_data(),
|
||||||
|
|||||||
@@ -617,7 +617,7 @@ impl VM {
|
|||||||
) -> Result<(), ICError> {
|
) -> Result<(), ICError> {
|
||||||
self.batch_device(source, prefab, None)
|
self.batch_device(source, prefab, None)
|
||||||
.map(|device| {
|
.map(|device| {
|
||||||
self.set_modified(device.borrow().get_id());
|
self.set_modified(*device.borrow().get_id());
|
||||||
device
|
device
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.as_mut_device()
|
.as_mut_device()
|
||||||
@@ -639,7 +639,7 @@ impl VM {
|
|||||||
) -> Result<(), ICError> {
|
) -> Result<(), ICError> {
|
||||||
self.batch_device(source, prefab, None)
|
self.batch_device(source, prefab, None)
|
||||||
.map(|device| {
|
.map(|device| {
|
||||||
self.set_modified(device.borrow().get_id());
|
self.set_modified(*device.borrow().get_id());
|
||||||
device
|
device
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.as_mut_device()
|
.as_mut_device()
|
||||||
@@ -661,7 +661,7 @@ impl VM {
|
|||||||
) -> Result<(), ICError> {
|
) -> Result<(), ICError> {
|
||||||
self.batch_device(source, prefab, Some(name))
|
self.batch_device(source, prefab, Some(name))
|
||||||
.map(|device| {
|
.map(|device| {
|
||||||
self.set_modified(device.borrow().get_id());
|
self.set_modified(*device.borrow().get_id());
|
||||||
device
|
device
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.as_mut_device()
|
.as_mut_device()
|
||||||
|
|||||||
@@ -41,11 +41,11 @@ impl<T: GWStorage + Object> Storage for T {
|
|||||||
fn get_slot_mut(&mut self, index: usize) -> Option<&mut Slot> {
|
fn get_slot_mut(&mut self, index: usize) -> Option<&mut Slot> {
|
||||||
self.slots_mut().get_mut(index)
|
self.slots_mut().get_mut(index)
|
||||||
}
|
}
|
||||||
fn get_slots(&self) -> &[Slot] {
|
fn get_slots(&self) -> Vec<&Slot> {
|
||||||
self.slots()
|
self.slots().iter().collect()
|
||||||
}
|
}
|
||||||
fn get_slots_mut(&mut self) -> &mut [Slot] {
|
fn get_slots_mut(&mut self) -> Vec<&mut Slot> {
|
||||||
self.slots_mut()
|
self.slots_mut().iter_mut().collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,57 +63,77 @@ impl<T: GWLogicable + Object> Logicable for T {
|
|||||||
self.get_name().hash
|
self.get_name().hash
|
||||||
}
|
}
|
||||||
fn is_logic_readable(&self) -> bool {
|
fn is_logic_readable(&self) -> bool {
|
||||||
LogicType::iter().any(|lt| self.can_logic_read(lt))
|
true
|
||||||
}
|
}
|
||||||
fn is_logic_writeable(&self) -> bool {
|
fn is_logic_writeable(&self) -> bool {
|
||||||
LogicType::iter().any(|lt| self.can_logic_write(lt))
|
LogicType::iter().any(|lt| self.can_logic_write(lt))
|
||||||
}
|
}
|
||||||
fn can_logic_read(&self, lt: LogicType) -> bool {
|
fn can_logic_read(&self, lt: LogicType) -> bool {
|
||||||
self.fields()
|
match lt {
|
||||||
.get(<)
|
LogicType::PrefabHash | LogicType::NameHash | LogicType::ReferenceId => true,
|
||||||
.map(|field| {
|
_ => self
|
||||||
matches!(
|
.fields()
|
||||||
field.field_type,
|
.get(<)
|
||||||
MemoryAccess::Read | MemoryAccess::ReadWrite
|
.map(|field| {
|
||||||
)
|
matches!(
|
||||||
})
|
field.field_type,
|
||||||
.unwrap_or(false)
|
MemoryAccess::Read | MemoryAccess::ReadWrite
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.unwrap_or(false),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fn can_logic_write(&self, lt: LogicType) -> bool {
|
fn can_logic_write(&self, lt: LogicType) -> bool {
|
||||||
self.fields()
|
match lt {
|
||||||
.get(<)
|
LogicType::PrefabHash | LogicType::NameHash | LogicType::ReferenceId => false,
|
||||||
.map(|field| {
|
_ => self
|
||||||
matches!(
|
.fields()
|
||||||
field.field_type,
|
.get(<)
|
||||||
MemoryAccess::Write | MemoryAccess::ReadWrite
|
.map(|field| {
|
||||||
)
|
matches!(
|
||||||
})
|
field.field_type,
|
||||||
.unwrap_or(false)
|
MemoryAccess::Write | MemoryAccess::ReadWrite
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.unwrap_or(false),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fn get_logic(&self, lt: LogicType) -> Result<f64, LogicError> {
|
fn get_logic(&self, lt: LogicType) -> Result<f64, LogicError> {
|
||||||
self.fields()
|
match lt {
|
||||||
.get(<)
|
LogicType::PrefabHash => Ok(self.get_prefab().hash as f64),
|
||||||
.and_then(|field| match field.field_type {
|
LogicType::NameHash => Ok(self.get_name().hash as f64),
|
||||||
MemoryAccess::Read | MemoryAccess::ReadWrite => Some(field.value),
|
LogicType::ReferenceId => Ok(*self.get_id() as f64),
|
||||||
_ => None,
|
_ => self
|
||||||
})
|
.fields()
|
||||||
.ok_or(LogicError::CantRead(lt))
|
.get(<)
|
||||||
|
.and_then(|field| match field.field_type {
|
||||||
|
MemoryAccess::Read | MemoryAccess::ReadWrite => Some(field.value),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.ok_or(LogicError::CantRead(lt)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fn set_logic(&mut self, lt: LogicType, value: f64, force: bool) -> Result<(), LogicError> {
|
fn set_logic(&mut self, lt: LogicType, value: f64, force: bool) -> Result<(), LogicError> {
|
||||||
self.fields_mut()
|
match lt {
|
||||||
.get_mut(<)
|
LogicType::PrefabHash | LogicType::NameHash | LogicType::ReferenceId => {
|
||||||
.ok_or(LogicError::CantWrite(lt))
|
Err(LogicError::CantWrite(lt))
|
||||||
.and_then(|field| match field.field_type {
|
}
|
||||||
MemoryAccess::Write | MemoryAccess::ReadWrite => {
|
_ => self
|
||||||
field.value = value;
|
.fields_mut()
|
||||||
Ok(())
|
.get_mut(<)
|
||||||
}
|
.ok_or(LogicError::CantWrite(lt))
|
||||||
_ if force => {
|
.and_then(|field| match field.field_type {
|
||||||
field.value = value;
|
MemoryAccess::Write | MemoryAccess::ReadWrite => {
|
||||||
Ok(())
|
field.value = value;
|
||||||
}
|
Ok(())
|
||||||
_ => Err(LogicError::CantWrite(lt)),
|
}
|
||||||
})
|
_ if force => {
|
||||||
|
field.value = value;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
_ => Err(LogicError::CantWrite(lt)),
|
||||||
|
}),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fn can_slot_logic_read(&self, slt: LogicSlotType, index: f64) -> bool {
|
fn can_slot_logic_read(&self, slt: LogicSlotType, index: f64) -> bool {
|
||||||
if index < 0.0 {
|
if index < 0.0 {
|
||||||
@@ -200,7 +220,7 @@ impl<T: GWLogicable + Object> Logicable for T {
|
|||||||
}
|
}
|
||||||
ReferenceId => {
|
ReferenceId => {
|
||||||
if let Some(occupant) = occupant {
|
if let Some(occupant) = occupant {
|
||||||
Ok(occupant.borrow().get_id() as f64)
|
Ok(*occupant.borrow().get_id() as f64)
|
||||||
} else {
|
} else {
|
||||||
Ok(0.0)
|
Ok(0.0)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ macro_rules! object_trait {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
(@body $trait_name:ident { $($trt:ident),* }; ) => {
|
(@body $trait_name:ident { $($trt:ident),* }; ) => {
|
||||||
fn get_id(&self) -> crate::vm::object::ObjectID;
|
fn get_id(&self) -> &crate::vm::object::ObjectID;
|
||||||
fn set_id(&mut self, id: crate::vm::object::ObjectID);
|
fn set_id(&mut self, id: crate::vm::object::ObjectID);
|
||||||
fn get_prefab(&self) -> &crate::vm::object::Name;
|
fn get_prefab(&self) -> &crate::vm::object::Name;
|
||||||
fn get_mut_prefab(&mut self) -> &mut crate::vm::object::Name;
|
fn get_mut_prefab(&mut self) -> &mut crate::vm::object::Name;
|
||||||
@@ -53,6 +53,74 @@ macro_rules! object_trait {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum [<$trait_name Ref>]<'a> {
|
||||||
|
DynRef(&'a dyn $trait_name),
|
||||||
|
VMObject(crate::vm::object::VMObject),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> [<$trait_name Ref>]<'a> {
|
||||||
|
pub fn from_ref(reference: &'a dyn $trait_name) -> Self {
|
||||||
|
Self::DynRef(reference)
|
||||||
|
}
|
||||||
|
pub fn from_vm_object(obj: crate::vm::object::VMObject) -> Self {
|
||||||
|
Self::VMObject(obj)
|
||||||
|
}
|
||||||
|
pub fn get_id(&self) -> u32 {
|
||||||
|
match self {
|
||||||
|
Self::DynRef(reference) => *reference.get_id(),
|
||||||
|
Self::VMObject(obj) => *obj.borrow().get_id(),
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// call func on the dyn refrence or a borrow of the vm object
|
||||||
|
pub fn map<F, R>(&self, mut func: F ) -> R
|
||||||
|
where
|
||||||
|
F: std::ops::FnMut(& dyn $trait_name) -> R
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
Self::DynRef(reference) => func(*reference),
|
||||||
|
Self::VMObject(obj) => {
|
||||||
|
let obj_ref = obj.borrow();
|
||||||
|
func(&*obj_ref)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum [<$trait_name RefMut>]<'a> {
|
||||||
|
DynRef(&'a mut dyn $trait_name),
|
||||||
|
VMObject(crate::vm::object::VMObject),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> [<$trait_name RefMut>]<'a> {
|
||||||
|
pub fn from_ref(reference: &'a mut dyn $trait_name) -> Self {
|
||||||
|
Self::DynRef(reference)
|
||||||
|
}
|
||||||
|
pub fn from_vm_object(obj: crate::vm::object::VMObject) -> Self {
|
||||||
|
Self::VMObject(obj)
|
||||||
|
}
|
||||||
|
pub fn get_id(&self) -> u32 {
|
||||||
|
match self {
|
||||||
|
Self::DynRef(refrence) => *refrence.get_id(),
|
||||||
|
Self::VMObject(obj) => *obj.borrow().get_id(),
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// call func on the dyn refrence or a borrow of the vm object
|
||||||
|
pub fn map<F, R>(&mut self, mut func: F ) -> R
|
||||||
|
where
|
||||||
|
F: std::ops::FnMut(&mut dyn $trait_name) -> R
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
Self::DynRef(reference) => func(*reference),
|
||||||
|
Self::VMObject(obj) => {
|
||||||
|
let mut obj_ref = obj.borrow_mut();
|
||||||
|
func(&mut *obj_ref)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
( $trait_name:ident $(: $($bound:tt)* )? {$($trt:ident),*}) => {
|
( $trait_name:ident $(: $($bound:tt)* )? {$($trt:ident),*}) => {
|
||||||
@@ -95,8 +163,8 @@ macro_rules! ObjectInterface {
|
|||||||
} => {
|
} => {
|
||||||
impl $trait_name for $struct {
|
impl $trait_name for $struct {
|
||||||
|
|
||||||
fn get_id(&self) -> crate::vm::object::ObjectID {
|
fn get_id(&self) -> &crate::vm::object::ObjectID {
|
||||||
self.$id_field
|
&self.$id_field
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_id(&mut self, id: crate::vm::object::ObjectID) {
|
fn set_id(&mut self, id: crate::vm::object::ObjectID) {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
mod integrated_circuit;
|
mod integrated_circuit;
|
||||||
|
mod circuit_holder;
|
||||||
|
|
||||||
pub use integrated_circuit::ItemIntegratedCircuit10;
|
pub use integrated_circuit::ItemIntegratedCircuit10;
|
||||||
|
|||||||
426
ic10emu/src/vm/object/stationpedia/structs/circuit_holder.rs
Normal file
426
ic10emu/src/vm/object/stationpedia/structs/circuit_holder.rs
Normal file
@@ -0,0 +1,426 @@
|
|||||||
|
use crate::{
|
||||||
|
network::{CableConnectionType, Connection, ConnectionRole},
|
||||||
|
vm::{
|
||||||
|
enums::{
|
||||||
|
basic_enums::Class as SlotClass,
|
||||||
|
prefabs::StationpediaPrefab,
|
||||||
|
script_enums::{LogicSlotType, LogicType},
|
||||||
|
},
|
||||||
|
object::{
|
||||||
|
errors::LogicError, macros::ObjectInterface, traits::*, Name, ObjectID, Slot, VMObject,
|
||||||
|
},
|
||||||
|
VM,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
use macro_rules_attribute::derive;
|
||||||
|
use std::rc::Rc;
|
||||||
|
use strum::EnumProperty;
|
||||||
|
|
||||||
|
#[derive(ObjectInterface!)]
|
||||||
|
#[custom(implements(Object { Structure, Device, Storage, Logicable, CircuitHolder }))]
|
||||||
|
pub struct StructureCircuitHousing {
|
||||||
|
#[custom(object_id)]
|
||||||
|
pub id: ObjectID,
|
||||||
|
#[custom(object_prefab)]
|
||||||
|
pub prefab: Name,
|
||||||
|
#[custom(object_name)]
|
||||||
|
pub name: Name,
|
||||||
|
#[custom(object_vm_ref)]
|
||||||
|
pub vm: Rc<VM>,
|
||||||
|
pub error: i32,
|
||||||
|
pub on: bool,
|
||||||
|
pub setting: f64,
|
||||||
|
pub slot: Slot,
|
||||||
|
pub pins: [Option<ObjectID>; 6],
|
||||||
|
pub connections: [crate::network::Connection; 2],
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
impl StructureCircuitHousing {
|
||||||
|
pub fn new(id: ObjectID, vm: Rc<VM>) -> Self {
|
||||||
|
StructureCircuitHousing {
|
||||||
|
id,
|
||||||
|
prefab: Name {
|
||||||
|
value: StationpediaPrefab::StructureCircuitHousing.to_string(),
|
||||||
|
hash: StationpediaPrefab::StructureCircuitHousing as i32,
|
||||||
|
},
|
||||||
|
name: Name::new(
|
||||||
|
StationpediaPrefab::StructureCircuitHousing
|
||||||
|
.get_str("name")
|
||||||
|
.unwrap(),
|
||||||
|
),
|
||||||
|
vm,
|
||||||
|
error: 0,
|
||||||
|
on: true,
|
||||||
|
setting: 0.0,
|
||||||
|
slot: Slot {
|
||||||
|
parent: id,
|
||||||
|
index: 0,
|
||||||
|
name: "Programmable Chip".to_string(),
|
||||||
|
typ: SlotClass::ProgrammableChip,
|
||||||
|
readable_logic: vec![
|
||||||
|
LogicSlotType::Class,
|
||||||
|
LogicSlotType::Damage,
|
||||||
|
LogicSlotType::LineNumber,
|
||||||
|
LogicSlotType::MaxQuantity,
|
||||||
|
LogicSlotType::OccupantHash,
|
||||||
|
LogicSlotType::Occupied,
|
||||||
|
LogicSlotType::PrefabHash,
|
||||||
|
LogicSlotType::Quantity,
|
||||||
|
LogicSlotType::ReferenceId,
|
||||||
|
LogicSlotType::SortingClass,
|
||||||
|
],
|
||||||
|
writeable_logic: vec![],
|
||||||
|
occupant: None,
|
||||||
|
quantity: 0,
|
||||||
|
},
|
||||||
|
pins: [None, None, None, None, None, None],
|
||||||
|
connections: [
|
||||||
|
Connection::CableNetwork {
|
||||||
|
net: None,
|
||||||
|
typ: CableConnectionType::Data,
|
||||||
|
role: ConnectionRole::Input,
|
||||||
|
},
|
||||||
|
Connection::CableNetwork {
|
||||||
|
net: None,
|
||||||
|
typ: CableConnectionType::Power,
|
||||||
|
role: ConnectionRole::None,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Structure for StructureCircuitHousing {
|
||||||
|
fn is_small_grid(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Storage for StructureCircuitHousing {
|
||||||
|
fn slots_count(&self) -> usize {
|
||||||
|
1
|
||||||
|
}
|
||||||
|
fn get_slot(&self, index: usize) -> Option<&Slot> {
|
||||||
|
if index != 0 {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(&self.slot)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn get_slot_mut(&mut self, index: usize) -> Option<&mut Slot> {
|
||||||
|
if index != 0 {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(&mut self.slot)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn get_slots(&self) -> Vec<&Slot> {
|
||||||
|
vec![&self.slot]
|
||||||
|
}
|
||||||
|
fn get_slots_mut(&mut self) -> Vec<&mut Slot> {
|
||||||
|
vec![&mut self.slot]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Logicable for StructureCircuitHousing {
|
||||||
|
fn prefab_hash(&self) -> i32 {
|
||||||
|
self.get_prefab().hash
|
||||||
|
}
|
||||||
|
fn name_hash(&self) -> i32 {
|
||||||
|
self.get_name().hash
|
||||||
|
}
|
||||||
|
fn is_logic_readable(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
fn is_logic_writeable(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
fn can_logic_read(&self, lt: LogicType) -> bool {
|
||||||
|
use LogicType::*;
|
||||||
|
matches!(lt, Error | LineNumber | NameHash | On | Power | PrefabHash | ReferenceId
|
||||||
|
| RequiredPower | Setting)
|
||||||
|
}
|
||||||
|
fn can_logic_write(&self, lt: LogicType) -> bool {
|
||||||
|
use LogicType::*;
|
||||||
|
matches!(lt, LineNumber | On | Setting)
|
||||||
|
}
|
||||||
|
fn get_logic(&self, lt: LogicType) -> Result<f64, LogicError> {
|
||||||
|
match lt {
|
||||||
|
LogicType::PrefabHash => Ok(self.get_prefab().hash as f64),
|
||||||
|
LogicType::NameHash => Ok(self.get_name().hash as f64),
|
||||||
|
LogicType::ReferenceId => Ok(*self.get_id() as f64),
|
||||||
|
LogicType::Error => Ok(self.error as f64),
|
||||||
|
LogicType::LineNumber => {
|
||||||
|
let result = self
|
||||||
|
.slot
|
||||||
|
.occupant
|
||||||
|
.and_then(|id| {
|
||||||
|
self.vm
|
||||||
|
.get_object(id)
|
||||||
|
.and_then(|obj| {
|
||||||
|
obj.borrow()
|
||||||
|
.as_logicable()
|
||||||
|
.map(|logicable| logicable.get_logic(LogicType::LineNumber))
|
||||||
|
})
|
||||||
|
});
|
||||||
|
result.unwrap_or(Ok(0.0))
|
||||||
|
}
|
||||||
|
LogicType::On => Ok(self.on as i32 as f64),
|
||||||
|
LogicType::Power => {
|
||||||
|
if let Connection::CableNetwork { net, .. } = self.connections[1] {
|
||||||
|
if net.is_some() {
|
||||||
|
Ok(1.0)
|
||||||
|
} else {
|
||||||
|
Ok(0.0)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Ok(0.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LogicType::RequiredPower => {
|
||||||
|
if let Connection::CableNetwork { net, .. } = self.connections[1] {
|
||||||
|
if net.is_some() {
|
||||||
|
if self.on {
|
||||||
|
Ok(10.0)
|
||||||
|
} else {
|
||||||
|
Ok(0.0)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Ok(-1.0)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Ok(-1.0)
|
||||||
|
}
|
||||||
|
} // 10 if on
|
||||||
|
LogicType::Setting => Ok(self.setting),
|
||||||
|
_ => Err(LogicError::CantRead(lt)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn set_logic(&mut self, lt: LogicType, value: f64, force: bool) -> Result<(), LogicError> {
|
||||||
|
match lt {
|
||||||
|
LogicType::LineNumber => self
|
||||||
|
.slot
|
||||||
|
.occupant
|
||||||
|
.and_then(|id| {
|
||||||
|
self.vm
|
||||||
|
.get_object(id)
|
||||||
|
.and_then(|obj| {
|
||||||
|
obj.borrow_mut().as_mut_logicable().map(|logicable| {
|
||||||
|
logicable.set_logic(LogicType::LineNumber, value, force)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.unwrap_or(Err(LogicError::CantWrite(lt))),
|
||||||
|
LogicType::On => {
|
||||||
|
self.on = value != 0.0;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
LogicType::Setting => {
|
||||||
|
self.setting = value;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
_ => Err(LogicError::CantWrite(lt)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn can_slot_logic_read(&self, _slt: LogicSlotType, _indexx: f64) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
fn get_slot_logic(&self, _slt: LogicSlotType, index: f64) -> Result<f64, LogicError> {
|
||||||
|
Err(LogicError::SlotIndexOutOfRange(index, self.slots_count()))
|
||||||
|
}
|
||||||
|
fn valid_logic_types(&self) -> Vec<LogicType> {
|
||||||
|
use LogicType::*;
|
||||||
|
vec![
|
||||||
|
Error,
|
||||||
|
LineNumber,
|
||||||
|
NameHash,
|
||||||
|
On,
|
||||||
|
Power,
|
||||||
|
PrefabHash,
|
||||||
|
ReferenceId,
|
||||||
|
RequiredPower,
|
||||||
|
Setting,
|
||||||
|
]
|
||||||
|
}
|
||||||
|
fn known_modes(&self) -> Option<Vec<(u32, String)>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Device for StructureCircuitHousing {
|
||||||
|
fn has_reagents(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
fn has_atmosphere(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
fn has_lock_state(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
fn has_mode_state(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
fn has_open_state(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
fn has_color_state(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
fn has_activate_state(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
fn has_on_off_state(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
fn get_reagents(&self) -> Vec<(i32, f64)> {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
fn set_reagents(&mut self, _reagents: &[(i32, f64)]) {
|
||||||
|
// nope
|
||||||
|
}
|
||||||
|
fn add_reagents(&mut self, _reagents: &[(i32, f64)]) {
|
||||||
|
// nope
|
||||||
|
}
|
||||||
|
fn connection_list(&self) -> &[crate::network::Connection] {
|
||||||
|
&self.connections
|
||||||
|
}
|
||||||
|
fn connection_list_mut(&mut self) -> &mut [crate::network::Connection] {
|
||||||
|
&mut self.connections
|
||||||
|
}
|
||||||
|
fn device_pins(&self) -> Option<&[Option<ObjectID>]> {
|
||||||
|
Some(&self.pins)
|
||||||
|
}
|
||||||
|
fn device_pins_mut(&mut self) -> Option<&mut [Option<ObjectID>]> {
|
||||||
|
Some(&mut self.pins)
|
||||||
|
}
|
||||||
|
fn can_slot_logic_write(&self, _slt: LogicSlotType, _index: f64) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
fn set_slot_logic(
|
||||||
|
&mut self,
|
||||||
|
slt: LogicSlotType,
|
||||||
|
index: f64,
|
||||||
|
_value: f64,
|
||||||
|
_force: bool,
|
||||||
|
) -> Result<(), LogicError> {
|
||||||
|
Err(LogicError::CantSlotWrite(slt, index))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CircuitHolder for StructureCircuitHousing {
|
||||||
|
fn clear_error(&mut self) {
|
||||||
|
self.error = 0
|
||||||
|
}
|
||||||
|
fn set_error(&mut self, state: i32) {
|
||||||
|
self.error = state;
|
||||||
|
}
|
||||||
|
/// i32::MAX is db
|
||||||
|
fn get_logicable_from_index(
|
||||||
|
&self,
|
||||||
|
device: i32,
|
||||||
|
connection: Option<usize>,
|
||||||
|
) -> Option<ObjectRef> {
|
||||||
|
if device == i32::MAX {
|
||||||
|
// self
|
||||||
|
if let Some(connection) = connection {
|
||||||
|
self.connections.get(connection).and_then(|conn| {
|
||||||
|
if let Connection::CableNetwork { net: Some(net), .. } = conn {
|
||||||
|
self.vm
|
||||||
|
.get_network(*net)
|
||||||
|
.map(ObjectRef::from_vm_object)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Some(ObjectRef::from_ref(self.as_object()))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if device < 0 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
self.pins.get(device as usize).and_then(|pin| {
|
||||||
|
pin.and_then(|id| {
|
||||||
|
self.vm
|
||||||
|
.get_object(id).map(ObjectRef::from_vm_object)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// i32::MAX is db
|
||||||
|
fn get_logicable_from_index_mut(
|
||||||
|
&mut self,
|
||||||
|
device: i32,
|
||||||
|
connection: Option<usize>,
|
||||||
|
) -> Option<ObjectRefMut> {
|
||||||
|
if device == i32::MAX {
|
||||||
|
// self
|
||||||
|
if let Some(connection) = connection {
|
||||||
|
self.connections.get(connection).and_then(|conn| {
|
||||||
|
if let Connection::CableNetwork { net: Some(net), .. } = conn {
|
||||||
|
self.vm
|
||||||
|
.get_network(*net)
|
||||||
|
.map(ObjectRefMut::from_vm_object)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Some(ObjectRefMut::from_ref(self.as_mut_object()))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if device < 0 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
self.pins.get(device as usize).and_then(|pin| {
|
||||||
|
pin.and_then(|id| {
|
||||||
|
self.vm
|
||||||
|
.get_object(id).map(ObjectRefMut::from_vm_object)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_logicable_from_id(
|
||||||
|
&self,
|
||||||
|
device: ObjectID,
|
||||||
|
connection: Option<usize>,
|
||||||
|
) -> Option<ObjectRef> {
|
||||||
|
if connection.is_some() {
|
||||||
|
return None; // this functionality is disabled in the game, no network access via ReferenceId
|
||||||
|
}
|
||||||
|
if device == self.id {
|
||||||
|
return Some(ObjectRef::from_ref(self.as_object()));
|
||||||
|
}
|
||||||
|
self.vm
|
||||||
|
.get_object(device).map(ObjectRef::from_vm_object)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_logicable_from_id_mut(
|
||||||
|
&mut self,
|
||||||
|
device: ObjectID,
|
||||||
|
connection: Option<usize>,
|
||||||
|
) -> Option<ObjectRefMut> {
|
||||||
|
if connection.is_some() {
|
||||||
|
return None; // this functionality is disabled in the game, no network access via ReferenceId
|
||||||
|
}
|
||||||
|
if device == self.id {
|
||||||
|
return Some(ObjectRefMut::from_ref(self.as_mut_object()));
|
||||||
|
}
|
||||||
|
self.vm
|
||||||
|
.get_object(device).map(ObjectRefMut::from_vm_object)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_ic(&self) -> Option<VMObject> {
|
||||||
|
self.slot.occupant.and_then(|id| self.vm.get_object(id))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_ic_mut(&self) -> Option<VMObject> {
|
||||||
|
self.slot.occupant.and_then(|id| self.vm.get_object(id))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn hault_and_catch_fire(&mut self) {
|
||||||
|
// TODO: do something here??
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -97,11 +97,11 @@ impl Storage for ItemIntegratedCircuit10 {
|
|||||||
fn get_slot_mut(&mut self, _index: usize) -> Option<&mut Slot> {
|
fn get_slot_mut(&mut self, _index: usize) -> Option<&mut Slot> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
fn get_slots(&self) -> &[Slot] {
|
fn get_slots(&self) -> Vec<&Slot> {
|
||||||
&[]
|
vec![]
|
||||||
}
|
}
|
||||||
fn get_slots_mut(&mut self) -> &mut [Slot] {
|
fn get_slots_mut(&mut self) -> Vec<&mut Slot> {
|
||||||
&mut []
|
vec![]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,11 +165,11 @@ impl Logicable for ItemIntegratedCircuit10 {
|
|||||||
_ => Err(LogicError::CantWrite(lt)),
|
_ => Err(LogicError::CantWrite(lt)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
fn can_slot_logic_read(&self, _slt: LogicSlotType,_indexx: f64) -> bool {
|
fn can_slot_logic_read(&self, _slt: LogicSlotType, _indexx: f64) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
fn get_slot_logic(&self, _slt: LogicSlotType, index: f64) -> Result<f64, LogicError> {
|
fn get_slot_logic(&self, _slt: LogicSlotType, index: f64) -> Result<f64, LogicError> {
|
||||||
return Err(LogicError::SlotIndexOutOfRange(index, self.slots_count()));
|
Err(LogicError::SlotIndexOutOfRange(index, self.slots_count()))
|
||||||
}
|
}
|
||||||
fn valid_logic_types(&self) -> Vec<LogicType> {
|
fn valid_logic_types(&self) -> Vec<LogicType> {
|
||||||
self.fields.keys().copied().collect()
|
self.fields.keys().copied().collect()
|
||||||
@@ -235,8 +235,7 @@ impl SourceCode for ItemIntegratedCircuit10 {
|
|||||||
impl IntegratedCircuit for ItemIntegratedCircuit10 {
|
impl IntegratedCircuit for ItemIntegratedCircuit10 {
|
||||||
fn get_circuit_holder(&self) -> Option<VMObject> {
|
fn get_circuit_holder(&self) -> Option<VMObject> {
|
||||||
self.get_parent_slot()
|
self.get_parent_slot()
|
||||||
.map(|parent_slot| self.get_vm().get_object(parent_slot.parent))
|
.and_then(|parent_slot| self.get_vm().get_object(parent_slot.parent))
|
||||||
.flatten()
|
|
||||||
}
|
}
|
||||||
fn get_instruction_pointer(&self) -> f64 {
|
fn get_instruction_pointer(&self) -> f64 {
|
||||||
self.ip as f64
|
self.ip as f64
|
||||||
@@ -371,7 +370,7 @@ impl IC10Marker for ItemIntegratedCircuit10 {}
|
|||||||
|
|
||||||
impl Programmable for ItemIntegratedCircuit10 {
|
impl Programmable for ItemIntegratedCircuit10 {
|
||||||
fn step(&mut self, advance_ip_on_err: bool) -> Result<(), crate::errors::ICError> {
|
fn step(&mut self, advance_ip_on_err: bool) -> Result<(), crate::errors::ICError> {
|
||||||
if matches!(&self.state, ICState::HasCaughtFire ) {
|
if matches!(&self.state, ICState::HasCaughtFire) {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
if matches!(&self.state, ICState::Error(_)) && !advance_ip_on_err {
|
if matches!(&self.state, ICState::Error(_)) && !advance_ip_on_err {
|
||||||
@@ -394,7 +393,7 @@ impl Programmable for ItemIntegratedCircuit10 {
|
|||||||
return Err(ICError::SleepDurationError(*sleep_for));
|
return Err(ICError::SleepDurationError(*sleep_for));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if self.ip >= self.program.len() || self.program.len() == 0 {
|
if self.ip >= self.program.len() || self.program.is_empty() {
|
||||||
self.state = ICState::Ended;
|
self.state = ICState::Ended;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
@@ -403,17 +402,34 @@ impl Programmable for ItemIntegratedCircuit10 {
|
|||||||
let line = self.program.get_line(self.ip)?.clone();
|
let line = self.program.get_line(self.ip)?.clone();
|
||||||
let operands = &line.operands;
|
let operands = &line.operands;
|
||||||
let instruction = line.instruction;
|
let instruction = line.instruction;
|
||||||
instruction.execute(self, operands)?;
|
let result = instruction.execute(self, operands);
|
||||||
self.ip = self.next_ip;
|
|
||||||
if self.ip >= self.program.len() {
|
let was_error = if let Err(_err) = result {
|
||||||
self.state = ICState::Ended;
|
self.get_circuit_holder()
|
||||||
|
.ok_or(ICError::NoCircuitHolder(self.id))?
|
||||||
|
.borrow_mut()
|
||||||
|
.as_mut_circuit_holder()
|
||||||
|
.ok_or(ICError::CircuitHolderNotLogicable(self.id))?
|
||||||
|
.set_error(1);
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
};
|
||||||
|
|
||||||
|
if !was_error || advance_ip_on_err {
|
||||||
|
self.ip = self.next_ip;
|
||||||
|
if self.ip >= self.program.len() {
|
||||||
|
self.state = ICState::Ended;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.get_circuit_holder()
|
self.get_circuit_holder()
|
||||||
.ok_or(ICError::NoCircuitHolder(self.id))?
|
.ok_or(ICError::NoCircuitHolder(self.id))?
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.as_mut_logicable()
|
.as_mut_logicable()
|
||||||
.ok_or(ICError::CircuitHolderNotLogicable(self.id))?
|
.ok_or(ICError::CircuitHolderNotLogicable(self.id))?
|
||||||
.set_logic(LogicType::LineNumber, self.ip as f64, true)?;
|
.set_logic(LogicType::LineNumber, self.ip as f64, true)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1167,7 +1167,7 @@ impl ObjectTemplate {
|
|||||||
logic: logic.into(),
|
logic: logic.into(),
|
||||||
memory: mem_r.into(),
|
memory: mem_r.into(),
|
||||||
})),
|
})),
|
||||||
_ => Err(TemplateError::NonConformingObject(obj_ref.get_id())),
|
_ => Err(TemplateError::NonConformingObject(*obj_ref.get_id())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1243,7 +1243,7 @@ impl From<&VMObject> for ObjectInfo {
|
|||||||
let obj_ref = obj.borrow();
|
let obj_ref = obj.borrow();
|
||||||
ObjectInfo {
|
ObjectInfo {
|
||||||
name: Some(obj_ref.get_name().value.clone()),
|
name: Some(obj_ref.get_name().value.clone()),
|
||||||
id: Some(obj_ref.get_id()),
|
id: Some(*obj_ref.get_id()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ pub struct ParentSlotInfo {
|
|||||||
pub parent: ObjectID,
|
pub parent: ObjectID,
|
||||||
pub slot: usize,
|
pub slot: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
tag_object_traits! {
|
tag_object_traits! {
|
||||||
#![object_trait(Object: Debug)]
|
#![object_trait(Object: Debug)]
|
||||||
|
|
||||||
@@ -34,8 +33,8 @@ tag_object_traits! {
|
|||||||
fn slots_count(&self) -> usize;
|
fn slots_count(&self) -> usize;
|
||||||
fn get_slot(&self, index: usize) -> Option<&Slot>;
|
fn get_slot(&self, index: usize) -> Option<&Slot>;
|
||||||
fn get_slot_mut(&mut self, index: usize) -> Option<&mut Slot>;
|
fn get_slot_mut(&mut self, index: usize) -> Option<&mut Slot>;
|
||||||
fn get_slots(&self) -> &[Slot];
|
fn get_slots(&self) -> Vec<&Slot>;
|
||||||
fn get_slots_mut(&mut self) -> &mut [Slot];
|
fn get_slots_mut(&mut self) -> Vec<&mut Slot>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait MemoryReadable {
|
pub trait MemoryReadable {
|
||||||
@@ -80,16 +79,25 @@ tag_object_traits! {
|
|||||||
&self,
|
&self,
|
||||||
device: i32,
|
device: i32,
|
||||||
connection: Option<usize>,
|
connection: Option<usize>,
|
||||||
) -> Option<VMObject>;
|
) -> Option<ObjectRef>;
|
||||||
/// i32::MAX is db
|
/// i32::MAX is db
|
||||||
|
fn get_logicable_from_index_mut(
|
||||||
|
&mut self,
|
||||||
|
device: i32,
|
||||||
|
connection: Option<usize>,
|
||||||
|
) -> Option<ObjectRefMut>;
|
||||||
fn get_logicable_from_id(
|
fn get_logicable_from_id(
|
||||||
&self,
|
&self,
|
||||||
device: ObjectID,
|
device: ObjectID,
|
||||||
connection: Option<usize>,
|
connection: Option<usize>,
|
||||||
) -> Option<VMObject>;
|
) -> Option<ObjectRef>;
|
||||||
fn get_source_code(&self) -> String;
|
fn get_logicable_from_id_mut(
|
||||||
fn set_source_code(&self, code: String);
|
&mut self,
|
||||||
fn get_ic(&self) -> Option<ObjectID>;
|
device: ObjectID,
|
||||||
|
connection: Option<usize>,
|
||||||
|
) -> Option<ObjectRefMut>;
|
||||||
|
fn get_ic(&self) -> Option<VMObject>;
|
||||||
|
fn get_ic_mut(&self) -> Option<VMObject>;
|
||||||
fn hault_and_catch_fire(&mut self);
|
fn hault_and_catch_fire(&mut self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user