refactor(vm) start reimpl of VM struct using object trait
This commit is contained in:
@@ -522,7 +522,7 @@ impl Device {
|
||||
pub fn get_fields(&self, vm: &VM) -> BTreeMap<LogicType, LogicField> {
|
||||
let mut copy = self.fields.clone();
|
||||
if let Some(ic_id) = &self.ic {
|
||||
let ic = vm.ics.get(ic_id).expect("our own ic to exist").borrow();
|
||||
let ic = vm.ic_holders.get(ic_id).expect("our own ic to exist").borrow();
|
||||
copy.insert(
|
||||
LogicType::LineNumber,
|
||||
LogicField {
|
||||
@@ -642,7 +642,7 @@ impl Device {
|
||||
pub fn get_field(&self, typ: LogicType, vm: &VM) -> Result<f64, ICError> {
|
||||
if typ == LogicType::LineNumber && self.ic.is_some() {
|
||||
let ic = vm
|
||||
.ics
|
||||
.ic_holders
|
||||
.get(&self.ic.unwrap())
|
||||
.ok_or_else(|| ICError::UnknownDeviceID(self.ic.unwrap() as f64))?
|
||||
.borrow();
|
||||
@@ -673,7 +673,7 @@ impl Device {
|
||||
Err(ICError::ReadOnlyField(typ.to_string()))
|
||||
} else if typ == LogicType::LineNumber && self.ic.is_some() {
|
||||
let ic = vm
|
||||
.ics
|
||||
.ic_holders
|
||||
.get(&self.ic.unwrap())
|
||||
.ok_or_else(|| ICError::UnknownDeviceID(self.ic.unwrap() as f64))?
|
||||
.borrow();
|
||||
@@ -714,7 +714,7 @@ impl Device {
|
||||
&& typ == LogicSlotType::LineNumber
|
||||
{
|
||||
let ic = vm
|
||||
.ics
|
||||
.ic_holders
|
||||
.get(&self.ic.unwrap())
|
||||
.ok_or_else(|| ICError::UnknownDeviceID(self.ic.unwrap() as f64))?
|
||||
.borrow();
|
||||
@@ -736,7 +736,7 @@ impl Device {
|
||||
let mut fields = slot.get_fields();
|
||||
if slot.typ == SlotClass::ProgrammableChip && slot.occupant.is_some() && self.ic.is_some() {
|
||||
let ic = vm
|
||||
.ics
|
||||
.ic_holders
|
||||
.get(&self.ic.unwrap())
|
||||
.ok_or_else(|| ICError::UnknownDeviceID(self.ic.unwrap() as f64))?
|
||||
.borrow();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::vm::instructions::enums::InstructionOp;
|
||||
use crate::vm::{instructions::enums::InstructionOp, object::{errors::{LogicError, MemoryError}, ObjectID}};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::error::Error as StdError;
|
||||
use std::fmt::Display;
|
||||
@@ -17,7 +17,7 @@ pub enum VMError {
|
||||
#[error("ic encountered an error: {0}")]
|
||||
LineError(#[from] LineError),
|
||||
#[error("invalid network id {0}")]
|
||||
InvalidNetwork(u32),
|
||||
InvalidNetwork(ObjectID),
|
||||
#[error("device {0} not visible to device {1} (not on the same networks)")]
|
||||
DeviceNotVisible(u32, u32),
|
||||
#[error("a device with id {0} already exists")]
|
||||
@@ -26,6 +26,12 @@ pub enum VMError {
|
||||
IdsInUse(Vec<u32>),
|
||||
#[error("atempt to use a set of id's with duplicates: id(s) {0:?} exsist more than once")]
|
||||
DuplicateIds(Vec<u32>),
|
||||
#[error("object {0} is not a device")]
|
||||
NotADevice(ObjectID),
|
||||
#[error("device object {0} has no pins")]
|
||||
NoDevicePins(ObjectID),
|
||||
#[error("object {0} has no slots")]
|
||||
NotStorage(ObjectID),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
@@ -98,6 +104,10 @@ impl ParseError {
|
||||
pub enum ICError {
|
||||
#[error("error compiling code: {0}")]
|
||||
ParseError(#[from] ParseError),
|
||||
#[error("{0}")]
|
||||
LogicError(#[from] LogicError),
|
||||
#[error("{0}")]
|
||||
MemoryError(#[from] MemoryError),
|
||||
#[error("duplicate label {0}")]
|
||||
DuplicateLabel(String),
|
||||
#[error("instruction pointer out of range: '{0}'")]
|
||||
@@ -138,10 +148,6 @@ pub enum ICError {
|
||||
ShiftUnderflowI32,
|
||||
#[error("shift overflow i32(signed int)")]
|
||||
ShiftOverflowI32,
|
||||
#[error("stack underflow")]
|
||||
StackUnderflow,
|
||||
#[error("stack overflow")]
|
||||
StackOverflow,
|
||||
#[error("duplicate define '{0}'")]
|
||||
DuplicateDefine(String),
|
||||
#[error("read only field '{0}'")]
|
||||
|
||||
@@ -2030,7 +2030,7 @@ impl IC {
|
||||
if ic_id == &this.id {
|
||||
this.peek_addr(addr)
|
||||
} else {
|
||||
let ic = vm.ics.get(ic_id).unwrap().borrow();
|
||||
let ic = vm.ic_holders.get(ic_id).unwrap().borrow();
|
||||
ic.peek_addr(addr)
|
||||
}
|
||||
}?;
|
||||
@@ -2063,7 +2063,7 @@ impl IC {
|
||||
if ic_id == &this.id {
|
||||
this.peek_addr(addr)
|
||||
} else {
|
||||
let ic = vm.ics.get(ic_id).unwrap().borrow();
|
||||
let ic = vm.ic_holders.get(ic_id).unwrap().borrow();
|
||||
ic.peek_addr(addr)
|
||||
}
|
||||
}?;
|
||||
@@ -2092,7 +2092,7 @@ impl IC {
|
||||
if ic_id == &this.id {
|
||||
this.poke(addr, val)?;
|
||||
} else {
|
||||
let ic = vm.ics.get(ic_id).unwrap().borrow();
|
||||
let ic = vm.ic_holders.get(ic_id).unwrap().borrow();
|
||||
ic.poke(addr, val)?;
|
||||
}
|
||||
vm.set_modified(device_id);
|
||||
@@ -2120,7 +2120,7 @@ impl IC {
|
||||
if ic_id == &this.id {
|
||||
this.poke(addr, val)?;
|
||||
} else {
|
||||
let ic = vm.ics.get(ic_id).unwrap().borrow();
|
||||
let ic = vm.ic_holders.get(ic_id).unwrap().borrow();
|
||||
ic.poke(addr, val)?;
|
||||
}
|
||||
vm.set_modified(device_id as u32);
|
||||
@@ -2532,7 +2532,7 @@ mod tests {
|
||||
let device_ref = device.borrow();
|
||||
device_ref.ic.unwrap()
|
||||
};
|
||||
let ic_chip = vm.ics.get(&ic_id).unwrap().borrow();
|
||||
let ic_chip = vm.ic_holders.get(&ic_id).unwrap().borrow();
|
||||
vm.set_code(
|
||||
ic,
|
||||
r#"lb r0 HASH("ItemActiveVent") On Sum
|
||||
@@ -2561,7 +2561,7 @@ mod tests {
|
||||
let device_ref = device.borrow();
|
||||
device_ref.ic.unwrap()
|
||||
};
|
||||
let ic_chip = vm.ics.get(&ic_id).unwrap().borrow();
|
||||
let ic_chip = vm.ic_holders.get(&ic_id).unwrap().borrow();
|
||||
vm.set_code(
|
||||
ic,
|
||||
r#"push 100
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
use std::{collections::HashSet, ops::Deref};
|
||||
|
||||
use crate::vm::{
|
||||
enums::script_enums::LogicType,
|
||||
object::{errors::LogicError, macros::ObjectInterface, traits::*, Name, ObjectID},
|
||||
};
|
||||
use itertools::Itertools;
|
||||
use macro_rules_attribute::derive;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use strum_macros::{AsRefStr, EnumIter};
|
||||
use thiserror::Error;
|
||||
|
||||
use itertools::Itertools;
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, Serialize, Deserialize)]
|
||||
pub enum CableConnectionType {
|
||||
Power,
|
||||
@@ -107,14 +111,171 @@ impl Connection {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Network {
|
||||
pub id: u32,
|
||||
pub devices: HashSet<u32>,
|
||||
pub power_only: HashSet<u32>,
|
||||
#[derive(ObjectInterface!, Debug, Serialize, Deserialize)]
|
||||
#[custom(implements(Object { Storage, Logicable, Network}))]
|
||||
pub struct CableNetwork {
|
||||
#[custom(object_id)]
|
||||
pub id: ObjectID,
|
||||
#[custom(object_prefab)]
|
||||
/// required by object interface but atm unused by network
|
||||
pub prefab: Name,
|
||||
#[custom(object_name)]
|
||||
/// required by object interface but atm unused by network
|
||||
pub name: Name,
|
||||
/// data enabled objects (must be devices)
|
||||
pub devices: HashSet<ObjectID>,
|
||||
/// power only connections
|
||||
pub power_only: HashSet<ObjectID>,
|
||||
/// channel data
|
||||
pub channels: [f64; 8],
|
||||
}
|
||||
|
||||
impl Storage for CableNetwork {
|
||||
fn slots_count(&self) -> usize {
|
||||
0
|
||||
}
|
||||
fn get_slot(&self, index: usize) -> Option<&crate::vm::object::Slot> {
|
||||
None
|
||||
}
|
||||
fn get_slot_mut(&mut self, index: usize) -> Option<&mut crate::vm::object::Slot> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl Logicable for CableNetwork {
|
||||
fn prefab_hash(&self) -> i32 {
|
||||
0
|
||||
}
|
||||
fn name_hash(&self) -> i32 {
|
||||
0
|
||||
}
|
||||
fn is_logic_readable(&self) -> bool {
|
||||
true
|
||||
}
|
||||
fn is_logic_writeable(&self) -> bool {
|
||||
true
|
||||
}
|
||||
fn can_logic_read(&self, lt: LogicType) -> bool {
|
||||
use LogicType::*;
|
||||
match lt {
|
||||
Channel0 | Channel1 | Channel2 | Channel3 | Channel4 | Channel5 | Channel6
|
||||
| Channel7 => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
fn can_logic_write(&self, lt: LogicType) -> bool {
|
||||
use LogicType::*;
|
||||
match lt {
|
||||
Channel0 | Channel1 | Channel2 | Channel3 | Channel4 | Channel5 | Channel6
|
||||
| Channel7 => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
fn get_logic(&self, lt: LogicType) -> Result<f64, crate::vm::object::errors::LogicError> {
|
||||
use LogicType::*;
|
||||
let index: usize = match lt {
|
||||
Channel0 => 0,
|
||||
Channel1 => 1,
|
||||
Channel2 => 2,
|
||||
Channel3 => 3,
|
||||
Channel4 => 4,
|
||||
Channel5 => 5,
|
||||
Channel6 => 6,
|
||||
Channel7 => 7,
|
||||
_ => return Err(LogicError::CantRead(lt)),
|
||||
};
|
||||
Ok(self.channels[index])
|
||||
}
|
||||
fn set_logic(&mut self, lt: LogicType, value: f64, force: bool) -> Result<(), LogicError> {
|
||||
use LogicType::*;
|
||||
let index: usize = match lt {
|
||||
Channel0 => 0,
|
||||
Channel1 => 1,
|
||||
Channel2 => 2,
|
||||
Channel3 => 3,
|
||||
Channel4 => 4,
|
||||
Channel5 => 5,
|
||||
Channel6 => 6,
|
||||
Channel7 => 7,
|
||||
_ => return Err(LogicError::CantWrite(lt)),
|
||||
};
|
||||
self.channels[index] = value;
|
||||
Ok(())
|
||||
}
|
||||
fn can_slot_logic_read(
|
||||
&self,
|
||||
slt: crate::vm::enums::script_enums::LogicSlotType,
|
||||
index: usize,
|
||||
) -> bool {
|
||||
false
|
||||
}
|
||||
fn get_slot_logic(
|
||||
&self,
|
||||
slt: crate::vm::enums::script_enums::LogicSlotType,
|
||||
index: usize,
|
||||
vm: &crate::vm::VM,
|
||||
) -> Result<f64, LogicError> {
|
||||
Err(LogicError::CantSlotRead(slt, index))
|
||||
}
|
||||
}
|
||||
|
||||
impl Network for CableNetwork {
|
||||
fn contains(&self, id: &ObjectID) -> bool {
|
||||
self.devices.contains(id) || self.power_only.contains(id)
|
||||
}
|
||||
|
||||
fn contains_all(&self, ids: &[ObjectID]) -> bool {
|
||||
ids.iter().all(|id| self.contains(id))
|
||||
}
|
||||
|
||||
fn contains_data(&self, id: &ObjectID) -> bool {
|
||||
self.devices.contains(id)
|
||||
}
|
||||
|
||||
fn contains_all_data(&self, ids: &[ObjectID]) -> bool {
|
||||
ids.iter().all(|id| self.contains_data(id))
|
||||
}
|
||||
|
||||
fn contains_power(&self, id: &ObjectID) -> bool {
|
||||
self.power_only.contains(id)
|
||||
}
|
||||
|
||||
fn contains_all_power(&self, ids: &[ObjectID]) -> bool {
|
||||
ids.iter().all(|id| self.contains_power(id))
|
||||
}
|
||||
|
||||
fn data_visible(&self, source: &ObjectID) -> Vec<ObjectID> {
|
||||
if self.contains_data(source) {
|
||||
self.devices
|
||||
.iter()
|
||||
.filter(|id| id != &source)
|
||||
.copied()
|
||||
.collect_vec()
|
||||
} else {
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
|
||||
fn add_data(&mut self, id: ObjectID) -> bool {
|
||||
self.devices.insert(id)
|
||||
}
|
||||
|
||||
fn add_power(&mut self, id: ObjectID) -> bool {
|
||||
self.power_only.insert(id)
|
||||
}
|
||||
|
||||
fn remove_all(&mut self, id: ObjectID) -> bool {
|
||||
self.devices.remove(&id) || self.power_only.remove(&id)
|
||||
}
|
||||
fn remove_data(&mut self, id: ObjectID) -> bool {
|
||||
self.devices.remove(&id)
|
||||
}
|
||||
|
||||
fn remove_power(&mut self, id: ObjectID) -> bool {
|
||||
self.devices.remove(&id)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct FrozenNetwork {
|
||||
pub id: u32,
|
||||
@@ -125,7 +286,7 @@ pub struct FrozenNetwork {
|
||||
|
||||
impl<T> From<T> for FrozenNetwork
|
||||
where
|
||||
T: Deref<Target = Network>,
|
||||
T: Deref<Target = CableNetwork>,
|
||||
{
|
||||
fn from(value: T) -> Self {
|
||||
FrozenNetwork {
|
||||
@@ -137,10 +298,12 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FrozenNetwork> for Network {
|
||||
impl From<FrozenNetwork> for CableNetwork {
|
||||
fn from(value: FrozenNetwork) -> Self {
|
||||
Network {
|
||||
CableNetwork {
|
||||
id: value.id,
|
||||
prefab: Name::new(""),
|
||||
name: Name::new(""),
|
||||
devices: value.devices.into_iter().collect(),
|
||||
power_only: value.power_only.into_iter().collect(),
|
||||
channels: value.channels,
|
||||
@@ -154,71 +317,18 @@ pub enum NetworkError {
|
||||
ChannelIndexOutOfRange,
|
||||
}
|
||||
|
||||
impl Network {
|
||||
impl CableNetwork {
|
||||
pub fn new(id: u32) -> Self {
|
||||
Network {
|
||||
CableNetwork {
|
||||
id,
|
||||
prefab: Name::new(""),
|
||||
name: Name::new(""),
|
||||
devices: HashSet::new(),
|
||||
power_only: HashSet::new(),
|
||||
channels: [f64::NAN; 8],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn contains(&self, id: &u32) -> bool {
|
||||
self.devices.contains(id) || self.power_only.contains(id)
|
||||
}
|
||||
|
||||
pub fn contains_all(&self, ids: &[u32]) -> bool {
|
||||
ids.iter().all(|id| self.contains(id))
|
||||
}
|
||||
|
||||
pub fn contains_data(&self, id: &u32) -> bool {
|
||||
self.devices.contains(id)
|
||||
}
|
||||
|
||||
pub fn contains_all_data(&self, ids: &[u32]) -> bool {
|
||||
ids.iter().all(|id| self.contains_data(id))
|
||||
}
|
||||
|
||||
pub fn contains_power(&self, id: &u32) -> bool {
|
||||
self.power_only.contains(id)
|
||||
}
|
||||
|
||||
pub fn contains_all_power(&self, ids: &[u32]) -> bool {
|
||||
ids.iter().all(|id| self.contains_power(id))
|
||||
}
|
||||
|
||||
pub fn data_visible(&self, source: &u32) -> Vec<u32> {
|
||||
if self.contains_data(source) {
|
||||
self.devices
|
||||
.iter()
|
||||
.filter(|id| id != &source)
|
||||
.copied()
|
||||
.collect_vec()
|
||||
} else {
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_data(&mut self, id: u32) -> bool {
|
||||
self.devices.insert(id)
|
||||
}
|
||||
|
||||
pub fn add_power(&mut self, id: u32) -> bool {
|
||||
self.power_only.insert(id)
|
||||
}
|
||||
|
||||
pub fn remove_all(&mut self, id: u32) -> bool {
|
||||
self.devices.remove(&id) || self.power_only.remove(&id)
|
||||
}
|
||||
pub fn remove_data(&mut self, id: u32) -> bool {
|
||||
self.devices.remove(&id)
|
||||
}
|
||||
|
||||
pub fn remove_power(&mut self, id: u32) -> bool {
|
||||
self.devices.remove(&id)
|
||||
}
|
||||
|
||||
pub fn set_channel(&mut self, chan: usize, val: f64) -> Result<f64, NetworkError> {
|
||||
if chan > 7 {
|
||||
Err(NetworkError::ChannelIndexOutOfRange)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,14 +1,15 @@
|
||||
use crate::errors::ICError;
|
||||
use crate::interpreter;
|
||||
use crate::vm::enums::script_enums::{
|
||||
LogicBatchMethod as BatchMode, LogicReagentMode as ReagentMode, LogicSlotType, LogicType,
|
||||
use crate::vm::{
|
||||
enums::script_enums::{
|
||||
LogicBatchMethod as BatchMode, LogicReagentMode as ReagentMode, LogicSlotType, LogicType,
|
||||
},
|
||||
instructions::enums::InstructionOp,
|
||||
object::traits::IntegratedCircuit,
|
||||
};
|
||||
use crate::vm::instructions::enums::InstructionOp;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use strum::EnumProperty;
|
||||
|
||||
use super::traits::IntegratedCircuit;
|
||||
|
||||
#[derive(PartialEq, Eq, Debug, Clone, Copy, Serialize, Deserialize)]
|
||||
pub enum Device {
|
||||
Db,
|
||||
@@ -191,28 +192,14 @@ impl Operand {
|
||||
) -> Result<(Option<u32>, Option<usize>), ICError> {
|
||||
match self.translate_alias(ic) {
|
||||
Operand::DeviceSpec(DeviceSpec { device, connection }) => match device {
|
||||
Device::Db => Ok((Some(ic.device), connection)),
|
||||
Device::Numbered(p) => {
|
||||
let dp = ic
|
||||
.pins
|
||||
.borrow()
|
||||
.get(p as usize)
|
||||
.ok_or(ICError::DeviceIndexOutOfRange(p as f64))
|
||||
.copied()?;
|
||||
Ok((dp, connection))
|
||||
}
|
||||
Device::Db => Ok((Some(0), connection)),
|
||||
Device::Numbered(p) => Ok((Some(p), connection)),
|
||||
Device::Indirect {
|
||||
indirection,
|
||||
target,
|
||||
} => {
|
||||
let val = ic.get_register(indirection, target)?;
|
||||
let dp = ic
|
||||
.pins
|
||||
.borrow()
|
||||
.get(val as usize)
|
||||
.ok_or(ICError::DeviceIndexOutOfRange(val))
|
||||
.copied()?;
|
||||
Ok((dp, connection))
|
||||
Ok((Some(val as u32), connection))
|
||||
}
|
||||
},
|
||||
Operand::Identifier(id) => Err(ICError::UnknownIdentifier(id.name.to_string())),
|
||||
@@ -287,11 +274,11 @@ impl Operand {
|
||||
pub fn translate_alias<IC: IntegratedCircuit>(&self, ic: &IC) -> Self {
|
||||
match &self {
|
||||
Operand::Identifier(id) | Operand::Type { identifier: id, .. } => {
|
||||
if let Some(alias) = ic.aliases.borrow().get(&id.name) {
|
||||
if let Some(alias) = ic.get_aliases().get(&id.name) {
|
||||
alias.clone()
|
||||
} else if let Some(define) = ic.defines.borrow().get(&id.name) {
|
||||
} else if let Some(define) = ic.get_defines().get(&id.name) {
|
||||
Operand::Number(Number::Float(*define))
|
||||
} else if let Some(label) = ic.program.borrow().labels.get(&id.name) {
|
||||
} else if let Some(label) = ic.get_labels().get(&id.name) {
|
||||
Operand::Number(Number::Float(*label as f64))
|
||||
} else {
|
||||
self.clone()
|
||||
|
||||
@@ -9,32 +9,7 @@
|
||||
//
|
||||
// =================================================
|
||||
|
||||
use crate::errors::ICError;
|
||||
use crate::vm::object::traits::{Logicable, MemoryWritable, SourceCode};
|
||||
use std::collections::BTreeMap;
|
||||
pub trait IntegratedCircuit: Logicable + MemoryWritable + SourceCode {
|
||||
fn get_instruction_pointer(&self) -> f64;
|
||||
fn set_next_instruction(&mut self, next_instruction: f64);
|
||||
fn set_next_instruction_relative(&mut self, offset: f64) {
|
||||
self.set_next_instruction(self.get_instruction_pointer() + offset);
|
||||
}
|
||||
fn reset(&mut self);
|
||||
fn get_real_target(&self, indirection: u32, target: u32) -> Result<f64, ICError>;
|
||||
fn get_register(&self, indirection: u32, target: u32) -> Result<f64, ICError>;
|
||||
fn set_register(&mut self, indirection: u32, target: u32, val: f64) -> Result<f64, ICError>;
|
||||
fn set_return_address(&mut self, addr: f64);
|
||||
fn al(&mut self) {
|
||||
self.set_return_address(self.get_instruction_pointer() + 1.0);
|
||||
}
|
||||
fn push_stack(&mut self, val: f64) -> Result<f64, ICError>;
|
||||
fn pop_stack(&mut self) -> Result<f64, ICError>;
|
||||
fn peek_stack(&self) -> Result<f64, ICError>;
|
||||
fn get_stack(&self, addr: f64) -> Result<f64, ICError>;
|
||||
fn put_stack(&self, addr: f64, val: f64) -> Result<f64, ICError>;
|
||||
fn get_aliases(&self) -> &BTreeMap<String, crate::vm::instructions::operands::Operand>;
|
||||
fn get_defines(&self) -> &BTreeMap<String, f64>;
|
||||
fn get_labels(&self) -> &BTreeMap<String, u32>;
|
||||
}
|
||||
use crate::vm::object::traits::IntegratedCircuit;
|
||||
pub trait AbsInstruction: IntegratedCircuit {
|
||||
/// abs r? a(r?|num)
|
||||
fn execute_abs(
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use std::{cell::RefCell, ops::Deref, rc::Rc, str::FromStr};
|
||||
use std::{cell::RefCell, ops::{Deref, DerefMut}, rc::Rc, str::FromStr};
|
||||
|
||||
use macro_rules_attribute::derive;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
@@ -19,6 +19,7 @@ use super::enums::prefabs::StationpediaPrefab;
|
||||
pub type ObjectID = u32;
|
||||
pub type BoxedObject = Rc<RefCell<dyn Object<ID = ObjectID>>>;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct VMObject(BoxedObject);
|
||||
|
||||
impl Deref for VMObject {
|
||||
@@ -30,6 +31,14 @@ impl Deref for VMObject {
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for VMObject {
|
||||
|
||||
#[inline(always)]
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl VMObject {
|
||||
pub fn new<T>(val: T) -> Self
|
||||
where
|
||||
@@ -65,7 +74,7 @@ impl Name {
|
||||
if let Some(prefab) = StationpediaPrefab::from_repr(hash) {
|
||||
Some(Name {
|
||||
value: prefab.to_string(),
|
||||
hash: hash,
|
||||
hash,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
|
||||
@@ -3,7 +3,7 @@ use thiserror::Error;
|
||||
|
||||
use crate::vm::enums::script_enums::{LogicSlotType, LogicType};
|
||||
|
||||
#[derive(Error, Debug, Serialize, Deserialize)]
|
||||
#[derive(Error, Debug, Clone, Serialize, Deserialize)]
|
||||
pub enum LogicError {
|
||||
#[error("can't read LogicType {0}")]
|
||||
CantRead(LogicType),
|
||||
@@ -17,7 +17,7 @@ pub enum LogicError {
|
||||
SlotIndexOutOfRange(usize, usize),
|
||||
}
|
||||
|
||||
#[derive(Error, Debug, Serialize, Deserialize)]
|
||||
#[derive(Error, Debug, Clone, Serialize, Deserialize)]
|
||||
pub enum MemoryError {
|
||||
#[error("stack underflow: {0} < range [0..{1})")]
|
||||
StackUnderflow(i32, usize),
|
||||
|
||||
@@ -79,7 +79,23 @@ macro_rules! GWDevice {
|
||||
$($body:tt)*
|
||||
}
|
||||
) => {
|
||||
impl GWDevice for $struct {}
|
||||
impl GWDevice for $struct {
|
||||
fn device_info(&self) -> &DeviceInfo {
|
||||
&self.device_info
|
||||
}
|
||||
fn device_connections(&self) -> &[Connection] {
|
||||
self.connections.as_slice()
|
||||
}
|
||||
fn device_connections_mut(&mut self) -> &mut [Connection] {
|
||||
self.connections.as_mut_slice()
|
||||
}
|
||||
fn device_pins(&self) -> Option<&[Option<ObjectID>]> {
|
||||
self.pins.as_ref().map(|pins| pins.as_slice())
|
||||
}
|
||||
fn device_pins_mut(&mut self) -> Option<&mut [Option<ObjectID>]> {
|
||||
self.pins.as_mut().map(|pins| pins.as_mut_slice())
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
pub(crate) use GWDevice;
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use super::{macros::*, traits::*};
|
||||
|
||||
use crate::vm::{
|
||||
use crate::{network::Connection, vm::{
|
||||
enums::script_enums::LogicType,
|
||||
object::{
|
||||
macros::ObjectInterface, templates::ItemInfo, traits::*, LogicField, Name, ObjectID, Slot,
|
||||
macros::ObjectInterface, templates::{DeviceInfo, ItemInfo}, traits::*, LogicField, Name, ObjectID, Slot,
|
||||
},
|
||||
};
|
||||
}};
|
||||
use macro_rules_attribute::derive;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
@@ -56,6 +56,9 @@ pub struct GenericLogicableDevice {
|
||||
pub name: Name,
|
||||
pub fields: BTreeMap<LogicType, LogicField>,
|
||||
pub slots: Vec<Slot>,
|
||||
pub device_info: DeviceInfo,
|
||||
pub connections: Vec<Connection>,
|
||||
pub pins: Option<Vec<Option<ObjectID>>>,
|
||||
}
|
||||
|
||||
#[derive(ObjectInterface!, GWStorage!, GWLogicable!, GWDevice!, GWMemoryReadable!, GWMemoryWritable!)]
|
||||
@@ -69,6 +72,9 @@ pub struct GenericLogicableDeviceMemoryReadable {
|
||||
pub name: Name,
|
||||
pub fields: BTreeMap<LogicType, LogicField>,
|
||||
pub slots: Vec<Slot>,
|
||||
pub device_info: DeviceInfo,
|
||||
pub connections: Vec<Connection>,
|
||||
pub pins: Option<Vec<Option<ObjectID>>>,
|
||||
pub memory: Vec<f64>,
|
||||
}
|
||||
|
||||
@@ -83,6 +89,9 @@ pub struct GenericLogicableDeviceMemoryReadWriteable {
|
||||
pub name: Name,
|
||||
pub fields: BTreeMap<LogicType, LogicField>,
|
||||
pub slots: Vec<Slot>,
|
||||
pub device_info: DeviceInfo,
|
||||
pub connections: Vec<Connection>,
|
||||
pub pins: Option<Vec<Option<ObjectID>>>,
|
||||
pub memory: Vec<f64>,
|
||||
}
|
||||
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
use crate::vm::{
|
||||
use crate::{network::Connection, vm::{
|
||||
enums::{
|
||||
basic_enums::{Class as SlotClass, GasType, SortingClass},
|
||||
script_enums::{LogicSlotType, LogicType},
|
||||
},
|
||||
object::{
|
||||
errors::{LogicError, MemoryError},
|
||||
templates::ItemInfo,
|
||||
traits::*,
|
||||
LogicField, MemoryAccess, Slot,
|
||||
errors::{LogicError, MemoryError}, templates::{DeviceInfo, ItemInfo}, traits::*, LogicField, MemoryAccess, ObjectID, Slot
|
||||
},
|
||||
VM,
|
||||
};
|
||||
}};
|
||||
use std::{collections::BTreeMap, usize};
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
@@ -166,9 +163,46 @@ impl<T: GWMemoryWritable + MemoryReadable + Object> MemoryWritable for T {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GWDevice: Logicable {}
|
||||
pub trait GWDevice: Logicable {
|
||||
fn device_info(&self) -> &DeviceInfo;
|
||||
fn device_connections(&self) -> &[Connection];
|
||||
fn device_connections_mut(&mut self) -> &mut [Connection];
|
||||
fn device_pins(&self) -> Option<&[Option<ObjectID>]>;
|
||||
fn device_pins_mut(&mut self) -> Option<&mut [Option<ObjectID>]>;
|
||||
}
|
||||
|
||||
impl<T: GWDevice + Object> Device for T {}
|
||||
impl<T: GWDevice + Object> Device for T {
|
||||
fn connection_list(&self) -> &[crate::network::Connection] {
|
||||
self.device_connections()
|
||||
}
|
||||
fn connection_list_mut(&mut self) -> &mut[Connection] {
|
||||
self.device_connections_mut()
|
||||
}
|
||||
fn device_pins(&self) -> Option<&[Option<ObjectID>]> {
|
||||
self.device_pins()
|
||||
}
|
||||
fn device_pins_mut(&self) -> Option<&mut[Option<ObjectID>]> {
|
||||
self.device_pins_mut()
|
||||
}
|
||||
fn has_reagents(&self) -> bool {
|
||||
self.device_info().has_reagents
|
||||
}
|
||||
fn has_lock_state(&self) -> bool {
|
||||
self.device_info().has_lock_state
|
||||
}
|
||||
fn has_mode_state(&self) -> bool {
|
||||
self.device_info().has_mode_state
|
||||
}
|
||||
fn has_open_state(&self) -> bool {
|
||||
self.device_info().has_open_state
|
||||
}
|
||||
fn has_on_off_state(&self) -> bool {
|
||||
self.device_info().has_on_off_state
|
||||
}
|
||||
fn has_activate_state(&self) -> bool {
|
||||
self.device_info().has_activate_state
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GWItem {
|
||||
fn item_info(&self) -> &ItemInfo;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
macro_rules! object_trait {
|
||||
(@intf {$trait_name:ident $trt:path}) => {
|
||||
(@intf {$trait_name:ident $trt:ident}) => {
|
||||
paste::paste! {
|
||||
#[allow(missing_docs, unused)]
|
||||
pub type [<$trt Ref>]<'a, T> = &'a dyn $trt<ID = <T as $trait_name>::ID>;
|
||||
@@ -7,7 +7,7 @@ macro_rules! object_trait {
|
||||
pub type [<$trt RefMut>]<'a, T> = &'a mut dyn $trt<ID = <T as $trait_name>::ID>;
|
||||
}
|
||||
};
|
||||
(@body $trait_name:ident $($trt:path),*) => {
|
||||
(@body $trait_name:ident { $($trt:ident),* }; ) => {
|
||||
type ID;
|
||||
fn id(&self) -> &Self::ID;
|
||||
fn prefab(&self) -> &crate::vm::object::Name;
|
||||
@@ -19,27 +19,30 @@ macro_rules! object_trait {
|
||||
|
||||
fn as_object_mut(&mut self) -> &mut dyn $trait_name<ID = Self::ID>;
|
||||
|
||||
|
||||
paste::paste!{$(
|
||||
$(
|
||||
paste::paste! {
|
||||
#[inline(always)]
|
||||
fn [<as_ $trt:snake>](&self) -> Option<[<$trt Ref>]<Self>> {
|
||||
None
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn [<as_ $trt:snake _mut>](&mut self) -> Option<[<$trt RefMut>]<Self>> {
|
||||
fn [<as_mut_ $trt:snake>](&mut self) -> Option<[<$trt RefMut>]<Self>> {
|
||||
None
|
||||
}
|
||||
)*}
|
||||
}
|
||||
)*
|
||||
};
|
||||
( $trait_name:ident $(: $($bound:tt)* )? {$($trt:path),*}) => {
|
||||
( $trait_name:ident $(: $($bound:tt)* )? {$($trt:ident),*}) => {
|
||||
$(
|
||||
$crate::vm::object::macros::object_trait!{@intf {$trait_name $trt}}
|
||||
)*
|
||||
|
||||
|
||||
#[doc = concat!("Generated with: ", stringify!($($trt),*))]
|
||||
pub trait $trait_name $(: $($bound)* )? {
|
||||
|
||||
$crate::vm::object::macros::object_trait!{@body $trait_name $($trt),*}
|
||||
$crate::vm::object::macros::object_trait!{@body $trait_name {$($trt),*}; }
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -91,7 +94,7 @@ macro_rules! ObjectInterface {
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn [<as_ $trt:snake _mut>](&mut self) -> Option<[<$trt RefMut>]<Self>> {
|
||||
fn [<as_mut_ $trt:snake>](&mut self) -> Option<[<$trt RefMut>]<Self>> {
|
||||
Some(self)
|
||||
}
|
||||
)*}
|
||||
@@ -508,25 +511,30 @@ macro_rules! tag_object_traits {
|
||||
{
|
||||
@tag
|
||||
tag=$trt_name:ident $(: $($obj_bound:tt)* )?;
|
||||
acc={ $($tagged_trt:ident,)* }
|
||||
acc={ $($tagged_trt:ident,)* };
|
||||
$(#[$attr:meta])*
|
||||
$viz:vis trait $trt:ident $(: $($trt_bound:path)* )? {
|
||||
$viz:vis trait $trt:ident $(: $trt_bound_first:tt $(+ $trt_bound_others:tt)* )? {
|
||||
$($tbody:tt)*
|
||||
}
|
||||
$($used:tt)*
|
||||
} => {
|
||||
#[doc = concat!("Autotagged with ", stringify!($trt_name))]
|
||||
$(#[$attr])*
|
||||
$viz trait $trt : $($($trt_bound)* +)? $trt_name {
|
||||
$viz trait $trt : $( $trt_bound_first $(+ $trt_bound_others)* +)? $trt_name {
|
||||
$($tbody)*
|
||||
}
|
||||
|
||||
$crate::vm::object::macros::tag_object_traits!{ @tag tag=$trt_name $(: $($obj_bound)* )?; acc={ $trt, $($tagged_trt,)* } $($used)* }
|
||||
$crate::vm::object::macros::tag_object_traits!{
|
||||
@tag
|
||||
tag=$trt_name $(: $($obj_bound)* )?;
|
||||
acc={ $trt, $($tagged_trt,)* };
|
||||
$($used)*
|
||||
}
|
||||
};
|
||||
{
|
||||
@tag
|
||||
tag=$trt_name:ident $(: $($obj_bound:tt)* )?;
|
||||
acc={ $($tagged_trt:ident,)* }
|
||||
acc={ $($tagged_trt:ident,)* };
|
||||
impl $name:ident for $trt:path {
|
||||
$($body:tt)*
|
||||
}
|
||||
@@ -536,12 +544,17 @@ macro_rules! tag_object_traits {
|
||||
impl $name for $trt {
|
||||
$($body)*
|
||||
}
|
||||
$crate::vm::object::macros::tag_object_traits!{ @tag tag=$trt_name $(: $($obj_bound)* )?; acc={ $($tagged_trt,)* } $($used)* }
|
||||
$crate::vm::object::macros::tag_object_traits!{
|
||||
@tag
|
||||
tag=$trt_name $(: $($obj_bound)* )?;
|
||||
acc={ $($tagged_trt,)* };
|
||||
$($used)*
|
||||
}
|
||||
};
|
||||
{
|
||||
@tag
|
||||
tag=$trt_name:ident $(: $($obj_bound:tt)* )?;
|
||||
acc={ $($tagged_trt:ident,)* }
|
||||
acc={ $($tagged_trt:ident,)* };
|
||||
} => {
|
||||
|
||||
// end tagged traits {$trt_name}
|
||||
@@ -549,7 +562,7 @@ macro_rules! tag_object_traits {
|
||||
$crate::vm::object::macros::object_trait!($trt_name $(: $($obj_bound)* )? { $($tagged_trt),* });
|
||||
};
|
||||
{ #![object_trait($trt_name:ident $(: $($bound:tt)* )? )] $($tree:tt)* } => {
|
||||
$crate::vm::object::macros::tag_object_traits!{ @tag tag=$trt_name; acc={} $($tree)* }
|
||||
$crate::vm::object::macros::tag_object_traits!{ @tag tag=$trt_name; acc={}; $($tree)* }
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -268,6 +268,12 @@ impl SourceCode for ItemIntegratedCircuit10 {
|
||||
}
|
||||
|
||||
impl IntegratedCircuit for ItemIntegratedCircuit10 {
|
||||
fn get_circuit_holder(&self, vm: &VM) -> Option<CircuitHolderRef> {
|
||||
// FIXME: implement correctly
|
||||
self.parent_slot().map(|parent_slot| {
|
||||
parent_slot.parent
|
||||
})
|
||||
}
|
||||
fn get_instruction_pointer(&self) -> f64 {
|
||||
self.ip as f64
|
||||
}
|
||||
@@ -950,6 +956,364 @@ impl BrgtzInstruction for ItemIntegratedCircuit10 {
|
||||
}
|
||||
}
|
||||
|
||||
impl BgeInstruction for ItemIntegratedCircuit10 {
|
||||
/// bge a(r?|num) b(r?|num) c(r?|num)
|
||||
fn execute_bge(
|
||||
&mut self,
|
||||
vm: &VM,
|
||||
a: &Operand,
|
||||
b: &Operand,
|
||||
c: &Operand,
|
||||
) -> Result<(), ICError> {
|
||||
let a = a.as_value(self, InstructionOp::Bge, 1)?;
|
||||
let b = b.as_value(self, InstructionOp::Bge, 2)?;
|
||||
let c = c.as_value(self, InstructionOp::Bge, 3)?;
|
||||
if a >= b {
|
||||
self.set_next_instruction(c);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl BgealInstruction for ItemIntegratedCircuit10 {
|
||||
/// bgeal a(r?|num) b(r?|num) c(r?|num)
|
||||
fn execute_bgeal(
|
||||
&mut self,
|
||||
vm: &VM,
|
||||
a: &Operand,
|
||||
b: &Operand,
|
||||
c: &Operand,
|
||||
) -> Result<(), ICError> {
|
||||
let a = a.as_value(self, InstructionOp::Bgeal, 1)?;
|
||||
let b = b.as_value(self, InstructionOp::Bgeal, 2)?;
|
||||
let c = c.as_value(self, InstructionOp::Bgeal, 3)?;
|
||||
if a >= b {
|
||||
self.set_next_instruction(c);
|
||||
self.al();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl BrgeInstruction for ItemIntegratedCircuit10 {
|
||||
/// brge a(r?|num) b(r?|num) c(r?|num)
|
||||
fn execute_brge(
|
||||
&mut self,
|
||||
vm: &VM,
|
||||
a: &Operand,
|
||||
b: &Operand,
|
||||
c: &Operand,
|
||||
) -> Result<(), ICError> {
|
||||
let a = a.as_value(self, InstructionOp::Brge, 1)?;
|
||||
let b = b.as_value(self, InstructionOp::Brge, 2)?;
|
||||
let c = c.as_value(self, InstructionOp::Brge, 3)?;
|
||||
if a >= b {
|
||||
self.set_next_instruction_relative(c);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl BgezInstruction for ItemIntegratedCircuit10 {
|
||||
/// bgez a(r?|num) b(r?|num)
|
||||
fn execute_bgez(&mut self, vm: &VM, a: &Operand, b: &Operand) -> Result<(), ICError> {
|
||||
let a = a.as_value(self, InstructionOp::Bgez, 1)?;
|
||||
let b = b.as_value(self, InstructionOp::Bgez, 2)?;
|
||||
if a >= 0.0 {
|
||||
self.set_next_instruction(b);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl BgezalInstruction for ItemIntegratedCircuit10 {
|
||||
/// bgezal a(r?|num) b(r?|num)
|
||||
fn execute_bgezal(&mut self, vm: &VM, a: &Operand, b: &Operand) -> Result<(), ICError> {
|
||||
let a = a.as_value(self, InstructionOp::Bgeal, 1)?;
|
||||
let b = b.as_value(self, InstructionOp::Bgeal, 2)?;
|
||||
if a >= 0.0 {
|
||||
self.set_next_instruction(b);
|
||||
self.al();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl BrgezInstruction for ItemIntegratedCircuit10 {
|
||||
/// brgez a(r?|num) b(r?|num)
|
||||
fn execute_brgez(&mut self, vm: &VM, a: &Operand, b: &Operand) -> Result<(), ICError> {
|
||||
let a = a.as_value(self, InstructionOp::Brgez, 1)?;
|
||||
let b = b.as_value(self, InstructionOp::Brgez, 2)?;
|
||||
if a >= 0.0 {
|
||||
self.set_next_instruction_relative(b);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl BapInstruction for ItemIntegratedCircuit10 {
|
||||
/// bap a(r?|num) b(r?|num) c(r?|num) d(r?|num)
|
||||
fn execute_bap(
|
||||
&mut self,
|
||||
vm: &VM,
|
||||
a: &Operand,
|
||||
b: &Operand,
|
||||
c: &Operand,
|
||||
d: &Operand,
|
||||
) -> Result<(), ICError> {
|
||||
let a = a.as_value(self, InstructionOp::Bap, 1)?;
|
||||
let b = b.as_value(self, InstructionOp::Bap, 2)?;
|
||||
let c = c.as_value(self, InstructionOp::Bap, 3)?;
|
||||
let d = d.as_value(self, InstructionOp::Bap, 4)?;
|
||||
if f64::abs(a - b) <= f64::max(c * f64::max(a.abs(), b.abs()), f64::EPSILON * 8.0) {
|
||||
self.set_next_instruction(d);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl BapalInstruction for ItemIntegratedCircuit10 {
|
||||
/// bapal a(r?|num) b(r?|num) c(r?|num) d(r?|num)
|
||||
fn execute_bapal(
|
||||
&mut self,
|
||||
vm: &VM,
|
||||
a: &Operand,
|
||||
b: &Operand,
|
||||
c: &Operand,
|
||||
d: &Operand,
|
||||
) -> Result<(), ICError> {
|
||||
let a = a.as_value(self, InstructionOp::Bapal, 1)?;
|
||||
let b = b.as_value(self, InstructionOp::Bapal, 2)?;
|
||||
let c = c.as_value(self, InstructionOp::Bapal, 3)?;
|
||||
let d = d.as_value(self, InstructionOp::Bapal, 4)?;
|
||||
if f64::abs(a - b) <= f64::max(c * f64::max(a.abs(), b.abs()), f64::EPSILON * 8.0) {
|
||||
self.set_next_instruction(d);
|
||||
self.al();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl BrapInstruction for ItemIntegratedCircuit10 {
|
||||
/// brap a(r?|num) b(r?|num) c(r?|num) d(r?|num)
|
||||
fn execute_brap(
|
||||
&mut self,
|
||||
vm: &VM,
|
||||
a: &Operand,
|
||||
b: &Operand,
|
||||
c: &Operand,
|
||||
d: &Operand,
|
||||
) -> Result<(), ICError> {
|
||||
let a = a.as_value(self, InstructionOp::Brap, 1)?;
|
||||
let b = b.as_value(self, InstructionOp::Brap, 2)?;
|
||||
let c = c.as_value(self, InstructionOp::Brap, 3)?;
|
||||
let d = d.as_value(self, InstructionOp::Brap, 4)?;
|
||||
if f64::abs(a - b) <= f64::max(c * f64::max(a.abs(), b.abs()), f64::EPSILON * 8.0) {
|
||||
self.set_next_instruction_relative(d);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl BapzInstruction for ItemIntegratedCircuit10 {
|
||||
/// bapz a(r?|num) b(r?|num) c(r?|num)
|
||||
fn execute_bapz(
|
||||
&mut self,
|
||||
vm: &VM,
|
||||
a: &Operand,
|
||||
b: &Operand,
|
||||
c: &Operand,
|
||||
) -> Result<(), ICError> {
|
||||
let a = a.as_value(self, InstructionOp::Bapz, 1)?;
|
||||
let b = b.as_value(self, InstructionOp::Bapz, 2)?;
|
||||
let c = c.as_value(self, InstructionOp::Bapz, 3)?;
|
||||
if a.abs() <= f64::max(b * a.abs(), f64::EPSILON * 8.0) {
|
||||
} else {
|
||||
self.set_next_instruction(c);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl BapzalInstruction for ItemIntegratedCircuit10 {
|
||||
/// bapzal a(r?|num) b(r?|num) c(r?|num)
|
||||
fn execute_bapzal(
|
||||
&mut self,
|
||||
vm: &VM,
|
||||
a: &Operand,
|
||||
b: &Operand,
|
||||
c: &Operand,
|
||||
) -> Result<(), ICError> {
|
||||
let a = a.as_value(self, InstructionOp::Bapzal, 1)?;
|
||||
let b = b.as_value(self, InstructionOp::Bapzal, 2)?;
|
||||
let c = c.as_value(self, InstructionOp::Bapzal, 3)?;
|
||||
if a.abs() <= f64::max(b * a.abs(), f64::EPSILON * 8.0) {
|
||||
} else {
|
||||
self.set_next_instruction(c);
|
||||
self.al();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl BrapzInstruction for ItemIntegratedCircuit10 {
|
||||
/// brapz a(r?|num) b(r?|num) c(r?|num)
|
||||
fn execute_brapz(
|
||||
&mut self,
|
||||
vm: &VM,
|
||||
a: &Operand,
|
||||
b: &Operand,
|
||||
c: &Operand,
|
||||
) -> Result<(), ICError> {
|
||||
let a = a.as_value(self, InstructionOp::Brapz, 1)?;
|
||||
let b = b.as_value(self, InstructionOp::Brapz, 2)?;
|
||||
let c = c.as_value(self, InstructionOp::Brapz, 3)?;
|
||||
if a.abs() <= f64::max(b * a.abs(), f64::EPSILON * 8.0) {
|
||||
} else {
|
||||
self.set_next_instruction_relative(c);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl BnaInstruction for ItemIntegratedCircuit10 {
|
||||
/// bna a(r?|num) b(r?|num) c(r?|num) d(r?|num)
|
||||
fn execute_bna(
|
||||
&mut self,
|
||||
vm: &VM,
|
||||
a: &Operand,
|
||||
b: &Operand,
|
||||
c: &Operand,
|
||||
d: &Operand,
|
||||
) -> Result<(), ICError> {
|
||||
let a = a.as_value(self, InstructionOp::Bna, 1)?;
|
||||
let b = b.as_value(self, InstructionOp::Bna, 2)?;
|
||||
let c = c.as_value(self, InstructionOp::Bna, 3)?;
|
||||
let d = d.as_value(self, InstructionOp::Bna, 4)?;
|
||||
if f64::abs(a - b) > f64::max(c * f64::max(a.abs(), b.abs()), f64::EPSILON * 8.0) {
|
||||
self.set_next_instruction(d);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
impl BnaalInstruction for ItemIntegratedCircuit10 {
|
||||
/// bnaal a(r?|num) b(r?|num) c(r?|num) d(r?|num)
|
||||
fn execute_bnaal(
|
||||
&mut self,
|
||||
vm: &VM,
|
||||
a: &Operand,
|
||||
b: &Operand,
|
||||
c: &Operand,
|
||||
d: &Operand,
|
||||
) -> Result<(), ICError> {
|
||||
let a = a.as_value(self, InstructionOp::Bnaal, 1)?;
|
||||
let b = b.as_value(self, InstructionOp::Bnaal, 2)?;
|
||||
let c = c.as_value(self, InstructionOp::Bnaal, 3)?;
|
||||
let d = d.as_value(self, InstructionOp::Bnaal, 4)?;
|
||||
if f64::abs(a - b) > f64::max(c * f64::max(a.abs(), b.abs()), f64::EPSILON * 8.0) {
|
||||
self.set_next_instruction(d);
|
||||
self.al();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
impl BrnaInstruction for ItemIntegratedCircuit10 {
|
||||
/// brna a(r?|num) b(r?|num) c(r?|num) d(r?|num)
|
||||
fn execute_brna(
|
||||
&mut self,
|
||||
vm: &VM,
|
||||
a: &Operand,
|
||||
b: &Operand,
|
||||
c: &Operand,
|
||||
d: &Operand,
|
||||
) -> Result<(), ICError> {
|
||||
let a = a.as_value(self, InstructionOp::Brna, 1)?;
|
||||
let b = b.as_value(self, InstructionOp::Brna, 2)?;
|
||||
let c = c.as_value(self, InstructionOp::Brna, 3)?;
|
||||
let d = d.as_value(self, InstructionOp::Brna, 4)?;
|
||||
if f64::abs(a - b) > f64::max(c * f64::max(a.abs(), b.abs()), f64::EPSILON * 8.0) {
|
||||
self.set_next_instruction_relative(d);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl BnazInstruction for ItemIntegratedCircuit10 {
|
||||
/// bnaz a(r?|num) b(r?|num) c(r?|num)
|
||||
fn execute_bnaz(
|
||||
&mut self,
|
||||
vm: &VM,
|
||||
a: &Operand,
|
||||
b: &Operand,
|
||||
c: &Operand,
|
||||
) -> Result<(), ICError> {
|
||||
let a = a.as_value(self, InstructionOp::Bnaz, 1)?;
|
||||
let b = b.as_value(self, InstructionOp::Bnaz, 2)?;
|
||||
let c = c.as_value(self, InstructionOp::Bnaz, 3)?;
|
||||
if a.abs() > f64::max(b * a.abs(), f64::EPSILON * 8.0) {
|
||||
self.set_next_instruction(c);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
impl BnazalInstruction for ItemIntegratedCircuit10 {
|
||||
/// bnazal a(r?|num) b(r?|num) c(r?|num)
|
||||
fn execute_bnazal(
|
||||
&mut self,
|
||||
vm: &VM,
|
||||
a: &Operand,
|
||||
b: &Operand,
|
||||
c: &Operand,
|
||||
) -> Result<(), ICError> {
|
||||
let a = a.as_value(self, InstructionOp::Bnazal, 1)?;
|
||||
let b = b.as_value(self, InstructionOp::Bnazal, 2)?;
|
||||
let c = c.as_value(self, InstructionOp::Bnazal, 3)?;
|
||||
if a.abs() > f64::max(b * a.abs(), f64::EPSILON * 8.0) {
|
||||
self.set_next_instruction(c);
|
||||
self.al();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
impl BrnazInstruction for ItemIntegratedCircuit10 {
|
||||
/// brnaz a(r?|num) b(r?|num) c(r?|num)
|
||||
fn execute_brnaz(
|
||||
&mut self,
|
||||
vm: &VM,
|
||||
a: &Operand,
|
||||
b: &Operand,
|
||||
c: &Operand,
|
||||
) -> Result<(), ICError> {
|
||||
let a = a.as_value(self, InstructionOp::Brnaz, 1)?;
|
||||
let b = b.as_value(self, InstructionOp::Brnaz, 2)?;
|
||||
let c = c.as_value(self, InstructionOp::Brnaz, 3)?;
|
||||
if a.abs() > f64::max(b * a.abs(), f64::EPSILON * 8.0) {
|
||||
self.set_next_instruction_relative(c);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
impl BdseInstruction for ItemIntegratedCircuit10 {
|
||||
/// bdse d? a(r?|num)
|
||||
fn execute_bdse(&mut self, vm: &VM, d: &Operand, a: &Operand) -> Result<(), ICError> {
|
||||
let (device, _connection) = d.as_device(self, InstructionOp::Bdse, 1)?;
|
||||
let a = a.as_value(self, InstructionOp::Bdse, 2)?;
|
||||
if device.is_some() {
|
||||
// FIXME: collect device and get logicable
|
||||
self.set_next_instruction(a);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
impl BdsealInstruction for ItemIntegratedCircuit10 {
|
||||
/// bdseal d? a(r?|num)
|
||||
fn execute_bdseal(&mut self, vm: &VM, d: &Operand, a: &Operand) -> Result<(), ICError>;
|
||||
}
|
||||
impl BrdseInstruction for ItemIntegratedCircuit10 {
|
||||
/// brdse d? a(r?|num)
|
||||
fn execute_brdse(&mut self, vm: &VM, d: &Operand, a: &Operand) -> Result<(), ICError>;
|
||||
}
|
||||
|
||||
impl AbsInstruction for ItemIntegratedCircuit10 {
|
||||
/// abs r? a(r?|num)
|
||||
fn execute_abs(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>;
|
||||
@@ -997,48 +1361,6 @@ impl Atan2Instruction for ItemIntegratedCircuit10 {
|
||||
b: &Operand,
|
||||
) -> Result<(), ICError>;
|
||||
}
|
||||
impl BapInstruction for ItemIntegratedCircuit10 {
|
||||
/// bap a(r?|num) b(r?|num) c(r?|num) d(r?|num)
|
||||
fn execute_bap(
|
||||
&mut self,
|
||||
vm: &VM,
|
||||
a: &Operand,
|
||||
b: &Operand,
|
||||
c: &Operand,
|
||||
d: &Operand,
|
||||
) -> Result<(), ICError>;
|
||||
}
|
||||
impl BapalInstruction for ItemIntegratedCircuit10 {
|
||||
/// bapal a(r?|num) b(r?|num) c(r?|num) d(r?|num)
|
||||
fn execute_bapal(
|
||||
&mut self,
|
||||
vm: &VM,
|
||||
a: &Operand,
|
||||
b: &Operand,
|
||||
c: &Operand,
|
||||
d: &Operand,
|
||||
) -> Result<(), ICError>;
|
||||
}
|
||||
impl BapzInstruction for ItemIntegratedCircuit10 {
|
||||
/// bapz a(r?|num) b(r?|num) c(r?|num)
|
||||
fn execute_bapz(
|
||||
&mut self,
|
||||
vm: &VM,
|
||||
a: &Operand,
|
||||
b: &Operand,
|
||||
c: &Operand,
|
||||
) -> Result<(), ICError>;
|
||||
}
|
||||
impl BapzalInstruction for ItemIntegratedCircuit10 {
|
||||
/// bapzal a(r?|num) b(r?|num) c(r?|num)
|
||||
fn execute_bapzal(
|
||||
&mut self,
|
||||
vm: &VM,
|
||||
a: &Operand,
|
||||
b: &Operand,
|
||||
c: &Operand,
|
||||
) -> Result<(), ICError>;
|
||||
}
|
||||
impl BdnsInstruction for ItemIntegratedCircuit10 {
|
||||
/// bdns d? a(r?|num)
|
||||
fn execute_bdns(&mut self, vm: &VM, d: &Operand, a: &Operand) -> Result<(), ICError>;
|
||||
@@ -1047,156 +1369,18 @@ impl BdnsalInstruction for ItemIntegratedCircuit10 {
|
||||
/// bdnsal d? a(r?|num)
|
||||
fn execute_bdnsal(&mut self, vm: &VM, d: &Operand, a: &Operand) -> Result<(), ICError>;
|
||||
}
|
||||
impl BdseInstruction for ItemIntegratedCircuit10 {
|
||||
/// bdse d? a(r?|num)
|
||||
fn execute_bdse(&mut self, vm: &VM, d: &Operand, a: &Operand) -> Result<(), ICError>;
|
||||
}
|
||||
impl BdsealInstruction for ItemIntegratedCircuit10 {
|
||||
/// bdseal d? a(r?|num)
|
||||
fn execute_bdseal(&mut self, vm: &VM, d: &Operand, a: &Operand) -> Result<(), ICError>;
|
||||
}
|
||||
impl BgeInstruction for ItemIntegratedCircuit10 {
|
||||
/// bge a(r?|num) b(r?|num) c(r?|num)
|
||||
fn execute_bge(
|
||||
&mut self,
|
||||
vm: &VM,
|
||||
a: &Operand,
|
||||
b: &Operand,
|
||||
c: &Operand,
|
||||
) -> Result<(), ICError>;
|
||||
}
|
||||
impl BgealInstruction for ItemIntegratedCircuit10 {
|
||||
/// bgeal a(r?|num) b(r?|num) c(r?|num)
|
||||
fn execute_bgeal(
|
||||
&mut self,
|
||||
vm: &VM,
|
||||
a: &Operand,
|
||||
b: &Operand,
|
||||
c: &Operand,
|
||||
) -> Result<(), ICError>;
|
||||
}
|
||||
impl BgezInstruction for ItemIntegratedCircuit10 {
|
||||
/// bgez a(r?|num) b(r?|num)
|
||||
fn execute_bgez(&mut self, vm: &VM, a: &Operand, b: &Operand) -> Result<(), ICError>;
|
||||
}
|
||||
impl BgezalInstruction for ItemIntegratedCircuit10 {
|
||||
/// bgezal a(r?|num) b(r?|num)
|
||||
fn execute_bgezal(&mut self, vm: &VM, a: &Operand, b: &Operand) -> Result<(), ICError>;
|
||||
}
|
||||
impl BnaInstruction for ItemIntegratedCircuit10 {
|
||||
/// bna a(r?|num) b(r?|num) c(r?|num) d(r?|num)
|
||||
fn execute_bna(
|
||||
&mut self,
|
||||
vm: &VM,
|
||||
a: &Operand,
|
||||
b: &Operand,
|
||||
c: &Operand,
|
||||
d: &Operand,
|
||||
) -> Result<(), ICError>;
|
||||
}
|
||||
impl BnaalInstruction for ItemIntegratedCircuit10 {
|
||||
/// bnaal a(r?|num) b(r?|num) c(r?|num) d(r?|num)
|
||||
fn execute_bnaal(
|
||||
&mut self,
|
||||
vm: &VM,
|
||||
a: &Operand,
|
||||
b: &Operand,
|
||||
c: &Operand,
|
||||
d: &Operand,
|
||||
) -> Result<(), ICError>;
|
||||
}
|
||||
impl BnanInstruction for ItemIntegratedCircuit10 {
|
||||
/// bnan a(r?|num) b(r?|num)
|
||||
fn execute_bnan(&mut self, vm: &VM, a: &Operand, b: &Operand) -> Result<(), ICError>;
|
||||
}
|
||||
impl BnazInstruction for ItemIntegratedCircuit10 {
|
||||
/// bnaz a(r?|num) b(r?|num) c(r?|num)
|
||||
fn execute_bnaz(
|
||||
&mut self,
|
||||
vm: &VM,
|
||||
a: &Operand,
|
||||
b: &Operand,
|
||||
c: &Operand,
|
||||
) -> Result<(), ICError>;
|
||||
}
|
||||
impl BnazalInstruction for ItemIntegratedCircuit10 {
|
||||
/// bnazal a(r?|num) b(r?|num) c(r?|num)
|
||||
fn execute_bnazal(
|
||||
&mut self,
|
||||
vm: &VM,
|
||||
a: &Operand,
|
||||
b: &Operand,
|
||||
c: &Operand,
|
||||
) -> Result<(), ICError>;
|
||||
}
|
||||
impl BrapInstruction for ItemIntegratedCircuit10 {
|
||||
/// brap a(r?|num) b(r?|num) c(r?|num) d(r?|num)
|
||||
fn execute_brap(
|
||||
&mut self,
|
||||
vm: &VM,
|
||||
a: &Operand,
|
||||
b: &Operand,
|
||||
c: &Operand,
|
||||
d: &Operand,
|
||||
) -> Result<(), ICError>;
|
||||
}
|
||||
impl BrapzInstruction for ItemIntegratedCircuit10 {
|
||||
/// brapz a(r?|num) b(r?|num) c(r?|num)
|
||||
fn execute_brapz(
|
||||
&mut self,
|
||||
vm: &VM,
|
||||
a: &Operand,
|
||||
b: &Operand,
|
||||
c: &Operand,
|
||||
) -> Result<(), ICError>;
|
||||
}
|
||||
impl BrdnsInstruction for ItemIntegratedCircuit10 {
|
||||
/// brdns d? a(r?|num)
|
||||
fn execute_brdns(&mut self, vm: &VM, d: &Operand, a: &Operand) -> Result<(), ICError>;
|
||||
}
|
||||
impl BrdseInstruction for ItemIntegratedCircuit10 {
|
||||
/// brdse d? a(r?|num)
|
||||
fn execute_brdse(&mut self, vm: &VM, d: &Operand, a: &Operand) -> Result<(), ICError>;
|
||||
}
|
||||
impl BrgeInstruction for ItemIntegratedCircuit10 {
|
||||
/// brge a(r?|num) b(r?|num) c(r?|num)
|
||||
fn execute_brge(
|
||||
&mut self,
|
||||
vm: &VM,
|
||||
a: &Operand,
|
||||
b: &Operand,
|
||||
c: &Operand,
|
||||
) -> Result<(), ICError>;
|
||||
}
|
||||
impl BrgezInstruction for ItemIntegratedCircuit10 {
|
||||
/// brgez a(r?|num) b(r?|num)
|
||||
fn execute_brgez(&mut self, vm: &VM, a: &Operand, b: &Operand) -> Result<(), ICError>;
|
||||
}
|
||||
impl BrnaInstruction for ItemIntegratedCircuit10 {
|
||||
/// brna a(r?|num) b(r?|num) c(r?|num) d(r?|num)
|
||||
fn execute_brna(
|
||||
&mut self,
|
||||
vm: &VM,
|
||||
a: &Operand,
|
||||
b: &Operand,
|
||||
c: &Operand,
|
||||
d: &Operand,
|
||||
) -> Result<(), ICError>;
|
||||
}
|
||||
impl BrnanInstruction for ItemIntegratedCircuit10 {
|
||||
/// brnan a(r?|num) b(r?|num)
|
||||
fn execute_brnan(&mut self, vm: &VM, a: &Operand, b: &Operand) -> Result<(), ICError>;
|
||||
}
|
||||
impl BrnazInstruction for ItemIntegratedCircuit10 {
|
||||
/// brnaz a(r?|num) b(r?|num) c(r?|num)
|
||||
fn execute_brnaz(
|
||||
&mut self,
|
||||
vm: &VM,
|
||||
a: &Operand,
|
||||
b: &Operand,
|
||||
c: &Operand,
|
||||
) -> Result<(), ICError>;
|
||||
}
|
||||
impl CeilInstruction for ItemIntegratedCircuit10 {
|
||||
/// ceil r? a(r?|num)
|
||||
fn execute_ceil(&mut self, vm: &VM, r: &Operand, a: &Operand) -> Result<(), ICError>;
|
||||
|
||||
@@ -53,7 +53,22 @@ impl ObjectTemplate {
|
||||
}
|
||||
}
|
||||
|
||||
fn build(&self, id: ObjectID) -> VMObject {
|
||||
pub fn object(&self) -> Option<&ObjectInfo> {
|
||||
use ObjectTemplate::*;
|
||||
match self {
|
||||
Structure(s) => s.object.as_ref(),
|
||||
StructureSlots(s) => s.object.as_ref(),
|
||||
StructureLogic(s) => s.object.as_ref(),
|
||||
StructureLogicDevice(s) => s.object.as_ref(),
|
||||
StructureLogicDeviceMemory(s) => s.object.as_ref(),
|
||||
Item(i) => i.object.as_ref(),
|
||||
ItemSlots(i) => i.object.as_ref(),
|
||||
ItemLogic(i) => i.object.as_ref(),
|
||||
ItemLogicMemory(i) => i.object.as_ref(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build(&self, id: ObjectID) -> VMObject {
|
||||
if let Some(obj) = stationpedia::object_from_prefab_template(&self, id) {
|
||||
obj
|
||||
} else {
|
||||
@@ -61,6 +76,120 @@ impl ObjectTemplate {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn connected_networks(&self) -> Vec<ObjectID> {
|
||||
use ObjectTemplate::*;
|
||||
match self {
|
||||
StructureLogicDevice(s) => s
|
||||
.device
|
||||
.connection_list
|
||||
.iter()
|
||||
.filter_map(|conn| conn.network.as_ref())
|
||||
.copied()
|
||||
.collect(),
|
||||
StructureLogicDeviceMemory(s) => s
|
||||
.device
|
||||
.connection_list
|
||||
.iter()
|
||||
.filter_map(|conn| conn.network.as_ref())
|
||||
.copied()
|
||||
.collect(),
|
||||
_ => vec![],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn contained_object_ids(&self) -> Vec<ObjectID> {
|
||||
use ObjectTemplate::*;
|
||||
match self {
|
||||
StructureSlots(s) => s
|
||||
.slots
|
||||
.iter()
|
||||
.filter_map(|info| {
|
||||
info.occupant
|
||||
.as_ref()
|
||||
.map(|obj| obj.object().map(|obj_info| obj_info.id).flatten())
|
||||
})
|
||||
.flatten()
|
||||
.collect(),
|
||||
StructureLogic(s) => s
|
||||
.slots
|
||||
.iter()
|
||||
.filter_map(|info| {
|
||||
info.occupant
|
||||
.as_ref()
|
||||
.map(|obj| obj.object().map(|obj_info| obj_info.id).flatten())
|
||||
})
|
||||
.flatten()
|
||||
.collect(),
|
||||
StructureLogicDevice(s) => s
|
||||
.slots
|
||||
.iter()
|
||||
.filter_map(|info| {
|
||||
info.occupant
|
||||
.as_ref()
|
||||
.map(|obj| obj.object().map(|obj_info| obj_info.id).flatten())
|
||||
})
|
||||
.flatten()
|
||||
.collect(),
|
||||
StructureLogicDeviceMemory(s) => s
|
||||
.slots
|
||||
.iter()
|
||||
.filter_map(|info| {
|
||||
info.occupant
|
||||
.as_ref()
|
||||
.map(|obj| obj.object().map(|obj_info| obj_info.id).flatten())
|
||||
})
|
||||
.flatten()
|
||||
.collect(),
|
||||
ItemSlots(i) => i
|
||||
.slots
|
||||
.iter()
|
||||
.filter_map(|info| {
|
||||
info.occupant
|
||||
.as_ref()
|
||||
.map(|obj| obj.object().map(|obj_info| obj_info.id).flatten())
|
||||
})
|
||||
.flatten()
|
||||
.collect(),
|
||||
ItemLogic(i) => i
|
||||
.slots
|
||||
.iter()
|
||||
.filter_map(|info| {
|
||||
info.occupant
|
||||
.as_ref()
|
||||
.map(|obj| obj.object().map(|obj_info| obj_info.id).flatten())
|
||||
})
|
||||
.flatten()
|
||||
.collect(),
|
||||
ItemLogicMemory(i) => i
|
||||
.slots
|
||||
.iter()
|
||||
.filter_map(|info| {
|
||||
info.occupant
|
||||
.as_ref()
|
||||
.map(|obj| obj.object().map(|obj_info| obj_info.id).flatten())
|
||||
})
|
||||
.flatten()
|
||||
.collect(),
|
||||
_ => vec![],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn templates_from_slots(&self) -> Vec<Option<ObjectTemplate>> {
|
||||
use ObjectTemplate::*;
|
||||
match self {
|
||||
StructureSlots(s) => s.slots.iter().map(|info| info.occupant.clone()).collect(),
|
||||
StructureLogic(s) => s.slots.iter().map(|info| info.occupant.clone()).collect(),
|
||||
StructureLogicDevice(s) => s.slots.iter().map(|info| info.occupant.clone()).collect(),
|
||||
StructureLogicDeviceMemory(s) => {
|
||||
s.slots.iter().map(|info| info.occupant.clone()).collect()
|
||||
}
|
||||
ItemSlots(i) => i.slots.iter().map(|info| info.occupant.clone()).collect(),
|
||||
ItemLogic(i) => i.slots.iter().map(|info| info.occupant.clone()).collect(),
|
||||
ItemLogicMemory(i) => i.slots.iter().map(|info| info.occupant.clone()).collect(),
|
||||
_ => vec![],
|
||||
}
|
||||
}
|
||||
|
||||
fn build_generic(&self, id: ObjectID) -> VMObject {
|
||||
use ObjectTemplate::*;
|
||||
match self {
|
||||
@@ -411,18 +540,20 @@ pub struct PrefabInfo {
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ObjectInfo {
|
||||
pub name: Option<String>,
|
||||
pub id: Option<ObjectID>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct SlotInfo {
|
||||
pub name: String,
|
||||
pub typ: SlotClass,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub occupant: Option<ObjectTemplate>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
|
||||
@@ -437,13 +568,15 @@ pub struct LogicTypes {
|
||||
pub types: BTreeMap<LogicType, MemoryAccess>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct LogicInfo {
|
||||
pub logic_slot_types: BTreeMap<u32, LogicSlotTypes>,
|
||||
pub logic_types: LogicTypes,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub modes: Option<BTreeMap<u32, String>>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub logic_values: Option<BTreeMap<LogicType, f64>>,
|
||||
pub transmission_receiver: bool,
|
||||
pub wireless_logic: bool,
|
||||
pub circuit_holder: bool,
|
||||
@@ -468,6 +601,8 @@ pub struct ItemInfo {
|
||||
pub struct ConnectionInfo {
|
||||
pub typ: ConnectionType,
|
||||
pub role: ConnectionRole,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub network: Option<ObjectID>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
|
||||
@@ -476,6 +611,8 @@ pub struct DeviceInfo {
|
||||
pub connection_list: Vec<ConnectionInfo>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub device_pins_length: Option<i64>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub device_pins: Option<Vec<Option<ObjectID>>>,
|
||||
pub has_activate_state: bool,
|
||||
pub has_atmosphere: bool,
|
||||
pub has_color_state: bool,
|
||||
|
||||
@@ -2,12 +2,13 @@ use serde_derive::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
errors::ICError,
|
||||
network::Connection,
|
||||
vm::{
|
||||
enums::{
|
||||
basic_enums::{Class as SlotClass, GasType, SortingClass},
|
||||
script_enums::{LogicSlotType, LogicType},
|
||||
},
|
||||
instructions::Instruction,
|
||||
instructions::{traits::ICInstructable, Instruction},
|
||||
object::{
|
||||
errors::{LogicError, MemoryError},
|
||||
macros::tag_object_traits,
|
||||
@@ -16,7 +17,6 @@ use crate::{
|
||||
VM,
|
||||
},
|
||||
};
|
||||
|
||||
use std::{collections::BTreeMap, fmt::Debug};
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
@@ -55,8 +55,8 @@ tag_object_traits! {
|
||||
fn set_logic(&mut self, lt: LogicType, value: f64, force: bool) -> Result<(), LogicError>;
|
||||
fn get_logic(&self, lt: LogicType) -> Result<f64, LogicError>;
|
||||
|
||||
fn can_slot_logic_read(&self, slt: LogicSlotType, index: usize) -> bool;
|
||||
fn get_slot_logic(&self, slt: LogicSlotType, index: usize, vm: &VM) -> Result<f64, LogicError>;
|
||||
fn can_slot_logic_read(&self, slt: LogicSlotType, index: f64) -> bool;
|
||||
fn get_slot_logic(&self, slt: LogicSlotType, index: f64, vm: &VM) -> Result<f64, LogicError>;
|
||||
}
|
||||
|
||||
pub trait SourceCode {
|
||||
@@ -66,7 +66,7 @@ tag_object_traits! {
|
||||
fn get_line(&self, line: usize) -> Result<&Instruction, ICError>;
|
||||
}
|
||||
|
||||
pub trait CircuitHolder: Logicable {
|
||||
pub trait CircuitHolder: Logicable + Storage {
|
||||
fn clear_error(&mut self);
|
||||
fn set_error(&mut self, state: i32);
|
||||
fn get_logicable_from_index(&self, device: usize, vm: &VM) -> Option<LogicableRef<Self>>;
|
||||
@@ -77,9 +77,46 @@ tag_object_traits! {
|
||||
fn set_source_code(&self, code: String);
|
||||
fn get_batch(&self) -> Vec<LogicableRef<Self>>;
|
||||
fn get_batch_mut(&self) -> Vec<LogicableRefMut<Self>>;
|
||||
fn get_ic(&self) -> Option<ObjectID>;
|
||||
}
|
||||
|
||||
pub trait Programmable: crate::vm::instructions::traits::ICInstructable {
|
||||
pub trait Item {
|
||||
fn consumable(&self) -> bool;
|
||||
fn filter_type(&self) -> Option<GasType>;
|
||||
fn ingredient(&self) -> bool;
|
||||
fn max_quantity(&self) -> u32;
|
||||
fn reagents(&self) -> Option<&BTreeMap<String, f64>>;
|
||||
fn slot_class(&self) -> SlotClass;
|
||||
fn sorting_class(&self) -> SortingClass;
|
||||
fn parent_slot(&self) -> Option<ParentSlotInfo>;
|
||||
}
|
||||
|
||||
pub trait IntegratedCircuit: Logicable + MemoryWritable + SourceCode + Item {
|
||||
fn get_circuit_holder(&self, vm: &VM) -> Option<CircuitHolderRef<Self>>;
|
||||
fn get_instruction_pointer(&self) -> f64;
|
||||
fn set_next_instruction(&mut self, next_instruction: f64);
|
||||
fn set_next_instruction_relative(&mut self, offset: f64) {
|
||||
self.set_next_instruction(self.get_instruction_pointer() + offset);
|
||||
}
|
||||
fn reset(&mut self);
|
||||
fn get_real_target(&self, indirection: u32, target: u32) -> Result<f64, ICError>;
|
||||
fn get_register(&self, indirection: u32, target: u32) -> Result<f64, ICError>;
|
||||
fn set_register(&mut self, indirection: u32, target: u32, val: f64) -> Result<f64, ICError>;
|
||||
fn set_return_address(&mut self, addr: f64);
|
||||
fn al(&mut self) {
|
||||
self.set_return_address(self.get_instruction_pointer() + 1.0);
|
||||
}
|
||||
fn push_stack(&mut self, val: f64) -> Result<f64, ICError>;
|
||||
fn pop_stack(&mut self) -> Result<f64, ICError>;
|
||||
fn peek_stack(&self) -> Result<f64, ICError>;
|
||||
fn get_stack(&self, addr: f64) -> Result<f64, ICError>;
|
||||
fn put_stack(&self, addr: f64, val: f64) -> Result<f64, ICError>;
|
||||
fn get_aliases(&self) -> &BTreeMap<String, crate::vm::instructions::operands::Operand>;
|
||||
fn get_defines(&self) -> &BTreeMap<String, f64>;
|
||||
fn get_labels(&self) -> &BTreeMap<String, u32>;
|
||||
}
|
||||
|
||||
pub trait Programmable: ICInstructable {
|
||||
fn get_source_code(&self) -> String;
|
||||
fn set_source_code(&self, code: String);
|
||||
fn step(&mut self) -> Result<(), crate::errors::ICError>;
|
||||
@@ -94,20 +131,50 @@ tag_object_traits! {
|
||||
}
|
||||
|
||||
pub trait Device: Logicable {
|
||||
fn set_slot_logic(
|
||||
&mut self,
|
||||
slt: LogicSlotType,
|
||||
index: f64,
|
||||
value: f64,
|
||||
vm: &VM,
|
||||
force: bool
|
||||
) -> Result<(), LogicError>;
|
||||
fn connection_list(&self) -> &[Connection];
|
||||
fn connection_list_mut(&mut self) -> &mut [Connection];
|
||||
fn device_pins(&self) -> Option<&[Option<ObjectID>]>;
|
||||
fn device_pins_mut(&self) -> Option<&mut [Option<ObjectID>]>;
|
||||
fn has_activate_state(&self) -> bool;
|
||||
fn has_lock_state(&self) -> bool;
|
||||
fn has_mode_state(&self) -> bool;
|
||||
fn has_on_off_state(&self) -> bool;
|
||||
fn has_open_state(&self) -> bool;
|
||||
fn has_reagents(&self) -> bool;
|
||||
}
|
||||
|
||||
pub trait WirelessTransmit: Logicable {
|
||||
|
||||
}
|
||||
|
||||
pub trait Item {
|
||||
fn consumable(&self) -> bool;
|
||||
fn filter_type(&self) -> Option<GasType>;
|
||||
fn ingredient(&self) -> bool;
|
||||
fn max_quantity(&self) -> u32;
|
||||
fn reagents(&self) -> Option<&BTreeMap<String, f64>>;
|
||||
fn slot_class(&self) -> SlotClass;
|
||||
fn sorting_class(&self) -> SortingClass;
|
||||
fn parent_slot(&self) -> Option<ParentSlotInfo>;
|
||||
pub trait WirelessReceive: Logicable {
|
||||
|
||||
}
|
||||
|
||||
pub trait Network: Logicable {
|
||||
fn contains(&self, id: &ObjectID) -> bool;
|
||||
fn contains_all(&self, ids: &[ObjectID]) -> bool;
|
||||
fn contains_data(&self, id: &ObjectID) -> bool;
|
||||
fn contains_all_data(&self, ids: &[ObjectID]) -> bool;
|
||||
fn contains_power(&self, id: &ObjectID) -> bool;
|
||||
fn contains_all_power(&self, ids: &[ObjectID]) -> bool;
|
||||
fn data_visible(&self, source: &ObjectID) -> Vec<u32>;
|
||||
fn add_data(&mut self, id: ObjectID) -> bool;
|
||||
fn add_power(&mut self, id: ObjectID) -> bool;
|
||||
fn remove_all(&mut self, id: ObjectID) -> bool;
|
||||
fn remove_data(&mut self, id: ObjectID) -> bool;
|
||||
fn remove_power(&mut self, id: ObjectID) -> bool;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
impl<T: Debug> Debug for dyn Object<ID = T> {
|
||||
|
||||
@@ -107,7 +107,7 @@ impl DeviceRef {
|
||||
self.device.borrow().ic.as_ref().and_then(|ic| {
|
||||
self.vm
|
||||
.borrow()
|
||||
.ics
|
||||
.ic_holders
|
||||
.get(ic)
|
||||
.map(|ic| ic.as_ref().borrow().ip())
|
||||
})
|
||||
@@ -118,7 +118,7 @@ impl DeviceRef {
|
||||
self.device.borrow().ic.as_ref().and_then(|ic| {
|
||||
self.vm
|
||||
.borrow()
|
||||
.ics
|
||||
.ic_holders
|
||||
.get(ic)
|
||||
.map(|ic| ic.as_ref().borrow().ic.get())
|
||||
})
|
||||
@@ -129,7 +129,7 @@ impl DeviceRef {
|
||||
self.device.borrow().ic.as_ref().and_then(|ic| {
|
||||
self.vm
|
||||
.borrow()
|
||||
.ics
|
||||
.ic_holders
|
||||
.get(ic)
|
||||
.map(|ic| Stack(*ic.as_ref().borrow().stack.borrow()))
|
||||
})
|
||||
@@ -140,7 +140,7 @@ impl DeviceRef {
|
||||
self.device.borrow().ic.as_ref().and_then(|ic| {
|
||||
self.vm
|
||||
.borrow()
|
||||
.ics
|
||||
.ic_holders
|
||||
.get(ic)
|
||||
.map(|ic| Registers(*ic.as_ref().borrow().registers.borrow()))
|
||||
})
|
||||
@@ -151,7 +151,7 @@ impl DeviceRef {
|
||||
let aliases = &self.device.borrow().ic.as_ref().and_then(|ic| {
|
||||
self.vm
|
||||
.borrow()
|
||||
.ics
|
||||
.ic_holders
|
||||
.get(ic)
|
||||
.map(|ic| ic.as_ref().borrow().aliases.borrow().clone())
|
||||
});
|
||||
@@ -163,7 +163,7 @@ impl DeviceRef {
|
||||
let defines = &self.device.borrow().ic.as_ref().and_then(|ic| {
|
||||
self.vm
|
||||
.borrow()
|
||||
.ics
|
||||
.ic_holders
|
||||
.get(ic)
|
||||
.map(|ic| ic.as_ref().borrow().defines.borrow().clone())
|
||||
});
|
||||
@@ -175,7 +175,7 @@ impl DeviceRef {
|
||||
let pins = &self.device.borrow().ic.as_ref().and_then(|ic| {
|
||||
self.vm
|
||||
.borrow()
|
||||
.ics
|
||||
.ic_holders
|
||||
.get(ic)
|
||||
.map(|ic| *ic.as_ref().borrow().pins.borrow())
|
||||
});
|
||||
@@ -191,7 +191,7 @@ impl DeviceRef {
|
||||
.and_then(|ic| {
|
||||
self.vm
|
||||
.borrow()
|
||||
.ics
|
||||
.ic_holders
|
||||
.get(ic)
|
||||
.map(|ic| ic.borrow().state.clone())
|
||||
})
|
||||
@@ -203,7 +203,7 @@ impl DeviceRef {
|
||||
let prog = &self.device.borrow().ic.as_ref().and_then(|ic| {
|
||||
self.vm
|
||||
.borrow()
|
||||
.ics
|
||||
.ic_holders
|
||||
.get(ic)
|
||||
.map(|ic| ic.borrow().program.borrow().clone())
|
||||
});
|
||||
@@ -215,7 +215,7 @@ impl DeviceRef {
|
||||
self.device.borrow().ic.as_ref().and_then(|ic| {
|
||||
self.vm
|
||||
.borrow()
|
||||
.ics
|
||||
.ic_holders
|
||||
.get(ic)
|
||||
.map(|ic| ic.borrow().code.borrow().clone())
|
||||
})
|
||||
@@ -263,7 +263,7 @@ impl DeviceRef {
|
||||
.ok_or(VMError::NoIC(self.device.borrow().id))?;
|
||||
let vm_borrow = self.vm.borrow();
|
||||
let ic = vm_borrow
|
||||
.ics
|
||||
.ic_holders
|
||||
.get(&ic_id)
|
||||
.ok_or(VMError::NoIC(self.device.borrow().id))?;
|
||||
let result = ic.borrow_mut().set_register(0, index, val)?;
|
||||
@@ -280,7 +280,7 @@ impl DeviceRef {
|
||||
.ok_or(VMError::NoIC(self.device.borrow().id))?;
|
||||
let vm_borrow = self.vm.borrow();
|
||||
let ic = vm_borrow
|
||||
.ics
|
||||
.ic_holders
|
||||
.get(&ic_id)
|
||||
.ok_or(VMError::NoIC(self.device.borrow().id))?;
|
||||
let result = ic.borrow_mut().poke(address, val)?;
|
||||
@@ -370,7 +370,7 @@ impl VMRef {
|
||||
|
||||
#[wasm_bindgen(js_name = "addDevice")]
|
||||
pub fn add_device(&self, network: Option<u32>) -> Result<u32, JsError> {
|
||||
Ok(self.vm.borrow_mut().add_device(network)?)
|
||||
Ok(self.vm.borrow_mut().add_object(network)?)
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "addDeviceFromTemplate", skip_typescript)]
|
||||
@@ -385,7 +385,7 @@ impl VMRef {
|
||||
|
||||
#[wasm_bindgen(js_name = "getDevice")]
|
||||
pub fn get_device(&self, id: u32) -> Option<DeviceRef> {
|
||||
let device = self.vm.borrow().get_device(id);
|
||||
let device = self.vm.borrow().get_object(id);
|
||||
device.map(|d| DeviceRef::from_device(d.clone(), self.vm.clone()))
|
||||
}
|
||||
|
||||
@@ -418,7 +418,7 @@ impl VMRef {
|
||||
|
||||
#[wasm_bindgen(getter, js_name = "defaultNetwork")]
|
||||
pub fn default_network(&self) -> u32 {
|
||||
self.vm.borrow().default_network
|
||||
self.vm.borrow().default_network_key
|
||||
}
|
||||
|
||||
#[wasm_bindgen(getter)]
|
||||
@@ -433,7 +433,7 @@ impl VMRef {
|
||||
|
||||
#[wasm_bindgen(getter)]
|
||||
pub fn ics(&self) -> Vec<u32> {
|
||||
self.vm.borrow().ics.keys().copied().collect_vec()
|
||||
self.vm.borrow().ic_holders.keys().copied().collect_vec()
|
||||
}
|
||||
|
||||
#[wasm_bindgen(getter, js_name = "lastOperationModified")]
|
||||
@@ -479,7 +479,7 @@ impl VMRef {
|
||||
|
||||
#[wasm_bindgen(js_name = "removeDevice")]
|
||||
pub fn remove_device(&self, id: u32) -> Result<(), JsError> {
|
||||
Ok(self.vm.borrow_mut().remove_device(id)?)
|
||||
Ok(self.vm.borrow_mut().remove_object(id)?)
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "setSlotOccupant", skip_typescript)]
|
||||
|
||||
@@ -22,7 +22,7 @@ pub fn generate_instructions(
|
||||
let mut writer =
|
||||
std::io::BufWriter::new(std::fs::File::create(instructions_path.join("traits.rs"))?);
|
||||
|
||||
write_instruction_interface_trait(&mut writer)?;
|
||||
write_instruction_trait_use(&mut writer)?;
|
||||
for (typ, info) in &stationpedia.script_commands {
|
||||
write_instruction_trait(&mut writer, (typ, info))?;
|
||||
}
|
||||
@@ -172,36 +172,11 @@ fn operand_names(example: &str) -> Vec<String> {
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn write_instruction_interface_trait<T: std::io::Write>(writer: &mut T) -> color_eyre::Result<()> {
|
||||
fn write_instruction_trait_use<T: std::io::Write>(writer: &mut T) -> color_eyre::Result<()> {
|
||||
write!(
|
||||
writer,
|
||||
"\
|
||||
use std::collections::BTreeMap;\n\
|
||||
use crate::vm::object::traits::{{Logicable, MemoryWritable, SourceCode}};\n\
|
||||
use crate::errors::ICError; \n\
|
||||
pub trait IntegratedCircuit: Logicable + MemoryWritable + SourceCode {{\n \
|
||||
fn get_instruction_pointer(&self) -> f64;\n \
|
||||
fn set_next_instruction(&mut self, next_instruction: f64);\n \
|
||||
fn set_next_instruction_relative(&mut self, offset: f64) {{\n \
|
||||
self.set_next_instruction(self.get_instruction_pointer() + offset);\n \
|
||||
}}\n \
|
||||
fn reset(&mut self);\n \
|
||||
fn get_real_target(&self, indirection: u32, target: u32) -> Result<f64, ICError>;\n \
|
||||
fn get_register(&self, indirection: u32, target: u32) -> Result<f64, ICError>;\n \
|
||||
fn set_register(&mut self, indirection: u32, target: u32, val: f64) -> Result<f64, ICError>;\n \
|
||||
fn set_return_address(&mut self, addr: f64);\n \
|
||||
fn al(&mut self) {{\n \
|
||||
self.set_return_address(self.get_instruction_pointer() + 1.0);\n \
|
||||
}}\n \
|
||||
fn push_stack(&mut self, val: f64) -> Result<f64, ICError>;\n \
|
||||
fn pop_stack(&mut self) -> Result<f64, ICError>;\n \
|
||||
fn peek_stack(&self) -> Result<f64, ICError>;\n \
|
||||
fn get_stack(&self, addr: f64) -> Result<f64, ICError>;\n \
|
||||
fn put_stack(&self, addr: f64, val: f64) -> Result<f64, ICError>;\n \
|
||||
fn get_aliases(&self) -> &BTreeMap<String, crate::vm::instructions::operands::Operand>;\n \
|
||||
fn get_defines(&self) -> &BTreeMap<String, f64>;\n \
|
||||
fn get_labels(&self) -> &BTreeMap<String, u32>;\n\
|
||||
}}\n\
|
||||
use crate::vm::object::traits::IntegratedCircuit;\n\
|
||||
"
|
||||
)?;
|
||||
Ok(())
|
||||
|
||||
Reference in New Issue
Block a user