talc/talc-bin/src/main.rs

65 lines
1.6 KiB
Rust

use talc_lang::{Parser, Vm, Symbol, value::{Value, NativeFunc}, compiler::repl};
use std::{io::Write, rc::Rc, cell::RefCell};
fn do_thing() -> impl Fn(Value, Vec<Value>) -> anyhow::Result<Value> {
let x = RefCell::new(0);
move |_, _| {
let v = *x.borrow();
if v > 5 {
Ok(Value::Nil)
} else {
*x.borrow_mut() += 1;
Ok(Value::Int(v))
}
}
}
fn main() {
let parser = Parser::new();
let mut lines = std::io::stdin().lines().map_while(Result::ok);
let mut vm = Vm::new(256);
let mut globals = Vec::new();
let prev1_sym = Symbol::get("_");
let prev2_sym = Symbol::get("__");
let prev3_sym = Symbol::get("___");
vm.set_global(prev1_sym, Value::Nil);
vm.set_global(prev2_sym, Value::Nil);
vm.set_global(prev3_sym, Value::Nil);
vm.set_global(Symbol::get("test"), Value::NativeFunc(NativeFunc {
arity: 0,
f: Box::new(do_thing()),
}.into()));
loop {
print!(">> ");
std::io::stdout().flush().expect("could not flush stdout");
let line = lines.next().expect("could not get next line");
let ex = match parser.parse(&line) {
Ok(ex) => ex,
Err(e) => { println!("Error: {e}"); continue },
};
let func = match repl(&ex, &globals) {
Ok((f, g)) => { globals = g; f },
Err(e) => { println!("Error: {e}"); continue },
};
match vm.run(Rc::new(func)) {
Ok(v) => {
vm.set_global(prev3_sym, vm.get_global(prev2_sym).unwrap().clone());
vm.set_global(prev2_sym, vm.get_global(prev1_sym).unwrap().clone());
vm.set_global(prev1_sym, v.clone());
if v != Value::Nil {
println!("{v}");
}
}
Err(e) => println!("Error: {e}"),
}
}
}