inc_complete/computation/
macros.rs

1/// Helper macro to define an intermediate computation type. This will
2/// define the type for you along with a `new` method, `Run` impl and
3/// a function wrapper for `db.get(ComputationType::new())`.
4#[macro_export]
5macro_rules! define_intermediate {
6    // No `cloned` on output_type
7    ( $type_name:ident $( { $($fields:tt)* } )? , 
8      $get_function_name:ident, $output_type:ty, $impl_function:expr) => {
9        define_intermediate!(@inner $type_name $( { $( $fields )* } )?, $get_function_name, $output_type, $impl_function; (|x|x); &'db);
10    };
11    // `cloned` on output_type
12    ( $type_name:ident $( { $($fields:tt)* } )? , 
13      $get_function_name:ident, cloned $output_type:ty, $impl_function:expr) => {
14        define_intermediate!(@inner $type_name $( { $($fields)* } )?, $get_function_name, $output_type, $impl_function; Clone::clone;);
15    };
16    (@inner $type_name:ident $( { $( $($(@$if_ref:tt)? &)? $field_name:ident : $field_type:ty),* } )? , 
17      $get_function_name:ident, $output_type:ty, $impl_function:expr; $clone_function:expr ; $($output_ref:tt)* ) => {
18        
19        paste::paste! {
20            #[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
21            struct [<$type_name Internal>] { $( $( $field_name : $field_type ),* )? }
22
23            type $type_name = $crate::HashMapStorage<$crate::Intermediate<[<$type_name Internal>]>>;
24
25            // Constructor function
26            #[allow(non_snake_case)]
27            #[allow(unused)]
28            fn $type_name($( $( $field_name : $field_type, )* )?) -> $type_name {
29                $crate::HashMapStorage::new($crate::Intermediate::new([<$type_name Internal>] { $( $( $field_name ),* )? }))
30            }
31
32            // Query function with DbHandle
33            #[allow(unused)]
34            fn $get_function_name<'db>($( $( $field_name : $field_type, )* )? db: &'db mut $crate::DbHandle<impl $crate::Computation>) -> $($output_ref)? $output_type {
35                $clone_function(db.get($type_name ( $( $( $field_name ),* )? )))
36            }
37
38            // TODO: Should create a trait to abstract over DbHandle and Db
39            // Query function with Db
40            #[allow(unused)]
41            fn [<$get_function_name _db>]<'db>($( $( $field_name : $field_type, )* )? db: &'db mut $crate::Db<impl $crate::Computation>) -> $($output_ref)? $output_type {
42                $clone_function(db.get($type_name ( $( $( $field_name ),* )? )))
43            }
44
45            impl $crate::Run for [<$type_name Internal>] {
46                type Output = $output_type;
47
48                fn run(&self, handle: &mut $crate::DbHandle<impl $crate::Computation>) -> Self::Output {
49                    $impl_function($( $( $($($if_ref)? & )? self. $field_name, )*)? handle)
50                }
51            }
52        }
53    };
54}
55
56/// Helper macro to define an input type. This will define the type for you along with
57/// an `OutputTypeForInput` impl and a function wrapper for `db.get(ComputationType::new())`.
58#[macro_export]
59macro_rules! define_input {
60    // No `cloned` on output_type
61    ( $type_name:ident $( { $($fields:tt)* } )? , 
62      $get_function_name:ident, $output_type:ty) => {
63        define_input!($type_name $( { $($fields)* } )?, $get_function_name, $output_type; (|x|x); &'db);
64    };
65    // `cloned` on output_type
66    ( $type_name:ident $( { $($fields:tt)* } )? , 
67      $get_function_name:ident, cloned $output_type:ty) => {
68        define_input!($type_name $( { $($fields)* } )?, $get_function_name, $output_type; Clone::clone;);
69    };
70
71    ( $type_name:ident $( { $( $field_name:ident : $field_type:ty),* } )? , 
72      $get_function_name:ident, $output_type:ty ; $clone_function:expr ; $($output_ref:tt)* ) => {
73        
74        paste::paste! {
75            #[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Default)]
76            pub struct [<$type_name Internal>] { $( $( $field_name : $field_type ),* )? }
77
78            pub type $type_name = $crate::HashMapStorage<$crate::Input<[<$type_name Internal>]>>;
79
80            // Constructor function
81            #[allow(non_snake_case)]
82            #[allow(unused)]
83            fn $type_name($( $( $field_name : $field_type, )* )?) -> $type_name {
84                $crate::HashMapStorage::new($crate::Input::new([<$type_name Internal>] { $( $( $field_name ),* )? }))
85            }
86
87            // Query function with DbHandle
88            #[allow(unused)]
89            fn $get_function_name<'db>($( $( $field_name : $field_type, )* )? db: &'db mut $crate::DbHandle<impl $crate::Computation>) -> $($output_ref)* $output_type {
90                let result = db.get($type_name ($( $( $field_name ),* )? ));
91                $clone_function(result)
92            }
93
94            // TODO: Should create a trait to abstract over DbHandle and Db
95            // Query function with Db
96            #[allow(unused)]
97            fn [<$get_function_name _db>]<'db>($( $( $field_name : $field_type, )* )? db: &'db mut $crate::Db<impl $crate::Computation>) -> $($output_ref)? $output_type {
98                let result = db.get($type_name ($( $( $field_name ),* )? ));
99                $clone_function(result)
100            }
101
102            impl $crate::OutputTypeForInput for [<$type_name Internal>] {
103                type Output = $output_type;
104            }
105        }
106    };
107}