refactor(vm): impl circuit holder, impl ObjectRef/Mut

This commit is contained in:
Rachel Powers
2024-05-18 04:11:38 -07:00
parent cc6cc355dc
commit 29ef54ca04
11 changed files with 952 additions and 344 deletions

View File

@@ -77,6 +77,11 @@ impl Program {
self.instructions.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn try_from_code(code: &str) -> Result<Self, ICError> {
let parse_tree = grammar::parse(code)?;
let mut labels_set = HashSet::new();

View File

@@ -865,10 +865,10 @@ impl<T: IC10Marker> BdseInstruction for T {
let a = a.as_value(self)?;
if self
.get_circuit_holder()
.ok_or(ICError::NoCircuitHolder(self.get_id()))?
.ok_or(ICError::NoCircuitHolder(*self.get_id()))?
.borrow()
.as_circuit_holder()
.ok_or(ICError::CircuitHolderNotLogicable(self.get_id()))?
.ok_or(ICError::CircuitHolderNotLogicable(*self.get_id()))?
.get_logicable_from_index(device, connection)
.is_some()
{
@@ -885,10 +885,10 @@ impl<T: IC10Marker> BdsealInstruction for T {
let a = a.as_value(self)?;
if self
.get_circuit_holder()
.ok_or(ICError::NoCircuitHolder(self.get_id()))?
.ok_or(ICError::NoCircuitHolder(*self.get_id()))?
.borrow()
.as_circuit_holder()
.ok_or(ICError::CircuitHolderNotLogicable(self.get_id()))?
.ok_or(ICError::CircuitHolderNotLogicable(*self.get_id()))?
.get_logicable_from_index(device, connection)
.is_some()
{
@@ -906,10 +906,10 @@ impl<T: IC10Marker> BrdseInstruction for T {
let a = a.as_value(self)?;
if self
.get_circuit_holder()
.ok_or(ICError::NoCircuitHolder(self.get_id()))?
.ok_or(ICError::NoCircuitHolder(*self.get_id()))?
.borrow()
.as_circuit_holder()
.ok_or(ICError::CircuitHolderNotLogicable(self.get_id()))?
.ok_or(ICError::CircuitHolderNotLogicable(*self.get_id()))?
.get_logicable_from_index(device, connection)
.is_some()
{
@@ -926,10 +926,10 @@ impl<T: IC10Marker> BdnsInstruction for T {
let a = a.as_value(self)?;
if self
.get_circuit_holder()
.ok_or(ICError::NoCircuitHolder(self.get_id()))?
.ok_or(ICError::NoCircuitHolder(*self.get_id()))?
.borrow()
.as_circuit_holder()
.ok_or(ICError::CircuitHolderNotLogicable(self.get_id()))?
.ok_or(ICError::CircuitHolderNotLogicable(*self.get_id()))?
.get_logicable_from_index(device, connection)
.is_none()
{
@@ -946,10 +946,10 @@ impl<T: IC10Marker> BdnsalInstruction for T {
let a = a.as_value(self)?;
if self
.get_circuit_holder()
.ok_or(ICError::NoCircuitHolder(self.get_id()))?
.ok_or(ICError::NoCircuitHolder(*self.get_id()))?
.borrow()
.as_circuit_holder()
.ok_or(ICError::CircuitHolderNotLogicable(self.get_id()))?
.ok_or(ICError::CircuitHolderNotLogicable(*self.get_id()))?
.get_logicable_from_index(device, connection)
.is_none()
{
@@ -967,10 +967,10 @@ impl<T: IC10Marker> BrdnsInstruction for T {
let a = a.as_value(self)?;
if self
.get_circuit_holder()
.ok_or(ICError::NoCircuitHolder(self.get_id()))?
.ok_or(ICError::NoCircuitHolder(*self.get_id()))?
.borrow()
.as_circuit_holder()
.ok_or(ICError::CircuitHolderNotLogicable(self.get_id()))?
.ok_or(ICError::CircuitHolderNotLogicable(*self.get_id()))?
.get_logicable_from_index(device, connection)
.is_none()
{
@@ -1341,14 +1341,16 @@ impl<T: IC10Marker> SdseInstruction for T {
target,
} = r.as_register(self)?;
let (device, connection) = d.as_device(self)?;
let obj = self
.get_circuit_holder()
.ok_or(ICError::NoCircuitHolder(self.get_id()))?
.borrow()
.as_circuit_holder()
.ok_or(ICError::CircuitHolderNotLogicable(self.get_id()))?
.get_logicable_from_index(device, connection);
self.set_register(indirection, target, if obj.is_some() { 1.0 } else { 0.0 })?;
let is_some = {
self.get_circuit_holder()
.ok_or(ICError::NoCircuitHolder(*self.get_id()))?
.borrow()
.as_circuit_holder()
.ok_or(ICError::CircuitHolderNotLogicable(*self.get_id()))?
.get_logicable_from_index(device, connection)
.is_some()
};
self.set_register(indirection, target, if is_some { 1.0 } else { 0.0 })?;
Ok(())
}
}
@@ -1360,14 +1362,16 @@ impl<T: IC10Marker> SdnsInstruction for T {
target,
} = r.as_register(self)?;
let (device, connection) = d.as_device(self)?;
let obj = self
.get_circuit_holder()
.ok_or(ICError::NoCircuitHolder(self.get_id()))?
.borrow()
.as_circuit_holder()
.ok_or(ICError::CircuitHolderNotLogicable(self.get_id()))?
.get_logicable_from_index(device, connection);
self.set_register(indirection, target, if obj.is_none() { 1.0 } else { 0.0 })?;
let is_none = {
self.get_circuit_holder()
.ok_or(ICError::NoCircuitHolder(*self.get_id()))?
.borrow()
.as_circuit_holder()
.ok_or(ICError::CircuitHolderNotLogicable(*self.get_id()))?
.get_logicable_from_index(device, connection)
.is_none()
};
self.set_register(indirection, target, if is_none { 1.0 } else { 0.0 })?;
Ok(())
}
}
@@ -1988,19 +1992,22 @@ impl<T: IC10Marker> GetInstruction for T {
} = r.as_register(self)?;
let address = address.as_value(self)?;
let (device, connection) = d.as_device(self)?;
let obj = self
.get_circuit_holder()
.ok_or(ICError::NoCircuitHolder(self.get_id()))?
self.get_circuit_holder()
.ok_or(ICError::NoCircuitHolder(*self.get_id()))?
.borrow()
.as_circuit_holder()
.ok_or(ICError::CircuitHolderNotLogicable(self.get_id()))?
.ok_or(ICError::CircuitHolderNotLogicable(*self.get_id()))?
.get_logicable_from_index(device, connection)
.ok_or(ICError::DeviceNotSet)?;
let obj_ref = obj.borrow();
let memory = obj_ref
.as_memory_readable()
.ok_or(MemoryError::NotReadable)?;
self.set_register(indirection, target, memory.get_memory(address as i32)?)?;
.ok_or(ICError::DeviceNotSet)
.and_then(|obj| {
obj.map(|obj_ref| {
let val = obj_ref
.as_memory_readable()
.ok_or(MemoryError::NotWriteable)?
.get_memory(address as i32)?;
self.set_register(indirection, target, val)
})
})?;
Ok(())
}
}
@@ -2019,19 +2026,22 @@ impl<T: IC10Marker> GetdInstruction for T {
} = r.as_register(self)?;
let id = id.as_value(self)?;
let address = address.as_value(self)?;
let obj = self
.get_circuit_holder()
.ok_or(ICError::NoCircuitHolder(self.get_id()))?
self.get_circuit_holder()
.ok_or(ICError::NoCircuitHolder(*self.get_id()))?
.borrow()
.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)
.ok_or(ICError::DeviceNotSet)?;
let obj_ref = obj.borrow();
let memory = obj_ref
.as_memory_readable()
.ok_or(MemoryError::NotReadable)?;
self.set_register(indirection, target, memory.get_memory(address as i32)?)?;
.ok_or(ICError::DeviceNotSet)
.and_then(|obj| {
obj.map(|obj_ref| {
let val = obj_ref
.as_memory_readable()
.ok_or(MemoryError::NotWriteable)?
.get_memory(address as i32)?;
self.set_register(indirection, target, val)
})
})?;
Ok(())
}
}
@@ -2047,19 +2057,22 @@ impl<T: IC10Marker> PutInstruction for T {
let (device, connection) = d.as_device(self)?;
let address = address.as_value(self)?;
let value = value.as_value(self)?;
let obj = self
.get_circuit_holder()
.ok_or(ICError::NoCircuitHolder(self.get_id()))?
.borrow()
.as_circuit_holder()
.ok_or(ICError::CircuitHolderNotLogicable(self.get_id()))?
.get_logicable_from_index(device, connection)
.ok_or(ICError::DeviceNotSet)?;
let mut obj_ref = obj.borrow_mut();
let memory = obj_ref
.as_mut_memory_writable()
.ok_or(MemoryError::NotWriteable)?;
memory.set_memory(address as i32, value)?;
self.get_circuit_holder()
.ok_or(ICError::NoCircuitHolder(*self.get_id()))?
.borrow_mut()
.as_mut_circuit_holder()
.ok_or(ICError::CircuitHolderNotLogicable(*self.get_id()))?
.get_logicable_from_index_mut(device, connection)
.ok_or(ICError::DeviceNotSet)
.and_then(|mut obj| {
obj.map(|obj_ref| {
obj_ref
.as_mut_memory_writable()
.ok_or(MemoryError::NotWriteable)?
.set_memory(address as i32, value)
.map_err(Into::into)
})
})?;
Ok(())
}
}
@@ -2075,19 +2088,22 @@ impl<T: IC10Marker> PutdInstruction for T {
let id = id.as_value(self)?;
let address = address.as_value(self)?;
let value = value.as_value(self)?;
let obj = self
.get_circuit_holder()
.ok_or(ICError::NoCircuitHolder(self.get_id()))?
.borrow()
.as_circuit_holder()
.ok_or(ICError::CircuitHolderNotLogicable(self.get_id()))?
.get_logicable_from_id(id as ObjectID, None)
.ok_or(ICError::DeviceNotSet)?;
let mut obj_ref = obj.borrow_mut();
let memory = obj_ref
.as_mut_memory_writable()
.ok_or(MemoryError::NotWriteable)?;
memory.set_memory(address as i32, value)?;
self.get_circuit_holder()
.ok_or(ICError::NoCircuitHolder(*self.get_id()))?
.borrow_mut()
.as_mut_circuit_holder()
.ok_or(ICError::CircuitHolderNotLogicable(*self.get_id()))?
.get_logicable_from_id_mut(id as ObjectID, None)
.ok_or(ICError::DeviceNotSet)
.and_then(|mut obj| {
obj.map(|obj_ref| {
obj_ref
.as_mut_memory_writable()
.ok_or(MemoryError::NotWriteable)?
.set_memory(address as i32, value)
.map_err(Into::into)
})
})?;
Ok(())
}
}
@@ -2096,19 +2112,22 @@ impl<T: IC10Marker> ClrInstruction for T {
/// clr d?
fn execute_inner(&mut self, d: &InstOperand) -> Result<(), ICError> {
let (device, connection) = d.as_device(self)?;
let obj = self
.get_circuit_holder()
.ok_or(ICError::NoCircuitHolder(self.get_id()))?
.borrow()
.as_circuit_holder()
.ok_or(ICError::CircuitHolderNotLogicable(self.get_id()))?
.get_logicable_from_index(device, connection)
.ok_or(ICError::DeviceNotSet)?;
let mut obj_ref = obj.borrow_mut();
let memory = obj_ref
.as_mut_memory_writable()
.ok_or(MemoryError::NotWriteable)?;
memory.clear_memory()?;
self.get_circuit_holder()
.ok_or(ICError::NoCircuitHolder(*self.get_id()))?
.borrow_mut()
.as_mut_circuit_holder()
.ok_or(ICError::CircuitHolderNotLogicable(*self.get_id()))?
.get_logicable_from_index_mut(device, connection)
.ok_or(ICError::DeviceNotSet)
.and_then(|mut obj| {
obj.map(|obj_ref| {
obj_ref
.as_mut_memory_writable()
.ok_or(MemoryError::NotWriteable)?
.clear_memory()
.map_err(Into::into)
})
})?;
Ok(())
}
}
@@ -2116,19 +2135,22 @@ impl<T: IC10Marker> ClrdInstruction for T {
/// clrd id(r?|num)
fn execute_inner(&mut self, id: &InstOperand) -> Result<(), ICError> {
let id = id.as_value(self)?;
let obj = self
.get_circuit_holder()
.ok_or(ICError::NoCircuitHolder(self.get_id()))?
.borrow()
.as_circuit_holder()
.ok_or(ICError::CircuitHolderNotLogicable(self.get_id()))?
.get_logicable_from_id(id as ObjectID, None)
.ok_or(ICError::DeviceNotSet)?;
let mut obj_ref = obj.borrow_mut();
let memory = obj_ref
.as_mut_memory_writable()
.ok_or(MemoryError::NotWriteable)?;
memory.clear_memory()?;
self.get_circuit_holder()
.ok_or(ICError::NoCircuitHolder(*self.get_id()))?
.borrow_mut()
.as_mut_circuit_holder()
.ok_or(ICError::CircuitHolderNotLogicable(*self.get_id()))?
.get_logicable_from_id_mut(id as ObjectID, None)
.ok_or(ICError::DeviceNotSet)
.and_then(|mut obj| {
obj.map(|obj_ref| {
obj_ref
.as_mut_memory_writable()
.ok_or(MemoryError::NotWriteable)?
.clear_memory()
.map_err(Into::into)
})
})?;
Ok(())
}
}
@@ -2144,23 +2166,30 @@ impl<T: IC10Marker> SInstruction for T {
let (device, connection) = d.as_device(self)?;
let logic_type = logic_type.as_logic_type(self)?;
let val = r.as_value(self)?;
let obj = self
.get_circuit_holder()
.ok_or(ICError::NoCircuitHolder(self.get_id()))?
.borrow()
.as_circuit_holder()
.ok_or(ICError::CircuitHolderNotLogicable(self.get_id()))?
.get_logicable_from_index(device, connection)
.ok_or(ICError::DeviceNotSet)?;
let mut obj_ref = obj.borrow_mut();
let device_id = obj_ref.get_id();
let logicable = obj_ref
.as_mut_logicable()
.ok_or(ICError::NotLogicable(device_id))?;
if !logicable.can_logic_write(logic_type) {
return Err(LogicError::CantWrite(logic_type).into());
}
logicable.set_logic(logic_type, val, false)?;
self.get_circuit_holder()
.ok_or(ICError::NoCircuitHolder(*self.get_id()))?
.borrow_mut()
.as_mut_circuit_holder()
.ok_or(ICError::CircuitHolderNotLogicable(*self.get_id()))?
.get_logicable_from_index_mut(device, connection)
.ok_or(ICError::DeviceNotSet)
.and_then(|mut obj| {
let obj_id = obj.get_id();
obj.map(|obj_ref| {
obj_ref
.as_mut_logicable()
.ok_or(ICError::NotLogicable(obj_id))
.and_then(|logicable| {
if !logicable.can_logic_write(logic_type) {
Err(LogicError::CantWrite(logic_type).into())
} else {
logicable
.set_logic(logic_type, val, false)
.map_err(Into::into)
}
})
})
})?;
Ok(())
}
}
@@ -2176,23 +2205,30 @@ impl<T: IC10Marker> SdInstruction for T {
let id = id.as_value(self)?;
let logic_type = logic_type.as_logic_type(self)?;
let val = r.as_value(self)?;
let obj = self
.get_circuit_holder()
.ok_or(ICError::NoCircuitHolder(self.get_id()))?
.borrow()
.as_circuit_holder()
.ok_or(ICError::CircuitHolderNotLogicable(self.get_id()))?
.get_logicable_from_id(id as ObjectID, None)
.ok_or(ICError::DeviceNotSet)?;
let mut obj_ref = obj.borrow_mut();
let device_id = obj_ref.get_id();
let logicable = obj_ref
.as_mut_logicable()
.ok_or(ICError::NotLogicable(device_id))?;
if !logicable.can_logic_write(logic_type) {
return Err(LogicError::CantWrite(logic_type).into());
}
logicable.set_logic(logic_type, val, false)?;
self.get_circuit_holder()
.ok_or(ICError::NoCircuitHolder(*self.get_id()))?
.borrow_mut()
.as_mut_circuit_holder()
.ok_or(ICError::CircuitHolderNotLogicable(*self.get_id()))?
.get_logicable_from_id_mut(id as ObjectID, None)
.ok_or(ICError::DeviceNotSet)
.and_then(|mut obj| {
let obj_id = obj.get_id();
obj.map(|obj_ref| {
obj_ref
.as_mut_logicable()
.ok_or(ICError::NotLogicable(obj_id))
.and_then(|logicable| {
if !logicable.can_logic_write(logic_type) {
Err(LogicError::CantWrite(logic_type).into())
} else {
logicable
.set_logic(logic_type, val, false)
.map_err(Into::into)
}
})
})
})?;
Ok(())
}
}
@@ -2210,27 +2246,30 @@ impl<T: IC10Marker> SsInstruction for T {
let slot_index = slot_index.as_value(self)?;
let logic_slot_type = logic_slot_type.as_slot_logic_type(self)?;
let val = r.as_value(self)?;
let obj = self
.get_circuit_holder()
.ok_or(ICError::NoCircuitHolder(self.get_id()))?
.borrow()
.as_circuit_holder()
.ok_or(ICError::CircuitHolderNotLogicable(self.get_id()))?
.get_logicable_from_index(device, connection)
.ok_or(ICError::DeviceNotSet)?;
let mut obj_ref = obj.borrow_mut();
let device_id = obj_ref.get_id();
let logicable = obj_ref
.as_mut_logicable()
.ok_or(ICError::NotLogicable(device_id))?;
let device_id = logicable.get_id();
let device = logicable
.as_mut_device()
.ok_or(ICError::NotSlotWriteable(device_id))?;
if !device.can_slot_logic_write(logic_slot_type, slot_index) {
return Err(LogicError::CantSlotWrite(logic_slot_type, slot_index).into());
}
device.set_slot_logic(logic_slot_type, slot_index, val, false)?;
self.get_circuit_holder()
.ok_or(ICError::NoCircuitHolder(*self.get_id()))?
.borrow_mut()
.as_mut_circuit_holder()
.ok_or(ICError::CircuitHolderNotLogicable(*self.get_id()))?
.get_logicable_from_index_mut(device, connection)
.ok_or(ICError::DeviceNotSet)
.and_then(|mut obj| {
let obj_id = obj.get_id();
obj.map(|obj_ref| {
obj_ref
.as_mut_device()
.ok_or(ICError::NotLogicable(obj_id))
.and_then(|logicable| {
if !logicable.can_slot_logic_write(logic_slot_type, slot_index) {
Err(LogicError::CantSlotWrite(logic_slot_type, slot_index).into())
} else {
logicable
.set_slot_logic(logic_slot_type, slot_index, val, false)
.map_err(Into::into)
}
})
})
})?;
Ok(())
}
}
@@ -2248,7 +2287,7 @@ impl<T: IC10Marker> SbInstruction for T {
let logic_type = logic_type.as_logic_type(self)?;
let val = r.as_value(self)?;
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(())
}
}
@@ -2268,7 +2307,7 @@ impl<T: IC10Marker> SbsInstruction for T {
let logic_slot_type = logic_slot_type.as_slot_logic_type(self)?;
let val = r.as_value(self)?;
self.get_vm().set_batch_device_slot_field(
self.get_id(),
*self.get_id(),
prefab,
slot_index,
logic_slot_type,
@@ -2294,7 +2333,7 @@ impl<T: IC10Marker> SbnInstruction for T {
let logic_type = logic_type.as_logic_type(self)?;
let val = r.as_value(self)?;
self.get_vm().set_batch_name_device_field(
self.get_id(),
*self.get_id(),
prefab,
name,
logic_type,
@@ -2320,22 +2359,29 @@ impl<T: IC10Marker> LInstruction for T {
} = r.as_register(self)?;
let (device, connection) = d.as_device(self)?;
let logic_type = logic_type.as_logic_type(self)?;
let obj = self
let val = self
.get_circuit_holder()
.ok_or(ICError::NoCircuitHolder(self.get_id()))?
.ok_or(ICError::NoCircuitHolder(*self.get_id()))?
.borrow()
.as_circuit_holder()
.ok_or(ICError::CircuitHolderNotLogicable(self.get_id()))?
.ok_or(ICError::CircuitHolderNotLogicable(*self.get_id()))?
.get_logicable_from_index(device, connection)
.ok_or(ICError::DeviceNotSet)?;
let obj_ref = obj.borrow();
let logicable = obj_ref
.as_logicable()
.ok_or(ICError::NotLogicable(obj_ref.get_id()))?;
if !logicable.can_logic_read(logic_type) {
return Err(LogicError::CantRead(logic_type).into());
}
self.set_register(indirection, target, logicable.get_logic(logic_type)?)?;
.ok_or(ICError::DeviceNotSet)
.and_then(|obj| {
obj.map(|obj_ref| {
obj_ref
.as_logicable()
.ok_or(ICError::NotLogicable(*obj_ref.get_id()))
.and_then(|logicable| {
if !logicable.can_logic_read(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(())
}
}
@@ -2354,22 +2400,29 @@ impl<T: IC10Marker> LdInstruction for T {
} = r.as_register(self)?;
let id = id.as_value(self)?;
let logic_type = logic_type.as_logic_type(self)?;
let obj = self
let val = self
.get_circuit_holder()
.ok_or(ICError::NoCircuitHolder(self.get_id()))?
.ok_or(ICError::NoCircuitHolder(*self.get_id()))?
.borrow()
.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)
.ok_or(ICError::DeviceNotSet)?;
let obj_ref = obj.borrow();
let logicable = obj_ref
.as_logicable()
.ok_or(ICError::NotLogicable(obj_ref.get_id()))?;
if !logicable.can_logic_read(logic_type) {
return Err(LogicError::CantRead(logic_type).into());
}
self.set_register(indirection, target, logicable.get_logic(logic_type)?)?;
.ok_or(ICError::DeviceNotSet)
.and_then(|obj| {
obj.map(|obj_ref| {
obj_ref
.as_logicable()
.ok_or(ICError::NotLogicable(*obj_ref.get_id()))
.and_then(|logicable| {
if !logicable.can_logic_read(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(())
}
}
@@ -2390,26 +2443,31 @@ impl<T: IC10Marker> LsInstruction for T {
let (device, connection) = d.as_device(self)?;
let slot_index = slot_index.as_value(self)?;
let logic_slot_type = logic_slot_type.as_slot_logic_type(self)?;
let obj = self
let val = self
.get_circuit_holder()
.ok_or(ICError::NoCircuitHolder(self.get_id()))?
.ok_or(ICError::NoCircuitHolder(*self.get_id()))?
.borrow()
.as_circuit_holder()
.ok_or(ICError::CircuitHolderNotLogicable(self.get_id()))?
.ok_or(ICError::CircuitHolderNotLogicable(*self.get_id()))?
.get_logicable_from_index(device, connection)
.ok_or(ICError::DeviceNotSet)?;
let obj_ref = obj.borrow();
let logicable = obj_ref
.as_logicable()
.ok_or(ICError::NotLogicable(obj_ref.get_id()))?;
if !logicable.can_slot_logic_read(logic_slot_type, slot_index) {
return Err(LogicError::CantSlotRead(logic_slot_type, slot_index).into());
}
self.set_register(
indirection,
target,
logicable.get_slot_logic(logic_slot_type, slot_index)?,
)?;
.ok_or(ICError::DeviceNotSet)
.and_then(|obj| {
obj.map(|obj_ref| {
obj_ref
.as_logicable()
.ok_or(ICError::NotLogicable(*obj_ref.get_id()))
.and_then(|logicable| {
if !logicable.can_slot_logic_read(logic_slot_type, slot_index) {
Err(LogicError::CantSlotRead(logic_slot_type, slot_index).into())
} else {
logicable
.get_slot_logic(logic_slot_type, slot_index)
.map_err(Into::into)
}
})
})
})?;
self.set_register(indirection, target, val)?;
Ok(())
}
}
@@ -2430,66 +2488,70 @@ impl<T: IC10Marker> LrInstruction for T {
let (device, connection) = d.as_device(self)?;
let reagent_mode = reagent_mode.as_reagent_mode(self)?;
let int = int.as_value(self)?;
let obj = self
let val = self
.get_circuit_holder()
.ok_or(ICError::NoCircuitHolder(self.get_id()))?
.ok_or(ICError::NoCircuitHolder(*self.get_id()))?
.borrow()
.as_circuit_holder()
.ok_or(ICError::CircuitHolderNotLogicable(self.get_id()))?
.ok_or(ICError::CircuitHolderNotLogicable(*self.get_id()))?
.get_logicable_from_index(device, connection)
.ok_or(ICError::DeviceNotSet)?;
let obj_ref = obj.borrow();
let logicable = obj_ref
.as_logicable()
.ok_or(ICError::NotLogicable(obj_ref.get_id()))?;
let result = match reagent_mode {
LogicReagentMode::Contents => {
let device = logicable
.as_device()
.ok_or(ICError::NotReagentReadable(logicable.get_id()))?;
device
.get_reagents()
.iter()
.find(|(hash, _)| *hash as f64 == int)
.map(|(_, quantity)| *quantity)
.unwrap_or(0.0)
}
LogicReagentMode::TotalContents => {
let device = logicable
.as_device()
.ok_or(ICError::NotReagentReadable(logicable.get_id()))?;
device
.get_reagents()
.iter()
.map(|(_, quantity)| quantity)
.sum()
}
LogicReagentMode::Required => {
let reagent_interface = logicable
.as_reagent_interface()
.ok_or(ICError::NotReagentReadable(logicable.get_id()))?;
reagent_interface
.get_current_required()
.iter()
.find(|(hash, _)| *hash as f64 == int)
.map(|(_, quantity)| *quantity)
.unwrap_or(0.0)
}
LogicReagentMode::Recipe => {
let reagent_interface = logicable
.as_reagent_interface()
.ok_or(ICError::NotReagentReadable(logicable.get_id()))?;
reagent_interface
.get_current_recipie()
.iter()
.find(|(hash, _)| *hash as f64 == int)
.map(|(_, quantity)| *quantity)
.unwrap_or(0.0)
}
};
self.set_register(indirection, target, result)?;
.ok_or(ICError::DeviceNotSet)
.and_then(|obj| {
obj.map(|obj_ref| {
obj_ref
.as_logicable()
.ok_or(ICError::NotLogicable(*obj_ref.get_id()))
.and_then(|logicable| {
let result = match reagent_mode {
LogicReagentMode::Contents => {
let device = logicable
.as_device()
.ok_or(ICError::NotReagentReadable(*logicable.get_id()))?;
device
.get_reagents()
.iter()
.find(|(hash, _)| *hash as f64 == int)
.map(|(_, quantity)| *quantity)
.unwrap_or(0.0)
}
LogicReagentMode::TotalContents => {
let device = logicable
.as_device()
.ok_or(ICError::NotReagentReadable(*logicable.get_id()))?;
device
.get_reagents()
.iter()
.map(|(_, quantity)| quantity)
.sum()
}
LogicReagentMode::Required => {
let reagent_interface = logicable
.as_reagent_interface()
.ok_or(ICError::NotReagentReadable(*logicable.get_id()))?;
reagent_interface
.get_current_required()
.iter()
.find(|(hash, _)| *hash as f64 == int)
.map(|(_, quantity)| *quantity)
.unwrap_or(0.0)
}
LogicReagentMode::Recipe => {
let reagent_interface = logicable
.as_reagent_interface()
.ok_or(ICError::NotReagentReadable(*logicable.get_id()))?;
reagent_interface
.get_current_recipie()
.iter()
.find(|(hash, _)| *hash as f64 == int)
.map(|(_, quantity)| *quantity)
.unwrap_or(0.0)
}
};
Ok(result)
})
})
})?;
self.set_register(indirection, target, val)?;
Ok(())
}
}
@@ -2513,7 +2575,7 @@ impl<T: IC10Marker> LbInstruction for T {
let batch_mode = batch_mode.as_batch_mode(self)?;
let val =
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)?;
Ok(())
}
@@ -2539,7 +2601,7 @@ impl<T: IC10Marker> LbnInstruction for T {
let logic_type = logic_type.as_logic_type(self)?;
let batch_mode = batch_mode.as_batch_mode(self)?;
let val = self.get_vm().get_batch_name_device_field(
self.get_id(),
*self.get_id(),
prefab,
name,
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 batch_mode = batch_mode.as_batch_mode(self)?;
let val = self.get_vm().get_batch_name_device_slot_field(
self.get_id(),
*self.get_id(),
prefab,
name,
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 batch_mode = batch_mode.as_batch_mode(self)?;
let val = self.get_vm().get_batch_device_slot_field(
self.get_id(),
*self.get_id(),
prefab,
slot_index,
logic_slot_type,
@@ -2618,12 +2680,14 @@ impl<T: IC10Marker> LbsInstruction for T {
impl<T: IC10Marker> HcfInstruction for T {
/// hcf
fn execute_inner(&mut self) -> Result<(), ICError> {
self.get_circuit_holder()
.ok_or(ICError::NoCircuitHolder(self.get_id()))?
.borrow_mut()
.as_mut_circuit_holder()
.ok_or(ICError::CircuitHolderNotLogicable(self.get_id()))?
.hault_and_catch_fire();
{
self.get_circuit_holder()
.ok_or(ICError::NoCircuitHolder(*self.get_id()))?
.borrow_mut()
.as_mut_circuit_holder()
.ok_or(ICError::CircuitHolderNotLogicable(*self.get_id()))?
.hault_and_catch_fire();
}
self.set_state(ICState::HasCaughtFire);
Ok(())
}

View File

@@ -235,11 +235,11 @@ impl Storage for CableNetwork {
fn get_slot_mut(&mut self, _index: usize) -> Option<&mut crate::vm::object::Slot> {
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] {
&mut []
fn get_slots_mut(&mut self) -> Vec<&mut crate::vm::object::Slot> {
vec![]
}
}
@@ -422,7 +422,7 @@ where
impl From<NetworkRef<'_>> for FrozenCableNetwork {
fn from(value: NetworkRef) -> Self {
FrozenCableNetwork {
id: value.get_id(),
id: *value.get_id(),
devices: value.get_devices(),
power_only: value.get_power_only(),
channels: *value.get_channel_data(),

View File

@@ -617,7 +617,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()
@@ -639,7 +639,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()
@@ -661,7 +661,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()

View File

@@ -41,11 +41,11 @@ impl<T: GWStorage + Object> Storage for T {
fn get_slot_mut(&mut self, index: usize) -> Option<&mut Slot> {
self.slots_mut().get_mut(index)
}
fn get_slots(&self) -> &[Slot] {
self.slots()
fn get_slots(&self) -> Vec<&Slot> {
self.slots().iter().collect()
}
fn get_slots_mut(&mut self) -> &mut [Slot] {
self.slots_mut()
fn get_slots_mut(&mut self) -> Vec<&mut Slot> {
self.slots_mut().iter_mut().collect()
}
}
@@ -63,57 +63,77 @@ impl<T: GWLogicable + Object> Logicable for T {
self.get_name().hash
}
fn is_logic_readable(&self) -> bool {
LogicType::iter().any(|lt| self.can_logic_read(lt))
true
}
fn is_logic_writeable(&self) -> bool {
LogicType::iter().any(|lt| self.can_logic_write(lt))
}
fn can_logic_read(&self, lt: LogicType) -> bool {
self.fields()
.get(&lt)
.map(|field| {
matches!(
field.field_type,
MemoryAccess::Read | MemoryAccess::ReadWrite
)
})
.unwrap_or(false)
match lt {
LogicType::PrefabHash | LogicType::NameHash | LogicType::ReferenceId => true,
_ => self
.fields()
.get(&lt)
.map(|field| {
matches!(
field.field_type,
MemoryAccess::Read | MemoryAccess::ReadWrite
)
})
.unwrap_or(false),
}
}
fn can_logic_write(&self, lt: LogicType) -> bool {
self.fields()
.get(&lt)
.map(|field| {
matches!(
field.field_type,
MemoryAccess::Write | MemoryAccess::ReadWrite
)
})
.unwrap_or(false)
match lt {
LogicType::PrefabHash | LogicType::NameHash | LogicType::ReferenceId => false,
_ => self
.fields()
.get(&lt)
.map(|field| {
matches!(
field.field_type,
MemoryAccess::Write | MemoryAccess::ReadWrite
)
})
.unwrap_or(false),
}
}
fn get_logic(&self, lt: LogicType) -> Result<f64, LogicError> {
self.fields()
.get(&lt)
.and_then(|field| match field.field_type {
MemoryAccess::Read | MemoryAccess::ReadWrite => Some(field.value),
_ => None,
})
.ok_or(LogicError::CantRead(lt))
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),
_ => self
.fields()
.get(&lt)
.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> {
self.fields_mut()
.get_mut(&lt)
.ok_or(LogicError::CantWrite(lt))
.and_then(|field| match field.field_type {
MemoryAccess::Write | MemoryAccess::ReadWrite => {
field.value = value;
Ok(())
}
_ if force => {
field.value = value;
Ok(())
}
_ => Err(LogicError::CantWrite(lt)),
})
match lt {
LogicType::PrefabHash | LogicType::NameHash | LogicType::ReferenceId => {
Err(LogicError::CantWrite(lt))
}
_ => self
.fields_mut()
.get_mut(&lt)
.ok_or(LogicError::CantWrite(lt))
.and_then(|field| match field.field_type {
MemoryAccess::Write | MemoryAccess::ReadWrite => {
field.value = value;
Ok(())
}
_ if force => {
field.value = value;
Ok(())
}
_ => Err(LogicError::CantWrite(lt)),
}),
}
}
fn can_slot_logic_read(&self, slt: LogicSlotType, index: f64) -> bool {
if index < 0.0 {
@@ -200,7 +220,7 @@ impl<T: GWLogicable + Object> Logicable for T {
}
ReferenceId => {
if let Some(occupant) = occupant {
Ok(occupant.borrow().get_id() as f64)
Ok(*occupant.borrow().get_id() as f64)
} else {
Ok(0.0)
}

View File

@@ -8,7 +8,7 @@ macro_rules! object_trait {
}
};
(@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 get_prefab(&self) -> &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),*}) => {
@@ -95,8 +163,8 @@ macro_rules! ObjectInterface {
} => {
impl $trait_name for $struct {
fn get_id(&self) -> crate::vm::object::ObjectID {
self.$id_field
fn get_id(&self) -> &crate::vm::object::ObjectID {
&self.$id_field
}
fn set_id(&mut self, id: crate::vm::object::ObjectID) {

View File

@@ -1,3 +1,4 @@
mod integrated_circuit;
mod circuit_holder;
pub use integrated_circuit::ItemIntegratedCircuit10;

View 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??
}
}

View File

@@ -97,11 +97,11 @@ impl Storage for ItemIntegratedCircuit10 {
fn get_slot_mut(&mut self, _index: usize) -> Option<&mut Slot> {
None
}
fn get_slots(&self) -> &[Slot] {
&[]
fn get_slots(&self) -> Vec<&Slot> {
vec![]
}
fn get_slots_mut(&mut self) -> &mut [Slot] {
&mut []
fn get_slots_mut(&mut self) -> Vec<&mut Slot> {
vec![]
}
}
@@ -165,11 +165,11 @@ impl Logicable for ItemIntegratedCircuit10 {
_ => 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
}
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> {
self.fields.keys().copied().collect()
@@ -235,8 +235,7 @@ impl SourceCode for ItemIntegratedCircuit10 {
impl IntegratedCircuit for ItemIntegratedCircuit10 {
fn get_circuit_holder(&self) -> Option<VMObject> {
self.get_parent_slot()
.map(|parent_slot| self.get_vm().get_object(parent_slot.parent))
.flatten()
.and_then(|parent_slot| self.get_vm().get_object(parent_slot.parent))
}
fn get_instruction_pointer(&self) -> f64 {
self.ip as f64
@@ -371,7 +370,7 @@ impl IC10Marker for ItemIntegratedCircuit10 {}
impl Programmable for ItemIntegratedCircuit10 {
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(());
}
if matches!(&self.state, ICState::Error(_)) && !advance_ip_on_err {
@@ -394,7 +393,7 @@ impl Programmable for ItemIntegratedCircuit10 {
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;
return Ok(());
}
@@ -403,17 +402,34 @@ impl Programmable for ItemIntegratedCircuit10 {
let line = self.program.get_line(self.ip)?.clone();
let operands = &line.operands;
let instruction = line.instruction;
instruction.execute(self, operands)?;
self.ip = self.next_ip;
if self.ip >= self.program.len() {
self.state = ICState::Ended;
let result = instruction.execute(self, operands);
let was_error = if let Err(_err) = result {
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()
.ok_or(ICError::NoCircuitHolder(self.id))?
.borrow_mut()
.as_mut_logicable()
.ok_or(ICError::CircuitHolderNotLogicable(self.id))?
.set_logic(LogicType::LineNumber, self.ip as f64, true)?;
Ok(())
}
}

View File

@@ -1167,7 +1167,7 @@ impl ObjectTemplate {
logic: logic.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();
ObjectInfo {
name: Some(obj_ref.get_name().value.clone()),
id: Some(obj_ref.get_id()),
id: Some(*obj_ref.get_id()),
}
}
}

View File

@@ -22,7 +22,6 @@ pub struct ParentSlotInfo {
pub parent: ObjectID,
pub slot: usize,
}
tag_object_traits! {
#![object_trait(Object: Debug)]
@@ -34,8 +33,8 @@ tag_object_traits! {
fn slots_count(&self) -> usize;
fn get_slot(&self, index: usize) -> Option<&Slot>;
fn get_slot_mut(&mut self, index: usize) -> Option<&mut Slot>;
fn get_slots(&self) -> &[Slot];
fn get_slots_mut(&mut self) -> &mut [Slot];
fn get_slots(&self) -> Vec<&Slot>;
fn get_slots_mut(&mut self) -> Vec<&mut Slot>;
}
pub trait MemoryReadable {
@@ -80,16 +79,25 @@ tag_object_traits! {
&self,
device: i32,
connection: Option<usize>,
) -> Option<VMObject>;
) -> Option<ObjectRef>;
/// i32::MAX is db
fn get_logicable_from_index_mut(
&mut self,
device: i32,
connection: Option<usize>,
) -> Option<ObjectRefMut>;
fn get_logicable_from_id(
&self,
device: ObjectID,
connection: Option<usize>,
) -> Option<VMObject>;
fn get_source_code(&self) -> String;
fn set_source_code(&self, code: String);
fn get_ic(&self) -> Option<ObjectID>;
) -> Option<ObjectRef>;
fn get_logicable_from_id_mut(
&mut self,
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);
}