mute/src/main.rs
2024-05-05 09:21:45 -04:00

95 lines
2 KiB
Rust

use anyhow::Result;
use clap::{Parser, Subcommand};
use node::Node;
use rustyline::{error::ReadlineError, DefaultEditor};
mod env;
mod error;
mod evaluator;
mod macros;
mod node;
mod parser;
#[derive(Debug, Parser)]
#[clap(version, author, about)]
struct Args {
#[clap(subcommand)]
command: Command,
}
#[derive(Debug, Subcommand)]
enum Command {
Run {
#[clap(short, long)]
command: String,
},
Repl,
}
impl std::default::Default for Command {
fn default() -> Self {
Command::Repl
}
}
fn main() {
if std::env::args().len() == 1 {
repl();
return;
}
let args = Args::parse();
match args.command {
Command::Run { command } => {
let res = run(&command);
match res {
Ok(expressions) => expressions.into_iter().for_each(|expr| println!("{expr}")),
Err(err) => println!("{}", err),
}
}
Command::Repl => repl(),
}
}
fn run(command: &str) -> Result<Vec<Node>> {
let env = env::Environment::new();
let ast = parser::parse_str(command)?;
evaluator::eval(&env, ast)
}
fn repl() {
let env = env::Environment::new();
let mut rl = DefaultEditor::new().unwrap();
println!("Mute -- REPL");
loop {
let readline = rl.readline("> ");
match readline {
Ok(line) => {
rl.add_history_entry(line.as_str()).unwrap();
let ast = parser::parse_str(&line).unwrap();
let res = evaluator::eval(&env, ast);
match res {
Ok(expressions) => expressions.into_iter().for_each(|expr| println!("{expr}")),
Err(err) => println!("{}", err),
}
}
Err(ReadlineError::Interrupted) => {
continue;
}
Err(ReadlineError::Eof) => {
break;
}
Err(err) => {
println!("Error: {:?}", err);
break;
}
}
}
}