65 lines
1.6 KiB
Rust
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}"),
|
|
}
|
|
}
|
|
}
|