2021-05-01 06:44:58 -05:00
|
|
|
use rustyline::Editor;
|
|
|
|
|
2021-05-25 13:26:01 -05:00
|
|
|
use crate::{interpret::ExecEnv, parser::Parser};
|
2021-05-01 06:44:58 -05:00
|
|
|
|
2021-06-16 10:29:27 -05:00
|
|
|
pub fn repl(ast_print: bool) {
|
2021-05-01 06:44:58 -05:00
|
|
|
let mut rl = Editor::<()>::new();
|
2021-05-25 13:26:01 -05:00
|
|
|
let mut env = ExecEnv::new();
|
2021-05-01 06:44:58 -05:00
|
|
|
loop {
|
|
|
|
let readline = rl.readline(":: ");
|
|
|
|
match readline {
|
|
|
|
Ok(line) => {
|
2021-07-13 13:54:27 -05:00
|
|
|
// NOTE(Alex): `readline()` leaves a newline at the
|
|
|
|
// end of the string if stdin is connected to a file
|
|
|
|
// or unsupported terminal; this can interfere with
|
|
|
|
// error printing.
|
|
|
|
let line = line.trim_end();
|
|
|
|
|
|
|
|
if line == "exit" {
|
2021-05-01 06:44:58 -05:00
|
|
|
println!("bye");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
let mut parser = Parser::new(&line);
|
2021-06-07 20:08:38 -05:00
|
|
|
let value = parser.init().and_then(|ast| {
|
2021-06-16 10:29:27 -05:00
|
|
|
if ast_print {
|
|
|
|
println!("{:#?}", &ast);
|
|
|
|
}
|
2021-06-07 20:08:38 -05:00
|
|
|
env.eval_stmts(&ast)
|
|
|
|
});
|
2021-06-04 18:56:26 -05:00
|
|
|
|
2021-06-07 20:08:38 -05:00
|
|
|
if let Err(e) = value {
|
2021-07-13 13:54:27 -05:00
|
|
|
println!("{}", e);
|
2021-06-07 20:08:38 -05:00
|
|
|
println!(" | {}", line);
|
|
|
|
println!(
|
2021-07-13 13:54:27 -05:00
|
|
|
" {}{}",
|
2021-06-07 20:08:38 -05:00
|
|
|
" ".repeat(e.span.start),
|
|
|
|
"^".repeat((e.span.end - e.span.start).max(1))
|
|
|
|
);
|
2021-05-02 08:43:25 -05:00
|
|
|
}
|
2021-05-01 06:44:58 -05:00
|
|
|
}
|
|
|
|
Err(rustyline::error::ReadlineError::Eof) => {
|
|
|
|
println!("bye");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
Err(rustyline::error::ReadlineError::Interrupted) => (),
|
|
|
|
Err(e) => {
|
|
|
|
println!("Error: {:?}", e);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|