mssh 0.0.0

Mssh Simple SHell. Bash interpreter/compiler. Will not support all the functionalities.
use super::ir::*;
use super::program::Program;
use std::fmt;

impl ToString for Program {
    fn to_string(&self) -> String {
        return prog_to_string(
            &self.functions,
            &self.consts,
            &self.expr,
            &self.name_to_var,
            &self.name_to_func,
        );
    }
}

impl fmt::Display for Index {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Index::Arg(idx) => write!(f, "arg<{}>", idx),
            Index::Loc(idx) => write!(f, "loc({})", idx),
            Index::Cmd(idx) => write!(f, "cmd({})", idx),
            Index::Expr(idx) => write!(f, "expr<{}>", idx),
            Index::Udf(idx) => write!(f, "udf<{}>", idx),
            Index::Const(idx) => write!(f, "const<{}>", idx),
        }
    }
}

impl fmt::Display for IR {
    fn fmt(&self, f: &mut fmt::Formatter) -> std::fmt::Result {
        match self {
            IR::LocalAssignement(var, val) => write!(f, "loc({}) = {}", var, val),
            IR::GlobalAssignement(var, val) => write!(f, "glob({}) = {}", var, *val),
            IR::CmdCall(idx, args) => _display_callable(f, "cmd_const", *idx, args),
            IR::UdfCall(idx, args) => _display_callable(f, "udf", *idx, args),
            IR::BuiltinCall(idx, args) => _display_callable(f, "built_in", *idx, args),
        }
    }
}

fn _display_callable(f: &mut fmt::Formatter, kind: &str, idx: u16, args: &[Index]) -> fmt::Result {
    let mut res = String::new();

    for arg in args.iter() {
        let val = format!("{},", arg);
        res.push_str(&val);
    }
    res.pop();
    write!(f, "{}<{}>({})", kind, idx, res)
}

impl fmt::Display for Expr {
    fn fmt(&self, f: &mut fmt::Formatter) -> std::fmt::Result {
        let var = &self.data;
        let len = var.len();
        let mut res: Vec<u8> = Vec::with_capacity(2 * len);
        let mut idx = 0;
        while idx < len {
            let ch = var[idx];
            res.push(ch);
            idx += 1;

            if ch == GLOB_VAR_INDIC {
                let _msb = var[idx] as u16;
                let lsb = var[idx + 1];
                res.push(lsb + '0' as u8);
                idx += 2;
            } else if ch == LOCL_VAR_INDIC {
                res.push(var[idx] + '0' as u8);
                idx += 1;
            }
        }

        let res = std::str::from_utf8(&res).unwrap().to_owned();
        write!(f, "{}", res)
    }
}
impl fmt::Display for UDF {
    fn fmt(&self, f: &mut fmt::Formatter) -> std::fmt::Result {
        write!(
            f,
            "fn({},{},{:?}):\n",
            self.nbr_args,
            self.instructions.len(),
            self.default_args
        )?;
        for instruct in self.instructions.iter() {
            writeln!(f, "  {}", instruct)?;
        }
        Ok(())
    }
}

pub fn prog_to_string(
    functions: &Vec<UDF>,
    consts: &Vec<String>,
    expr: &Vec<Expr>,
    name_to_var: &NameToIndex,
    name_to_func: &NameToIndex,
) -> String {
    let mut res = String::with_capacity(1000);
    res.push_str("\n---- const : idx->value ----\n");
    for idx in 0..consts.len() {
        let val = &consts[idx as usize];
        let val = format!("{}->{}\n", idx, val);
        res.push_str(&val);
    }

    res.push_str("\n---- expressions: idx->value ----\n");
    for idx in 0..expr.len() {
        let val = &expr[idx as usize];
        let val = format!("{}->{}\n", idx, val);
        res.push_str(&val);
    }

    res.push_str("\n---- name to var: name->idx ----\n");
    let mut tmp_bfr = Vec::new();

    for (key, val) in name_to_var {
        tmp_bfr.push((val, key));
    }

    tmp_bfr.sort_by_key(|k| k.0);
    for i in 0..tmp_bfr.len() {
        let idx = tmp_bfr[i].0;
        let val = format!("{}->{}\n", tmp_bfr[i].1, idx);
        res.push_str(&val);
    }

    res.push_str("\n---- funcs: idx->name->fn(nbr_args, nbr_instructions, defaults): body ----\n");

    let mut tmp_bfr = Vec::new();

    for (key, val) in name_to_func {
        tmp_bfr.push((val, key));
    }
    tmp_bfr.sort_by_key(|k| k.0);
    for i in 0..tmp_bfr.len() {
        let idx = tmp_bfr[i].0;
        let func = &functions[*idx as usize];
        let val = format!("{}->{}->{}\n", idx, tmp_bfr[i].1, func);
        res.push_str(&val);
    }
    return res;
}