81 lines
2.0 KiB
Rust
81 lines
2.0 KiB
Rust
#![feature(array_windows)]
|
|
#![feature(assert_matches)]
|
|
#![feature(box_patterns)]
|
|
#![feature(crate_visibility_modifier)]
|
|
#![feature(let_else)]
|
|
|
|
use std::cell::RefCell;
|
|
use std::io;
|
|
use std::rc::Rc;
|
|
|
|
use rustyline::validate::{
|
|
MatchingBracketValidator, ValidationContext, ValidationResult, Validator,
|
|
};
|
|
use rustyline::Editor;
|
|
use rustyline_derive::{Completer, Helper, Highlighter, Hinter};
|
|
|
|
mod ast;
|
|
mod eval;
|
|
#[allow(clippy::all)]
|
|
mod grammar;
|
|
mod prims;
|
|
#[cfg(test)]
|
|
mod tests;
|
|
mod value;
|
|
|
|
fn main() {
|
|
let args = std::env::args().collect::<Vec<_>>();
|
|
match &args[..] {
|
|
[_] => repl(),
|
|
[_, file] => run_file(file).unwrap(),
|
|
_ => panic!("To many args `{:?}`", args),
|
|
}
|
|
}
|
|
|
|
fn run_file(file: &str) -> io::Result<()> {
|
|
let src = std::fs::read_to_string(file)?;
|
|
let tree = grammar::FileParser::new().parse(&src).unwrap();
|
|
let env = Rc::new(RefCell::new(eval::default_env()));
|
|
for i in tree {
|
|
eval::eval(&i, Rc::clone(&env)).unwrap();
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
fn repl() {
|
|
let mut rl = Editor::new();
|
|
rl.set_helper(Some(InputValidator {
|
|
brackets: MatchingBracketValidator::new(),
|
|
}));
|
|
|
|
let env = Rc::new(RefCell::new(eval::default_env()));
|
|
|
|
while let Ok(line) = rl.readline("> ") {
|
|
rl.add_history_entry(&line);
|
|
|
|
let tree = grammar::TreeParser::new().parse(&line).unwrap();
|
|
// dbg!(&tree);
|
|
match eval::eval(&tree, Rc::clone(&env)) {
|
|
Ok(v) => {
|
|
// Cant use == because it will panic. This is the only
|
|
// valid comparison to trap
|
|
if !matches!(v, value::Value::Trap) {
|
|
println!("{}", v)
|
|
}
|
|
}
|
|
Err(e) => println!("! {}", e.0),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Completer, Helper, Highlighter, Hinter)]
|
|
struct InputValidator {
|
|
brackets: MatchingBracketValidator,
|
|
}
|
|
|
|
impl Validator for InputValidator {
|
|
fn validate(&self, ctx: &mut ValidationContext) -> rustyline::Result<ValidationResult> {
|
|
self.brackets.validate(ctx)
|
|
}
|
|
}
|