1use std::any::{Any, TypeId};
2
3use crate::{Cell, Computation, Db, DbHandle};
4
5macro_rules! impl_computation_for_tuple {
6 ($($Middle:ident),+ ; $Last:ident) => {
7 impl<$($Middle,)+ $Last> Computation for ($($Middle,)+ $Last) where
8 $($Middle: Computation,)+
9 $Last: Computation
10 {
11 type Storage = (
12 $($Middle::Storage,)+
13 $Last::Storage
14 );
15 type Output = ();
16
17 fn run(&self, _: &mut DbHandle<impl Computation>) -> Self::Output {
18 panic!("Type dispatch failed in `run`")
19 }
20
21 fn input_to_cell(_: &Self, _: &Self::Storage) -> Option<Cell> {
22 panic!("Type dispatch failed in `input_to_cell`")
23 }
24
25 fn insert_new_cell(_: Cell, _: Self, _: &mut Self::Storage) {
26 panic!("Type dispatch failed in `insert_new_cell`")
27 }
28
29 fn get_function_and_output(_: Cell, _: &Self::Storage) -> (&Self, Option<&Self::Output>) {
30 panic!("Type dispatch failed in `get_function_and_output`")
31 }
32
33 fn set_output(_: Cell, _: Self::Output, _: &mut Self::Storage) {
34 panic!("Type dispatch failed in `set_output`")
35 }
36
37 fn computation_id_of<Concrete: Computation>() -> u32 {
38 let mut i = 0;
39
40 $(
41 if TypeId::of::<Concrete>() == TypeId::of::<$Middle>() {
42 return i;
43 }
44 i += 1;
45 )+
46
47 i + $Last::computation_id_of::<Concrete>()
48 }
49
50 fn get_storage<Concrete: Computation + 'static>(computation_id: u32, storage: &Self::Storage) -> &Concrete::Storage {
51 let mut i = 0;
52 #[allow(non_snake_case)]
53 let ($($Middle,)+ $Last,) = storage;
54
55 $(
56 if computation_id == i {
57 return $Middle::get_storage::<Concrete>(computation_id - i, $Middle)
58 }
59 i += 1;
60 )+
61
62 $Last::get_storage::<Concrete>(computation_id - i, $Last)
63 }
64
65 fn get_storage_mut<Concrete: Computation + 'static>(computation_id: u32, storage: &mut Self::Storage) -> &mut Concrete::Storage {
66 let mut i = 0;
67 #[allow(non_snake_case)]
68 let ($($Middle,)+ $Last,) = storage;
69
70 $(
71 if computation_id == i {
72 return $Middle::get_storage_mut::<Concrete>(computation_id - i, $Middle)
73 }
74 i += 1;
75 )+
76
77 $Last::get_storage_mut::<Concrete>(computation_id - i, $Last)
78 }
79
80 fn output_is_unset<FullComputation: Computation>(
81 cell: Cell,
82 computation_id: u32,
83 original_computation_id: u32,
84 db: &Db<FullComputation>,
85 ) -> bool {
86 let mut i = 0;
87
88 $(
89 if computation_id == i {
90 return $Middle::output_is_unset(cell, computation_id - i, original_computation_id, db);
91 }
92 i += 1;
93 )+
94
95 $Last::output_is_unset(cell, computation_id - i, original_computation_id, db)
96 }
97
98 fn dispatch_run<FullComputation>(
99 cell: Cell,
100 computation_id: u32,
101 original_computation_id: u32,
102 db: &mut Db<FullComputation>,
103 ) -> bool where
104 FullComputation: Computation,
105 Self: Clone,
106 Self::Output: Eq,
107 {
108 let mut i = 0;
109
110 $(
111 if computation_id == i {
112 return $Middle::dispatch_run(cell, computation_id - i, original_computation_id, db);
113 }
114 i += 1;
115 )+
116
117 $Last::dispatch_run(cell, computation_id - i, original_computation_id, db)
118 }
119
120 fn dispatch_update_output<Concrete, FullComputation>(cell: Cell, computation_id: u32, original_computation_id: u32, output: Concrete::Output, db: &mut Db<FullComputation>) -> bool
121 where Concrete: Computation,
122 FullComputation: Computation,
123 Self::Output: Eq,
124 {
125 let mut i = 0;
126
127 $(
128 if computation_id == i {
129 return $Middle::dispatch_update_output::<Concrete, FullComputation>(cell, computation_id - i, original_computation_id, output, db);
130 }
131 i += 1;
132 )+
133
134 $Last::dispatch_update_output::<Concrete, FullComputation>(cell, computation_id - i, original_computation_id, output, db)
135 }
136
137 fn dispatch_input_to_cell<Concrete>(input: &Concrete, storage: &Self::Storage) -> Option<Cell>
138 where Concrete: 'static + Computation + Any
139 {
140 #[allow(non_snake_case)]
141 let ($($Middle,)+ $Last) = storage;
142
143 $(
144 if TypeId::of::<Concrete>() == TypeId::of::<$Middle>() {
145 return $Middle::dispatch_input_to_cell::<Concrete>(input, $Middle);
146 }
147 )+
148
149 $Last::dispatch_input_to_cell::<Concrete>(input, $Last)
150 }
151
152 fn dispatch_insert_new_cell<Concrete>(cell: Cell, input: Concrete, storage: &mut Self::Storage)
153 where Concrete: 'static + Computation + Any,
154 Concrete::Storage: 'static,
155 {
156 #[allow(non_snake_case)]
157 let ($($Middle,)+ $Last) = storage;
158
159 $(
160 if TypeId::of::<Concrete>() == TypeId::of::<$Middle>() {
161 return $Middle::dispatch_insert_new_cell::<Concrete>(cell, input, $Middle);
162 }
163 )+
164
165 $Last::dispatch_insert_new_cell::<Concrete>(cell, input, $Last)
166 }
167 }
168 };
169}
170
171impl_computation_for_tuple!(A; Z);
174impl_computation_for_tuple!(A, B; Z);
175impl_computation_for_tuple!(A, B, C; Z);
176impl_computation_for_tuple!(A, B, C, D; Z);
177impl_computation_for_tuple!(A, B, C, D, E; Z);
178impl_computation_for_tuple!(A, B, C, D, E, F; Z);
179impl_computation_for_tuple!(A, B, C, D, E, F, G; Z);
180impl_computation_for_tuple!(A, B, C, D, E, F, G, H; Z);
181impl_computation_for_tuple!(A, B, C, D, E, F, G, H, I; Z);
182impl_computation_for_tuple!(A, B, C, D, E, F, G, H, I, J; Z);
183impl_computation_for_tuple!(A, B, C, D, E, F, G, H, I, J, K; Z);
184impl_computation_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L; Z);
185impl_computation_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M; Z);
186impl_computation_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N; Z);
187impl_computation_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O; Z);
188impl_computation_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P; Z);
189impl_computation_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q; Z);
190impl_computation_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R; Z);
191impl_computation_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S; Z);
192impl_computation_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T; Z);
193impl_computation_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U; Z);
194impl_computation_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V; Z);
195impl_computation_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W; Z);
196impl_computation_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X; Z);
197impl_computation_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y; Z);