mamba 0.3.6

A transpiler which converts Mamba files to Python 3 files
Documentation
use python_parser::ast::Funcdef;

use crate::check::context::arg::generic::GenericFunctionArg;
use crate::check::context::function;
use crate::check::context::function::generic::GenericFunction;
use crate::check::name::{Empty, Name};
use crate::check::name::string_name::StringName;
use crate::common::position::Position;

pub const INIT: &str = "__init__";

pub const ADD: &str = "__add__";
pub const DIV: &str = "__truediv__";
pub const EQ: &str = "__eq__";
pub const NEQ: &str = "__ne__";
pub const FDIV: &str = "__floordiv__";
pub const GE: &str = "__gt__";
pub const GEQ: &str = "__ge__";
pub const LE: &str = "__lt__";
pub const LEQ: &str = "__le__";
pub const MOD: &str = "__mod__";
pub const MUL: &str = "__mul__";
pub const POW: &str = "__pow__";
pub const SUB: &str = "__sub__";

pub const STR: &str = "__str__";
pub const TRUTHY: &str = "__bool__";
pub const NEXT: &str = "__next__";
pub const ITER: &str = "__iter__";

pub const SUPER: &str = "super";

pub const GET_ITEM: &str = "__getitem__";

impl From<&Funcdef> for GenericFunction {
    fn from(func_def: &Funcdef) -> GenericFunction {
        GenericFunction {
            is_py_type: true,
            name: StringName::from(convert_name(&func_def.name).as_str()),
            pure: false,
            pos: Position::invisible(),
            arguments: func_def
                .parameters
                .positional_args
                .iter()
                .map(|(name, ty, expr)| GenericFunctionArg::from((name, ty, expr)))
                .collect(),
            raises: Name::empty(),
            in_class: None,
            ret_ty: func_def.return_type.as_ref().map(Name::from),
        }
    }
}

fn convert_name(name: &str) -> String {
    match name {
        INIT => String::from(function::INIT),

        ADD => String::from(function::ADD),
        DIV => String::from(function::DIV),
        EQ => String::from(function::EQ),
        FDIV => String::from(function::FDIV),
        GE => String::from(function::GE),
        GEQ => String::from(function::GEQ),
        LE => String::from(function::LE),
        LEQ => String::from(function::LEQ),
        MOD => String::from(function::MOD),
        MUL => String::from(function::MUL),
        POW => String::from(function::POW),
        SUB => String::from(function::SUB),

        TRUTHY => String::from(function::TRUTHY),

        other => String::from(other),
    }
}

#[cfg(test)]
mod test {
    use std::ops::Deref;

    use python_parser::ast::{CompoundStatement, Funcdef, Statement};

    use crate::check::context::function::generic::GenericFunction;
    use crate::check::name::{Empty, Name};
    use crate::check::name::string_name::StringName;

    fn fun_def(stmt: &Statement) -> Funcdef {
        match &stmt {
            Statement::Compound(compound) => match compound.deref() {
                CompoundStatement::Funcdef(funcdef) => funcdef.clone(),
                other => panic!("Not func def but {:?}", other),
            },
            other => panic!("Not compound statement but {:?}", other),
        }
    }

    #[test]
    fn from_py() {
        let source = "def f(a: int, b, c: Str, d: Str = 'default') -> complex: pass";
        let (_, statements) =
            python_parser::file_input(python_parser::make_strspan(&source)).expect("parse source");

        let first = statements.first().expect("non empty statements");
        let funcdef: Funcdef = fun_def(&first);
        let generic_function = GenericFunction::from(&funcdef);

        assert!(generic_function.is_py_type);
        assert_eq!(generic_function.name, StringName::from("f"));
        assert!(!generic_function.pure);
        assert_eq!(generic_function.raises, Name::empty());
        assert!(generic_function.in_class.is_none());
        assert_eq!(generic_function.ret_ty, Some(Name::from("Complex")));

        assert_eq!(generic_function.arguments[0].name, String::from("a"));
        assert_eq!(generic_function.arguments[0].ty, Some(Name::from("Int")));
        assert!(!generic_function.arguments[0].has_default);
        assert!(generic_function.arguments[0].mutable);

        assert_eq!(generic_function.arguments[1].name, String::from("b"));
        assert_eq!(generic_function.arguments[1].ty, None);
        assert!(!generic_function.arguments[1].has_default);
        assert!(generic_function.arguments[1].mutable);

        assert_eq!(generic_function.arguments[2].name, String::from("c"));
        assert_eq!(generic_function.arguments[2].ty, Some(Name::from("Str")));
        assert!(!generic_function.arguments[2].has_default);
        assert!(generic_function.arguments[2].mutable);

        assert_eq!(generic_function.arguments[3].name, String::from("d"));
        assert_eq!(generic_function.arguments[3].ty, Some(Name::from("Str")));
        assert!(generic_function.arguments[3].has_default);
        assert!(generic_function.arguments[3].mutable);
    }
}