rpn_cli/core/
action.rs

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
43// noinspection RsLift
44impl<'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// noinspection DuplicatedCode
125#[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}