1use rustyline::error::ReadlineError;
7use rustyline::{DefaultEditor, Result};
8use std::cell::RefCell;
9use std::fs;
10use std::rc::Rc;
11
12use crate::eval;
13use crate::eval::environment::Env;
14use crate::parser;
15
16pub fn start() -> Result<()> {
18 let mut rl = DefaultEditor::new()?;
19 let env: Env = Rc::new(RefCell::new(Default::default()));
20 let history_path = "/tmp/.monkey-history.txt";
21
22 match rl.load_history(history_path) {
23 Ok(_) => {}
24 Err(ReadlineError::Io(_)) => {
25 fs::File::create(history_path)?;
26 }
27 Err(err) => {
28 eprintln!("monkey-rs: Error loading history: {}", err);
29 }
30 };
31
32 println!(
33 r"
34 __ ___ __
35 / |/ /__ ___ / /_____ __ __
36 / /|_/ / _ \/ _ \/ '_/ -_) // /
37 /_/ /_/\___/_//_/_/\_\\__/\_, /
38 /___/
39 "
40 );
41 println!("Welcome to the Monkey programming language!");
42 println!("Feel free to type in commands\n");
43
44 loop {
45 let readline = rl.readline(">> ");
46 let mut input = String::new();
47
48 match readline {
49 Ok(mut line) => {
50 while line.ends_with(' ') {
51 line.pop();
52 }
53 if line.is_empty() {
54 continue;
55 }
56
57 loop {
58 if line.as_bytes().ends_with(b"\\") {
59 line.pop();
61 input += &line;
62
63 match rl.readline(".. ") {
65 Ok(next) => {
66 line = next;
67 while line.ends_with(' ') {
68 line.pop();
69 }
70 }
71 Err(ReadlineError::Eof | ReadlineError::Interrupted) => {
72 println!("Exiting...");
73 rl.save_history(history_path)?;
74 return Ok(());
75 }
76 Err(err) => {
77 println!("Error: {:?}", err);
78 return Err(err);
79 }
80 }
81 } else {
82 while line.ends_with(' ') {
84 line.pop();
85 }
86 input += &line;
87 break;
88 }
89 }
90
91 rl.add_history_entry(&input)?;
92
93 match parser::parse(&input) {
94 Ok(program) => match eval::eval(program, &Rc::clone(&env)) {
95 Ok(evaluated) => println!("{}", evaluated),
96 Err(e) => eprintln!("{}", e),
97 },
98 Err(e) => eprintln!("{}", e),
99 }
100 }
101 Err(ReadlineError::Eof | ReadlineError::Interrupted) => {
102 println!("Exiting...");
103 rl.save_history(history_path)?;
104 break;
105 }
106 Err(err) => {
107 println!("Error: {:?}", err);
108 break;
109 }
110 }
111 }
112
113 Ok(())
114}