Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions integration-tests/ixa-runner-tests/tests/macros.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#[cfg(test)]
mod tests {
use std::cell::RefCell;
use std::hash::{Hash, Hasher};
use std::rc::Rc;

use ixa::prelude::*;
use ixa::HashSet;
Expand Down Expand Up @@ -138,6 +140,26 @@ mod tests {
// Test rng macro
define_rng!(TestRngId);

fn record_sum(
context: &mut Context,
records: Rc<RefCell<Vec<(f64, u32)>>>,
arg1: u32,
arg2: u32,
arg3: u32,
) {
records
.borrow_mut()
.push((context.get_current_time(), arg1 + arg2 + arg3));
}

fn record_current_time(context: &mut Context, records: Rc<RefCell<Vec<f64>>>) {
records.borrow_mut().push(context.get_current_time());
}

fn passthrough_context(context: &mut Context) -> &mut Context {
context
}

#[test]
fn compile_and_run_macros() {
let mut ctx = Context::new();
Expand Down Expand Up @@ -238,4 +260,56 @@ mod tests {
let b = 1.0f64 + 1e-12;
ixa::assert_almost_eq!(a, b, 1e-10);
}

#[test]
fn schedule_relative_accepts_function_name_with_arguments() {
let mut context = Context::new();
let records = Rc::new(RefCell::new(Vec::new()));
let observed_records = records.clone();

schedule_relative!(&mut context, 2.5, record_sum, records, 1, 2, 3);

context.execute();
assert_eq!(*observed_records.borrow(), vec![(2.5, 6)]);
}

#[test]
fn schedule_relative_accepts_closure_action() {
let mut context = Context::new();
let records = Rc::new(RefCell::new(Vec::new()));
let observed_records = records.clone();

schedule_relative!(
&mut context,
1.25,
|context: &mut Context, records: Rc<RefCell<Vec<(f64, u32)>>>, value: u32| {
records
.borrow_mut()
.push((context.get_current_time(), value));
},
records,
42
);

context.execute();
assert_eq!(*observed_records.borrow(), vec![(1.25, 42)]);
}

#[test]
fn schedule_relative_accepts_context_expression_and_no_action_arguments() {
let mut context = Context::new();
let records = Rc::new(RefCell::new(Vec::new()));
let observed_records = records.clone();

schedule_relative!(
passthrough_context(&mut context),
0.75,
record_current_time,
records
);
schedule_relative!(passthrough_context(&mut context), 1.5, Context::shutdown);

context.execute();
assert_eq!(*observed_records.borrow(), vec![0.75]);
}
}
1 change: 1 addition & 0 deletions src/macros/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ mod define_rng;
mod edge_impl;
mod entity_impl;
mod property_impl;
mod schedule_relative;
mod with;
32 changes: 32 additions & 0 deletions src/macros/schedule_relative.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/// Schedules an action after a delay relative to the context's current time.
///
/// The scheduled action is called with the executing `context: &mut Context` as
/// its first argument, followed by each remaining macro argument in the same
/// order.
///
/// For example:
///
/// ```ignore
/// schedule_relative!(context, my_delay, my_handler, arg1, arg2, arg3);
/// ```
///
/// expands to code like:
///
/// ```ignore
/// {
/// let time = context.get_current_time() + my_delay;
/// context.add_plan(time, move |context| {
/// my_handler(context, arg1, arg2, arg3)
/// })
/// }
/// ```
#[macro_export]
macro_rules! schedule_relative {
($context:expr, $delay:expr, $action:expr $(, $arg:expr)* $(,)?) => {{
let context = ($context);
let time = context.get_current_time() + $delay;
context.add_plan(time, move |context| {
($action)(context $(, $arg)*)
})
}};
}
2 changes: 1 addition & 1 deletion src/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ pub use crate::report::ContextReportExt;
pub use crate::{
define_data_plugin, define_derived_property, define_edge_type, define_entity,
define_global_property, define_multi_property, define_property, define_report, define_rng,
impl_edge_type, impl_entity, impl_property, with, PluginContext,
impl_edge_type, impl_entity, impl_property, schedule_relative, with, PluginContext,
};