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
31impl<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#[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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}