refactor(vm) start reimpl of VM struct using object trait

This commit is contained in:
Rachel Powers
2024-05-12 02:08:25 -07:00
parent 17bde04c86
commit 8288d8ae6f
18 changed files with 1362 additions and 740 deletions

View File

@@ -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();

View File

@@ -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}'")]

View File

@@ -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

View File

@@ -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

View File

@@ -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()

View File

@@ -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(

View File

@@ -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

View File

@@ -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),

View File

@@ -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;

View File

@@ -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>,
}

View File

@@ -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;

View File

@@ -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)* }
};
}

View File

@@ -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>;

View File

@@ -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,

View File

@@ -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> {

View File

@@ -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)]

View File

@@ -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(())