mamba 0.3.6

A transpiler which converts Mamba files to Python 3 files
Documentation
use std::collections::BTreeMap;

use itertools::Itertools;

use crate::check::name::Name;
use crate::generate::ast::node::Core;
use crate::generate::GenArguments;

#[derive(Clone, Debug)]
pub struct State {
    pub interface: bool,

    pub tup: usize,
    pub expand_ty: bool,
    pub def_as_fun_arg: bool,

    pub tup_lit: bool,
    pub annotate: bool,

    pub is_last_must_be_ret: bool,
    pub must_assign_to: Option<(Core, Option<Name>)>,
    pub is_remove_last_ret: bool,
}

impl From<&GenArguments> for State {
    fn from(gen_arguments: &GenArguments) -> Self {
        State { annotate: gen_arguments.annotate, ..State::new() }
    }
}

impl State {
    pub fn new() -> State {
        State {
            tup: 1,
            interface: false,
            expand_ty: true,
            def_as_fun_arg: false,
            tup_lit: false,
            is_last_must_be_ret: false,
            is_remove_last_ret: false,
            must_assign_to: None,
            annotate: false,
        }
    }

    pub fn in_tup(&self, tup: usize) -> State {
        State { tup, ..self.clone() }
    }

    pub fn tuple_literal(&self) -> State {
        State { tup_lit: true, ..self.clone() }
    }

    pub fn in_interface(&self, interface: bool) -> State {
        State { interface, ..self.clone() }
    }

    pub fn expand_ty(&self, expand_ty: bool) -> State {
        State { expand_ty, ..self.clone() }
    }

    pub fn remove_ret(&self, remove_ret: bool) -> State {
        State { is_remove_last_ret: remove_ret, ..self.clone() }
    }

    pub fn is_last_must_be_ret(&self, last_return: bool) -> State { State { is_last_must_be_ret: last_return, ..self.clone() } }

    pub fn def_as_fun_arg(&self, def_as_fun_arg: bool) -> State {
        State { def_as_fun_arg, ..self.clone() }
    }

    pub fn must_assign_to(&self, must_assign_to: Option<&Core>, name: Option<Name>) -> State {
        if let Some(must_assign_to) = must_assign_to {
            State { must_assign_to: Some((must_assign_to.clone(), name)), ..self.clone() }
        } else {
            State { must_assign_to: None, ..self.clone() }
        }
    }
}

pub struct Imports {
    imports: Vec<Core>,
    from_imports: BTreeMap<String, Core>,
}

impl Default for Imports {
    fn default() -> Self {
        Self::new()
    }
}

impl Imports {
    pub fn new() -> Imports {
        Imports { imports: vec![], from_imports: BTreeMap::new() }
    }

    pub fn add_import(&mut self, import: &str) {
        let import = Core::Import {
            from: None,
            import: vec![Core::Id { lit: String::from(import) }],
            alias: vec![],
        };
        if !self.imports.contains(&import) {
            self.imports.push(import);
        }
    }

    pub fn add_from_import(&mut self, from: &str, import: &str) {
        if let Some(Core::Import { import: imports, alias, .. }) =
            self.from_imports.get(&String::from(from))
        {
            let new = Core::Id { lit: String::from(import) };
            let imports: Vec<Core> = if !imports.contains(&new) {
                imports.clone().into_iter().chain(vec![new]).collect()
            } else {
                imports.to_vec()
            };

            let import = Core::Import {
                from: Some(Box::from(Core::Id { lit: String::from(from) })),
                import: imports
                    .iter()
                    .sorted_by_key(|c| match c {
                        Core::Id { lit } => lit.clone(),
                        _ => String::from(""),
                    })
                    .cloned()
                    .collect(),
                alias: alias.clone(),
            };
            self.from_imports.insert(String::from(from), import);
            return;
        }

        let import = Core::Import {
            from: Some(Box::from(Core::Id { lit: String::from(from) })),
            import: vec![Core::Id { lit: String::from(import) }],
            alias: vec![],
        };
        self.from_imports.insert(String::from(from), import);
    }

    pub fn is_empty(&self) -> bool {
        self.imports.is_empty() && self.from_imports.is_empty()
    }

    pub fn imports(&self) -> Vec<Core> {
        let mut statements = self.imports.clone();
        statements.append(&mut self.from_imports.clone().into_values().collect());
        statements
    }
}