use std::process::exit;
use std::time::{SystemTime, UNIX_EPOCH};
use rustyline::error::ReadlineError;
use rustyline::Editor;
use lep::{builtin, eval_stmt, obj, stringify, Domain, Fun, FunMut, Obj, Res, State};
struct Sequence {
n: i64,
}
impl FunMut for Sequence {
fn invoke(&mut self, args: &Obj) -> Res {
if args.is::<()>() {
self.n += 1;
Ok(obj::int(self.n))
} else {
Err("sequence: too many arguments".to_string())
}
}
}
struct Time;
impl Fun for Time {
fn invoke(&self, args: &Obj) -> Res {
if args.is::<()>() {
match SystemTime::now().duration_since(UNIX_EPOCH) {
Ok(n) => Ok(obj::int(n.as_secs() as i64)),
Err(e) => Err(format!("time: {}", e)),
}
} else {
Err("time: too many arguments".to_string())
}
}
}
fn main() {
let mut sequence = Sequence { n: -1 };
let time = Time {};
let mut domain = Domain::new();
builtin::register(&mut domain);
domain.register_fun_mut("sequence", &mut sequence);
domain.register_fun("time", &time);
let mut state = State::new();
let mut rl = Editor::<()>::new();
let mut prefix = "".to_string();
loop {
match rl.readline(&format!("{}>> ", prefix)) {
Ok(line) => {
rl.add_history_entry(&line);
match eval_stmt(&mut domain, state.clone(), &line) {
Ok(res) => {
if res.result.value.is::<()>() {
if res.result.name == "_" {
prefix = "".to_string();
} else if !res.result.name.is_empty() {
println!("{} = ()", res.result.name);
}
} else {
let repr = stringify(&res.result.value).unwrap_or("?".to_string());
if res.result.name == "_" {
prefix = repr + " ";
} else if !res.result.name.is_empty() {
println!("{} = {}", res.result.name, repr);
}
}
state = res;
}
Err(msg) => {
println!("error: {}", msg);
}
}
}
Err(ReadlineError::Eof) => {
break;
}
Err(x) => {
println!("read error: {}", x);
exit(1);
}
}
}
}