mamba 0.3.6

A transpiler which converts Mamba files to Python 3 files
Documentation
use std::convert::TryFrom;

use crate::check::constrain::constraint::builder::ConstrBuilder;
use crate::check::constrain::constraint::expected::Expected;
use crate::check::constrain::generate::{Constrained, generate};
use crate::check::constrain::generate::definition::{constrain_args, id_from_var};
use crate::check::constrain::generate::env::Environment;
use crate::check::context::Context;
use crate::check::name::Name;
use crate::check::result::TypeErr;
use crate::parse::ast::{AST, Node, OptAST};

pub fn gen_expr(
    ast: &AST,
    env: &Environment,
    ctx: &Context,
    constr: &mut ConstrBuilder,
) -> Constrained {
    match &ast.node {
        Node::AnonFun { args, body } => {
            let anon_env = constrain_args(args, &env.is_def_mode(true), ctx, constr)?;
            generate(body, &anon_env, ctx, constr)?;
            Ok(env.clone())
        }
        Node::ExpressionType { expr, mutable, ty } =>
            match_id(expr, ty, *mutable, env, ctx, constr),
        Node::Id { .. } => match_id(ast, &None, false, env, ctx, constr),
        Node::Question { left, right } => {
            constr.add("question", &Expected::from(left), &Expected::none(left.pos), env);

            generate(left, env, ctx, constr)?;
            generate(right, env, ctx, constr)?;
            Ok(env.clone())
        }
        Node::Pass => if let Some(expected_ret_ty) = &env.return_type {
            constr.add("pass", &Expected::none(ast.pos), expected_ret_ty, env);
            Ok(env.clone())
        } else {
            Ok(env.clone())
        },

        _ => Err(vec![TypeErr::new(ast.pos, "Expected an expression")])
    }
}

fn match_id(ast: &AST, ty: &OptAST, mutable: bool, env: &Environment, ctx: &Context, constr: &mut ConstrBuilder) -> Constrained {
    match &ast.node {
        Node::Id { lit } => if env.is_def_mode {
            let ty = if let Some(ty) = ty { Some(Name::try_from(ty)?) } else { None };
            id_from_var(ast, &ty, &None, mutable, ctx, constr, env)
        } else if env.is_destruct_mode {
            Ok(env.remove_var(lit))
        } else if env.get_var(lit, &constr.var_mapping).is_some() {
            Ok(env.clone())
        } else {
            Err(vec![TypeErr::new(ast.pos, &format!("Undefined variable: {lit}"))])
        }
        _ => Ok(env.clone())
    }
}