refactor(vm): VMObjects should carry around a VM reference

This commit is contained in:
Rachel Powers
2024-05-14 05:13:12 -07:00
parent d6ebbcf7e0
commit de2698c2e2
9 changed files with 370 additions and 323 deletions

View File

@@ -1,8 +1,12 @@
use std::{collections::HashSet, ops::Deref};
use std::{collections::HashSet, ops::Deref, rc::Rc};
use crate::vm::{
enums::script_enums::LogicType,
object::{errors::LogicError, macros::ObjectInterface, templates::ConnectionInfo, traits::*, Name, ObjectID},
object::{
errors::LogicError, macros::ObjectInterface, templates::ConnectionInfo, traits::*, Name,
ObjectID,
},
VM,
};
use itertools::Itertools;
use macro_rules_attribute::derive;
@@ -134,16 +138,68 @@ impl Connection {
pub fn to_info(&self) -> ConnectionInfo {
match self {
Self::None => ConnectionInfo { typ:ConnectionType::None, role: ConnectionRole::None, network: None },
Self::CableNetwork { net, typ: CableConnectionType::Data, role } => ConnectionInfo { typ: ConnectionType::Data, role, network: net },
Self::CableNetwork { net, typ: CableConnectionType::Power, role } => ConnectionInfo { typ: ConnectionType::Power, role, network: net },
Self::CableNetwork { net, typ: CableConnectionType::PowerAndData, role } => ConnectionInfo { typ: ConnectionType::PowerAndData, role, network: net },
Self::Chute { role } => ConnectionInfo { typ: ConnectionType::Chute, role, network: None },
Self::Pipe { role } => ConnectionInfo { typ: ConnectionType::Pipe, role, network: None },
Self::PipeLiquid { role } => ConnectionInfo { typ: ConnectionType::PipeLiquid, role, network: None },
Self::Elevator { role } => ConnectionInfo { typ: ConnectionType::Elevator, role, network: None },
Self::LandingPad { role } => ConnectionInfo { typ: ConnectionType::LandingPad, role, network: None },
Self::LaunchPad { role } => ConnectionInfo { typ: ConnectionType::LaunchPad, role, network: None },
Self::None => ConnectionInfo {
typ: ConnectionType::None,
role: ConnectionRole::None,
network: None,
},
Self::CableNetwork {
net,
typ: CableConnectionType::Data,
role,
} => ConnectionInfo {
typ: ConnectionType::Data,
role: *role,
network: *net,
},
Self::CableNetwork {
net,
typ: CableConnectionType::Power,
role,
} => ConnectionInfo {
typ: ConnectionType::Power,
role: *role,
network: *net,
},
Self::CableNetwork {
net,
typ: CableConnectionType::PowerAndData,
role,
} => ConnectionInfo {
typ: ConnectionType::PowerAndData,
role: *role,
network: *net,
},
Self::Chute { role } => ConnectionInfo {
typ: ConnectionType::Chute,
role: *role,
network: None,
},
Self::Pipe { role } => ConnectionInfo {
typ: ConnectionType::Pipe,
role: *role,
network: None,
},
Self::PipeLiquid { role } => ConnectionInfo {
typ: ConnectionType::PipeLiquid,
role: *role,
network: None,
},
Self::Elevator { role } => ConnectionInfo {
typ: ConnectionType::Elevator,
role: *role,
network: None,
},
Self::LandingPad { role } => ConnectionInfo {
typ: ConnectionType::LandingPad,
role: *role,
network: None,
},
Self::LaunchPad { role } => ConnectionInfo {
typ: ConnectionType::LaunchPad,
role: *role,
network: None,
},
}
}
}
@@ -159,6 +215,9 @@ pub struct CableNetwork {
#[custom(object_name)]
/// required by object interface but atm unused by network
pub name: Name,
#[custom(object_vm_ref)]
#[serde(skip)]
pub vm: Option<Rc<VM>>,
/// data enabled objects (must be devices)
pub devices: HashSet<ObjectID>,
/// power only connections
@@ -177,10 +236,10 @@ impl Storage for CableNetwork {
fn get_slot_mut(&mut self, index: usize) -> Option<&mut crate::vm::object::Slot> {
None
}
fn get_slots(&self) -> &[crate::vm::object::Slot] {
fn get_slots(&self) -> &[crate::vm::object::Slot] {
&vec![]
}
fn get_slots_mut(&mut self) -> &mut[crate::vm::object::Slot] {
fn get_slots_mut(&mut self) -> &mut [crate::vm::object::Slot] {
&mut vec![]
}
}
@@ -258,13 +317,15 @@ impl Logicable for CableNetwork {
index: f64,
vm: &crate::vm::VM,
) -> Result<f64, LogicError> {
Err(LogicError::CantSlotRead(slt, index as usize))
Err(LogicError::CantSlotRead(slt, index))
}
fn valid_logic_types(&self) -> Vec<LogicType> {
use LogicType::*;
vec![Channel0, Channel1, Channel2, Channel3, Channel4, Channel5, Channel6, Channel7]
vec![
Channel0, Channel1, Channel2, Channel3, Channel4, Channel5, Channel6, Channel7,
]
}
fn known_modes(&self) -> Option<Vec<(u32,String)>> {
fn known_modes(&self) -> Option<Vec<(u32, String)>> {
None
}
}
@@ -354,6 +415,7 @@ impl From<FrozenNetwork> for CableNetwork {
id: value.id,
prefab: Name::new(""),
name: Name::new(""),
vm: None,
devices: value.devices.into_iter().collect(),
power_only: value.power_only.into_iter().collect(),
channels: value.channels,
@@ -373,6 +435,7 @@ impl CableNetwork {
id,
prefab: Name::new(""),
name: Name::new(""),
vm: None,
devices: HashSet::new(),
power_only: HashSet::new(),
channels: [f64::NAN; 8],

View File

@@ -28,24 +28,21 @@ pub type ObjectID = u32;
pub type BoxedObject = Rc<RefCell<dyn Object>>;
#[derive(Debug, Clone)]
pub struct VMObject {
obj: BoxedObject,
vm: Rc<VM>,
}
pub struct VMObject(BoxedObject);
impl Deref for VMObject {
type Target = BoxedObject;
#[inline(always)]
fn deref(&self) -> &Self::Target {
&self.obj
&self.0
}
}
impl DerefMut for VMObject {
#[inline(always)]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.obj
&mut self.0
}
}
@@ -54,18 +51,21 @@ impl VMObject {
where
T: Object + 'static,
{
VMObject {
obj: Rc::new(RefCell::new(val)),
vm,
}
let mut obj = VMObject(Rc::new(RefCell::new(val)));
obj.set_vm(vm);
obj
}
pub fn set_vm(&mut self, vm: Rc<VM>) {
self.vm = vm;
self.borrow_mut().set_vm(vm);
}
pub fn get_vm(&self) -> &Rc<VM> {
&self.vm
pub fn get_vm(&self) -> Rc<VM> {
self
.borrow()
.get_vm()
.expect("VMObject with no VM?")
.clone()
}
}

View File

@@ -47,7 +47,7 @@ macro_rules! GWLogicable {
fn fields_mut(&mut self) -> &mut BTreeMap<LogicType, LogicField> {
&mut self.fields
}
fn modes(&self) -> Option<&BTreeMap<u32, String>> {
fn known_modes(&self) -> Option<&BTreeMap<u32, String>> {
self.modes.as_ref()
}
}

View File

@@ -4,10 +4,10 @@ use crate::{network::Connection, vm::{
enums::script_enums::LogicType,
object::{
macros::ObjectInterface, templates::{DeviceInfo, ItemInfo}, traits::*, LogicField, Name, ObjectID, Slot,
},
}, VM,
}};
use macro_rules_attribute::derive;
use std::collections::BTreeMap;
use std::{collections::BTreeMap, rc::Rc};
#[derive(ObjectInterface!, GWStructure!)]
#[custom(implements(Object { Structure }))]
@@ -18,6 +18,8 @@ pub struct Generic {
pub prefab: Name,
#[custom(object_name)]
pub name: Name,
#[custom(object_vm_ref)]
pub vm: Option<Rc<VM>>,
pub small_grid: bool,
}
@@ -30,6 +32,8 @@ pub struct GenericStorage {
pub prefab: Name,
#[custom(object_name)]
pub name: Name,
#[custom(object_vm_ref)]
pub vm: Option<Rc<VM>>,
pub small_grid: bool,
pub slots: Vec<Slot>,
}
@@ -43,6 +47,8 @@ pub struct GenericLogicable {
pub prefab: Name,
#[custom(object_name)]
pub name: Name,
#[custom(object_vm_ref)]
pub vm: Option<Rc<VM>>,
pub small_grid: bool,
pub slots: Vec<Slot>,
pub fields: BTreeMap<LogicType, LogicField>,
@@ -58,6 +64,8 @@ pub struct GenericLogicableDevice {
pub prefab: Name,
#[custom(object_name)]
pub name: Name,
#[custom(object_vm_ref)]
pub vm: Option<Rc<VM>>,
pub small_grid: bool,
pub slots: Vec<Slot>,
pub fields: BTreeMap<LogicType, LogicField>,
@@ -76,6 +84,8 @@ pub struct GenericLogicableDeviceMemoryReadable {
pub prefab: Name,
#[custom(object_name)]
pub name: Name,
#[custom(object_vm_ref)]
pub vm: Option<Rc<VM>>,
pub small_grid: bool,
pub slots: Vec<Slot>,
pub fields: BTreeMap<LogicType, LogicField>,
@@ -95,6 +105,8 @@ pub struct GenericLogicableDeviceMemoryReadWriteable {
pub prefab: Name,
#[custom(object_name)]
pub name: Name,
#[custom(object_vm_ref)]
pub vm: Option<Rc<VM>>,
pub small_grid: bool,
pub slots: Vec<Slot>,
pub fields: BTreeMap<LogicType, LogicField>,
@@ -114,6 +126,8 @@ pub struct GenericItem {
pub prefab: Name,
#[custom(object_name)]
pub name: Name,
#[custom(object_vm_ref)]
pub vm: Option<Rc<VM>>,
pub item_info: ItemInfo,
pub parent_slot: Option<ParentSlotInfo>,
}
@@ -127,6 +141,8 @@ pub struct GenericItemStorage {
pub prefab: Name,
#[custom(object_name)]
pub name: Name,
#[custom(object_vm_ref)]
pub vm: Option<Rc<VM>>,
pub item_info: ItemInfo,
pub parent_slot: Option<ParentSlotInfo>,
pub slots: Vec<Slot>,
@@ -141,6 +157,8 @@ pub struct GenericItemLogicable {
pub prefab: Name,
#[custom(object_name)]
pub name: Name,
#[custom(object_vm_ref)]
pub vm: Option<Rc<VM>>,
pub item_info: ItemInfo,
pub parent_slot: Option<ParentSlotInfo>,
pub slots: Vec<Slot>,
@@ -157,6 +175,8 @@ pub struct GenericItemLogicableMemoryReadable {
pub prefab: Name,
#[custom(object_name)]
pub name: Name,
#[custom(object_vm_ref)]
pub vm: Option<Rc<VM>>,
pub item_info: ItemInfo,
pub parent_slot: Option<ParentSlotInfo>,
pub slots: Vec<Slot>,
@@ -174,6 +194,8 @@ pub struct GenericItemLogicableMemoryReadWriteable {
pub prefab: Name,
#[custom(object_name)]
pub name: Name,
#[custom(object_vm_ref)]
pub vm: Option<Rc<VM>>,
pub item_info: ItemInfo,
pub parent_slot: Option<ParentSlotInfo>,
pub slots: Vec<Slot>,

View File

@@ -53,7 +53,7 @@ impl<T: GWStorage + Object> Storage for T {
pub trait GWLogicable: Storage {
fn fields(&self) -> &BTreeMap<LogicType, LogicField>;
fn fields_mut(&mut self) -> &mut BTreeMap<LogicType, LogicField>;
fn modes(&self) -> Option<&BTreeMap<u32, String>>;
fn known_modes(&self) -> Option<&BTreeMap<u32, String>>;
}
impl<T: GWLogicable + Object> Logicable for T {
@@ -148,8 +148,13 @@ impl<T: GWLogicable + Object> Logicable for T {
fn valid_logic_types(&self) -> Vec<LogicType> {
self.fields().keys().copied().collect()
}
fn known_modes(&self) -> Option<Vec<(u32,String)>> {
self.modes().map(|modes| modes.iter().collect())
fn known_modes(&self) -> Option<Vec<(u32, String)>> {
self.known_modes().map(|modes| {
modes
.iter()
.map(|(mode, name)| (*mode, name.clone()))
.collect()
})
}
}
@@ -171,7 +176,7 @@ impl<T: GWMemoryReadable + Object> MemoryReadable for T {
Ok(self.memory()[index as usize])
}
}
fn get_memory_slice(&self) -> &[f64] {
fn get_memory_slice(&self) -> &[f64] {
self.memory()
}
}

View File

@@ -14,6 +14,8 @@ macro_rules! object_trait {
fn get_mut_prefab(&mut self) -> &mut crate::vm::object::Name;
fn get_name(&self) -> &crate::vm::object::Name;
fn get_mut_name(&mut self) -> &mut crate::vm::object::Name;
fn get_vm(&self) -> Option<&std::rc::Rc<crate::vm::VM>>;
fn set_vm(&mut self, vm: std::rc::Rc<crate::vm::VM>);
fn type_name(&self) -> &str;
fn as_object(&self) -> &dyn $trait_name;
fn as_mut_object(&mut self) -> &mut dyn $trait_name;
@@ -71,14 +73,25 @@ macro_rules! object_trait {
pub(crate) use object_trait;
/// use macro_rules_attribute::derive to apply this macro to a struct
///
/// use `#[custom(object_id)]`, `#[custom(object_prefab)]`, `#[custom(object_name)]`, and `#[custom(object_vm_ref)]`
/// to tag struct fields appropriately
///
/// the tags for `id`, `prefab`, and `name` may appear in any order but `vm_ref` must come last
///
/// - `id` must be `crate::vm::object::ObjectID`
/// - `prefab` and `name` must be `crate::vm::object::Name`
/// - `vm_ref` must be `Option<std::rc::Rc<crate::vm::VM>>`
macro_rules! ObjectInterface {
{
@body_id_prefab_name
@body_final
@trt $trait_name:ident; $struct:ident;
@impls $($trt:path),*;
@id $id_field:ident: $id_typ:ty;
@prefab $prefab_field:ident: $prefab_typ:ty;
@name $name_field:ident: $name_typ:ty;
@vm_ref $vm_ref_field:ident: $vm_ref_typ:ty;
} => {
impl $trait_name for $struct {
@@ -106,6 +119,14 @@ macro_rules! ObjectInterface {
&mut self.$name_field
}
fn get_vm(&self) -> Option<&std::rc::Rc<crate::vm::VM>> {
self.$vm_ref_field.as_ref()
}
fn set_vm(&mut self, vm: std::rc::Rc<crate::vm::VM>) {
self.$vm_ref_field = Some(vm);
}
fn type_name(&self) -> &str {
std::any::type_name::<Self>()
}
@@ -135,301 +156,117 @@ macro_rules! ObjectInterface {
}
};
{
@body_id_name
@body_final
@trt $trait_name:ident; $struct:ident;
@impls $($trt:path),*;
@id $id_field:ident: $id_typ:ty;
@name $name_field:ident: $name_typ:ty;
#[custom(object_prefab)]
$(#[$prefab_attr:meta])*
$prefab_viz:vis $prefab_field:ident: $prefab_typ:ty,
$( $rest:tt )*
} => {
$crate::vm::object::macros::ObjectInterface!{
@body_id_prefab_name
@trt $trait_name; $struct;
@impls $($trt),*;
@id $id_field: $id_typ;
@prefab $prefab_field: $prefab_typ;
@name $name_field: $name_typ;
}
};
{
@body_id_name
@trt $trait_name:ident; $struct:ident;
@impls $($trt:path),*;
@id $id_field:ident: $id_typ:ty;
@name $name_field:ident: $name_typ:ty;
$(#[#field:meta])*
$field_viz:vis
$field_name:ident : $field_ty:ty,
$( $rest:tt )*
} => {
$crate::vm::object::macros::ObjectInterface!{
@body_id_name
@trt $trait_name; $struct;
@impls $($trt),*;
@id $id_field: $id_typ;
@name $name_field: $name_typ;
$( $rest )*
}
};
{
@body_id_prefab
@trt $trait_name:ident; $struct:ident;
@impls $($trt:path),*;
@id $id_field:ident: $id_typ:ty;
@prefab $prefab_field:ident: $prefab_typ:ty;
#[custom(object_name)]
$(#[$name_attr:meta])*
$name_viz:vis $name_field:ident: $name_typ:ty,
$( $rest:tt )*
@vm_ref $vm_ref_field:ident: $vm_ref_typ:ty;
} => {
$crate::vm::object::macros::ObjectInterface!{
@body_id_prefab_name
@body_final
@trt $trait_name; $struct;
@impls $($trt),*;
@id $id_field: $id_typ;
@prefab $prefab_field: $prefab_typ;
@name $name_field: $name_typ;
@vm_ref $vm_ref_field: $vm_ref_typ;
}
};
{
@body_id_prefab
@trt $trait_name:ident; $struct:ident;
@impls $($trt:path),*;
@id $id_field:ident: $id_typ:ty;
@prefab $prefab_field:ident: $prefab_typ:ty;
$(#[#field:meta])*
$field_viz:vis
$field_name:ident : $field_ty:ty,
$( $rest:tt )*
} => {
$crate::vm::object::macros::ObjectInterface!{
@body_id_prefab
@trt $trait_name; $struct;
@impls $($trt),*;
@id $id_field: $id_typ;
@prefab $prefab_field: $prefab_typ;
$( $rest )*
}
};
{
@body_prefab_name
@body_final
@trt $trait_name:ident; $struct:ident;
@impls $($trt:path),*;
@prefab $prefab_field:ident: $prefab_typ:ty;
@name $name_field:ident: $name_typ:ty;
#[custom(object_id)]
$(#[$id_attr:meta])*
$id_viz:vis $id_field:ident: $id_typ:ty,
$( $rest:tt )*
} => {
$crate::vm::object::macros::ObjectInterface!{
@body_id_prefab_name
@trt $trait_name; $struct;
@impls $($trt),*;
@prefab $prefab_field: $prefab_typ;
@name $name_field: $name_typ;
}
};
{
@body_prefab_name
@trt $trait_name:ident; $struct:ident;
@impls $($trt:path),*;
@prefab $prefab_field:ident: $prefab_typ:ty;
@name $name_field:ident: $name_typ:ty;
$(#[#field:meta])*
$field_viz:vis
$field_name:ident : $field_ty:ty,
$( $rest:tt )*
} => {
$crate::vm::object::macros::ObjectInterface!{
@body_prefab_name
@trt $trait_name; $struct;
@impls $($trt),*;
@prefab $prefab_field: $prefab_typ;
@name $name_field: $name_typ;
$( $rest )*
}
};
{
@body_name
@trt $trait_name:ident; $struct:ident;
@impls $($trt:path),*;
@name $name_field:ident: $name_typ:ty;
#[custom(object_prefab)]
$(#[$prefab_attr:meta])*
$prefab_viz:vis $prefab_field:ident: $prefab_typ:ty,
$( $rest:tt )*
} => {
$crate::vm::object::macros::ObjectInterface!{
@body_prefab_name
@trt $trait_name; $struct;
@impls $($trt),*;
@prefab $prefab_field: $prefab_typ;
@name $name_field: $name_typ;
$( $rest )*
}
};
{
@body_name
@trt $trait_name:ident; $struct:ident;
@impls $($trt:path),*;
@name $name_field:ident: $name_typ:ty;
#[custom(object_id)]
$(#[$id_attr:meta])*
$id_viz:vis $id_field:ident: $id_typ:ty,
$( $rest:tt )*
} => {
$crate::vm::object::macros::ObjectInterface!{
@body_id_name
@trt $trait_name; $struct;
@impls $($trt),*;
@id $id_field: $id_typ;
@name $name_field: $name_typ;
$( $rest )*
}
};
{
@body_name
@trt $trait_name:ident; $struct:ident;
@impls $($trt:path),*;
@name $name_field:ident: $name_typ:ty;
$(#[#field:meta])*
$field_viz:vis
$field_name:ident : $field_ty:ty,
$( $rest:tt )*
} => {
$crate::vm::object::macros::ObjectInterface!{
@body_name
@trt $trait_name; $struct;
@impls $($trt),*;
@name $name_field: $name_typ;
$( $rest )*
}
};
{
@body_id
@trt $trait_name:ident; $struct:ident;
@impls $($trt:path),*;
@id $id_field:ident: $id_typ:ty;
#[custom(object_name)]
$(#[$name_attr:meta])*
$name_viz:vis $name_field:ident: $name_typ:ty,
$( $rest:tt )*
@vm_ref $vm_ref_field:ident: $vm_ref_typ:ty;
} => {
$crate::vm::object::macros::ObjectInterface!{
@body_id_name
@body_final
@trt $trait_name; $struct;
@impls $($trt),*;
@id $id_field: $id_typ;
@name $name_field: $name_typ;
$( $rest )*
}
};
{
@body_id
@trt $trait_name:ident; $struct:ident;
@impls $($trt:path),*;
@id $id_field:ident: $id_typ:ty;
#[custom(object_prefab)]
$(#[$prefab_attr:meta])*
$prefab_viz:vis $prefab_field:ident: $prefab_typ:ty,
$( $rest:tt )*
} => {
$crate::vm::object::macros::ObjectInterface!{
@body_id_prefab
@trt $trait_name; $struct;
@impls $($trt),*;
@id $id_field: $id_typ;
@prefab $prefab_field: $prefab_typ;
$( $rest )*
}
};
{
@body_id
@trt $trait_name:ident; $struct:ident;
@impls $($trt:path),*;
@id $id_field:ident: $id_typ:ty;
$(#[#field:meta])*
$field_viz:vis
$field_name:ident : $field_ty:ty,
$( $rest:tt )*
} => {
$crate::vm::object::macros::ObjectInterface!{
@body_id
@trt $trait_name; $struct;
@impls $($trt),*;
@id $id_field: $id_typ;
$( $rest )*
}
};
{
@body_prefab
@trt $trait_name:ident; $struct:ident;
@impls $($trt:path),*;
@prefab $prefab_field:ident: $prefab_typ:ty;
#[custom(object_name)]
$(#[$name_attr:meta])*
$name_viz:vis $name_field:ident: $name_typ:ty,
$( $rest:tt )*
} => {
$crate::vm::object::macros::ObjectInterface!{
@body_prefab_name
@trt $trait_name; $struct;
@impls $($trt),*;
@prefab $prefab_field: $prefab_typ;
@name $name_field: $name_typ;
$( $rest )*
@vm_ref $vm_ref_field: $vm_ref_typ;
}
};
{
@body_prefab
@body_final
@trt $trait_name:ident; $struct:ident;
@impls $($trt:path),*;
@prefab $prefab_field:ident: $prefab_typ:ty;
#[custom(object_id)]
$(#[$id_attr:meta])*
$id_viz:vis $id_field:ident: $id_typ:ty,
$( $rest:tt )*
@id $id_field:ident: $id_typ:ty;
@name $name_field:ident: $name_typ:ty;
@vm_ref $vm_ref_field:ident: $vm_ref_typ:ty;
} => {
$crate::vm::object::macros::ObjectInterface!{
@body_id_prefab
@body_final
@trt $trait_name; $struct;
@impls $($trt),*;
@id $id_field: $id_typ;
@prefab $prefab_field: $prefab_typ;
$( $rest )*
@name $name_field: $name_typ;
@vm_ref $vm_ref_field: $vm_ref_typ;
}
};
{
@body_prefab
@body_final
@trt $trait_name:ident; $struct:ident;
@impls $($trt:path),*;
@name $name_field:ident: $name_typ:ty;
@prefab $prefab_field:ident: $prefab_typ:ty;
$(#[#field:meta])*
$field_viz:vis
$field_name:ident : $field_ty:ty,
@id $id_field:ident: $id_typ:ty;
@vm_ref $vm_ref_field:ident: $vm_ref_typ:ty;
} => {
$crate::vm::object::macros::ObjectInterface!{
@body_final
@trt $trait_name; $struct;
@impls $($trt),*;
@id $id_field: $id_typ;
@prefab $prefab_field: $prefab_typ;
@name $name_field: $name_typ;
@vm_ref $vm_ref_field: $vm_ref_typ;
}
};
{
@body_final
@trt $trait_name:ident; $struct:ident;
@impls $($trt:path),*;
@name $name_field:ident: $name_typ:ty;
@id $id_field:ident: $id_typ:ty;
@prefab $prefab_field:ident: $prefab_typ:ty;
@vm_ref $vm_ref_field:ident: $vm_ref_typ:ty;
} => {
$crate::vm::object::macros::ObjectInterface!{
@body_final
@trt $trait_name; $struct;
@impls $($trt),*;
@id $id_field: $id_typ;
@prefab $prefab_field: $prefab_typ;
@name $name_field: $name_typ;
@vm_ref $vm_ref_field: $vm_ref_typ;
}
};{
@body
@trt $trait_name:ident; $struct:ident;
@impls $($trt:path),*;
@tags {
$(@$tag:tt $tag_field:ident: $tag_typ:ty;)*
};
#[custom(object_vm_ref)]
$(#[$vm_ref_attr:meta])*
$vm_ref_viz:vis $vm_ref_field:ident: $vm_ref_typ:ty,
$( $rest:tt )*
} => {
$crate::vm::object::macros::ObjectInterface!{
@body_prefab
@body
@trt $trait_name; $struct;
@impls $($trt),*;
@prefab $prefab_field: $prefab_typ;
@tags {$(@$tag $tag_field: $tag_typ;)* @vm_ref $vm_ref_field: $vm_ref_typ;};
$( $rest )*
}
};
@@ -437,6 +274,9 @@ macro_rules! ObjectInterface {
@body
@trt $trait_name:ident; $struct:ident;
@impls $($trt:path),*;
@tags {
$(@$tag:tt $tag_field:ident: $tag_typ:ty;)*
};
#[custom(object_name)]
$(#[$name_attr:meta])*
$name_viz:vis $name_field:ident: $name_typ:ty,
@@ -444,10 +284,10 @@ macro_rules! ObjectInterface {
} => {
$crate::vm::object::macros::ObjectInterface!{
@body_name
@body
@trt $trait_name; $struct;
@impls $($trt),*;
@name $name_field: $name_typ;
@tags {$(@$tag $tag_field: $tag_typ;)* @name $name_field: $name_typ;};
$( $rest )*
}
};
@@ -455,6 +295,9 @@ macro_rules! ObjectInterface {
@body
@trt $trait_name:ident; $struct:ident;
@impls $($trt:path),*;
@tags {
$(@$tag:tt $tag_field:ident: $tag_typ:ty;)*
};
#[custom(object_prefab)]
$(#[$prefab_attr:meta])*
$prefab_viz:vis $prefab_field:ident: $prefab_typ:ty,
@@ -462,10 +305,10 @@ macro_rules! ObjectInterface {
} => {
$crate::vm::object::macros::ObjectInterface!{
@body_prefab
@body
@trt $trait_name; $struct;
@impls $($trt),*;
@prefab $prefab_field: $prefab_typ;
@tags {$(@$tag $tag_field: $tag_typ;)* @prefab $prefab_field: $prefab_typ;};
$( $rest )*
}
};
@@ -473,6 +316,9 @@ macro_rules! ObjectInterface {
@body
@trt $trait_name:ident; $struct:ident;
@impls $($trt:path),*;
@tags {
$(@$tag:tt $tag_field:ident: $tag_typ:ty;)*
};
#[custom(object_id)]
$(#[$id_attr:meta])*
$id_viz:vis $id_field:ident: $id_typ:ty,
@@ -480,10 +326,10 @@ macro_rules! ObjectInterface {
} => {
$crate::vm::object::macros::ObjectInterface!{
@body_id
@body
@trt $trait_name; $struct;
@impls $($trt),*;
@id $id_field: $id_typ;
@tags {$(@$tag $tag_field: $tag_typ;)* @id $id_field: $id_typ;};
$( $rest )*
}
};
@@ -491,7 +337,10 @@ macro_rules! ObjectInterface {
@body
@trt $trait_name:ident; $struct:ident;
@impls $($trt:path),*;
$(#[#field:meta])*
@tags {
$(@$tag:tt $tag_field:ident: $tag_typ:ty;)*
};
$(#[$field:meta])*
$field_viz:vis
$field_name:ident : $field_ty:ty,
$( $rest:tt )*
@@ -501,9 +350,27 @@ macro_rules! ObjectInterface {
@body
@trt $trait_name; $struct;
@impls $($trt),*;
@tags {$(@$tag $tag_field: $tag_typ;)*};
$( $rest )*
}
};
{
@body
@trt $trait_name:ident; $struct:ident;
@impls $($trt:path),*;
@tags {
$(@$tag:tt $tag_field:ident: $tag_typ:ty;)*
};
} => {
$crate::vm::object::macros::ObjectInterface!{
@body_final
@trt $trait_name; $struct;
@impls $($trt),*;
$(
@$tag $tag_field: $tag_typ;
)*
}
};
{
#[custom(implements($trait_name:ident {$($trt:path),*}))]
$( #[$attr:meta] )*
@@ -515,6 +382,7 @@ macro_rules! ObjectInterface {
@body
@trt $trait_name; $struct;
@impls $($trt),*;
@tags {};
$( $body )*
}
};

View File

@@ -1,10 +1,11 @@
use crate::{
errors::{ICError, LineError},
grammar,
interpreter::ICState,
vm::{
enums::{
basic_enums::{Class as SlotClass, GasType, SortingClass},
script_enums::LogicType,
script_enums::{LogicSlotType, LogicType},
},
instructions::{
enums::InstructionOp,
@@ -13,11 +14,10 @@ use crate::{
Instruction,
},
object::{
errors::MemoryError,
generic::{macros::GWLogicable, traits::GWLogicable},
errors::{LogicError, MemoryError},
macros::ObjectInterface,
traits::*,
LogicField, Name, ObjectID, Slot,
LogicField, MemoryAccess, Name, ObjectID, Slot,
},
VM,
},
@@ -25,7 +25,10 @@ use crate::{
use itertools::Itertools;
use macro_rules_attribute::derive;
use serde_derive::{Deserialize, Serialize};
use std::collections::{BTreeMap, HashSet};
use std::{
collections::{BTreeMap, HashSet},
rc::Rc,
};
use ICError::*;
#[derive(Debug, Clone, Serialize, Deserialize)]
@@ -139,20 +142,10 @@ impl Program {
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ICState {
Start,
Running,
Yield,
Sleep(time::OffsetDateTime, f64),
HasCaughtFire,
Error(LineError),
}
static RETURN_ADDRESS_INDEX: usize = 17;
static STACK_POINTER_INDEX: usize = 16;
#[derive(ObjectInterface!, GWLogicable!)]
#[derive(ObjectInterface!)]
#[custom(implements(Object { Item, Storage, Logicable, MemoryReadable, MemoryWritable }))]
pub struct ItemIntegratedCircuit10 {
#[custom(object_id)]
@@ -161,6 +154,8 @@ pub struct ItemIntegratedCircuit10 {
pub prefab: Name,
#[custom(object_name)]
pub name: Name,
#[custom(object_vm_ref)]
pub vm: Option<Rc<VM>>,
pub fields: BTreeMap<LogicType, LogicField>,
pub memory: [f64; 512],
pub parent_slot: Option<ParentSlotInfo>,
@@ -218,13 +213,86 @@ impl Storage for ItemIntegratedCircuit10 {
fn get_slot_mut(&mut self, index: usize) -> Option<&mut Slot> {
None
}
fn get_slots(&self) -> &[Slot] {
fn get_slots(&self) -> &[Slot] {
&[]
}
fn get_slots_mut(&mut self) -> &mut[Slot] {
fn get_slots_mut(&mut self) -> &mut [Slot] {
&mut []
}
}
impl Logicable for ItemIntegratedCircuit10 {
fn prefab_hash(&self) -> i32 {
self.get_prefab().hash
}
fn name_hash(&self) -> i32 {
self.get_name().hash
}
fn is_logic_readable(&self) -> bool {
true
}
fn is_logic_writeable(&self) -> bool {
true
}
fn can_logic_read(&self, lt: LogicType) -> bool {
self.fields
.get(&lt)
.map(|field| {
matches!(
field.field_type,
MemoryAccess::Read | MemoryAccess::ReadWrite
)
})
.unwrap_or(false)
}
fn can_logic_write(&self, lt: LogicType) -> bool {
self.fields
.get(&lt)
.map(|field| {
matches!(
field.field_type,
MemoryAccess::Write | MemoryAccess::ReadWrite
)
})
.unwrap_or(false)
}
fn get_logic(&self, lt: LogicType) -> Result<f64, LogicError> {
self.fields
.get(&lt)
.and_then(|field| match field.field_type {
MemoryAccess::Read | MemoryAccess::ReadWrite => Some(field.value),
_ => None,
})
.ok_or(LogicError::CantRead(lt))
}
fn set_logic(&mut self, lt: LogicType, value: f64, force: bool) -> Result<(), LogicError> {
self.fields
.get_mut(&lt)
.ok_or(LogicError::CantWrite(lt))
.and_then(|field| match field.field_type {
MemoryAccess::Write | MemoryAccess::ReadWrite => {
field.value = value;
Ok(())
}
_ if force => {
field.value = value;
Ok(())
}
_ => Err(LogicError::CantWrite(lt)),
})
}
fn can_slot_logic_read(&self, slt: LogicSlotType, index: f64) -> bool {
false
}
fn get_slot_logic(&self, slt: LogicSlotType, index: f64, _vm: &VM) -> Result<f64, LogicError> {
return Err(LogicError::SlotIndexOutOfRange(index, self.slots_count()));
}
fn valid_logic_types(&self) -> Vec<LogicType> {
self.fields.keys().copied().collect()
}
fn known_modes(&self) -> Option<Vec<(u32, String)>> {
None
}
}
impl MemoryReadable for ItemIntegratedCircuit10 {
fn memory_size(&self) -> usize {
@@ -239,7 +307,7 @@ impl MemoryReadable for ItemIntegratedCircuit10 {
Ok(self.memory[index as usize])
}
}
fn get_memory_slice(&self) -> &[f64] {
fn get_memory_slice(&self) -> &[f64] {
&self.memory
}
}
@@ -280,9 +348,14 @@ impl SourceCode for ItemIntegratedCircuit10 {
}
impl IntegratedCircuit for ItemIntegratedCircuit10 {
fn get_circuit_holder(&self, vm: &VM) -> Option<CircuitHolderRef> {
// FIXME: implement correctly
self.get_parent_slot().map(|parent_slot| parent_slot.parent)
fn get_circuit_holder(&self, vm: &Rc<VM>) -> Option<CircuitHolderRef> {
self.get_parent_slot()
.map(|parent_slot| {
vm.get_object(parent_slot.parent)
.map(|obj| obj.borrow().as_circuit_holder())
.flatten()
})
.flatten()
}
fn get_instruction_pointer(&self) -> f64 {
self.ip as f64
@@ -338,9 +411,9 @@ impl IntegratedCircuit for ItemIntegratedCircuit10 {
fn push_stack(&mut self, val: f64) -> Result<f64, ICError> {
let sp = (self.registers[STACK_POINTER_INDEX].round()) as i32;
if sp < 0 {
Err(ICError::StackUnderflow)
Err(MemoryError::StackUnderflow(sp, self.memory.len()).into())
} else if sp as usize >= self.memory.len() {
Err(ICError::StackOverflow)
Err(MemoryError::StackOverflow(sp, self.memory.len()).into())
} else {
let last = self.memory[sp as usize];
self.memory[sp as usize] = val;
@@ -352,9 +425,9 @@ impl IntegratedCircuit for ItemIntegratedCircuit10 {
self.registers[STACK_POINTER_INDEX] -= 1.0;
let sp = (self.registers[STACK_POINTER_INDEX].round()) as i32;
if sp < 0 {
Err(ICError::StackUnderflow)
Err(MemoryError::StackUnderflow(sp, self.memory.len()).into())
} else if sp as usize >= self.memory.len() {
Err(ICError::StackOverflow)
Err(MemoryError::StackOverflow(sp, self.memory.len()).into())
} else {
let last = self.memory[sp as usize];
Ok(last)
@@ -363,9 +436,9 @@ impl IntegratedCircuit for ItemIntegratedCircuit10 {
fn peek_stack(&self) -> Result<f64, ICError> {
let sp = (self.registers[STACK_POINTER_INDEX] - 1.0).round() as i32;
if sp < 0 {
Err(ICError::StackUnderflow)
Err(MemoryError::StackUnderflow(sp, self.memory.len()).into())
} else if sp as usize >= self.memory.len() {
Err(ICError::StackOverflow)
Err(MemoryError::StackOverflow(sp, self.memory.len()).into())
} else {
let last = self.memory[sp as usize];
Ok(last)
@@ -1325,7 +1398,6 @@ impl BdseInstruction for ItemIntegratedCircuit10 {
}
}
// impl BdsealInstruction for ItemIntegratedCircuit10 {
// /// bdseal d? a(r?|num)
// fn execute_bdseal(&mut self, vm: &VM, d: &Operand, a: &Operand) -> Result<(), ICError>;

View File

@@ -203,6 +203,7 @@ impl ObjectTemplate {
id,
prefab: Name::from_prefab_name(&s.prefab.prefab_name),
name: Name::new(&s.prefab.name),
vm: None,
small_grid: s.structure.small_grid,
},
vm.clone(),
@@ -212,6 +213,7 @@ impl ObjectTemplate {
id,
prefab: Name::from_prefab_name(&s.prefab.prefab_name),
name: Name::new(&s.prefab.name),
vm: None,
small_grid: s.structure.small_grid,
slots: s
.slots
@@ -235,6 +237,7 @@ impl ObjectTemplate {
id,
prefab: Name::from_prefab_name(&s.prefab.prefab_name),
name: Name::new(&s.prefab.name),
vm: None,
small_grid: s.structure.small_grid,
slots: s
.slots
@@ -314,6 +317,7 @@ impl ObjectTemplate {
id,
prefab: Name::from_prefab_name(&s.prefab.prefab_name),
name: Name::new(&s.prefab.name),
vm: None,
small_grid: s.structure.small_grid,
slots: s
.slots
@@ -414,6 +418,7 @@ impl ObjectTemplate {
id,
prefab: Name::from_prefab_name(&s.prefab.prefab_name),
name: Name::new(&s.prefab.name),
vm: None,
small_grid: s.structure.small_grid,
slots: s
.slots
@@ -521,6 +526,7 @@ impl ObjectTemplate {
id,
prefab: Name::from_prefab_name(&s.prefab.prefab_name),
name: Name::new(&s.prefab.name),
vm: None,
small_grid: s.structure.small_grid,
slots: s
.slots
@@ -623,6 +629,7 @@ impl ObjectTemplate {
id,
prefab: Name::from_prefab_name(&i.prefab.prefab_name),
name: Name::new(&i.prefab.name),
vm: None,
item_info: i.item.clone(),
parent_slot: None,
},
@@ -633,6 +640,7 @@ impl ObjectTemplate {
id,
prefab: Name::from_prefab_name(&i.prefab.prefab_name),
name: Name::new(&i.prefab.name),
vm: None,
item_info: i.item.clone(),
parent_slot: None,
slots: i
@@ -657,6 +665,7 @@ impl ObjectTemplate {
id,
prefab: Name::from_prefab_name(&i.prefab.prefab_name),
name: Name::new(&i.prefab.name),
vm: None,
item_info: i.item.clone(),
parent_slot: None,
slots: i
@@ -738,6 +747,7 @@ impl ObjectTemplate {
id,
prefab: Name::from_prefab_name(&i.prefab.prefab_name),
name: Name::new(&i.prefab.name),
vm: None,
item_info: i.item.clone(),
parent_slot: None,
slots: i
@@ -824,6 +834,7 @@ impl ObjectTemplate {
id,
prefab: Name::from_prefab_name(&i.prefab.prefab_name),
name: Name::new(&i.prefab.name),
vm: None,
item_info: i.item.clone(),
parent_slot: None,
slots: i
@@ -1308,7 +1319,7 @@ impl From<LogicableRef<'_>> for LogicInfo {
.iter()
.filter_map(|lt| match logic.get_logic(*lt) {
Ok(val) => Some((*lt, val)),
_ => None
_ => None,
})
.collect(),
),
@@ -1377,9 +1388,15 @@ pub struct DeviceInfo {
impl From<DeviceRef<'_>> for DeviceInfo {
fn from(device: DeviceRef) -> Self {
DeviceInfo {
connection_list: device.connection_list().iter().map(|conn| conn.to_info()).collect(),
connection_list: device
.connection_list()
.iter()
.map(|conn| conn.to_info())
.collect(),
device_pins_length: device.device_pins().map(|pins| pins.len()),
device_pins: device.device_pins().map(|pins| pins.iter().copied().collect()),
device_pins: device
.device_pins()
.map(|pins| pins.iter().copied().collect()),
has_reagents: device.has_reagents(),
has_lock_state: device.has_lock_state(),
has_mode_state: device.has_mode_state(),

View File

@@ -15,7 +15,7 @@ use crate::{
VM,
}
};
use std::{collections::BTreeMap, fmt::Debug};
use std::{collections::BTreeMap, fmt::Debug, rc::Rc};
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct ParentSlotInfo {
@@ -99,7 +99,7 @@ tag_object_traits! {
}
pub trait IntegratedCircuit: Logicable + MemoryWritable + SourceCode + Item {
fn get_circuit_holder(&self, vm: &VM) -> Option<CircuitHolderRef>;
fn get_circuit_holder(&self, vm: &Rc<VM>) -> Option<CircuitHolderRef>;
fn get_instruction_pointer(&self) -> f64;
fn set_next_instruction(&mut self, next_instruction: f64);
fn set_next_instruction_relative(&mut self, offset: f64) {