#![macro_use]
#![allow(dead_code)]
#![allow(unused_imports)]
#![allow(unreachable_code)]
mod compiler;
mod libc;
mod parser;
mod runtime;
mod shell;
mod utils;
use runtime::eval::Evaluator;
use crate::utils::parse_file;
use crate::shell::cmd;
fn usage() -> &'static str {
let txt = "Usage: sbash [COMMAND] [SCRIPT PATH]
Commands:
'' start a repl if no command is provided
show <PATH> display the different representations of the script located at PATH
compile <PATH> <DST> compile the script located at PATH and save it to DST
run <PATH> compile then evaluate the script located at PATH
";
eprintln!("{}", txt);
std::process::exit(1);
}
fn main() -> Result<(), String> {
let mut args: Vec<String> = std::env::args().skip(1).collect();
let default_path = "tests/inputs/runtime/cmd_eval.sh";
if args.len() == 0 {
unimplemented!("start repl");
}
if args.len() == 1 {
args.push(default_path.to_string());
}
let commands = std::collections::HashSet::from(["show", "compile", "run", "identify"]);
let cmd = args[0].as_str();
if !commands.contains(cmd) {
eprintln!("unknown command");
usage();
}
let path = &args[1];
let tokens = parse_file(path).unwrap();
let ast = parser::parse(&tokens).unwrap();
let program = compiler::compile(&ast);
match cmd {
"show" => {
println!("--------- AST --------");
ast.print();
println!("\n--------- Program IR--------");
program.print();
}
"run" => {
let mut evaluator = Evaluator::new(program);
let _ = evaluator.eval();
}
"compile" => {
unimplemented!("serialize compiled program")
}
"identify" => {
shell::repl::tty::identify_key_code();
}
_ => unreachable!(""),
}
return Ok(());
}