refactor(vm): generic impls for generic Objects (not implimented with special logic)
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
This commit is contained in:
@@ -54,6 +54,7 @@ pub struct VM {
|
||||
|
||||
/// list of device id's touched on the last operation
|
||||
operation_modified: RefCell<Vec<u32>>,
|
||||
#[allow(unused)]
|
||||
objects: Vec<object::BoxedObject>,
|
||||
}
|
||||
|
||||
|
||||
28
ic10emu/src/vm/object/errors.rs
Normal file
28
ic10emu/src/vm/object/errors.rs
Normal file
@@ -0,0 +1,28 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::grammar::{LogicType, SlotLogicType};
|
||||
|
||||
#[derive(Error, Debug, Serialize, Deserialize)]
|
||||
pub enum LogicError {
|
||||
#[error("can't read LogicType {0}")]
|
||||
CantRead(LogicType),
|
||||
#[error("can't read slot {1} SlotLogicType {0}")]
|
||||
CantSlotRead(SlotLogicType, usize),
|
||||
#[error("can't write LogicType {0}")]
|
||||
CantWrite(LogicType),
|
||||
#[error("can't write slot {1} SlotLogicType {0}")]
|
||||
CantSlotWrite(SlotLogicType, usize),
|
||||
#[error("slot id {0} is out of range 0..{1}")]
|
||||
SlotIndexOutOfRange(usize, usize)
|
||||
}
|
||||
|
||||
#[derive(Error, Debug, Serialize, Deserialize)]
|
||||
pub enum MemoryError {
|
||||
#[error("stack underflow: {0} < range [0..{1})")]
|
||||
StackUnderflow(i32, usize),
|
||||
#[error("stack overflow: {0} > range [0..{1})")]
|
||||
StackOverflow(i32, usize),
|
||||
#[error("memory unit not present")]
|
||||
NotPresent,
|
||||
}
|
||||
@@ -1,15 +1,16 @@
|
||||
macro_rules! object_trait {
|
||||
(@intf {$trait_name:ident $trt:path}) => {
|
||||
paste::paste! {
|
||||
#[allow(missing_docs)]
|
||||
#[allow(missing_docs, unused)]
|
||||
pub type [<$trt Ref>]<'a, T> = &'a dyn $trt<ID = <T as $trait_name>::ID>;
|
||||
#[allow(missing_docs)]
|
||||
#[allow(missing_docs, unused)]
|
||||
pub type [<$trt RefMut>]<'a, T> = &'a mut dyn $trt<ID = <T as $trait_name>::ID>;
|
||||
}
|
||||
};
|
||||
(@body $trait_name:ident $($trt:path),*) => {
|
||||
type ID;
|
||||
fn id(&self) -> &Self::ID;
|
||||
fn prefab(&self) -> &crate::vm::object::Name;
|
||||
|
||||
fn type_name(&self) -> &str;
|
||||
|
||||
@@ -46,29 +47,21 @@ pub(crate) use object_trait;
|
||||
|
||||
macro_rules! ObjectInterface {
|
||||
{
|
||||
#[custom(implements($trait_name:ident {$($trt:path),*}))]
|
||||
$( #[$attr:meta] )*
|
||||
$viz:vis struct $struct:ident {
|
||||
$(
|
||||
$(#[#field1:meta])*
|
||||
$field1_viz:vis
|
||||
$field1_name:ident : $field1_ty:ty,
|
||||
),*
|
||||
#[custom(object_id)]
|
||||
$(#[$id_attr:meta])*
|
||||
$id_viz:vis $field_id:ident: $id_typ:ty,
|
||||
$(
|
||||
$(#[#field2:meta])*
|
||||
$field2_viz:vis
|
||||
$field2_name:ident : $field2_ty:ty,
|
||||
),*
|
||||
}
|
||||
@final
|
||||
@trt $trait_name:ident; $struct:ident;
|
||||
@impls $($trt:path),*;
|
||||
@id $id_field:ident: $id_typ:ty;
|
||||
@prefab $prefab_field:ident: $prefab_typ:ty;
|
||||
} => {
|
||||
impl $trait_name for $struct {
|
||||
type ID = $id_typ;
|
||||
|
||||
fn id(&self) -> &Self::ID {
|
||||
&self.$field_id
|
||||
&self.$id_field
|
||||
}
|
||||
|
||||
fn prefab(&self) -> &crate::vm::object::Name {
|
||||
&self.$prefab_field
|
||||
}
|
||||
|
||||
fn type_name(&self) -> &str {
|
||||
@@ -87,18 +80,158 @@ macro_rules! ObjectInterface {
|
||||
|
||||
paste::paste!{$(
|
||||
#[inline(always)]
|
||||
fn [<as_ $trt:lower>](&self) -> Option<[<$trt Ref>]<Self>> {
|
||||
fn [<as_ $trt:snake>](&self) -> Option<[<$trt Ref>]<Self>> {
|
||||
Some(self)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn [<as_ $trt:lower _mut>](&mut self) -> Option<[<$trt RefMut>]<Self>> {
|
||||
fn [<as_ $trt:snake _mut>](&mut self) -> Option<[<$trt RefMut>]<Self>> {
|
||||
Some(self)
|
||||
}
|
||||
)*}
|
||||
|
||||
}
|
||||
};
|
||||
{
|
||||
@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!{
|
||||
@final
|
||||
@trt $trait_name; $struct;
|
||||
@impls $($trt),*;
|
||||
@id $id_field: $id_typ;
|
||||
@prefab $prefab_field: $prefab_typ;
|
||||
}
|
||||
};
|
||||
{
|
||||
@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_id)]
|
||||
$(#[$id_attr:meta])*
|
||||
$id_viz:vis $id_field:ident: $id_typ:ty,
|
||||
$( $rest:tt )*
|
||||
|
||||
} => {
|
||||
$crate::vm::object::macros::ObjectInterface!{
|
||||
@final
|
||||
@trt $trait_name; $struct;
|
||||
@impls $($trt),*;
|
||||
@id $id_field: $id_typ;
|
||||
@prefab $prefab_field: $prefab_typ;
|
||||
}
|
||||
};
|
||||
{
|
||||
@body_prefab
|
||||
@trt $trait_name:ident; $struct:ident;
|
||||
@impls $($trt:path),*;
|
||||
@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_prefab
|
||||
@trt $trait_name; $struct;
|
||||
@impls $($trt),*;
|
||||
@prefab $prefab_field: $prefab_typ;
|
||||
$( $rest )*
|
||||
}
|
||||
};
|
||||
{
|
||||
@body
|
||||
@trt $trait_name:ident; $struct:ident;
|
||||
@impls $($trt:path),*;
|
||||
#[custom(object_prefab)]
|
||||
$(#[$prefab_attr:meta])*
|
||||
$prefab_viz:vis $prefab_field:ident: $prefab_typ:ty,
|
||||
$( $rest:tt )*
|
||||
|
||||
} => {
|
||||
$crate::vm::object::macros::ObjectInterface!{
|
||||
@body_prefab
|
||||
@trt $trait_name; $struct;
|
||||
@impls $($trt),*;
|
||||
@prefab $prefab_field: $prefab_typ;
|
||||
$( $rest )*
|
||||
}
|
||||
};
|
||||
{
|
||||
@body
|
||||
@trt $trait_name:ident; $struct:ident;
|
||||
@impls $($trt:path),*;
|
||||
#[custom(object_id)]
|
||||
$(#[$id_attr:meta])*
|
||||
$id_viz:vis $id_field:ident: $id_typ:ty,
|
||||
$( $rest:tt )*
|
||||
|
||||
} => {
|
||||
$crate::vm::object::macros::ObjectInterface!{
|
||||
@body_id
|
||||
@trt $trait_name; $struct;
|
||||
@impls $($trt),*;
|
||||
@id $id_field: $id_typ;
|
||||
$( $rest )*
|
||||
}
|
||||
};
|
||||
{
|
||||
@body
|
||||
@trt $trait_name:ident; $struct:ident;
|
||||
@impls $($trt:path),*;
|
||||
$(#[#field:meta])*
|
||||
$field_viz:vis
|
||||
$field_name:ident : $field_ty:ty,
|
||||
$( $rest:tt )*
|
||||
|
||||
} => {
|
||||
$crate::vm::object::macros::ObjectInterface!{
|
||||
@body
|
||||
@trt $trait_name; $struct;
|
||||
@impls $($trt),*;
|
||||
$( $rest )*
|
||||
}
|
||||
};
|
||||
{
|
||||
#[custom(implements($trait_name:ident {$($trt:path),*}))]
|
||||
$( #[$attr:meta] )*
|
||||
$viz:vis struct $struct:ident {
|
||||
$( $body:tt )*
|
||||
}
|
||||
} => {
|
||||
$crate::vm::object::macros::ObjectInterface!{
|
||||
@body
|
||||
@trt $trait_name; $struct;
|
||||
@impls $($trt),*;
|
||||
$( $body )*
|
||||
}
|
||||
};
|
||||
}
|
||||
pub(crate) use ObjectInterface;
|
||||
|
||||
@@ -1,38 +1,55 @@
|
||||
use macro_rules_attribute::derive;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
mod macros;
|
||||
mod traits;
|
||||
mod stationpedia;
|
||||
mod errors;
|
||||
|
||||
use macros::ObjectInterface;
|
||||
use traits::*;
|
||||
|
||||
use crate::{device::SlotType, grammar::SlotLogicType};
|
||||
|
||||
pub type ObjectID = u32;
|
||||
pub type BoxedObject = Box<dyn Object<ID = ObjectID>>;
|
||||
|
||||
|
||||
#[derive(ObjectInterface!)]
|
||||
#[custom(implements(Object { Memory }))]
|
||||
pub struct Generic {
|
||||
mem1: Vec<f64>,
|
||||
|
||||
#[custom(object_id)]
|
||||
id: ObjectID,
|
||||
|
||||
mem2: Vec<f64>,
|
||||
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
||||
pub struct Name {
|
||||
pub value: String,
|
||||
pub hash: i32,
|
||||
}
|
||||
|
||||
impl Memory for Generic {
|
||||
fn get_memory(&self) -> &Vec<f64> {
|
||||
&self.mem1
|
||||
#[allow(unused)]
|
||||
impl Name {
|
||||
pub fn new(name: &str) -> Self {
|
||||
Name {
|
||||
value: name.to_owned(),
|
||||
hash: const_crc32::crc32(name.as_bytes()) as i32,
|
||||
}
|
||||
}
|
||||
|
||||
fn set_memory(&mut self, index: usize, val: f64) {
|
||||
self.mem2[index] = val;
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
self.mem1.len()
|
||||
pub fn set(&mut self, name: &str) {
|
||||
self.value = name.to_owned();
|
||||
self.hash = const_crc32::crc32(name.as_bytes()) as i32;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum FieldType {
|
||||
Read,
|
||||
Write,
|
||||
ReadWrite,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct LogicField {
|
||||
pub field_type: FieldType,
|
||||
pub value: f64,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
||||
pub struct Slot {
|
||||
pub typ: SlotType,
|
||||
pub enabeled_logic: Vec<SlotLogicType>,
|
||||
pub occupant: Option<ObjectID>,
|
||||
}
|
||||
|
||||
@@ -7,11 +7,13 @@ use crate::vm::object::BoxedObject;
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/stationpedia_prefabs.rs"));
|
||||
|
||||
#[allow(unused)]
|
||||
pub enum PrefabTemplate {
|
||||
Hash(i32),
|
||||
Name(String),
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn object_from_prefab_template(template: &PrefabTemplate) -> Option<BoxedObject> {
|
||||
let prefab = match template {
|
||||
PrefabTemplate::Hash(hash) => StationpediaPrefab::from_repr(*hash),
|
||||
@@ -24,3 +26,5 @@ pub fn object_from_prefab_template(template: &PrefabTemplate) -> Option<BoxedObj
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
mod generic;
|
||||
|
||||
323
ic10emu/src/vm/object/stationpedia/generic.rs
Normal file
323
ic10emu/src/vm/object/stationpedia/generic.rs
Normal file
@@ -0,0 +1,323 @@
|
||||
use crate::{
|
||||
grammar::{LogicType, SlotLogicType},
|
||||
vm::{
|
||||
object::{
|
||||
errors::{LogicError, MemoryError},
|
||||
macros::ObjectInterface,
|
||||
traits::*,
|
||||
FieldType, LogicField, Name, ObjectID, Slot,
|
||||
},
|
||||
VM,
|
||||
},
|
||||
};
|
||||
use macro_rules_attribute::derive;
|
||||
use std::{collections::BTreeMap, usize};
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
pub trait GWLogicable {
|
||||
fn name(&self) -> &Option<Name>;
|
||||
fn fields(&self) -> &BTreeMap<LogicType, LogicField>;
|
||||
fn fields_mut(&mut self) -> &mut BTreeMap<LogicType, LogicField>;
|
||||
fn slots(&self) -> &Vec<Slot>;
|
||||
fn slots_mut(&mut self) -> &mut Vec<Slot>;
|
||||
}
|
||||
macro_rules! GWLogicable {
|
||||
(
|
||||
$( #[$attr:meta] )*
|
||||
$viz:vis struct $struct:ident {
|
||||
$($body:tt)*
|
||||
}
|
||||
) => {
|
||||
impl GWLogicable for $struct {
|
||||
fn name(&self) -> &Option<Name> {
|
||||
&self.name
|
||||
}
|
||||
fn fields(&self) -> &BTreeMap<LogicType, LogicField> {
|
||||
&self.fields
|
||||
}
|
||||
fn fields_mut(&mut self) -> &mut BTreeMap<LogicType, LogicField> {
|
||||
&mut self.fields
|
||||
}
|
||||
fn slots(&self) -> &Vec<Slot> {
|
||||
&self.slots
|
||||
}
|
||||
fn slots_mut(&mut self) -> &mut Vec<Slot> {
|
||||
&mut self.slots
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
pub trait GWMemory {
|
||||
fn memory_size(&self) -> usize;
|
||||
}
|
||||
macro_rules! GWMemory {
|
||||
(
|
||||
$( #[$attr:meta] )*
|
||||
$viz:vis struct $struct:ident {
|
||||
$($body:tt)*
|
||||
}
|
||||
) => {
|
||||
impl GWMemory for $struct {
|
||||
fn memory_size(&self) -> usize {
|
||||
self.memory.len()
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub trait GWMemoryReadable: GWMemory {
|
||||
fn memory(&self) -> &Vec<f64>;
|
||||
}
|
||||
macro_rules! GWMemoryReadable {
|
||||
(
|
||||
$( #[$attr:meta] )*
|
||||
$viz:vis struct $struct:ident {
|
||||
$($body:tt)*
|
||||
}
|
||||
) => {
|
||||
impl GWMemoryReadable for $struct {
|
||||
fn memory(&self) -> &Vec<f64> {
|
||||
&self.memory
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
pub trait GWMemoryWritable: GWMemory + GWMemoryReadable {
|
||||
fn memory_mut(&mut self) -> &mut Vec<f64>;
|
||||
}
|
||||
macro_rules! GWMemoryWritable {
|
||||
(
|
||||
$( #[$attr:meta] )*
|
||||
$viz:vis struct $struct:ident {
|
||||
$($body:tt)*
|
||||
}
|
||||
) => {
|
||||
impl GWMemoryWritable for $struct {
|
||||
fn memory_mut(&mut self) -> &mut Vec<f64> {
|
||||
&mut self.memory
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub trait GWDevice: GWLogicable {}
|
||||
macro_rules! GWDevice {
|
||||
(
|
||||
$( #[$attr:meta] )*
|
||||
$viz:vis struct $struct:ident {
|
||||
$($body:tt)*
|
||||
}
|
||||
) => {
|
||||
impl GWDevice for $struct {}
|
||||
};
|
||||
}
|
||||
|
||||
pub trait GWCircuitHolder: GWLogicable {}
|
||||
|
||||
impl<T: GWLogicable + Object> Logicable for T {
|
||||
fn prefab_hash(&self) -> i32 {
|
||||
self.prefab().hash
|
||||
}
|
||||
fn name_hash(&self) -> i32 {
|
||||
self.name().as_ref().map(|name| name.hash).unwrap_or(0)
|
||||
}
|
||||
fn is_logic_readable(&self) -> bool {
|
||||
LogicType::iter().any(|lt| self.can_logic_read(lt))
|
||||
}
|
||||
fn is_logic_writeable(&self) -> bool {
|
||||
LogicType::iter().any(|lt| self.can_logic_write(lt))
|
||||
}
|
||||
fn can_logic_read(&self, lt: LogicType) -> bool {
|
||||
self.fields()
|
||||
.get(<)
|
||||
.map(|field| matches!(field.field_type, FieldType::Read | FieldType::ReadWrite))
|
||||
.unwrap_or(false)
|
||||
}
|
||||
fn can_logic_write(&self, lt: LogicType) -> bool {
|
||||
self.fields()
|
||||
.get(<)
|
||||
.map(|field| matches!(field.field_type, FieldType::Write | FieldType::ReadWrite))
|
||||
.unwrap_or(false)
|
||||
}
|
||||
fn get_logic(&self, lt: LogicType) -> Result<f64, LogicError> {
|
||||
self.fields()
|
||||
.get(<)
|
||||
.and_then(|field| match field.field_type {
|
||||
FieldType::Read | FieldType::ReadWrite => Some(field.value),
|
||||
_ => None,
|
||||
})
|
||||
.ok_or(LogicError::CantRead(lt))
|
||||
}
|
||||
fn set_logic(&mut self, lt: LogicType, value: f64, force: bool) -> Result<(), LogicError> {
|
||||
self.fields_mut()
|
||||
.get_mut(<)
|
||||
.ok_or(LogicError::CantWrite(lt))
|
||||
.and_then(|field| match field.field_type {
|
||||
FieldType::Write | FieldType::ReadWrite => {
|
||||
field.value = value;
|
||||
Ok(())
|
||||
}
|
||||
_ if force => {
|
||||
field.value = value;
|
||||
Ok(())
|
||||
}
|
||||
_ => Err(LogicError::CantWrite(lt)),
|
||||
})
|
||||
}
|
||||
fn slots_count(&self) -> usize {
|
||||
self.slots().len()
|
||||
}
|
||||
fn get_slot(&self, index: usize) -> Option<&Slot> {
|
||||
self.slots().get(index)
|
||||
}
|
||||
fn get_slot_mut(&mut self, index: usize) -> Option<&mut Slot> {
|
||||
self.slots_mut().get_mut(index)
|
||||
}
|
||||
fn can_slot_logic_read(&self, slt: SlotLogicType, index: usize) -> bool {
|
||||
self.get_slot(index)
|
||||
.map(|slot| slot.enabeled_logic.contains(&slt))
|
||||
.unwrap_or(false)
|
||||
}
|
||||
fn get_slot_logic(
|
||||
&self,
|
||||
slt: SlotLogicType,
|
||||
index: usize,
|
||||
_vm: &VM,
|
||||
) -> Result<f64, LogicError> {
|
||||
self.get_slot(index)
|
||||
.ok_or_else(|| LogicError::SlotIndexOutOfRange(index, self.slots().len()))
|
||||
.and_then(|slot| {
|
||||
if slot.enabeled_logic.contains(&slt) {
|
||||
match slot.occupant {
|
||||
Some(_id) => {
|
||||
// FIXME: impliment by accessing VM to get occupant
|
||||
Ok(0.0)
|
||||
}
|
||||
None => Ok(0.0),
|
||||
}
|
||||
} else {
|
||||
Err(LogicError::CantSlotRead(slt, index))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: GWMemory + Object> Memory for T {
|
||||
fn memory_size(&self) -> usize {
|
||||
self.memory_size()
|
||||
}
|
||||
}
|
||||
impl<T: GWMemoryReadable + Memory + Object> MemoryReadable for T {
|
||||
fn get_memory(&self, index: i32) -> Result<f64, MemoryError> {
|
||||
if index < 0 {
|
||||
Err(MemoryError::StackUnderflow(index, self.memory().len()))
|
||||
} else if index as usize >= self.memory().len() {
|
||||
Err(MemoryError::StackOverflow(index, self.memory().len()))
|
||||
} else {
|
||||
Ok(self.memory()[index as usize])
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<T: GWMemoryWritable + Memory + Object> MemoryWritable for T {
|
||||
fn set_memory(&mut self, index: i32, val: f64) -> Result<(), MemoryError> {
|
||||
if index < 0 {
|
||||
Err(MemoryError::StackUnderflow(index, self.memory().len()))
|
||||
} else if index as usize >= self.memory().len() {
|
||||
Err(MemoryError::StackOverflow(index, self.memory().len()))
|
||||
} else {
|
||||
self.memory_mut()[index as usize] = val;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
fn clear_memory(&mut self) -> Result<(), MemoryError> {
|
||||
self.memory_mut().fill(0.0);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: GWDevice + Object> Device for T {}
|
||||
|
||||
#[derive(ObjectInterface!)]
|
||||
#[custom(implements(Object { }))]
|
||||
pub struct Generic {
|
||||
#[custom(object_id)]
|
||||
id: ObjectID,
|
||||
#[custom(object_prefab)]
|
||||
prefab: Name,
|
||||
}
|
||||
|
||||
#[derive(ObjectInterface!, GWLogicable!)]
|
||||
#[custom(implements(Object { Logicable }))]
|
||||
pub struct GenericLogicable {
|
||||
#[custom(object_id)]
|
||||
id: ObjectID,
|
||||
#[custom(object_prefab)]
|
||||
prefab: Name,
|
||||
name: Option<Name>,
|
||||
fields: BTreeMap<LogicType, LogicField>,
|
||||
slots: Vec<Slot>,
|
||||
}
|
||||
|
||||
#[derive(ObjectInterface!, GWLogicable!, GWDevice!)]
|
||||
#[custom(implements(Object { Logicable, Device }))]
|
||||
pub struct GenericLogicableDevice {
|
||||
#[custom(object_id)]
|
||||
id: ObjectID,
|
||||
#[custom(object_prefab)]
|
||||
prefab: Name,
|
||||
name: Option<Name>,
|
||||
fields: BTreeMap<LogicType, LogicField>,
|
||||
slots: Vec<Slot>,
|
||||
}
|
||||
|
||||
#[derive(ObjectInterface!, GWLogicable!, GWMemory!, GWMemoryReadable!)]
|
||||
#[custom(implements(Object { Logicable, Memory, MemoryReadable }))]
|
||||
pub struct GenericLogicableMemoryReadable {
|
||||
#[custom(object_id)]
|
||||
id: ObjectID,
|
||||
#[custom(object_prefab)]
|
||||
prefab: Name,
|
||||
name: Option<Name>,
|
||||
fields: BTreeMap<LogicType, LogicField>,
|
||||
slots: Vec<Slot>,
|
||||
memory: Vec<f64>,
|
||||
}
|
||||
|
||||
#[derive(ObjectInterface!, GWLogicable!, GWMemory!, GWMemoryReadable!, GWMemoryWritable!)]
|
||||
#[custom(implements(Object { Logicable, Memory, MemoryReadable, MemoryWritable }))]
|
||||
pub struct GenericLogicableMemoryReadWritable {
|
||||
#[custom(object_id)]
|
||||
id: ObjectID,
|
||||
#[custom(object_prefab)]
|
||||
prefab: Name,
|
||||
name: Option<Name>,
|
||||
fields: BTreeMap<LogicType, LogicField>,
|
||||
slots: Vec<Slot>,
|
||||
memory: Vec<f64>,
|
||||
}
|
||||
|
||||
#[derive(ObjectInterface!, GWLogicable!, GWDevice!, GWMemory!, GWMemoryReadable!, GWMemoryWritable!)]
|
||||
#[custom(implements(Object { Logicable, Device, Memory, MemoryReadable }))]
|
||||
pub struct GenericLogicableDeviceMemoryReadable {
|
||||
#[custom(object_id)]
|
||||
id: ObjectID,
|
||||
#[custom(object_prefab)]
|
||||
prefab: Name,
|
||||
name: Option<Name>,
|
||||
fields: BTreeMap<LogicType, LogicField>,
|
||||
slots: Vec<Slot>,
|
||||
memory: Vec<f64>,
|
||||
}
|
||||
|
||||
#[derive(ObjectInterface!, GWLogicable!, GWDevice!, GWMemory!, GWMemoryReadable!, GWMemoryWritable!)]
|
||||
#[custom(implements(Object { Logicable, Device, Memory, MemoryReadable, MemoryWritable }))]
|
||||
pub struct GenericLogicableDeviceMemoryReadWriteablable {
|
||||
#[custom(object_id)]
|
||||
id: ObjectID,
|
||||
#[custom(object_prefab)]
|
||||
prefab: Name,
|
||||
name: Option<Name>,
|
||||
fields: BTreeMap<LogicType, LogicField>,
|
||||
slots: Vec<Slot>,
|
||||
memory: Vec<f64>,
|
||||
}
|
||||
@@ -1,42 +1,52 @@
|
||||
use std::fmt::Debug;
|
||||
|
||||
use crate::{grammar, vm::{object::{macros::tag_object_traits, ObjectID}, VM}};
|
||||
use crate::{grammar, vm::{object::{errors::{LogicError, MemoryError}, macros::tag_object_traits, ObjectID, Slot}, VM}};
|
||||
|
||||
tag_object_traits! {
|
||||
#![object_trait(Object: Debug)]
|
||||
|
||||
pub trait Memory {
|
||||
fn size(&self) -> usize;
|
||||
fn memory_size(&self) -> usize;
|
||||
}
|
||||
|
||||
pub trait MemoryWritable: Memory {
|
||||
fn set_memory(&mut self, index: usize, val: f64);
|
||||
fn clear_memory(&mut self);
|
||||
fn set_memory(&mut self, index: i32, val: f64) -> Result<(), MemoryError>;
|
||||
fn clear_memory(&mut self) -> Result<(), MemoryError>;
|
||||
}
|
||||
|
||||
pub trait MemoryReadable: Memory {
|
||||
fn get_memory(&self) -> &Vec<f64>;
|
||||
fn get_memory(&self, index: i32) -> Result<f64, MemoryError>;
|
||||
}
|
||||
|
||||
pub trait Logicable {
|
||||
fn prefab_hash(&self) -> i32;
|
||||
/// returns 0 if not set
|
||||
fn name_hash(&self) -> i32;
|
||||
fn is_logic_readable(&self) -> bool;
|
||||
fn is_logic_writeable(&self) -> bool;
|
||||
fn set_logic(&mut self, lt: grammar::LogicType, value: f64);
|
||||
fn get_logic(&self, lt: grammar::LogicType) -> Option<f64>;
|
||||
fn can_logic_read(&self, lt: grammar::LogicType) -> bool;
|
||||
fn can_logic_write(&self, lt: grammar::LogicType) -> bool;
|
||||
fn set_logic(&mut self, lt: grammar::LogicType, value: f64, force: bool) -> Result<(), LogicError>;
|
||||
fn get_logic(&self, lt: grammar::LogicType) -> Result<f64, LogicError>;
|
||||
|
||||
fn slots_count(&self) -> usize;
|
||||
// fn get_slot(&self, index: usize) -> Slot;
|
||||
fn set_slot_logic(&mut self, slt: grammar::SlotLogicType, value: f64);
|
||||
fn get_slot_logic(&self, slt: grammar::SlotLogicType) -> Option<f64>;
|
||||
fn get_slot(&self, index: usize) -> Option<&Slot>;
|
||||
fn get_slot_mut(&mut self, index: usize) -> Option<&mut Slot>;
|
||||
fn can_slot_logic_read(&self, slt: grammar::SlotLogicType, index: usize) -> bool;
|
||||
fn get_slot_logic(&self, slt: grammar::SlotLogicType, index: usize, vm: &VM) -> Result<f64, LogicError>;
|
||||
}
|
||||
|
||||
pub trait CircuitHolder: Logicable {
|
||||
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>>;
|
||||
fn get_logicable_from_index_mut(&self, device: usize, vm: &VM) -> Option<LogicableRefMut<Self>>;
|
||||
fn get_logicable_from_id(&self, device: ObjectID, vm: &VM) -> Option<LogicableRef<Self>>;
|
||||
fn get_logicable_from_id_mut(&self, device: ObjectID, vm: &VM) -> Option<LogicableRefMut<Self>>;
|
||||
fn get_source_code(&self) -> String;
|
||||
fn set_source_code(&self, code: String);
|
||||
fn get_batch(&self) -> Vec<LogicableRef<Self>>;
|
||||
fn get_batch_mut(&self) -> Vec<LogicableRefMut<Self>>;
|
||||
}
|
||||
|
||||
pub trait SourceCode {
|
||||
@@ -53,6 +63,10 @@ tag_object_traits! {
|
||||
// fn logic_stack(&self) -> LogicStack;
|
||||
}
|
||||
|
||||
pub trait Device: Logicable {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl<T: Debug> Debug for dyn Object<ID = T> {
|
||||
|
||||
Reference in New Issue
Block a user