rpn_cli/
engine.rs

1use crate::calc::context::{Context, Format};
2use crate::calc::undo::Undo;
3use crate::calc::value::{Value, ValueRef};
4use crate::config::Config;
5use crate::error::{EngineError, MyError, MyResult};
6use crate::read::action;
7use crate::read::action::{Action, Actions};
8use crate::read::helper::CommandEditor;
9use crate::read::interface::{Directive, Interface, Operation};
10use crate::util::text::create_padding;
11use fileinput::FileInput;
12use itertools::Itertools;
13use std::cell::RefCell;
14use std::fs::File;
15use std::io::{BufRead, BufReader, Write};
16use std::rc::Rc;
17
18pub struct Engine<W: Write> {
19    config: Config,
20    editor: CommandEditor,
21    interface: Rc<RefCell<Interface<W>>>,
22    context: Rc<RefCell<Context>>,
23    stack: Vec<ValueRef>,
24    undos: Vec<Undo>,
25    redos: Vec<Undo>,
26    clip: Option<ValueRef>,
27    dirty: bool,
28    interact: bool,
29}
30
31// noinspection RsLift
32impl<W: Write> Engine<W> {
33    pub fn new(config: Config) -> MyResult<Self> {
34        let interface = Rc::new(RefCell::new(Interface::build()));
35        let editor = interface.borrow().create_editor()?;
36        let context = Rc::new(RefCell::new(Context::new()));
37        let stack = Vec::new();
38        let undos = Vec::new();
39        let redos = Vec::new();
40        let engine = Self {
41            config,
42            editor,
43            interface,
44            context,
45            stack,
46            undos,
47            redos,
48            clip: None,
49            dirty: false,
50            interact: false,
51        };
52        Ok(engine)
53    }
54
55    pub fn parse_input(&mut self, writer: &mut W) -> MyResult<()> {
56        if let Some(import) = &self.config.import {
57            let import = vec![String::from(import)];
58            self.import_file(writer, import)?;
59        }
60        if !self.config.values.is_empty() {
61            self.parse_values(writer)?;
62            if !self.config.mock {
63                self.show_simple(writer)?;
64            }
65        } else if !self.config.paths.is_empty() || atty::isnt(atty::Stream::Stdin) || atty::isnt(atty::Stream::Stdout) {
66            let reader = FileInput::new(&self.config.paths);
67            self.parse_files(writer, reader)?;
68            self.show_simple(writer)?;
69        } else {
70            self.parse_loop(writer)?;
71        }
72        Ok(())
73    }
74
75    fn parse_values(&mut self, writer: &mut W) -> MyResult<()> {
76        let values = self.config.values.drain(..).collect::<Vec<String>>();
77        if self.config.mock {
78            for (index, value) in values.iter().enumerate() {
79                self.interact = index + 1 == values.len();
80                self.interact_line(writer, &value)?;
81            }
82        } else {
83            for value in values {
84                self.parse_line(writer, &value)?;
85            }
86        }
87        Ok(())
88    }
89
90    fn parse_files(&mut self, writer: &mut W, reader: FileInput) -> MyResult<()> {
91        let reader = BufReader::new(reader);
92        for line in reader.lines() {
93            let line = line?;
94            self.parse_line(writer, &line)?;
95        }
96        Ok(())
97    }
98
99    fn parse_loop(&mut self, writer: &mut W) -> MyResult<()> {
100        self.interact = true;
101        loop {
102            let line = self.editor.readline("rpn> ")?;
103            self.editor.add_history_entry(&line)?;
104            self.interact_line(writer, &line)?;
105        }
106    }
107
108    fn interact_line(&mut self, writer: &mut W, line: &str) -> MyResult<()> {
109        let result = match self.parse_line(writer, line) {
110            Ok(()) => {
111                if self.interact && self.dirty {
112                    self.show_stack(writer)?;
113                }
114                Ok(())
115            }
116            Err(MyError::Engine(error)) => {
117                if self.interact {
118                    writeln!(writer, "  {}", error)?;
119                }
120                Ok(())
121            }
122            Err(error) => {
123                Err(error)
124            }
125        };
126        self.dirty = false;
127        result
128    }
129
130    fn parse_line(&mut self, writer: &mut W, line: &str) -> MyResult<()> {
131        let mut empty = true;
132        let mut undo = Undo::default();
133        let mut redo = Undo::default();
134        let (line, comment) = Self::split_comment(line);
135        let actions = Actions::new(&self.interface, line.split_ascii_whitespace());
136        for action in actions {
137            let action = match action {
138                Ok((action, token)) => self.apply_action(
139                    writer,
140                    &mut undo,
141                    &mut redo,
142                    action,
143                    Some(token),
144                ),
145                Err(error) => Err(error),
146            };
147            if let Err(error) = action {
148                undo.apply_to(&mut self.stack);
149                return Err(error);
150            }
151            empty = false;
152        }
153        if let Some(comment) = comment {
154            if let Err(error) = self.apply_comment(comment) {
155                undo.apply_to(&mut self.stack);
156                return Err(error);
157            }
158            empty = false;
159        }
160        self.commit_undo(undo, redo);
161        self.dirty |= empty;
162        Ok(())
163    }
164
165    fn split_comment(line: &str) -> (&str, Option<&str>) {
166        if let Some(stop) = line.find('#') {
167            let start = stop + 1;
168            let values = line[..stop].trim();
169            let comment = line[start..].trim();
170            let comment = if comment.is_empty() { None } else { Some(comment) };
171            (values, comment)
172        } else {
173            let values = line.trim();
174            (values, None)
175        }
176    }
177
178    fn apply_action(
179        &mut self,
180        writer: &mut W,
181        undo: &mut Undo,
182        redo: &mut Undo,
183        action: Action<W>,
184        token: Option<&str>,
185    ) -> MyResult<()> {
186        match action {
187            Action::Operation(operation) => {
188                match operation.as_ref() {
189                    Operation::ValueNone(function) => {
190                        let result = function()?;
191                        self.push_single(undo, result, token);
192                        self.dirty = true;
193                    }
194                    Operation::ValueOne(function) => {
195                        let value = self.pop_single(undo, None)?;
196                        let result = function(value)?;
197                        self.push_single(undo, result, token);
198                        self.dirty = true;
199                    }
200                    Operation::ValueTwo(function) => {
201                        let (value1, value2) = self.pop_double(undo, None)?;
202                        let result = function(value1, value2)?;
203                        self.push_single(undo, result, token);
204                        self.dirty = true;
205                    }
206                    Operation::ValueAll(function) => {
207                        let values = self.stack.drain(..).collect::<Vec<ValueRef>>();
208                        let result = function(values.clone())?;
209                        self.stack.push(result);
210                        self.dirty = true;
211                        undo.merge(1, values, token);
212                    }
213                    Operation::TimeNow(function) => {
214                        let result = function(&self.config.now)?;
215                        self.push_single(undo, result, token);
216                        self.dirty = true;
217                    }
218                    Operation::TimeCast(function) => {
219                        let value = self.peek_single()?;
220                        function(value)?;
221                        self.dirty = true;
222                    }
223                    Operation::ContextNone(function) => {
224                        function(&mut self.context.borrow_mut());
225                        self.dirty = true;
226                    }
227                    Operation::ContextOne(function) => {
228                        let value = self.pop_single(undo, token)?;
229                        function(&mut self.context.borrow_mut(), value);
230                        self.dirty = true;
231                    }
232                    Operation::EngineNone(function) => {
233                        self.dirty |= function(self, writer)?;
234                    }
235                    Operation::EngineUndo(function, _, _) => {
236                        self.dirty |= function(self, undo, redo, token)?;
237                    }
238                }
239            }
240            Action::Directive(directive, tokens) => {
241                match directive.as_ref() {
242                    Directive::EngineOne(function, _) => {
243                        if let Some(token) = tokens.first() {
244                            self.dirty |= function(self, writer, token.to_string())?;
245                        }
246                    }
247                    Directive::EngineAll(function, _) => {
248                        self.dirty |= function(self, writer, tokens)?;
249                    }
250                }
251            }
252            Action::Definition(actions) => {
253                for action in actions {
254                    self.apply_action(writer, undo, redo, action, None)?;
255                }
256                undo.merge(0, vec![], token);
257            }
258            Action::Value(value, dirty) => {
259                self.push_single(undo, value, token);
260                self.dirty |= dirty;
261            }
262        }
263        Ok(())
264    }
265
266    fn apply_comment(
267        &mut self,
268        comment: &str,
269    ) -> MyResult<()> {
270        let value = self.peek_single()?;
271        value.borrow_mut().set_comment(comment);
272        self.dirty = true;
273        Ok(())
274    }
275
276    fn commit_undo(
277        &mut self,
278        undo: Undo,
279        redo: Undo,
280    ) {
281        if !undo.is_empty() {
282            self.undos.push(undo);
283            self.redos.clear();
284        } else if !redo.is_empty() {
285            self.redos.push(redo);
286        }
287    }
288
289    fn peek_single(&mut self) -> MyResult<ValueRef> {
290        if let Some(value) = self.stack.last() {
291            Ok(Rc::clone(value))
292        } else {
293            Err(MyError::from(EngineError::MissingValue))
294        }
295    }
296
297    fn pop_single(
298        &mut self,
299        undo: &mut Undo,
300        token: Option<&str>,
301    ) -> MyResult<ValueRef> {
302        if let Some(value) = self.stack.pop() {
303            undo.merge(0, vec![Rc::clone(&value)], token);
304            Ok(value)
305        } else {
306            Err(MyError::from(EngineError::MissingValue))
307        }
308    }
309
310    fn pop_double(
311        &mut self,
312        undo: &mut Undo,
313        token: Option<&str>,
314    ) -> MyResult<(ValueRef, ValueRef)> {
315        if self.stack.len() >= 2 {
316            let value2 = self.stack.pop().unwrap_or_default();
317            let value1 = self.stack.pop().unwrap_or_default();
318            undo.merge(0, vec![Rc::clone(&value1), Rc::clone(&value2)], token);
319            Ok((value1, value2))
320        } else {
321            Err(MyError::from(EngineError::MissingValue))
322        }
323    }
324
325    fn push_single(
326        &mut self,
327        undo: &mut Undo,
328        value: ValueRef,
329        token: Option<&str>,
330    ) {
331        self.stack.push(value);
332        undo.merge(1, vec![], token);
333    }
334
335    pub fn clear_values(
336        &mut self,
337        undo: &mut Undo,
338        redo: &mut Undo,
339        token: Option<&str>,
340    ) -> MyResult<bool> {
341        let values = self.stack.drain(..).collect();
342        undo.merge(0, values, token);
343        redo.clear();
344        Ok(true)
345    }
346
347    pub fn pop_value(
348        &mut self,
349        undo: &mut Undo,
350        redo: &mut Undo,
351        token: Option<&str>,
352    ) -> MyResult<bool> {
353        self.pop_single(undo, token)?;
354        redo.clear();
355        Ok(true)
356    }
357
358    pub fn dup_value(
359        &mut self,
360        undo: &mut Undo,
361        redo: &mut Undo,
362        token: Option<&str>,
363    ) -> MyResult<bool> {
364        if let Some(value) = self.stack.last() {
365            self.push_single(undo, Rc::clone(value), token);
366            redo.clear();
367            Ok(true)
368        } else {
369            Err(MyError::from(EngineError::MissingValue))
370        }
371    }
372
373    pub fn swap_values(
374        &mut self,
375        undo: &mut Undo,
376        redo: &mut Undo,
377        token: Option<&str>,
378    ) -> MyResult<bool> {
379        let (value1, value2) = self.pop_double(undo, None)?;
380        self.push_single(undo, value2, None);
381        self.push_single(undo, value1, token);
382        redo.clear();
383        Ok(true)
384    }
385
386    pub fn cut_value(
387        &mut self,
388        undo: &mut Undo,
389        redo: &mut Undo,
390        token: Option<&str>,
391    ) -> MyResult<bool> {
392        let value = self.pop_single(undo, token)?;
393        self.clip = Some(value);
394        redo.clear();
395        Ok(true)
396    }
397
398    pub fn copy_value(
399        &mut self,
400        _undo: &mut Undo,
401        _redo: &mut Undo,
402        _token: Option<&str>,
403    ) -> MyResult<bool> {
404        if let Some(value) = self.stack.last() {
405            self.clip = Some(Rc::clone(value));
406            Ok(false)
407        } else {
408            Err(MyError::from(EngineError::MissingValue))
409        }
410    }
411
412    pub fn paste_value(
413        &mut self,
414        undo: &mut Undo,
415        redo: &mut Undo,
416        token: Option<&str>,
417    ) -> MyResult<bool> {
418        if let Some(clip) = &self.clip {
419            self.push_single(undo, Rc::clone(clip), token);
420            redo.clear();
421            Ok(true)
422        } else {
423            Err(MyError::from(EngineError::MissingClip))
424        }
425    }
426
427    pub fn import_file(
428        &mut self,
429        writer: &mut W,
430        tokens: Vec<String>,
431    ) -> MyResult<bool> {
432        let reader = FileInput::new(&tokens);
433        self.parse_files(writer, reader)?;
434        Ok(true)
435    }
436
437    pub fn export_file(
438        &mut self,
439        _writer: &mut W,
440        tokens: Vec<String>,
441    ) -> MyResult<bool> {
442        if let Some(path) = tokens.first() {
443            let mut writer = File::create(path)?;
444            let sep = self.context.borrow_mut().swap_sep(false);
445            let result = self.write_simple(&mut writer);
446            self.context.borrow_mut().swap_sep(sep);
447            result?;
448        }
449        Ok(false)
450    }
451
452    pub fn set_variable(
453        &mut self,
454        _writer: &mut W,
455        token: String,
456    ) -> MyResult<bool> {
457        if let Some(value) = self.stack.pop() {
458            if self.interface.borrow_mut().insert_variable(token.clone(), value.clone()) {
459                for value in &mut self.stack {
460                    let mut inner = value.borrow_mut();
461                    if let Some(previous) = &inner.variable {
462                        if previous == &token {
463                            inner.variable = None;
464                        }
465                    }
466                }
467            }
468            {
469                let mut inner = value.borrow_mut();
470                if let Some(previous) = &inner.variable {
471                    if previous != &token {
472                        self.interface.borrow_mut().remove_variable(previous);
473                    }
474                }
475                inner.variable = Some(token);
476            }
477            self.stack.push(value);
478            self.interface.borrow().adjust_editor(&mut self.editor);
479            Ok(true)
480        } else {
481            Err(MyError::from(EngineError::MissingValue))
482        }
483    }
484
485    pub fn define_function(
486        &mut self,
487        writer: &mut W,
488        tokens: Vec<String>,
489    ) -> MyResult<bool> {
490        let mut tokens = tokens.iter();
491        if let Some(keyword) = tokens.next() {
492            let description = tokens.clone().join(" ");
493            let tokens = tokens.map(String::as_ref);
494            let actions = Actions::new(&self.interface, tokens);
495            let actions = actions
496                .map(|result| result.map(|(x, _)| x))
497                .collect::<MyResult<Vec<Action<W>>>>()?;
498            if !actions.is_empty() {
499                let (input, output) = action::fold_actions(&actions);
500                self.interface.borrow_mut().insert_definition(
501                    keyword,
502                    actions,
503                    input,
504                    output,
505                    description,
506                );
507            } else {
508                self.interface.borrow_mut().remove_definition(keyword);
509            }
510            self.interface.borrow().adjust_editor(&mut self.editor);
511        } else {
512            self.interface.borrow().show_definitions(writer, self.interact)?;
513        }
514        Ok(false)
515    }
516
517    pub fn undo_stack(
518        &mut self,
519        undo: &mut Undo,
520        redo: &mut Undo,
521        _token: Option<&str>,
522    ) -> MyResult<bool> {
523        if !undo.is_empty() {
524            self.redos.push(undo.apply_to(&mut self.stack));
525            redo.clear();
526            Ok(true)
527        } else if let Some(mut undo) = self.undos.pop() {
528            self.redos.push(undo.apply_to(&mut self.stack));
529            redo.clear();
530            Ok(true)
531        } else {
532            Err(MyError::from(EngineError::MissingUndo))
533        }
534    }
535
536    pub fn redo_stack(
537        &mut self,
538        undo: &mut Undo,
539        redo: &mut Undo,
540        _token: Option<&str>,
541    ) -> MyResult<bool> {
542        if undo.is_empty() {
543            if !redo.is_empty() {
544                self.undos.push(redo.apply_to(&mut self.stack));
545                return Ok(true);
546            } else if let Some(mut redo) = self.redos.pop() {
547                self.undos.push(redo.apply_to(&mut self.stack));
548                return Ok(true);
549            }
550        }
551        Err(MyError::from(EngineError::MissingRedo))
552    }
553
554    pub fn show_history(&mut self, writer: &mut W) -> MyResult<bool> {
555        if self.interact {
556            self.limit_history(writer, 10)?;
557        }
558        Ok(false)
559    }
560
561    fn limit_history(&mut self, writer: &mut W, limit: usize) -> MyResult<()> {
562        if self.undos.is_empty() {
563            writeln!(writer, "  <==")?;
564        } else {
565            if self.undos.len() > limit {
566                writeln!(writer, "  ...")?;
567            }
568            for (index, undo) in self.undos.iter().rev().enumerate().take(limit).rev() {
569                if index == 0 {
570                    writeln!(writer, "  {} <==", undo)?;
571                } else {
572                    writeln!(writer, "  {}", undo)?;
573                }
574            }
575        }
576        for redo in self.redos.iter().rev().take(limit) {
577            writeln!(writer, "  {}", redo)?;
578        }
579        if self.redos.len() > limit {
580            writeln!(writer, "  ...")?;
581        }
582        Ok(())
583    }
584
585    fn show_simple(&mut self, writer: &mut W) -> Result<(), MyError> {
586        if self.config.sum {
587            let values = self.stack.drain(..).collect::<Vec<ValueRef>>();
588            let result = Value::calc_sum(values)?;
589            self.stack.push(result);
590        }
591        if self.config.hex {
592            self.context.borrow_mut().set_hex();
593        }
594        if self.config.sep {
595            self.context.borrow_mut().set_sep();
596        }
597        if let Some(dp) = self.config.dp {
598            self.context.borrow_mut().set_dp_u8(dp);
599        }
600        self.write_simple(writer)?;
601        Ok(())
602    }
603
604    fn write_simple<V: Write>(&mut self, writer: &mut V) -> MyResult<()> {
605        self.measure_hexadecimal();
606        let context = self.context.borrow();
607        for value in &self.stack {
608            let (integer, fraction, _, _) = value.borrow().to_strings(&context);
609            writeln!(writer, "{}{}", integer, fraction)?;
610        }
611        Ok(())
612    }
613
614    pub fn show_stack(&mut self, writer: &mut W) -> MyResult<bool> {
615        if self.interact {
616            self.measure_hexadecimal();
617            let context = self.context.borrow();
618            let table = self.stack.iter()
619                .map(|value| value.borrow().to_strings(&context))
620                .collect::<Vec<_>>();
621            let integer_width = table.iter()
622                .map(|(x, _, _, _)| x.len())
623                .max()
624                .unwrap_or_default();
625            let fraction_width = table.iter()
626                .map(|(_, x, _, _)| x.len())
627                .max()
628                .unwrap_or_default();
629            for (integer, fraction, variable, comment) in table {
630                let padding = create_padding(' ', integer_width + 2, integer.len(), 0);
631                write!(writer, "{}{}{}", padding, integer, fraction)?;
632                if variable.is_some() || comment.is_some() {
633                    let padding = create_padding(' ', fraction_width, fraction.len(), 0);
634                    write!(writer, "{}", padding)?;
635                }
636                if let Some(variable) = variable {
637                    write!(writer, " = {}", variable)?;
638                }
639                if let Some(comment) = comment {
640                    write!(writer, " # {}", comment)?;
641                }
642                writeln!(writer)?;
643            }
644        }
645        Ok(false)
646    }
647
648    fn measure_hexadecimal(&mut self) {
649        let mut context = self.context.borrow_mut();
650        if let Format::Base16(_) = context.format {
651            let chunks = self.stack.iter()
652                .map(|x| x.borrow().measure_hexadecimal())
653                .max()
654                .unwrap_or_default();
655            context.format = Format::Base16(chunks);
656        }
657    }
658
659    pub fn show_help(&mut self, writer: &mut W) -> MyResult<bool> {
660        self.interface.borrow().show_help(writer, self.interact)?;
661        Ok(false)
662    }
663}
664
665// noinspection DuplicatedCode
666#[cfg(test)]
667pub mod tests {
668    use crate::calc::context::Format;
669    use crate::calc::undo::tests::create_undo;
670    use crate::calc::value::tests::{parse_string, parse_strings};
671    use crate::config::Config;
672    use crate::engine::Engine;
673    use crate::error::MyResult;
674    use crate::util::text::tests::BufferWriter;
675    use pretty_assertions::assert_eq;
676    use std::collections::HashMap;
677    use std::io::Write;
678
679    #[test]
680    fn test_split_comment_finds_first_hash() {
681        assert_eq!(Engine::<BufferWriter>::split_comment("\tone two three\t"), ("one two three", None));
682        assert_eq!(Engine::<BufferWriter>::split_comment("\tone two three #\t"), ("one two three", None));
683        assert_eq!(Engine::<BufferWriter>::split_comment("\tone # two # three\t"), ("one", Some("two # three")));
684    }
685
686    // VALUE CREATION
687
688    #[test]
689    fn test_create_values_modifies_stack() {
690        let expected_stack = parse_strings(vec!["1", "2", "3", "4", "5", "6"]);
691        let expected_undos = vec![
692            create_undo(3, vec![], vec!["1", "2", "3"]),
693            create_undo(3, vec![], vec!["4", "5", "6"]),
694        ];
695        let expected_redos = vec![];
696        let mut engine = create_engine();
697        let mut writer = BufferWriter::new();
698        assert!(parse_line(&mut engine, &mut writer, "1 2 3").is_ok());
699        assert!(parse_line(&mut engine, &mut writer, "4 5 6").is_ok());
700        assert_eq!(engine.stack, expected_stack);
701        assert_eq!(engine.undos, expected_undos);
702        assert_eq!(engine.redos, expected_redos);
703        assert_eq!(writer.buffer, "");
704    }
705
706    #[test]
707    fn test_comment_modifies_current_line() {
708        let expected_stack = vec![
709            parse_string("1"),
710            parse_string("2"),
711            parse_string("3"),
712            parse_string("42 # the answer"),
713        ];
714        let expected_undos = vec![
715            create_undo(2, vec![], vec!["1", "2"]),
716            create_undo(2, vec![], vec!["3", "42"]),
717        ];
718        let expected_redos = vec![];
719        let mut engine = create_engine();
720        let mut writer = BufferWriter::new();
721        assert!(parse_line(&mut engine, &mut writer, "1 2").is_ok());
722        assert!(parse_line(&mut engine, &mut writer, "3 42 # the answer").is_ok());
723        assert_eq!(engine.stack, expected_stack);
724        assert_eq!(engine.undos, expected_undos);
725        assert_eq!(engine.redos, expected_redos);
726        assert_eq!(writer.buffer, "");
727    }
728
729    #[test]
730    fn test_comment_modifies_previous_line() {
731        let expected_stack = vec![
732            parse_string("1"),
733            parse_string("2"),
734            parse_string("3"),
735            parse_string("42 # the answer"),
736        ];
737        let expected_undos = vec![
738            create_undo(4, vec![], vec!["1", "2", "3", "42"]),
739        ];
740        let expected_redos = vec![];
741        let mut engine = create_engine();
742        let mut writer = BufferWriter::new();
743        assert!(parse_line(&mut engine, &mut writer, "1 2 3 42").is_ok());
744        assert!(parse_line(&mut engine, &mut writer, "# the answer").is_ok());
745        assert_eq!(engine.stack, expected_stack);
746        assert_eq!(engine.undos, expected_undos);
747        assert_eq!(engine.redos, expected_redos);
748        assert_eq!(writer.buffer, "");
749    }
750
751    #[test]
752    fn test_comment_fails_cleanly() {
753        let expected_stack = vec![];
754        let expected_undos = vec![];
755        let expected_redos = vec![];
756        let mut engine = create_engine();
757        let mut writer = BufferWriter::new();
758        assert!(parse_line(&mut engine, &mut writer, "# the answer").is_err());
759        assert_eq!(engine.stack, expected_stack);
760        assert_eq!(engine.undos, expected_undos);
761        assert_eq!(engine.redos, expected_redos);
762        assert_eq!(writer.buffer, "Not enough values on stack\n");
763    }
764
765    // UNKNOWN OPERATIONS
766
767    #[test]
768    fn test_unknown_operation_fails_cleanly() {
769        let expected_stack = parse_strings(vec!["1", "2", "3"]);
770        let expected_undos = vec![
771            create_undo(3, vec![], vec!["1", "2", "3"]),
772        ];
773        let expected_redos = vec![];
774        let mut engine = create_engine();
775        let mut writer = BufferWriter::new();
776        assert!(parse_line(&mut engine, &mut writer, "1 2 3").is_ok());
777        assert!(parse_line(&mut engine, &mut writer, "4 5 xyz 999").is_err());
778        assert_eq!(engine.stack, expected_stack);
779        assert_eq!(engine.undos, expected_undos);
780        assert_eq!(engine.redos, expected_redos);
781        assert_eq!(writer.buffer, "Invalid number or keyword: xyz\n");
782    }
783
784    // NULLARY OPERATIONS
785
786    #[test]
787    fn test_nullary_operation_modifies_stack() {
788        let expected_undos = vec![
789            create_undo(1, vec![], vec!["now"]),
790        ];
791        let expected_redos = vec![];
792        let mut engine = create_engine();
793        let mut writer = BufferWriter::new();
794        assert!(parse_line(&mut engine, &mut writer, "now").is_ok());
795        assert_eq!(engine.stack.len(), 1);
796        assert_eq!(engine.undos, expected_undos);
797        assert_eq!(engine.redos, expected_redos);
798        assert_eq!(writer.buffer, "");
799    }
800
801    // UNARY OPERATIONS
802
803    #[test]
804    fn test_unary_operation_modifies_stack() {
805        let expected_stack = parse_strings(vec!["1", "-2"]);
806        let expected_undos = vec![
807            create_undo(3, vec![], vec!["1", "2", "3"]),
808            create_undo(1, vec!["2", "3"], vec!["pop", "neg"]),
809        ];
810        let expected_redos = vec![];
811        let mut engine = create_engine();
812        let mut writer = BufferWriter::new();
813        assert!(parse_line(&mut engine, &mut writer, "1 2 3").is_ok());
814        assert!(parse_line(&mut engine, &mut writer, "pop neg").is_ok());
815        assert_eq!(engine.stack, expected_stack);
816        assert_eq!(engine.undos, expected_undos);
817        assert_eq!(engine.redos, expected_redos);
818        assert_eq!(writer.buffer, "");
819    }
820
821    #[test]
822    fn test_unary_operation_fails_cleanly() {
823        let expected_stack = parse_strings(vec!["1", "2", "3"]);
824        let expected_undos = vec![
825            create_undo(3, vec![], vec!["1", "2", "3"]),
826        ];
827        let expected_redos = vec![];
828        let mut engine = create_engine();
829        let mut writer = BufferWriter::new();
830        assert!(parse_line(&mut engine, &mut writer, "1 2 3").is_ok());
831        assert!(parse_line(&mut engine, &mut writer, "pop pop pop neg 999").is_err());
832        assert_eq!(engine.stack, expected_stack);
833        assert_eq!(engine.undos, expected_undos);
834        assert_eq!(engine.redos, expected_redos);
835        assert_eq!(writer.buffer, "Not enough values on stack\n");
836    }
837
838    // BINARY OPERATIONS
839
840    #[test]
841    fn test_binary_operation_modifies_stack() {
842        let expected_stack = parse_strings(vec!["1", "5"]);
843        let expected_undos = vec![
844            create_undo(3, vec![], vec!["1", "2", "3"]),
845            create_undo(1, vec!["2", "3"], vec!["add"]),
846        ];
847        let expected_redos = vec![];
848        let mut engine = create_engine();
849        let mut writer = BufferWriter::new();
850        assert!(parse_line(&mut engine, &mut writer, "1 2 3").is_ok());
851        assert!(parse_line(&mut engine, &mut writer, "add").is_ok());
852        assert_eq!(engine.stack, expected_stack);
853        assert_eq!(engine.undos, expected_undos);
854        assert_eq!(engine.redos, expected_redos);
855        assert_eq!(writer.buffer, "");
856    }
857
858    #[test]
859    fn test_binary_operation_fails_cleanly() {
860        let expected_stack = parse_strings(vec!["1", "2", "3"]);
861        let expected_undos = vec![
862            create_undo(3, vec![], vec!["1", "2", "3"]),
863        ];
864        let expected_redos = vec![];
865        let mut engine = create_engine();
866        let mut writer = BufferWriter::new();
867        assert!(parse_line(&mut engine, &mut writer, "1 2 3").is_ok());
868        assert!(parse_line(&mut engine, &mut writer, "pop pop add 999").is_err());
869        assert_eq!(engine.stack, expected_stack);
870        assert_eq!(engine.undos, expected_undos);
871        assert_eq!(engine.redos, expected_redos);
872        assert_eq!(writer.buffer, "Not enough values on stack\n");
873    }
874
875    // SERIES OPERATIONS
876
877    #[test]
878    fn test_series_operation_modifies_stack() {
879        let expected_stack = parse_strings(vec!["6"]);
880        let expected_undos = vec![
881            create_undo(3, vec![], vec!["1", "2", "3"]),
882            create_undo(1, vec!["1", "2", "3"], vec!["sum"]),
883        ];
884        let expected_redos = vec![];
885        let mut engine = create_engine();
886        let mut writer = BufferWriter::new();
887        assert!(parse_line(&mut engine, &mut writer, "1 2 3").is_ok());
888        assert!(parse_line(&mut engine, &mut writer, "sum").is_ok());
889        assert_eq!(engine.stack, expected_stack);
890        assert_eq!(engine.undos, expected_undos);
891        assert_eq!(engine.redos, expected_redos);
892        assert_eq!(writer.buffer, "");
893    }
894
895    // CAST OPERATIONS
896
897    #[test]
898    fn test_cast_modifies_current_line() {
899        let expected_stack = vec![
900            parse_string("1"),
901            parse_string("2"),
902            parse_string("3"),
903            parse_string("5025.678 [delta]"),
904        ];
905        let expected_undos = vec![
906            create_undo(2, vec![], vec!["1", "2"]),
907            create_undo(2, vec![], vec!["3", "5025.678"]),
908        ];
909        let expected_redos = vec![];
910        let mut engine = create_engine();
911        let mut writer = BufferWriter::new();
912        assert!(parse_line(&mut engine, &mut writer, "1 2").is_ok());
913        assert!(parse_line(&mut engine, &mut writer, "3 5025.678 delta").is_ok());
914        assert_eq!(engine.stack, expected_stack);
915        assert_eq!(engine.undos, expected_undos);
916        assert_eq!(engine.redos, expected_redos);
917        assert_eq!(writer.buffer, "");
918    }
919
920    #[test]
921    fn test_cast_modifies_previous_line() {
922        let expected_stack = vec![
923            parse_string("1"),
924            parse_string("2"),
925            parse_string("3"),
926            parse_string("5025.678 [delta]"),
927        ];
928        let expected_undos = vec![
929            create_undo(4, vec![], vec!["1", "2", "3", "5025.678"]),
930        ];
931        let expected_redos = vec![];
932        let mut engine = create_engine();
933        let mut writer = BufferWriter::new();
934        assert!(parse_line(&mut engine, &mut writer, "1 2 3 5025.678").is_ok());
935        assert!(parse_line(&mut engine, &mut writer, "delta").is_ok());
936        assert_eq!(engine.stack, expected_stack);
937        assert_eq!(engine.undos, expected_undos);
938        assert_eq!(engine.redos, expected_redos);
939        assert_eq!(writer.buffer, "");
940    }
941
942    #[test]
943    fn test_cast_fails_cleanly() {
944        let expected_stack = vec![];
945        let expected_undos = vec![];
946        let expected_redos = vec![];
947        let mut engine = create_engine();
948        let mut writer = BufferWriter::new();
949        assert!(parse_line(&mut engine, &mut writer, "delta").is_err());
950        assert_eq!(engine.stack, expected_stack);
951        assert_eq!(engine.undos, expected_undos);
952        assert_eq!(engine.redos, expected_redos);
953        assert_eq!(writer.buffer, "Not enough values on stack\n");
954    }
955
956    // CLEAR OPERATIONS
957
958    #[test]
959    fn test_clear_operation_modifies_stack() {
960        let expected_stack = vec![];
961        let expected_undos = vec![
962            create_undo(3, vec![], vec!["1", "2", "3"]),
963            create_undo(0, vec!["1", "2", "3"], vec!["clear"]),
964        ];
965        let expected_redos = vec![];
966        let mut engine = create_engine();
967        let mut writer = BufferWriter::new();
968        assert!(parse_line(&mut engine, &mut writer, "1 2 3").is_ok());
969        assert!(parse_line(&mut engine, &mut writer, "clear").is_ok());
970        assert_eq!(engine.stack, expected_stack);
971        assert_eq!(engine.undos, expected_undos);
972        assert_eq!(engine.redos, expected_redos);
973        assert_eq!(writer.buffer, "");
974    }
975
976    // POP OPERATIONS
977
978    #[test]
979    fn test_pop_operation_modifies_stack() {
980        let expected_stack = parse_strings(vec!["1", "2"]);
981        let expected_undos = vec![
982            create_undo(3, vec![], vec!["1", "2", "3"]),
983            create_undo(0, vec!["3"], vec!["pop"]),
984        ];
985        let expected_redos = vec![];
986        let mut engine = create_engine();
987        let mut writer = BufferWriter::new();
988        assert!(parse_line(&mut engine, &mut writer, "1 2 3").is_ok());
989        assert!(parse_line(&mut engine, &mut writer, "pop").is_ok());
990        assert_eq!(engine.stack, expected_stack);
991        assert_eq!(engine.undos, expected_undos);
992        assert_eq!(engine.redos, expected_redos);
993        assert_eq!(writer.buffer, "");
994    }
995
996    #[test]
997    fn test_pop_operation_fails_cleanly() {
998        let expected_stack = parse_strings(vec!["1", "2", "3"]);
999        let expected_undos = vec![
1000            create_undo(3, vec![], vec!["1", "2", "3"]),
1001        ];
1002        let expected_redos = vec![];
1003        let mut engine = create_engine();
1004        let mut writer = BufferWriter::new();
1005        assert!(parse_line(&mut engine, &mut writer, "1 2 3").is_ok());
1006        assert!(parse_line(&mut engine, &mut writer, "pop pop pop pop 999").is_err());
1007        assert_eq!(engine.stack, expected_stack);
1008        assert_eq!(engine.undos, expected_undos);
1009        assert_eq!(engine.redos, expected_redos);
1010        assert_eq!(writer.buffer, "Not enough values on stack\n");
1011    }
1012
1013    // DUP OPERATIONS
1014
1015    #[test]
1016    fn test_dup_operation_modifies_stack() {
1017        let expected_stack = parse_strings(vec!["1", "2", "3", "3"]);
1018        let expected_undos = vec![
1019            create_undo(3, vec![], vec!["1", "2", "3"]),
1020            create_undo(1, vec![], vec!["dup"]),
1021        ];
1022        let expected_redos = vec![];
1023        let mut engine = create_engine();
1024        let mut writer = BufferWriter::new();
1025        assert!(parse_line(&mut engine, &mut writer, "1 2 3").is_ok());
1026        assert!(parse_line(&mut engine, &mut writer, "dup").is_ok());
1027        assert_eq!(engine.stack, expected_stack);
1028        assert_eq!(engine.undos, expected_undos);
1029        assert_eq!(engine.redos, expected_redos);
1030        assert_eq!(writer.buffer, "");
1031    }
1032
1033    #[test]
1034    fn test_dup_operation_fails_cleanly() {
1035        let expected_stack = parse_strings(vec!["1", "2", "3"]);
1036        let expected_undos = vec![
1037            create_undo(3, vec![], vec!["1", "2", "3"]),
1038        ];
1039        let expected_redos = vec![];
1040        let mut engine = create_engine();
1041        let mut writer = BufferWriter::new();
1042        assert!(parse_line(&mut engine, &mut writer, "1 2 3").is_ok());
1043        assert!(parse_line(&mut engine, &mut writer, "pop pop pop dup 999").is_err());
1044        assert_eq!(engine.stack, expected_stack);
1045        assert_eq!(engine.undos, expected_undos);
1046        assert_eq!(engine.redos, expected_redos);
1047        assert_eq!(writer.buffer, "Not enough values on stack\n");
1048    }
1049
1050    // SWAP OPERATIONS
1051
1052    #[test]
1053    fn test_swap_operation_modifies_stack() {
1054        let expected_stack = parse_strings(vec!["1", "3", "2"]);
1055        let expected_undos = vec![
1056            create_undo(3, vec![], vec!["1", "2", "3"]),
1057            create_undo(2, vec!["2", "3"], vec!["swap"]),
1058        ];
1059        let expected_redos = vec![];
1060        let mut engine = create_engine();
1061        let mut writer = BufferWriter::new();
1062        assert!(parse_line(&mut engine, &mut writer, "1 2 3").is_ok());
1063        assert!(parse_line(&mut engine, &mut writer, "swap").is_ok());
1064        assert_eq!(engine.stack, expected_stack);
1065        assert_eq!(engine.undos, expected_undos);
1066        assert_eq!(engine.redos, expected_redos);
1067        assert_eq!(writer.buffer, "");
1068    }
1069
1070    #[test]
1071    fn test_swap_operation_fails_cleanly() {
1072        let expected_stack = parse_strings(vec!["1", "2", "3"]);
1073        let expected_undos = vec![
1074            create_undo(3, vec![], vec!["1", "2", "3"]),
1075        ];
1076        let expected_redos = vec![];
1077        let mut engine = create_engine();
1078        let mut writer = BufferWriter::new();
1079        assert!(parse_line(&mut engine, &mut writer, "1 2 3").is_ok());
1080        assert!(parse_line(&mut engine, &mut writer, "pop pop swap 999").is_err());
1081        assert_eq!(engine.stack, expected_stack);
1082        assert_eq!(engine.undos, expected_undos);
1083        assert_eq!(engine.redos, expected_redos);
1084        assert_eq!(writer.buffer, "Not enough values on stack\n");
1085    }
1086
1087    // CUT OPERATIONS
1088
1089    #[test]
1090    fn test_cut_operation_copies_value() {
1091        let expected_stack = vec![];
1092        let expected_undos = vec![
1093            create_undo(1, vec![], vec!["42"]),
1094            create_undo(0, vec!["42"], vec!["cut"]),
1095        ];
1096        let expected_redos = vec![];
1097        let mut engine = create_engine();
1098        let mut writer = BufferWriter::new();
1099        assert!(parse_line(&mut engine, &mut writer, "42").is_ok());
1100        assert!(parse_line(&mut engine, &mut writer, "cut").is_ok());
1101        assert_eq!(engine.stack, expected_stack);
1102        assert_eq!(engine.undos, expected_undos);
1103        assert_eq!(engine.redos, expected_redos);
1104        assert_eq!(engine.clip, Some(parse_string("42")));
1105        assert_eq!(writer.buffer, "");
1106    }
1107
1108    #[test]
1109    fn test_cut_operation_fails_cleanly() {
1110        let expected_stack = vec![];
1111        let expected_undos = vec![];
1112        let expected_redos = vec![];
1113        let mut engine = create_engine();
1114        let mut writer = BufferWriter::new();
1115        assert!(parse_line(&mut engine, &mut writer, "cut").is_err());
1116        assert_eq!(engine.stack, expected_stack);
1117        assert_eq!(engine.undos, expected_undos);
1118        assert_eq!(engine.redos, expected_redos);
1119        assert_eq!(engine.clip, None);
1120        assert_eq!(writer.buffer, "Not enough values on stack\n");
1121    }
1122
1123    // COPY OPERATIONS
1124
1125    #[test]
1126    fn test_copy_operation_copies_value() {
1127        let expected_stack = parse_strings(vec!["42"]);
1128        let expected_undos = vec![
1129            create_undo(1, vec![], vec!["42"]),
1130        ];
1131        let expected_redos = vec![];
1132        let mut engine = create_engine();
1133        let mut writer = BufferWriter::new();
1134        assert!(parse_line(&mut engine, &mut writer, "42").is_ok());
1135        assert!(parse_line(&mut engine, &mut writer, "copy").is_ok());
1136        assert_eq!(engine.stack, expected_stack);
1137        assert_eq!(engine.undos, expected_undos);
1138        assert_eq!(engine.redos, expected_redos);
1139        assert_eq!(engine.clip, Some(parse_string("42")));
1140        assert_eq!(writer.buffer, "");
1141    }
1142
1143    #[test]
1144    fn test_copy_operation_fails_cleanly() {
1145        let expected_stack = vec![];
1146        let expected_undos = vec![];
1147        let expected_redos = vec![];
1148        let mut engine = create_engine();
1149        let mut writer = BufferWriter::new();
1150        assert!(parse_line(&mut engine, &mut writer, "copy").is_err());
1151        assert_eq!(engine.stack, expected_stack);
1152        assert_eq!(engine.undos, expected_undos);
1153        assert_eq!(engine.redos, expected_redos);
1154        assert_eq!(engine.clip, None);
1155        assert_eq!(writer.buffer, "Not enough values on stack\n");
1156    }
1157
1158    // PASTE OPERATIONS
1159
1160    #[test]
1161    fn test_paste_operation_copies_value() {
1162        let expected_stack = parse_strings(vec!["42", "42"]);
1163        let expected_undos = vec![
1164            create_undo(1, vec![], vec!["42"]),
1165            create_undo(1, vec![], vec!["paste"]),
1166        ];
1167        let expected_redos = vec![];
1168        let mut engine = create_engine();
1169        let mut writer = BufferWriter::new();
1170        assert!(parse_line(&mut engine, &mut writer, "42").is_ok());
1171        assert!(parse_line(&mut engine, &mut writer, "copy").is_ok());
1172        assert!(parse_line(&mut engine, &mut writer, "paste").is_ok());
1173        assert_eq!(engine.stack, expected_stack);
1174        assert_eq!(engine.undos, expected_undos);
1175        assert_eq!(engine.redos, expected_redos);
1176        assert_eq!(engine.clip, Some(parse_string("42")));
1177        assert_eq!(writer.buffer, "");
1178    }
1179
1180    #[test]
1181    fn test_paste_operation_fails_cleanly() {
1182        let expected_stack = parse_strings(vec!["42"]);
1183        let expected_undos = vec![
1184            create_undo(1, vec![], vec!["42"]),
1185        ];
1186        let expected_redos = vec![];
1187        let mut engine = create_engine();
1188        let mut writer = BufferWriter::new();
1189        assert!(parse_line(&mut engine, &mut writer, "42").is_ok());
1190        assert!(parse_line(&mut engine, &mut writer, "paste").is_err());
1191        assert_eq!(engine.stack, expected_stack);
1192        assert_eq!(engine.undos, expected_undos);
1193        assert_eq!(engine.redos, expected_redos);
1194        assert_eq!(engine.clip, None);
1195        assert_eq!(writer.buffer, "No value on clipboard\n");
1196    }
1197
1198    // UNDO OPERATIONS
1199
1200    #[test]
1201    fn test_single_undo_resets_previous_line() {
1202        let expected_stack = parse_strings(vec!["4", "5", "6"]);
1203        let expected_undos = vec![
1204            create_undo(3, vec![], vec!["4", "5", "6"]),
1205        ];
1206        let expected_redos = vec![
1207            create_undo(2, vec!["11"], vec!["add"]),
1208        ];
1209        let mut engine = create_engine();
1210        let mut writer = BufferWriter::new();
1211        assert!(parse_line(&mut engine, &mut writer, "4 5 6").is_ok());
1212        assert!(parse_line(&mut engine, &mut writer, "add").is_ok());
1213        assert!(parse_line(&mut engine, &mut writer, "undo").is_ok());
1214        assert_eq!(engine.stack, expected_stack);
1215        assert_eq!(engine.undos, expected_undos);
1216        assert_eq!(engine.redos, expected_redos);
1217        assert_eq!(writer.buffer, "");
1218    }
1219
1220    #[test]
1221    fn test_double_undo_resets_previous_lines() {
1222        let expected_stack = vec![];
1223        let expected_undos = vec![];
1224        let expected_redos = vec![
1225            create_undo(2, vec!["11"], vec!["add"]),
1226            create_undo(0, vec!["4", "5", "6"], vec!["4", "5", "6"]),
1227        ];
1228        let mut engine = create_engine();
1229        let mut writer = BufferWriter::new();
1230        assert!(parse_line(&mut engine, &mut writer, "4 5 6").is_ok());
1231        assert!(parse_line(&mut engine, &mut writer, "add").is_ok());
1232        assert!(parse_line(&mut engine, &mut writer, "undo undo").is_ok());
1233        assert_eq!(engine.stack, expected_stack);
1234        assert_eq!(engine.undos, expected_undos);
1235        assert_eq!(engine.redos, expected_redos);
1236        assert_eq!(writer.buffer, "");
1237    }
1238
1239    #[test]
1240    fn test_single_undo_with_suffix_resets_previous_line() {
1241        let expected_stack = parse_strings(vec!["4", "30"]);
1242        let expected_undos = vec![
1243            create_undo(3, vec![], vec!["4", "5", "6"]),
1244            create_undo(1, vec!["5", "6"], vec!["mul"]),
1245        ];
1246        let expected_redos = vec![];
1247        let mut engine = create_engine();
1248        let mut writer = BufferWriter::new();
1249        assert!(parse_line(&mut engine, &mut writer, "4 5 6").is_ok());
1250        assert!(parse_line(&mut engine, &mut writer, "add").is_ok());
1251        assert!(parse_line(&mut engine, &mut writer, "undo mul").is_ok());
1252        assert_eq!(engine.stack, expected_stack);
1253        assert_eq!(engine.undos, expected_undos);
1254        assert_eq!(engine.redos, expected_redos);
1255        assert_eq!(writer.buffer, "");
1256    }
1257
1258    #[test]
1259    fn test_double_undo_with_suffix_resets_previous_lines() {
1260        let expected_stack = parse_strings(vec!["1", "6"]);
1261        let expected_undos = vec![
1262            create_undo(3, vec![], vec!["1", "2", "3"]),
1263            create_undo(1, vec!["2", "3"], vec!["mul"]),
1264        ];
1265        let expected_redos = vec![];
1266        let mut engine = create_engine();
1267        let mut writer = BufferWriter::new();
1268        assert!(parse_line(&mut engine, &mut writer, "1 2 3").is_ok());
1269        assert!(parse_line(&mut engine, &mut writer, "4 5 6").is_ok());
1270        assert!(parse_line(&mut engine, &mut writer, "add").is_ok());
1271        assert!(parse_line(&mut engine, &mut writer, "undo undo mul").is_ok());
1272        assert_eq!(engine.stack, expected_stack);
1273        assert_eq!(engine.undos, expected_undos);
1274        assert_eq!(engine.redos, expected_redos);
1275        assert_eq!(writer.buffer, "");
1276    }
1277
1278    #[test]
1279    fn test_single_undo_with_prefix_resets_current_line() {
1280        let expected_stack = parse_strings(vec!["4", "11"]);
1281        let expected_undos = vec![
1282            create_undo(3, vec![], vec!["4", "5", "6"]),
1283            create_undo(1, vec!["5", "6"], vec!["add"]),
1284        ];
1285        let expected_redos = vec![
1286            create_undo(2, vec!["15"], vec!["add"]),
1287        ];
1288        let mut engine = create_engine();
1289        let mut writer = BufferWriter::new();
1290        assert!(parse_line(&mut engine, &mut writer, "4 5 6").is_ok());
1291        assert!(parse_line(&mut engine, &mut writer, "add").is_ok());
1292        assert!(parse_line(&mut engine, &mut writer, "add undo").is_ok());
1293        assert_eq!(engine.stack, expected_stack);
1294        assert_eq!(engine.undos, expected_undos);
1295        assert_eq!(engine.redos, expected_redos);
1296        assert_eq!(writer.buffer, "");
1297    }
1298
1299    #[test]
1300    fn test_double_undo_with_prefix_resets_current_and_previous_lines() {
1301        let expected_stack = parse_strings(vec!["4", "5", "6"]);
1302        let expected_undos = vec![
1303            create_undo(3, vec![], vec!["4", "5", "6"]),
1304        ];
1305        let expected_redos = vec![
1306            create_undo(2, vec!["15"], vec!["add"]),
1307            create_undo(2, vec!["11"], vec!["add"]),
1308        ];
1309        let mut engine = create_engine();
1310        let mut writer = BufferWriter::new();
1311        assert!(parse_line(&mut engine, &mut writer, "4 5 6").is_ok());
1312        assert!(parse_line(&mut engine, &mut writer, "add").is_ok());
1313        assert!(parse_line(&mut engine, &mut writer, "add undo undo").is_ok());
1314        assert_eq!(engine.stack, expected_stack);
1315        assert_eq!(engine.undos, expected_undos);
1316        assert_eq!(engine.redos, expected_redos);
1317        assert_eq!(writer.buffer, "");
1318    }
1319
1320    #[test]
1321    fn test_single_undo_with_prefix_and_suffix_resets_current_line() {
1322        let expected_stack = parse_strings(vec!["44"]);
1323        let expected_undos = vec![
1324            create_undo(3, vec![], vec!["4", "5", "6"]),
1325            create_undo(1, vec!["5", "6"], vec!["add"]),
1326            create_undo(1, vec!["4", "11"], vec!["mul"]),
1327        ];
1328        let expected_redos = vec![];
1329        let mut engine = create_engine();
1330        let mut writer = BufferWriter::new();
1331        assert!(parse_line(&mut engine, &mut writer, "4 5 6").is_ok());
1332        assert!(parse_line(&mut engine, &mut writer, "add").is_ok());
1333        assert!(parse_line(&mut engine, &mut writer, "add undo mul").is_ok());
1334        assert_eq!(engine.stack, expected_stack);
1335        assert_eq!(engine.undos, expected_undos);
1336        assert_eq!(engine.redos, expected_redos);
1337        assert_eq!(writer.buffer, "");
1338    }
1339
1340    #[test]
1341    fn test_double_undo_with_prefix_and_suffix_resets_current_and_previous_lines() {
1342        let expected_stack = parse_strings(vec!["4", "30"]);
1343        let expected_undos = vec![
1344            create_undo(3, vec![], vec!["4", "5", "6"]),
1345            create_undo(1, vec!["5", "6"], vec!["mul"]),
1346        ];
1347        let expected_redos = vec![];
1348        let mut engine = create_engine();
1349        let mut writer = BufferWriter::new();
1350        assert!(parse_line(&mut engine, &mut writer, "4 5 6").is_ok());
1351        assert!(parse_line(&mut engine, &mut writer, "add").is_ok());
1352        assert!(parse_line(&mut engine, &mut writer, "add undo undo mul").is_ok());
1353        assert_eq!(engine.stack, expected_stack);
1354        assert_eq!(engine.undos, expected_undos);
1355        assert_eq!(engine.redos, expected_redos);
1356        assert_eq!(writer.buffer, "");
1357    }
1358
1359    #[test]
1360    fn test_triple_undo_operation_fails_cleanly() {
1361        let expected_stack = vec![];
1362        let expected_undos = vec![];
1363        let expected_redos = vec![
1364            create_undo(2, vec!["11"], vec!["add"]),
1365            create_undo(0, vec!["4", "5", "6"], vec!["4", "5", "6"]),
1366        ];
1367        let mut engine = create_engine();
1368        let mut writer = BufferWriter::new();
1369        assert!(parse_line(&mut engine, &mut writer, "4 5 6").is_ok());
1370        assert!(parse_line(&mut engine, &mut writer, "add").is_ok());
1371        assert!(parse_line(&mut engine, &mut writer, "undo undo undo").is_err());
1372        assert_eq!(engine.stack, expected_stack);
1373        assert_eq!(engine.undos, expected_undos);
1374        assert_eq!(engine.redos, expected_redos);
1375        assert_eq!(writer.buffer, "Start of undo history\n");
1376    }
1377
1378    // REDO OPERATIONS
1379
1380    #[test]
1381    fn test_single_redo_operation_modifies_stack() {
1382        let expected_stack = parse_strings(vec!["4", "11"]);
1383        let expected_undos = vec![
1384            create_undo(3, vec![], vec!["4", "5", "6"]),
1385            create_undo(1, vec!["5", "6"], vec!["add"]),
1386        ];
1387        let expected_redos = vec![
1388            create_undo(2, vec!["15"], vec!["add"]),
1389        ];
1390        let mut engine = create_engine();
1391        let mut writer = BufferWriter::new();
1392        assert!(parse_line(&mut engine, &mut writer, "4 5 6").is_ok());
1393        assert!(parse_line(&mut engine, &mut writer, "add").is_ok());
1394        assert!(parse_line(&mut engine, &mut writer, "add").is_ok());
1395        assert!(parse_line(&mut engine, &mut writer, "undo undo").is_ok());
1396        assert!(parse_line(&mut engine, &mut writer, "redo").is_ok());
1397        assert_eq!(engine.stack, expected_stack);
1398        assert_eq!(engine.undos, expected_undos);
1399        assert_eq!(engine.redos, expected_redos);
1400        assert_eq!(writer.buffer, "");
1401    }
1402
1403    #[test]
1404    fn test_double_redo_operation_modifies_stack() {
1405        let expected_stack = parse_strings(vec!["15"]);
1406        let expected_undos = vec![
1407            create_undo(3, vec![], vec!["4", "5", "6"]),
1408            create_undo(1, vec!["5", "6"], vec!["add"]),
1409            create_undo(1, vec!["4", "11"], vec!["add"]),
1410        ];
1411        let expected_redos = vec![];
1412        let mut engine = create_engine();
1413        let mut writer = BufferWriter::new();
1414        assert!(parse_line(&mut engine, &mut writer, "4 5 6").is_ok());
1415        assert!(parse_line(&mut engine, &mut writer, "add").is_ok());
1416        assert!(parse_line(&mut engine, &mut writer, "add").is_ok());
1417        assert!(parse_line(&mut engine, &mut writer, "undo undo").is_ok());
1418        assert!(parse_line(&mut engine, &mut writer, "redo redo").is_ok());
1419        assert_eq!(engine.stack, expected_stack);
1420        assert_eq!(engine.undos, expected_undos);
1421        assert_eq!(engine.redos, expected_redos);
1422        assert_eq!(writer.buffer, "");
1423    }
1424
1425    #[test]
1426    fn test_single_redo_operation_with_prefix_fails_cleanly() {
1427        let expected_stack = parse_strings(vec!["4", "5", "6"]);
1428        let expected_undos = vec![
1429            create_undo(3, vec![], vec!["4", "5", "6"]),
1430        ];
1431        let expected_redos = vec![
1432            create_undo(2, vec!["15"], vec!["add"]),
1433            create_undo(2, vec!["11"], vec!["add"]),
1434        ];
1435        let mut engine = create_engine();
1436        let mut writer = BufferWriter::new();
1437        assert!(parse_line(&mut engine, &mut writer, "4 5 6").is_ok());
1438        assert!(parse_line(&mut engine, &mut writer, "add").is_ok());
1439        assert!(parse_line(&mut engine, &mut writer, "add").is_ok());
1440        assert!(parse_line(&mut engine, &mut writer, "undo undo").is_ok());
1441        assert!(parse_line(&mut engine, &mut writer, "mul redo 999").is_err());
1442        assert_eq!(engine.stack, expected_stack);
1443        assert_eq!(engine.undos, expected_undos);
1444        assert_eq!(engine.redos, expected_redos);
1445        assert_eq!(writer.buffer, "End of undo history\n");
1446    }
1447
1448    #[test]
1449    fn test_triple_redo_operation_fails_cleanly() {
1450        let expected_stack = parse_strings(vec!["15"]);
1451        let expected_undos = vec![
1452            create_undo(3, vec![], vec!["4", "5", "6"]),
1453            create_undo(1, vec!["5", "6"], vec!["add"]),
1454            create_undo(1, vec!["4", "11"], vec!["add"]),
1455        ];
1456        let expected_redos = vec![];
1457        let mut engine = create_engine();
1458        let mut writer = BufferWriter::new();
1459        assert!(parse_line(&mut engine, &mut writer, "4 5 6").is_ok());
1460        assert!(parse_line(&mut engine, &mut writer, "add").is_ok());
1461        assert!(parse_line(&mut engine, &mut writer, "add").is_ok());
1462        assert!(parse_line(&mut engine, &mut writer, "undo undo").is_ok());
1463        assert!(parse_line(&mut engine, &mut writer, "redo redo redo 999").is_err());
1464        assert_eq!(engine.stack, expected_stack);
1465        assert_eq!(engine.undos, expected_undos);
1466        assert_eq!(engine.redos, expected_redos);
1467        assert_eq!(writer.buffer, "End of undo history\n");
1468    }
1469
1470    // VARIABLE ASSIGNMENT
1471
1472    #[test]
1473    fn test_variable_not_assigned_by_default() {
1474        let expected_stack = vec![
1475            parse_string("1"),
1476            parse_string("2"),
1477            parse_string("3"),
1478        ];
1479        let expected_variables = HashMap::new();
1480        let mut engine = create_engine();
1481        let mut writer = BufferWriter::new();
1482        assert!(parse_line(&mut engine, &mut writer, "1 2 3").is_ok());
1483        assert_eq!(engine.stack, expected_stack);
1484        assert_eq!(engine.interface.borrow().get_variables(), &expected_variables);
1485    }
1486
1487    #[test]
1488    fn test_variable_is_assigned_to_new_entry() {
1489        let expected_stack = vec![
1490            parse_string("1"),
1491            parse_string("2 = foo"),
1492            parse_string("3"),
1493        ];
1494        let expected_variables = HashMap::from([
1495            (String::from("foo"), parse_string("2 = foo")),
1496        ]);
1497        let mut engine = create_engine();
1498        let mut writer = BufferWriter::new();
1499        assert!(parse_line(&mut engine, &mut writer, "1 2").is_ok());
1500        assert!(parse_line(&mut engine, &mut writer, "set foo").is_ok());
1501        assert!(parse_line(&mut engine, &mut writer, "3").is_ok());
1502        assert_eq!(engine.stack, expected_stack);
1503        assert_eq!(engine.interface.borrow().get_variables(), &expected_variables);
1504    }
1505
1506    #[test]
1507    fn test_variable_is_reassigned_to_new_entry() {
1508        let expected_stack = vec![
1509            parse_string("1"),
1510            parse_string("2"),
1511            parse_string("3 = foo"),
1512        ];
1513        let expected_variables = HashMap::from([
1514            (String::from("foo"), parse_string("3 = foo")),
1515        ]);
1516        let mut engine = create_engine();
1517        let mut writer = BufferWriter::new();
1518        assert!(parse_line(&mut engine, &mut writer, "1 2").is_ok());
1519        assert!(parse_line(&mut engine, &mut writer, "set foo").is_ok());
1520        assert!(parse_line(&mut engine, &mut writer, "3").is_ok());
1521        assert!(parse_line(&mut engine, &mut writer, "set foo").is_ok());
1522        assert_eq!(engine.stack, expected_stack);
1523        assert_eq!(engine.interface.borrow().get_variables(), &expected_variables);
1524    }
1525
1526    #[test]
1527    fn test_variable_is_replaced_with_same_name() {
1528        let expected_stack = vec![
1529            parse_string("1"),
1530            parse_string("2"),
1531            parse_string("3 = foo"),
1532        ];
1533        let expected_variables = HashMap::from([
1534            (String::from("foo"), parse_string("3 = foo")),
1535        ]);
1536        let mut engine = create_engine();
1537        let mut writer = BufferWriter::new();
1538        assert!(parse_line(&mut engine, &mut writer, "1 2 3").is_ok());
1539        assert!(parse_line(&mut engine, &mut writer, "set foo").is_ok());
1540        assert!(parse_line(&mut engine, &mut writer, "set foo").is_ok());
1541        assert_eq!(engine.stack, expected_stack);
1542        assert_eq!(engine.interface.borrow().get_variables(), &expected_variables);
1543    }
1544
1545    #[test]
1546    fn test_variable_is_replaced_with_new_name() {
1547        let expected_stack = vec![
1548            parse_string("1"),
1549            parse_string("2"),
1550            parse_string("3 = bar"),
1551        ];
1552        let expected_variables = HashMap::from([
1553            (String::from("bar"), parse_string("3 = bar")),
1554        ]);
1555        let mut engine = create_engine();
1556        let mut writer = BufferWriter::new();
1557        assert!(parse_line(&mut engine, &mut writer, "1 2 3").is_ok());
1558        assert!(parse_line(&mut engine, &mut writer, "set foo").is_ok());
1559        assert!(parse_line(&mut engine, &mut writer, "set bar").is_ok());
1560        assert_eq!(engine.stack, expected_stack);
1561        assert_eq!(engine.interface.borrow().get_variables(), &expected_variables);
1562    }
1563
1564    #[test]
1565    fn test_variable_assignment_fails_cleanly() {
1566        let expected_variables = HashMap::new();
1567        let mut engine = create_engine();
1568        let mut writer = BufferWriter::new();
1569        assert!(parse_line(&mut engine, &mut writer, "set foo").is_err());
1570        assert_eq!(engine.interface.borrow().get_variables(), &expected_variables);
1571        assert_eq!(writer.buffer, "Not enough values on stack\n");
1572    }
1573
1574    // TEXT OUTPUT
1575
1576    #[test]
1577    fn test_prints_error_on_invalid_decimal() {
1578        let mut engine = create_engine();
1579        let mut writer = BufferWriter::new();
1580        assert!(parse_line(&mut engine, &mut writer, "xyz").is_err());
1581        assert_eq!(writer.buffer, "Invalid number or keyword: xyz\n");
1582    }
1583
1584    #[test]
1585    fn test_prints_error_on_invalid_hexadecimal() {
1586        let mut engine = create_engine();
1587        let mut writer = BufferWriter::new();
1588        engine.context.borrow_mut().set_hex();
1589        assert!(parse_line(&mut engine, &mut writer, "xyz").is_err());
1590        assert_eq!(writer.buffer, "Invalid number or keyword: xyz\n");
1591    }
1592
1593    #[test]
1594    fn test_shows_history_from_start() {
1595        let expected = "\
1596<==
1597111
1598222
1599333 444 555
1600666 777
1601...
1602";
1603        let mut engine = create_engine();
1604        let mut writer = BufferWriter::new();
1605        engine.redos.insert(0, create_undo(0, vec![], vec!["111"]));
1606        engine.redos.insert(0, create_undo(0, vec![], vec!["222"]));
1607        engine.redos.insert(0, create_undo(0, vec![], vec!["333", "444", "555"]));
1608        engine.redos.insert(0, create_undo(0, vec![], vec!["666", "777"]));
1609        engine.redos.insert(0, create_undo(0, vec![], vec!["888"]));
1610        engine.redos.insert(0, create_undo(0, vec![], vec!["999"]));
1611        assert!(engine.limit_history(&mut writer, 4).is_ok());
1612        assert_eq!(writer.buffer, indent_multiline(expected));
1613    }
1614
1615    #[test]
1616    fn test_shows_history_with_lower_limit() {
1617        let expected = "\
1618...
1619222
1620333 444 555 <==
1621666 777
1622888
1623...
1624";
1625        let mut engine = create_engine();
1626        let mut writer = BufferWriter::new();
1627        engine.undos.push(create_undo(0, vec![], vec!["111"]));
1628        engine.undos.push(create_undo(0, vec![], vec!["222"]));
1629        engine.undos.push(create_undo(0, vec![], vec!["333", "444", "555"]));
1630        engine.redos.insert(0, create_undo(0, vec![], vec!["666", "777"]));
1631        engine.redos.insert(0, create_undo(0, vec![], vec!["888"]));
1632        engine.redos.insert(0, create_undo(0, vec![], vec!["999"]));
1633        assert!(engine.limit_history(&mut writer, 2).is_ok());
1634        assert_eq!(writer.buffer, indent_multiline(expected));
1635    }
1636
1637    #[test]
1638    fn test_shows_history_with_equal_limit() {
1639        let expected = "\
1640111
1641222
1642333 444 555 <==
1643666 777
1644888
1645999
1646";
1647        let mut engine = create_engine();
1648        let mut writer = BufferWriter::new();
1649        engine.undos.push(create_undo(0, vec![], vec!["111"]));
1650        engine.undos.push(create_undo(0, vec![], vec!["222"]));
1651        engine.undos.push(create_undo(0, vec![], vec!["333", "444", "555"]));
1652        engine.redos.insert(0, create_undo(0, vec![], vec!["666", "777"]));
1653        engine.redos.insert(0, create_undo(0, vec![], vec!["888"]));
1654        engine.redos.insert(0, create_undo(0, vec![], vec!["999"]));
1655        assert!(engine.limit_history(&mut writer, 3).is_ok());
1656        assert_eq!(writer.buffer, indent_multiline(expected));
1657    }
1658
1659    #[test]
1660    fn test_shows_history_with_higher_limit() {
1661        let expected = "\
1662111
1663222
1664333 444 555 <==
1665666 777
1666888
1667999
1668";
1669        let mut engine = create_engine();
1670        let mut writer = BufferWriter::new();
1671        engine.undos.push(create_undo(0, vec![], vec!["111"]));
1672        engine.undos.push(create_undo(0, vec![], vec!["222"]));
1673        engine.undos.push(create_undo(0, vec![], vec!["333", "444", "555"]));
1674        engine.redos.insert(0, create_undo(0, vec![], vec!["666", "777"]));
1675        engine.redos.insert(0, create_undo(0, vec![], vec!["888"]));
1676        engine.redos.insert(0, create_undo(0, vec![], vec!["999"]));
1677        assert!(engine.limit_history(&mut writer, 4).is_ok());
1678        assert_eq!(writer.buffer, indent_multiline(expected));
1679    }
1680
1681    #[test]
1682    fn test_shows_history_to_end() {
1683        let expected = "\
1684...
1685333 444 555
1686666 777
1687888
1688999 <==
1689";
1690        let mut engine = create_engine();
1691        let mut writer = BufferWriter::new();
1692        engine.undos.push(create_undo(0, vec![], vec!["111"]));
1693        engine.undos.push(create_undo(0, vec![], vec!["222"]));
1694        engine.undos.push(create_undo(0, vec![], vec!["333", "444", "555"]));
1695        engine.undos.push(create_undo(0, vec![], vec!["666", "777"]));
1696        engine.undos.push(create_undo(0, vec![], vec!["888"]));
1697        engine.undos.push(create_undo(0, vec![], vec!["999"]));
1698        assert!(engine.limit_history(&mut writer, 4).is_ok());
1699        assert_eq!(writer.buffer, indent_multiline(expected));
1700    }
1701
1702    #[test]
1703    fn test_shows_stack_with_no_values() {
1704        let mut engine = create_engine();
1705        let mut writer = BufferWriter::new();
1706        assert!(engine.show_stack(&mut writer).is_ok());
1707        assert_eq!(writer.buffer, "");
1708    }
1709
1710    #[test]
1711    fn test_shows_stack_as_decimal() {
1712        let expected = "\
171399999
171499999     # integer value
171599999     = foo
171699999     = bar # integer value
1717  123.45
1718  123.45  # decimal value
1719  123.45  = baz
1720  123.45  = qux # decimal value
1721    3.142
1722    3.142 # decimal value
1723    3.142 = quux
1724    3.142 = quuux # decimal value
1725";
1726        let mut engine = create_engine();
1727        let mut writer = BufferWriter::new();
1728        engine.stack.push(parse_string("99999"));
1729        engine.stack.push(parse_string("99999 # integer value"));
1730        engine.stack.push(parse_string("99999 = foo"));
1731        engine.stack.push(parse_string("99999 = bar # integer value"));
1732        engine.stack.push(parse_string("123.45"));
1733        engine.stack.push(parse_string("123.45 # decimal value"));
1734        engine.stack.push(parse_string("123.45 = baz"));
1735        engine.stack.push(parse_string("123.45 = qux # decimal value"));
1736        engine.stack.push(parse_string("3.142"));
1737        engine.stack.push(parse_string("3.142 # decimal value"));
1738        engine.stack.push(parse_string("3.142 = quux"));
1739        engine.stack.push(parse_string("3.142 = quuux # decimal value"));
1740        assert!(engine.show_stack(&mut writer).is_ok());
1741        assert_eq!(writer.buffer, indent_multiline(expected));
1742    }
1743
1744    #[test]
1745    fn test_shows_stack_as_single_hexadecimal_no_sep() {
1746        let expected = "\
17470x7fffffff
17480x7fffffff # large value
17490x7fffffff = foo
17500x7fffffff = bar # large value
17510x00000001
17520x00000001 # small value
17530x00000001 = baz
17540x00000001 = qux # small value
1755";
1756        let mut engine = create_engine();
1757        let mut writer = BufferWriter::new();
1758        engine.context.borrow_mut().format = Format::Base16(0);
1759        engine.context.borrow_mut().sep = false;
1760        engine.stack.push(parse_string("2147483647"));
1761        engine.stack.push(parse_string("2147483647 # large value"));
1762        engine.stack.push(parse_string("2147483647 = foo"));
1763        engine.stack.push(parse_string("2147483647 = bar # large value"));
1764        engine.stack.push(parse_string("1"));
1765        engine.stack.push(parse_string("1 # small value"));
1766        engine.stack.push(parse_string("1 = baz"));
1767        engine.stack.push(parse_string("1 = qux # small value"));
1768        assert!(engine.show_stack(&mut writer).is_ok());
1769        assert_eq!(writer.buffer, indent_multiline(expected));
1770    }
1771
1772    #[test]
1773    fn test_shows_stack_as_double_hexadecimal_with_sep() {
1774        let expected = "\
17750x,00000001,00000000
17760x,00000001,00000000 # large value
17770x,00000001,00000000 = foo
17780x,00000001,00000000 = bar # large value
17790x,00000000,00000001
17800x,00000000,00000001 # small value
17810x,00000000,00000001 = baz
17820x,00000000,00000001 = qux # small value
1783";
1784        let mut engine = create_engine();
1785        let mut writer = BufferWriter::new();
1786        engine.context.borrow_mut().format = Format::Base16(0);
1787        engine.context.borrow_mut().sep = true;
1788        engine.stack.push(parse_string("4294967296"));
1789        engine.stack.push(parse_string("4294967296 # large value"));
1790        engine.stack.push(parse_string("4294967296 = foo"));
1791        engine.stack.push(parse_string("4294967296 = bar # large value"));
1792        engine.stack.push(parse_string("1"));
1793        engine.stack.push(parse_string("1 # small value"));
1794        engine.stack.push(parse_string("1 = baz"));
1795        engine.stack.push(parse_string("1 = qux # small value"));
1796        assert!(engine.show_stack(&mut writer).is_ok());
1797        assert_eq!(writer.buffer, indent_multiline(expected));
1798    }
1799
1800    fn indent_multiline(lines: &str) -> String {
1801        lines.lines()
1802            .map(|x| format!("  {}\n", x))
1803            .collect::<Vec<String>>()
1804            .join("")
1805    }
1806
1807    fn create_engine() -> Engine<BufferWriter> {
1808        let config = Config::default();
1809        Engine::new(config).unwrap().with_interact(true)
1810    }
1811
1812    fn parse_line(
1813        engine: &mut Engine<BufferWriter>,
1814        writer: &mut BufferWriter,
1815        line: &str,
1816    ) -> MyResult<()> {
1817        let result = engine.parse_line(writer, line);
1818        if let Err(error) = &result {
1819            writeln!(writer, "{}", error)?;
1820        }
1821        result
1822    }
1823
1824    impl<W: Write> Engine<W> {
1825        pub fn with_interact(mut self, interact: bool) -> Self {
1826            self.interact = interact;
1827            self
1828        }
1829    }
1830}