1use crate::calc::value::{Value, ValueRef};
2use crate::core::count;
3use crate::core::count::Count;
4use crate::core::interface::{Directive, Interface, Operation};
5use crate::error::{EngineError, MyError, MyResult};
6use std::cell::RefCell;
7use std::io::Write;
8use std::rc::Rc;
9
10pub enum Action<W: Write> {
11 Operation(Rc<Operation<W>>),
12 Directive(Rc<Directive<W>>, Vec<String>),
13 Definition(Vec<Action<W>>),
14 Value(ValueRef, bool),
15}
16
17impl<W: Write> Clone for Action<W> {
18 fn clone(&self) -> Self {
19 match self {
20 Self::Operation(operation) => Self::Operation(Rc::clone(operation)),
21 Self::Directive(directive, tokens) => Self::Directive(Rc::clone(directive), tokens.clone()),
22 Self::Definition(actions) => Self::Definition(actions.clone()),
23 Self::Value(value, dirty) => Self::Value(Rc::clone(value), *dirty),
24 }
25 }
26}
27
28pub struct Actions<'a, W: Write, I: Iterator<Item = &'a str>> {
29 interface: Rc<RefCell<Interface<W>>>,
30 tokens: I,
31}
32
33impl<'a, W: Write, I: Iterator<Item = &'a str>> Actions<'a, W, I> {
34 pub fn new(
35 interface: &Rc<RefCell<Interface<W>>>,
36 tokens: I,
37 ) -> Self {
38 let interface = Rc::clone(interface);
39 Self { interface, tokens }
40 }
41}
42
43impl<'a, W: Write, I: Iterator<Item = &'a str>> Iterator for Actions<'a, W, I> {
45 type Item = MyResult<(Action<W>, &'a str)>;
46
47 fn next(&mut self) -> Option<Self::Item> {
48 if let Some(token) = self.tokens.next() {
49 let interface = self.interface.borrow();
50 if let Some(operation) = interface.get_operation(token) {
51 let action = Action::Operation(operation);
52 return Some(Ok((action, token)));
53 } else if let Some(directive) = interface.get_directive(token) {
54 let mut tokens = Vec::new();
55 if let Directive::EngineOne(_, _) = *directive {
56 if let Some(token) = self.tokens.next() {
57 tokens.push(String::from(token));
58 }
59 } else {
60 while let Some(token) = self.tokens.next() {
61 tokens.push(String::from(token));
62 }
63 }
64 let action = Action::Directive(directive, tokens);
65 return Some(Ok((action, token)));
66 } else if let Some(actions) = interface.get_definition(token) {
67 let action = Action::Definition(actions);
68 return Some(Ok((action, token)));
69 } else if let Some(value) = interface.get_variable(token) {
70 let action = Action::Value(value, true);
71 return Some(Ok((action, token)));
72 } else {
73 match Value::from_string(token) {
74 Ok(value) => {
75 let value = Rc::new(RefCell::new(value));
76 let action = Action::Value(value, false);
77 return Some(Ok((action, token)));
78 }
79 Err(_) => {
80 let error = EngineError::ParseError(String::from(token));
81 return Some(Err(MyError::from(error)));
82 }
83 }
84 }
85 }
86 None
87 }
88}
89
90pub fn fold_actions<W: Write>(actions: &Vec<Action<W>>) -> (Count, Count) {
91 actions.iter().fold((Count::N(0), Count::N(0)), fold_action)
92}
93
94fn fold_action<W: Write>((input, output): (Count, Count), action: &Action<W>) -> (Count, Count) {
95 match action {
96 Action::Operation(operation) => fold_operation(input, output, operation),
97 Action::Directive(_, _) => (input, output),
98 Action::Definition(actions) => fold_definition(input, output, actions),
99 Action::Value(_, _) => fold_value(input, output),
100 }
101}
102
103fn fold_operation<W: Write>(
104 input: Count,
105 output: Count,
106 operation: &Rc<Operation<W>>,
107) -> (Count, Count) {
108 let (input2, output2) = operation.count_parameters();
109 count::fold_counts(input, output, input2, output2)
110}
111
112fn fold_definition<W: Write>(
113 input: Count,
114 output: Count,
115 actions: &Vec<Action<W>>,
116) -> (Count, Count) {
117 actions.iter().fold((input, output), fold_action)
118}
119
120fn fold_value(input: Count, output: Count) -> (Count, Count) {
121 (input, output + Count::N(1))
122}
123
124#[cfg(test)]
126pub mod tests {
127 use crate::calc::value::tests::create_nan;
128 use crate::core::action::{fold_actions, Action};
129 use crate::core::count::Count;
130 use crate::core::interface::tests::{
131 dummy_binary,
132 dummy_binary_series,
133 dummy_directive,
134 dummy_nullary,
135 dummy_series,
136 dummy_series_series,
137 dummy_unary,
138 };
139 use crate::core::interface::{Completion, Directive, Operation};
140 use crate::util::text::tests::BufferWriter;
141 use std::rc::Rc;
142
143 #[test]
144 fn test_folds_values_only() {
145 let actions: Vec<Action<BufferWriter>> = vec![
146 ];
147 std::assert_eq!(fold_actions(&actions), (Count::N(0), Count::N(0)));
148
149 let actions: Vec<Action<BufferWriter>> = vec![
150 Action::Value(create_nan(), false),
151 Action::Value(create_nan(), false),
152 Action::Value(create_nan(), false),
153 ];
154 std::assert_eq!(fold_actions(&actions), (Count::N(0), Count::N(3)));
155 }
156
157 #[test]
158 fn test_folds_nullary_operation() {
159 let actions: Vec<Action<BufferWriter>> = vec![
160 Action::Value(create_nan(), false),
161 Action::Value(create_nan(), false),
162 Action::Operation(Rc::new(Operation::ValueNone(dummy_nullary))),
163 ];
164 std::assert_eq!(fold_actions(&actions), (Count::N(0), Count::N(3)));
165
166 let actions: Vec<Action<BufferWriter>> = vec![
167 Action::Value(create_nan(), false),
168 Action::Value(create_nan(), false),
169 Action::Operation(Rc::new(Operation::ValueNone(dummy_nullary))),
170 Action::Operation(Rc::new(Operation::ValueNone(dummy_nullary))),
171 ];
172 std::assert_eq!(fold_actions(&actions), (Count::N(0), Count::N(4)));
173 }
174
175 #[test]
176 fn test_folds_unary_operation() {
177 let actions: Vec<Action<BufferWriter>> = vec![
178 Action::Value(create_nan(), false),
179 Action::Value(create_nan(), false),
180 Action::Operation(Rc::new(Operation::ValueOne(dummy_unary))),
181 ];
182 std::assert_eq!(fold_actions(&actions), (Count::N(0), Count::N(2)));
183
184 let actions: Vec<Action<BufferWriter>> = vec![
185 Action::Value(create_nan(), false),
186 Action::Value(create_nan(), false),
187 Action::Operation(Rc::new(Operation::ValueOne(dummy_unary))),
188 Action::Operation(Rc::new(Operation::ValueOne(dummy_unary))),
189 ];
190 std::assert_eq!(fold_actions(&actions), (Count::N(0), Count::N(2)));
191 }
192
193 #[test]
194 fn test_folds_binary_operation() {
195 let actions: Vec<Action<BufferWriter>> = vec![
196 Action::Value(create_nan(), false),
197 Action::Value(create_nan(), false),
198 Action::Operation(Rc::new(Operation::ValueTwo(dummy_binary))),
199 ];
200 std::assert_eq!(fold_actions(&actions), (Count::N(0), Count::N(1)));
201
202 let actions: Vec<Action<BufferWriter>> = vec![
203 Action::Value(create_nan(), false),
204 Action::Value(create_nan(), false),
205 Action::Operation(Rc::new(Operation::ValueTwo(dummy_binary))),
206 Action::Operation(Rc::new(Operation::ValueTwo(dummy_binary))),
207 ];
208 std::assert_eq!(fold_actions(&actions), (Count::N(1), Count::N(1)));
209
210 let actions: Vec<Action<BufferWriter>> = vec![
211 Action::Value(create_nan(), false),
212 Action::Value(create_nan(), false),
213 Action::Operation(Rc::new(Operation::ValueTwo(dummy_binary))),
214 Action::Operation(Rc::new(Operation::ValueTwo(dummy_binary))),
215 Action::Operation(Rc::new(Operation::ValueTwo(dummy_binary))),
216 ];
217 std::assert_eq!(fold_actions(&actions), (Count::N(2), Count::N(1)));
218 }
219
220 #[test]
221 fn test_folds_series_to_value_operation() {
222 let actions: Vec<Action<BufferWriter>> = vec![
223 Action::Value(create_nan(), false),
224 Action::Value(create_nan(), false),
225 Action::Operation(Rc::new(Operation::ValueAll(dummy_series))),
226 ];
227 std::assert_eq!(fold_actions(&actions), (Count::All, Count::N(1)));
228
229 let actions: Vec<Action<BufferWriter>> = vec![
230 Action::Value(create_nan(), false),
231 Action::Value(create_nan(), false),
232 Action::Value(create_nan(), false),
233 Action::Operation(Rc::new(Operation::ValueAll(dummy_series))),
234 ];
235 std::assert_eq!(fold_actions(&actions), (Count::All, Count::N(1)));
236
237 let actions: Vec<Action<BufferWriter>> = vec![
238 Action::Value(create_nan(), false),
239 Action::Value(create_nan(), false),
240 Action::Value(create_nan(), false),
241 Action::Value(create_nan(), false),
242 Action::Operation(Rc::new(Operation::ValueAll(dummy_series))),
243 ];
244 std::assert_eq!(fold_actions(&actions), (Count::All, Count::N(1)));
245 }
246
247 #[test]
248 fn test_folds_binary_to_series_operation() {
249 let actions: Vec<Action<BufferWriter>> = vec![
250 Action::Value(create_nan(), false),
251 Action::Value(create_nan(), false),
252 Action::Operation(Rc::new(Operation::SeriesTwo(dummy_binary_series))),
253 ];
254 std::assert_eq!(fold_actions(&actions), (Count::N(0), Count::All));
255
256 let actions: Vec<Action<BufferWriter>> = vec![
257 Action::Value(create_nan(), false),
258 Action::Value(create_nan(), false),
259 Action::Operation(Rc::new(Operation::SeriesTwo(dummy_binary_series))),
260 Action::Operation(Rc::new(Operation::SeriesTwo(dummy_binary_series))),
261 ];
262 std::assert_eq!(fold_actions(&actions), (Count::N(0), Count::All));
263
264 let actions: Vec<Action<BufferWriter>> = vec![
265 Action::Value(create_nan(), false),
266 Action::Value(create_nan(), false),
267 Action::Operation(Rc::new(Operation::SeriesTwo(dummy_binary_series))),
268 Action::Operation(Rc::new(Operation::SeriesTwo(dummy_binary_series))),
269 Action::Operation(Rc::new(Operation::SeriesTwo(dummy_binary_series))),
270 ];
271 std::assert_eq!(fold_actions(&actions), (Count::N(0), Count::All));
272 }
273
274 #[test]
275 fn test_folds_series_to_series_operation() {
276 let actions: Vec<Action<BufferWriter>> = vec![
277 Action::Value(create_nan(), false),
278 Action::Value(create_nan(), false),
279 Action::Operation(Rc::new(Operation::SeriesAll(dummy_series_series))),
280 ];
281 std::assert_eq!(fold_actions(&actions), (Count::All, Count::All));
282 }
283
284 #[test]
285 fn test_folds_directive_as_noop() {
286 let actions: Vec<Action<BufferWriter>> = vec![
287 Action::Value(create_nan(), false),
288 Action::Value(create_nan(), false),
289 Action::Directive(Rc::new(Directive::EngineAll(dummy_directive, Completion::Keyword)), vec![]),
290 ];
291 std::assert_eq!(fold_actions(&actions), (Count::N(0), Count::N(2)));
292
293 let actions: Vec<Action<BufferWriter>> = vec![
294 Action::Value(create_nan(), false),
295 Action::Value(create_nan(), false),
296 Action::Directive(Rc::new(Directive::EngineAll(dummy_directive, Completion::Keyword)), vec![]),
297 Action::Directive(Rc::new(Directive::EngineAll(dummy_directive, Completion::Keyword)), vec![]),
298 ];
299 std::assert_eq!(fold_actions(&actions), (Count::N(0), Count::N(2)));
300 }
301
302 #[test]
303 fn test_folds_defined_function() {
304 let actions: Vec<Action<BufferWriter>> = vec![
305 Action::Value(create_nan(), false),
306 Action::Value(create_nan(), false),
307 Action::Operation(Rc::new(Operation::ValueNone(dummy_nullary))),
308 Action::Operation(Rc::new(Operation::ValueNone(dummy_nullary))),
309 ];
310 let actions: Vec<Action<BufferWriter>> = vec![
311 Action::Definition(actions),
312 ];
313 std::assert_eq!(fold_actions(&actions), (Count::N(0), Count::N(4)));
314
315 let actions: Vec<Action<BufferWriter>> = vec![
316 Action::Value(create_nan(), false),
317 Action::Value(create_nan(), false),
318 Action::Operation(Rc::new(Operation::ValueOne(dummy_unary))),
319 Action::Operation(Rc::new(Operation::ValueOne(dummy_unary))),
320 ];
321 let actions: Vec<Action<BufferWriter>> = vec![
322 Action::Definition(actions),
323 ];
324 std::assert_eq!(fold_actions(&actions), (Count::N(0), Count::N(2)));
325
326 let actions: Vec<Action<BufferWriter>> = vec![
327 Action::Value(create_nan(), false),
328 Action::Value(create_nan(), false),
329 Action::Operation(Rc::new(Operation::ValueTwo(dummy_binary))),
330 Action::Operation(Rc::new(Operation::ValueTwo(dummy_binary))),
331 Action::Operation(Rc::new(Operation::ValueTwo(dummy_binary))),
332 ];
333 let actions: Vec<Action<BufferWriter>> = vec![
334 Action::Definition(actions),
335 ];
336 std::assert_eq!(fold_actions(&actions), (Count::N(2), Count::N(1)));
337
338 let actions: Vec<Action<BufferWriter>> = vec![
339 Action::Value(create_nan(), false),
340 Action::Value(create_nan(), false),
341 Action::Operation(Rc::new(Operation::ValueAll(dummy_series))),
342 ];
343 let actions: Vec<Action<BufferWriter>> = vec![
344 Action::Definition(actions),
345 ];
346 std::assert_eq!(fold_actions(&actions), (Count::All, Count::N(1)));
347 }
348}