#[macro_export]
macro_rules! system {
( $system_name:ident { $($contents:tt)* } ) => {
pub mod $system_name {
use std::any::Any;
use shared_mutex::{ SharedMutex };
#[allow(unused_imports)]
use $crate::entities::{ ComponentList };
use shared_mutex::{ MappedSharedMutexReadGuard, MappedSharedMutexWriteGuard };
use std::sync::Arc;
system_contents!{ ( $($contents)* ) [ ] [ ] }
}
}
}
#[macro_export]
macro_rules! append_path_component {
($($path_component:ident)::+, $extension:ident) => ( $($path_component)::*::$extension )
}
#[macro_export]
macro_rules! system_contents {
(
(
on $event_name:ident, {$($event_declaration_mut:tt)*}, {$($event_declaration:tt)*},
($_self:ident, $_data:ident) => $event_body:block $($rest:tt)*
) [
$( $saved_decl:tt ),*
] [
$( $saved_sync_decl:tt ),*
]
) => (
on! { ($event_name, { $( $event_declaration_mut )* }, { $( $event_declaration)* } ) $_self , $_data => $event_body }
system_contents!{
( $($rest)* )
[ ( $event_name, { $( $event_declaration_mut)* }, {$( $event_declaration)* } ) $(, $saved_decl)* ]
[ $($saved_sync_decl),* ]
}
);
(
(
on_sync $event_name:ident, ($_self:ident, $_data:ident) => $event_body:block $($rest:tt)*
) [
$( $saved_decl:tt ),*
] [
$( $saved_sync_decl:tt ),*
]
) => (
on_sync! { ($event_name, $_self, $_data) $event_body }
system_contents!{
( $($rest)* )
[ $($saved_decl),* ]
[ $event_name $(, $saved_sync_decl)* ]
}
);
(
(
state { $($state_declaration:tt)* } $state_initalizer:block $($rest:tt)*
) [
$( $saved_decl:tt ),*
] [
$( $saved_sync_decl:tt ),*
]
) => (
state! { ($($state_declaration)*), $state_initalizer }
system_contents!{
( $($rest)* )
[ $( $saved_decl ),* ]
[ $(, $saved_sync_decl)* ]
}
);
(
(
$token_tree:item $($rest:tt)*
) [
$( $saved_decl:tt ),*
] [
$( $saved_sync_decl:tt ),*
]
) => (
$token_tree
system_contents!{
( $($rest)* )
[ $( $saved_decl ),* ]
[ $(, $saved_sync_decl)* ]
}
);
(
() [ $( $event_declaration:tt ),* ] [ $( $sync_event_declaration:tt ),* ]
) => (
system_register!{ ($( $event_declaration ),*) ($( $sync_event_declaration ),*) }
)
}
#[macro_export]
macro_rules! on {
( ($event_name:ident, { $( $mut_name:ident : $mut_typ:tt )* } , { $($name:ident : $typ:tt)* } )
$_self:ident, $_data:ident => $event_body:block ) => (
impl State {
#[allow(unused_variables)]
pub fn $event_name(&mut $_self,
$_data: &Vec<$event_name::Data>,
$( $name : &MappedSharedMutexReadGuard<ComponentList<append_path_component!($typ,Component)>>),*
$( $mut_name : &MappedSharedMutexWriteGuard<ComponentList<append_path_component!($mut_typ,Component)>> ),* ) $event_body
}
#[allow(unused_variables)]
#[allow(unused_mut)]
pub fn $event_name(
state: Arc<Any>,
data: &Vec<$event_name::Data>,
components: Vec<MappedSharedMutexReadGuard<Any>>,
mut_components: Vec<MappedSharedMutexWriteGuard<Any>>
) {
let mut components_iter = components.into_iter();
let mut mut_components_iter = mut_components.into_iter();
$(
let $name : MappedSharedMutexReadGuard<ComponentList<append_path_component!($typ,Component)>> = components_iter
.next().expect("Event components list too short.")
.map(|v| v.downcast_ref().expect("Event component not of expected type."));
)*
$(
let $mut_name: MappedSharedMutexWriteGuard<ComponentList<append_path_component!($mut_typ,Component)>> = mut_components_iter
.next().expect("Event mut_components list too short.")
.map(|v| v.downcast_mut().expect("Event component not of expected type."));
)*
let state_casted : &SharedMutex<State> = state.downcast_ref().expect("State not of expected type.");
state_casted.write().expect("Event state corrupted").$event_name(
data,
$(&$name),*
$(&$mut_name),*
);
}
)
}
#[macro_export]
macro_rules! on_sync {
( ($event_name:ident, $_self:ident, $_data:ident) $event_body:block ) => (
impl State {
#[allow(unused_variables)]
pub fn $event_name(&mut $_self,
$_data: $event_name::Argument) $event_body
}
#[allow(unused_variables)]
#[allow(unused_mut)]
pub fn $event_name(
state: Arc<Any+Send+Sync>,
data: $event_name::Argument
) {
let state_ref : &Any = &*state;
let state_casted : &SharedMutex<State> = state_ref.downcast_ref().expect("State not of expected type.");
state_casted.write().expect("Event state corrupted").$event_name(data);
}
)
}
#[macro_export]
macro_rules! state {
( ($( $name:ident : $field:ty ),*), $initializer:block ) => (
pub struct State {
$(pub $name : $field),*
}
pub fn default_state() -> State {
$(let mut $name : $field);* ;
$initializer ;
State {
$($name: $name),*
}
}
)
}
#[macro_export]
macro_rules! system_register {
(
(
$(
(
$event_name:ident,
{ $( $mut_name:ident : $mut_typ:ident )* } ,
{ $( $name:ident : $typ:ident )* }
)
),*
)
(
$(
$sync_event_name:ident
),*
)
) => (
pub fn register() {
#[allow(unused_imports)]
use std::any::TypeId;
let state = default_state();
let state = Arc::new(SharedMutex::new(state));
$(
let mut_ts = vec![ $( TypeId::of::< $mut_typ::Component >() ),* ];
let ts = vec![ $( TypeId::of::< $typ::Component >() ),* ];
$event_name::register_handler(state.clone(), $event_name, ts, mut_ts);
)*
$(
$sync_event_name::register_handler(state.clone(), $sync_event_name);
)*
}
)
}