mamba 0.3.6

A transpiler which converts Mamba files to Python 3 files
Documentation
use crate::{ASTTy, Context};
use crate::check::ast::NodeTy;
use crate::generate::ast::node::Core;
use crate::generate::convert::convert_node;
use crate::generate::convert::state::{Imports, State};
use crate::generate::name::ToPy;
use crate::generate::result::{GenResult, UnimplementedErr};

pub fn convert_handle(ast: &ASTTy, imp: &mut Imports, state: &State, ctx: &Context) -> GenResult {
    Ok(match &ast.node {
        NodeTy::Raise { error } => Core::Raise { error: Box::from(convert_node(error, imp, state, ctx)?) },

        NodeTy::Handle { expr_or_stmt, cases } => {
            let (var, ty) = if let NodeTy::VariableDef { var, ty, .. } = &expr_or_stmt.node {
                let ty = ty.as_ref().map(|ty| ty.to_py(imp)).map(Box::from);
                (Some(Box::from(convert_node(var, imp, state, ctx)?)), ty)
            } else {
                (None, None)
            };

            let assign_state = state.must_assign_to(var.as_deref(), expr_or_stmt.ty.clone());
            Core::TryExcept {
                setup: var.map(|var| Box::from(Core::VarDef { var, ty, expr: None })),
                attempt: Box::from(convert_node(&expr_or_stmt.clone(), imp, state, ctx)?),
                except: {
                    let mut except = Vec::new();
                    for case in cases {
                        let (cond, body) = match &case.node {
                            NodeTy::Case { cond, body } => (cond, body),
                            other => {
                                let msg = format!("Expected case, was {other:?}");
                                return Err(Box::from(UnimplementedErr::new(case, &msg)));
                            }
                        };

                        match &cond.node {
                            NodeTy::ExpressionType { expr, ty, .. } => {
                                let expr = Box::from(convert_node(expr, imp, state, ctx)?);
                                let class = Box::from(ty.as_ref()
                                    .map_or_else(|| panic!("handle case must have class"), |ty| ty.to_py(imp)));
                                let body = Box::from(convert_node(body, imp, &assign_state, ctx)?);

                                except.push(if *expr == Core::UnderScore {
                                    Core::Except { class, body }
                                } else {
                                    Core::ExceptId { id: expr, class, body }
                                });
                            }
                            other => {
                                let msg = format!("Expected id type, was {other:?}");
                                return Err(Box::from(UnimplementedErr::new(case, &msg)));
                            }
                        };
                    }
                    except
                },
            }
        }
        other => {
            let msg = format!("Expected handle, was {other:?}");
            return Err(Box::from(UnimplementedErr::new(ast, &msg)));
        }
    })
}