use codemap;
#[macro_use]
extern crate starlark;
use codemap_diagnostic::{ColorConfig, Emitter};
use linefeed::{Interface, ReadResult};
use starlark::environment::{Environment, TypeValues};
use starlark::eval::eval_lexer;
use starlark::eval::simple::SimpleFileLoader;
use starlark::syntax::dialect::Dialect;
use starlark::syntax::lexer::{BufferedLexer, LexerIntoIter, LexerItem};
use starlark::values::none::NoneType;
use starlark::values::Value;
use std::env;
use std::path::PathBuf;
use std::sync::{Arc, Mutex};
fn print_eval<T1: Iterator<Item = LexerItem>, T2: LexerIntoIter<T1>>(
map: Arc<Mutex<codemap::CodeMap>>,
filename: &str,
content: &str,
lexer: T2,
dialect: Dialect,
env: &mut Environment,
type_values: &TypeValues,
file_loader_env: Environment,
) {
match eval_lexer(
&map,
filename,
content,
dialect,
lexer,
env,
type_values,
&SimpleFileLoader::new(&map.clone(), file_loader_env),
) {
Ok(v) => {
if v.get_type() != "NoneType" {
println!("{}", v.to_repr())
}
}
Err(p) => Emitter::stderr(ColorConfig::Always, Some(&map.lock().unwrap())).emit(&[p]),
}
}
starlark_module! {print_function =>
print(*args) {
let mut r = String::new();
let mut first = true;
for arg in args {
if !first {
r.push_str(" ");
}
first = false;
r.push_str(&arg.to_str());
}
eprintln!("{}", r);
Ok(Value::new(NoneType::None))
}
}
pub fn repl(global_environment: &mut Environment, type_values: &TypeValues, dialect: Dialect) {
let map = Arc::new(Mutex::new(codemap::CodeMap::new()));
let reader = Interface::new("Starlark").unwrap();
let mut env = global_environment.child("repl");
let mut n = 0;
reader.set_history_size(100_000);
let histfile = env::var_os("STARLARK_RUST_HISTFILE").map(PathBuf::from);
if let Some(ref histfile) = histfile {
if histfile.exists() {
if let Err(e) = reader.load_history(histfile) {
eprintln!("Failed to load history from {}: {}", histfile.display(), e);
}
}
}
reader.set_prompt(">>> ").unwrap();
while let Ok(ReadResult::Input(input)) = reader.read_line() {
if !input.is_empty() {
reader.set_prompt("... ").unwrap();
n += 1;
let input = input + "\n";
let mut lexer = BufferedLexer::new(&input);
let mut content = input;
while lexer.need_more() {
if let Ok(ReadResult::Input(input)) = reader.read_line() {
let input = input + "\n";
content += &input;
lexer.input(&input);
} else {
break;
}
}
let mut hist = content.clone();
hist.pop();
reader.add_history(hist);
print_eval(
map.clone(),
&format!("<{}>", n),
&content,
lexer,
dialect,
&mut env,
type_values,
global_environment.clone(),
)
}
reader.set_prompt(">>> ").unwrap();
}
println!();
if let Some(ref histfile) = histfile {
if let Err(e) = reader.save_history(histfile) {
eprintln!("Failed to save history to {}: {}", histfile.display(), e);
}
}
println!("Goodbye!");
}