msbash 0.0.0

Bash interpreter/compiler. Will not support all the functionalities.
#![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 ast::parser::ir::*;

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 {
        // start repl
        // shell::repl::run();
        unimplemented!("start repl");
    }

    if args.len() == 1 {
        // TODO: remove default path after implem
        args.push(default_path.to_string());
        //usage();
    }

    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!(""),
    }

    /*let mut args: Vec<String> = Vec::new();
        args.push("-la".to_owned());
        let out = cmd::run(&"ls".to_string(), &args, cmd::IO::Pipe, cmd::IO::Pipe);
        let val = out.unwrap().stdout;
        let val = std::str::from_utf8(&val).unwrap();
        panic!("stop {}", val);
    */

    return Ok(());
}