rpn_cli/core/
action.rs

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