#[macro_export]
macro_rules! impl_struct_data {
($name:ident = $value:expr $(, $from:literal => $to:literal)* $(,)?) => {
impl_name_by_member! { $name }
impl_default_by_value! { $name = $value }
impl_display_by_patched_debug! { $name $(, $from => $to)* }
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! impl_name_by_member {
($name:ident) => {
impl total_space::Name for $name {
fn name(&self) -> String {
let name: &'static str = std::convert::From::from(self.name);
name.to_string()
}
}
};
}
#[macro_export]
macro_rules! impl_enum_data {
($name:ident = $value:expr $(, $from:literal => $to:literal)* $(,)?) => {
impl_default_by_value! { $name = $value }
impl_name_for_into_static_str! { $name $(, $from => $to)* }
impl_display_by_patched_debug! { $name, "name=" => "" $(, $from => $to)* }
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! impl_default_by_value {
($name:ident = $value:expr) => {
impl Default for $name {
fn default() -> Self {
$value
}
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! impl_name_for_into_static_str {
($name:ident $(, $from:literal => $to:literal)* $(,)?) => {
impl total_space::Name for $name {
fn name(&self) -> String {
let static_str: &'static str = self.into();
let string = static_str.to_string();
$(
let string = string.replace($from, $to);
)*
string
}
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! impl_display_by_patched_debug {
($name:ident $(, $from:literal => $to:literal)* $(,)?) => {
impl Display for $name {
fn fmt(&self, formatter: &mut Formatter<'_>) -> FormatterResult {
let string = format!("{:?}", self)
.replace(" ", "")
.replace(":", "=")
.replace("{", "(")
.replace("}", ")");
$(
let string = string.replace($from, $to);
)*
write!(formatter, "{}", string)
}
}
};
}
#[macro_export]
macro_rules! declare_agent_type_data {
($name:ident, $agent:ident, $model:ident) => {
std::thread_local! {
static $name: std::cell::RefCell<
Option<
std::rc::Rc<
AgentTypeData::<
$agent,
<$model as MetaModel>::StateId,
<$model as MetaModel>::Payload,
>
>
>
> = std::cell::RefCell::new(None);
}
};
}
#[macro_export]
macro_rules! init_agent_type_data {
($name:ident, $agent_type:expr) => {
$name.with(|data| *data.borrow_mut() = Some($agent_type.clone()))
};
}
#[macro_export]
macro_rules! declare_agent_indices {
($name:ident) => {
thread_local! {
static $name: std::cell::RefCell<Vec<usize>> = std::cell::RefCell::new(Vec::new());
}
};
}
#[macro_export]
macro_rules! declare_agent_index {
($name:ident) => {
thread_local! {
static $name: std::cell::RefCell<usize> = std::cell::RefCell::new(usize::max_value());
}
};
}
#[macro_export]
macro_rules! init_agent_indices {
($name:ident, $agent_type:expr) => {{
assert!(!$agent_type.is_singleton());
$name.with(|refcell| {
let mut indices = refcell.borrow_mut();
indices.clear();
for instance in 0..$agent_type.instances_count() {
indices.push($agent_type.first_index() + instance);
}
});
}};
}
#[macro_export]
macro_rules! init_agent_index {
($name:ident, $agent_type:expr) => {
assert!($agent_type.is_singleton());
$name.with(|refcell| *refcell.borrow_mut() = $agent_type.first_index());
};
}
#[macro_export]
macro_rules! agent_index {
($name:ident) => {{
$name.with(|refcell| *refcell.borrow())
}};
($name:ident[$index:expr]) => {
$name.with(|refcell| refcell.borrow()[$index])
};
}
#[macro_export]
macro_rules! agents_count {
($name:ident) => {
$name.with(|refcell| refcell.borrow().len())
};
}
#[macro_export]
macro_rules! activity_alternatives {
($payload1:expr, $payload2:expr $(,)?) => {
total_space::Activity::Process1Of([
Some($payload1),
Some($payload2),
None,
None,
None,
None,
])
};
($payload1:expr, $payload2:expr $(,)?) => {
total_space::Activity::Process1Of([
Some($payload1),
Some($payload2),
None,
None,
None,
None,
])
};
($payload1:expr, $payload2:expr, $payload3:expr $(,)?) => {
total_space::Activity::Process1Of([
Some($payload1),
Some($payload2),
Some($payload3),
None,
None,
None,
])
};
($payload1:expr, $payload2:expr, $payload3:expr, $payload4:expr $(,)?) => {
total_space::Activity::Process1Of([
Some($payload1),
Some($payload2),
Some($payload3),
Some($payload4),
None,
None,
])
};
($payload1:expr, $payload2:expr, $payload3:expr, $payload4:expr, $payload5:expr $(,)?) => {
total_space::Activity::Process1Of([
Some($payload1),
Some($payload2),
Some($payload3),
Some($payload4),
Some($payload5),
None,
])
};
($payload1:expr, $payload2:expr, $payload3:expr, $payload4:expr, $payload5:expr, $payload6:expr $(,)?) => {
total_space::Activity::Process1Of([
Some($payload1),
Some($payload2),
Some($payload3),
Some($payload4),
Some($payload5),
Some($payload6),
])
};
($_:tt) => {
compile_error!("expected 2 to 6 payloads");
};
}
#[macro_export]
macro_rules! reaction_alternatives {
($action1:expr, $action2:expr $(,)?) => {
total_space::Reaction::Do1Of([Some(action1), Some(action2), None, None, None, None])
};
($action1:expr, $action2:expr, $action3:expr $(,)?) => {
total_space::Reaction::Do1Of([
Some(action1),
Some(action2),
Some(action3),
None,
None,
None,
])
};
($action1:expr, $action2:expr, $action3:expr, $action4:expr $(,)?) => {
total_space::Reaction::Do1Of([
Some(action1),
Some(action2),
Some(action3),
Some(action4),
None,
None,
])
};
($action1:expr, $action2:expr, $action3:expr, $action4:expr, $action5:expr $(,)?) => {
total_space::Reaction::Do1Of([
Some(action1),
Some(action2),
Some(action3),
Some(action4),
Some(action5),
None,
])
};
($action1:expr, $action2:expr, $action3:expr, $action4:expr, $action5:expr, $action6:expr $(,)?) => {
total_space::Reaction::Do1Of([
Some(action1),
Some(action2),
Some(action3),
Some(action4),
Some(action5),
Some(action6),
])
};
($_:tt) => {
compile_error!("expected 2 to 6 actions");
};
}
#[macro_export]
macro_rules! action_sends {
($emit1:expr, $emit2:expr $(,)?) => {
total_space::Action::Sends([Some($emit1), Some($emit2), None, None, None, None])
};
($emit1:expr, $emit2:expr, $emit3:expr $(,)?) => {
total_space::Action::Sends([Some($emit1), Some($emit2), Some($emit3), None, None, None])
};
($emit1:expr, $emit2:expr, $emit3:expr, $emit4:expr $(,)?) => {
total_space::Action::Sends([
Some($emit1),
Some($emit2),
Some($emit3),
Some($emit4),
None,
None,
])
};
($emit1:expr, $emit2:expr, $emit3:expr, $emit4:expr, $emit5:expr $(,)?) => {
total_space::Action::Sends([
Some($emit1),
Some($emit2),
Some($emit3),
Some($emit4),
Some($emit5),
None,
])
};
($emit1:expr, $emit2:expr, $emit3:expr, $emit4:expr, $emit5:expr, $emit6:expr $(,)?) => {
total_space::Action::Sends([
Some($emit1),
Some($emit2),
Some($emit3),
Some($emit4),
Some($emit5),
Some($emit6),
])
};
($_:tt) => {
compile_error!("expected 2 to 6 emits");
};
}
#[macro_export]
macro_rules! action_change_and_sends {
($state:expr, $emit1:expr, $emit2:expr $(,)?) => {
total_space::Action::ChangeAndSends(
$state,
[Some($emit1), Some($emit2), None, None, None, None],
)
};
($state:expr, $emit1:expr, $emit2:expr, $emit3:expr $(,)?) => {
total_space::Action::ChangeAndSends(
$state,
[Some($emit1), Some($emit2), Some($emit3), None, None, None],
)
};
($state:expr, $emit1:expr, $emit2:expr, $emit3:expr, $emit4:expr $(,)?) => {
total_space::Action::ChangeAndSends(
$state,
[
Some($emit1),
Some($emit2),
Some($emit3),
Some($emit4),
None,
None,
],
)
};
($state:expr, $emit1:expr, $emit2:expr, $emit3:expr, $emit4:expr, $emit5:expr $(,)?) => {
total_space::Action::ChangeAndSends(
$state,
[
Some($emit1),
Some($emit2),
Some($emit3),
Some($emit4),
Some($emit5),
None,
],
)
};
($state:expr, $emit1:expr, $emit2:expr, $emit3:expr, $emit4:expr, $emit5:expr, $emit6:expr $(,)?) => {
total_space::Action::ChangeAndSends(
$state,
[
Some($emit1),
Some($emit2),
Some($emit3),
Some($emit4),
Some($emit5),
Some($emit6),
],
)
};
($_:tt) => {
compile_error!("expected state and 2 to 6 emits");
};
}
#[macro_export]
macro_rules! assert_configuration_hash_entry_size {
($model:ident, $size:literal) => {
const _: usize = 0
- (std::mem::size_of::<<$model as MetaModel>::ConfigurationHashEntry>() != $size)
as usize;
};
}
#[macro_export]
macro_rules! agent_states_iter {
($configuration:expr, $name:ident, $($iter:tt)*) => {
$name.with(|refcell| {
if let Some(agent_type) = refcell.borrow().as_ref() {
(0..agent_type.instances_count())
.map(|agent_instance| {
let agent_index = agent_type.first_index() + agent_instance;
let state_id = $configuration.state_ids[agent_index];
agent_type.get_state(state_id)
})
.$($iter)*
} else {
unreachable!()
}
})
};
}
#[macro_export]
macro_rules! messages_iter {
($model:expr, $configuration:expr, $($iter:tt)*) => {
$configuration
.message_ids
.iter()
.take_while(|message_id| message_id.is_valid())
.map(|message_id| $model.get_message(*message_id))
.$($iter)*
};
}