complexpr/complexpr-bin/src/main.rs

88 lines
2.9 KiB
Rust
Raw Normal View History

2022-09-18 06:05:01 +00:00
use std::{fs, panic::{self, PanicInfo}};
2022-09-06 13:52:29 +00:00
use backtrace::Backtrace;
use complexpr::{env::Environment, interpreter::interpret, value::Value, stdlib};
2022-09-18 06:05:01 +00:00
use rustyline::{self, error::ReadlineError, Config, CompletionType, EditMode, hint::HistoryHinter, validate::MatchingBracketValidator, Editor};
mod helper;
use helper::CxprHelper;
2022-09-06 13:52:29 +00:00
2022-09-11 17:02:18 +00:00
const C_RESET: &str = "\x1b[0m";
const C_BLUE: &str = "\x1b[94m";
2022-09-17 23:23:54 +00:00
const C_RED: &str = "\x1b[91m";
2022-09-11 17:02:18 +00:00
const PROMPT: &str = "\x1b[94m>> \x1b[0m";
2022-09-07 20:11:51 +00:00
fn panic_hook(info: &PanicInfo) {
eprintln!("{:?}", Backtrace::new());
eprintln!("!!! Internal interpreter error occured !!!");
if let Some(s) = std::thread::current().name() {
eprintln!("Thread: {}", s);
}
if let Some(loc) = info.location() {
eprintln!("Location: {}:{}:{}", loc.file(), loc.line(), loc.column())
}
if let Some(s) = info.payload().downcast_ref::<&str>() {
eprintln!("Message: {}", s);
} else if let Some(s) = info.payload().downcast_ref::<String>() {
eprintln!("Message: {}", s);
}
}
2022-09-06 13:52:29 +00:00
fn main() -> Result<(), Box<dyn std::error::Error>> {
panic::set_hook(Box::new(panic_hook));
2022-09-06 13:52:29 +00:00
let args: Vec<String> = std::env::args().collect();
if args.len() == 2 {
let fname = &args[1];
let src = fs::read_to_string(fname)?;
2022-09-07 20:11:51 +00:00
let res = interpret(&src, Some(fname.into()), None, false);
if let Err(e) = res {
2022-09-17 23:23:54 +00:00
eprintln!("Error: {}", e);
2022-09-07 20:11:51 +00:00
}
2022-09-06 13:52:29 +00:00
} else {
repl()?;
}
Ok(())
}
fn repl() -> Result<(), Box<dyn std::error::Error>> {
2022-09-18 06:05:01 +00:00
let config = Config::builder()
.history_ignore_space(true)
.completion_type(CompletionType::List)
.edit_mode(EditMode::Emacs)
.build();
let env = Environment::new().wrap();
let h = CxprHelper {
hinter: HistoryHinter {},
colored_prompt: PROMPT.to_owned(),
validator: MatchingBracketValidator::new(),
env: env.clone(),
};
let mut rl = Editor::with_config(config)?;
rl.set_helper(Some(h));
2022-09-07 20:11:51 +00:00
println!("Press {}Ctrl+D{} to exit.", C_BLUE, C_RESET);
stdlib::load(&mut env.borrow_mut());
2022-09-20 13:06:45 +00:00
stdlib::io::load(&mut env.borrow_mut());
stdlib::iter::load(&mut env.borrow_mut());
stdlib::math::load(&mut env.borrow_mut());
2022-09-06 13:52:29 +00:00
loop {
2022-09-18 06:05:01 +00:00
let readline = rl.readline(">> ");
2022-09-06 13:52:29 +00:00
match readline {
Ok(line) => {
2022-09-07 20:11:51 +00:00
let result = interpret(&line, None, Some(env.clone()), true);
2022-09-06 13:52:29 +00:00
match result {
Ok(value) => {
if value != Value::Nil {
println!("{}", value.repr());
}
env.borrow_mut().declare("_".into(), value);
}
2022-09-17 23:23:54 +00:00
Err(e) => eprintln!("{}Error: {}{}", C_RED, C_RESET, e)
2022-09-06 13:52:29 +00:00
}
}
Err(ReadlineError::Eof) => break,
Err(_) => (),
}
}
Ok(())
2022-09-11 17:02:18 +00:00
}