refactor: intorduction of a macro enabled Object trait
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
This commit is contained in:
@@ -1,27 +1,24 @@
|
||||
|
||||
macro_rules! __define_object_interface_for {
|
||||
($trt:ident) => {
|
||||
macro_rules! object_trait {
|
||||
(@intf $trait_name:ident $trt:path) => {
|
||||
paste::paste! {
|
||||
#[allow(missing_docs)]
|
||||
pub type [<$trt Ref>]<'a, T> = &'a dyn $trt<ID = <T as Object>::ID>;
|
||||
pub type [<$trt Ref>]<'a, T> = &'a dyn $trt<ID = <T as $trait_name>::ID>;
|
||||
#[allow(missing_docs)]
|
||||
pub type [<$trt RefMut>]<'a, T> = &'a mut dyn $trt<ID = <T as Object>::ID>;
|
||||
pub type [<$trt RefMut>]<'a, T> = &'a mut dyn $trt<ID = <T as $trait_name>::ID>;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! object_trait_for {
|
||||
( $($trt:ident),*) => {
|
||||
( $trait_name:ident {$($trt:path),*}) => {
|
||||
$(
|
||||
__define_object_interface_for!{$trt}
|
||||
object_trait!{@intf $trait_name $trt}
|
||||
)*
|
||||
pub trait Object {
|
||||
|
||||
pub trait $trait_name {
|
||||
type ID;
|
||||
fn id(&self) -> &Self::ID;
|
||||
|
||||
fn as_object(&self) -> &dyn Object<ID = Self::ID>;
|
||||
fn as_object(&self) -> &dyn $trait_name<ID = Self::ID>;
|
||||
|
||||
fn as_object_mut(&mut self) -> &mut dyn Object<ID = Self::ID>;
|
||||
fn as_object_mut(&mut self) -> &mut dyn $trait_name<ID = Self::ID>;
|
||||
|
||||
paste::paste!{$(
|
||||
#[inline(always)]
|
||||
@@ -38,57 +35,77 @@ macro_rules! object_trait_for {
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! __emit_dollar__ {
|
||||
($($rules:tt)*) => {
|
||||
macro_rules! __emit__ { $($rules)* }
|
||||
__emit__! { $ }
|
||||
};
|
||||
}
|
||||
pub(in crate) use object_trait;
|
||||
|
||||
pub(in crate) use __emit_dollar__;
|
||||
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,
|
||||
),*
|
||||
}
|
||||
} => {
|
||||
impl $trait_name for $struct {
|
||||
type ID = $id_typ;
|
||||
|
||||
macro_rules! alias {
|
||||
($($name:ident -> $(#[$($stuff:tt)*])+;)* ) => {
|
||||
$(
|
||||
$crate::vm::object::macros::__emit_dollar__! { ($_:tt) => (
|
||||
#[allow(nonstandard_style)]
|
||||
macro_rules! $name {($_($item:tt)*) => (
|
||||
$( #[$($stuff)*] )+
|
||||
$_($item)*
|
||||
)}
|
||||
#[allow(unused_imports)]
|
||||
pub(in crate) use $name;
|
||||
)}
|
||||
)*
|
||||
fn id(&self) -> &Self::ID {
|
||||
&self.$field_id
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn as_object(&self) -> &dyn $trait_name<ID = Self::ID> {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn as_object_mut(&mut self) -> &mut dyn $trait_name<ID = Self::ID> {
|
||||
self
|
||||
}
|
||||
|
||||
paste::paste!{$(
|
||||
#[inline(always)]
|
||||
fn [<as_ $trt:lower>](&self) -> Option<[<$trt Ref>]<Self>> {
|
||||
Some(self)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn [<as_ $trt:lower _mut>](&mut self) -> Option<[<$trt RefMut>]<Self>> {
|
||||
Some(self)
|
||||
}
|
||||
)*}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
pub(in crate) use alias;
|
||||
pub(in crate) use ObjectInterface;
|
||||
|
||||
|
||||
|
||||
macro_rules! impl_trait_interfaces {
|
||||
( $($trt:ident),*) => {
|
||||
#[inline(always)]
|
||||
fn as_object(&self) -> &dyn Object<ID = Self::ID> {
|
||||
self
|
||||
macro_rules! ObjectTrait {
|
||||
{
|
||||
#[custom(object_trait = $trait_name:ident)]
|
||||
$(#[$attr:meta])*
|
||||
$viz:vis trait $trt:ident $(: $($bound:path)* )? {
|
||||
$($tbody:tt)*
|
||||
}
|
||||
} => {
|
||||
$(#[$attr])*
|
||||
$viz trait $trt: $($($bound)* +)? $trait_name {
|
||||
$($tbody)*
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn as_object_mut(&mut self) -> &mut dyn Object<ID = Self::ID> {
|
||||
self
|
||||
}
|
||||
|
||||
paste::paste!{$(
|
||||
#[inline(always)]
|
||||
fn [<as_ $trt:lower>](&self) -> Option<[<$trt Ref>]<Self>> {
|
||||
Some(self)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn [<as_ $trt:lower _mut>](&mut self) -> Option<[<$trt RefMut>]<Self>> {
|
||||
Some(self)
|
||||
}
|
||||
)*}
|
||||
};
|
||||
}
|
||||
|
||||
pub(in crate) use ObjectTrait;
|
||||
|
||||
@@ -1,5 +1,34 @@
|
||||
use macro_rules_attribute::derive;
|
||||
|
||||
mod macros;
|
||||
mod traits;
|
||||
|
||||
use macros::alias;
|
||||
use macros::{object_trait, ObjectInterface};
|
||||
use traits::Memory;
|
||||
|
||||
use crate::vm::object::traits::Test;
|
||||
|
||||
object_trait!(VmObject { Memory });
|
||||
|
||||
#[derive(ObjectInterface!)]
|
||||
#[custom(implements(VmObject { Memory }))]
|
||||
pub struct Generic {
|
||||
mem1: Vec<u32>,
|
||||
|
||||
#[custom(object_id)]
|
||||
id: u32,
|
||||
|
||||
mem2: Vec<u32>,
|
||||
}
|
||||
|
||||
impl Memory for Generic {
|
||||
fn get_memory(&self) -> &Vec<u32> {
|
||||
&self.mem1
|
||||
}
|
||||
|
||||
fn set_memory(&mut self, index: usize, val: u32) {
|
||||
self.mem2[index] = val;
|
||||
}
|
||||
}
|
||||
|
||||
impl Test for Generic {}
|
||||
|
||||
17
ic10emu/src/vm/object/traits.rs
Normal file
17
ic10emu/src/vm/object/traits.rs
Normal file
@@ -0,0 +1,17 @@
|
||||
use macro_rules_attribute::apply;
|
||||
use crate::vm::object::macros::ObjectTrait;
|
||||
use crate::vm::object::VmObject;
|
||||
|
||||
#[apply(ObjectTrait!)]
|
||||
#[custom(object_trait = VmObject)]
|
||||
pub trait Memory: Test {
|
||||
fn get_memory(&self) -> &Vec<u32>;
|
||||
fn set_memory(&mut self, index: usize, val: u32);
|
||||
}
|
||||
|
||||
|
||||
pub trait Test {
|
||||
fn test(&self) {
|
||||
println!("test!");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user