1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
use std::collections::BTreeSet; use arret_syntax::span::Span; use arret_runtime::boxed; use crate::mir::builder::Builder; use crate::mir::error; use crate::mir::error::{Error, Result}; use crate::mir::eval_hir::EvalHirCtx; use crate::mir::ops; use crate::mir::polymorph::PolymorphAbi; use crate::mir::value; use crate::mir::value::Value; fn ideal_polymorph_abi_for_arret_fun(arret_fun: &value::ArretFun) -> PolymorphAbi { use crate::hir::destruc::poly_for_list_destruc; use crate::mir::polymorph::polymorph_abi_for_list_ty; let has_env = !arret_fun.env_values().free_values.is_empty(); let fun_expr = arret_fun.fun_expr(); let param_list_type = poly_for_list_destruc(&fun_expr.params); polymorph_abi_for_list_ty(has_env, ¶m_list_type, &fun_expr.ret_ty) } fn add_ops_categories<'a>( categories: &mut BTreeSet<ops::OpCategory>, ops: impl IntoIterator<Item = &'a ops::Op>, ) { for op in ops { categories.insert(op.kind().category()); if let ops::OpKind::Cond(cond_op) = op.kind() { add_ops_categories(categories, cond_op.true_ops.iter()); add_ops_categories(categories, cond_op.false_ops.iter()); } } } fn op_category_to_string(category: ops::OpCategory) -> &'static str { use crate::mir::ops::OpCategory; match category { OpCategory::AllocBoxed => ":alloc-boxed", OpCategory::Call => ":call", OpCategory::ConstBox => ":const-box", OpCategory::ConstCastBoxed => ":const-cast-box", OpCategory::ConstReg => ":const-reg", OpCategory::Cond => ":cond", OpCategory::MakeCallback => ":make-callback", OpCategory::MemLoad => ":mem-load", OpCategory::CastBoxed => ":cast-boxed", OpCategory::RegOp => ":reg-op", OpCategory::Ret => ":ret", OpCategory::Unreachable => ":unreachable", } } pub fn fn_op_categories( ehx: &mut EvalHirCtx, b: &mut Option<Builder>, span: Span, arg_list_value: &Value, ) -> Result<Option<Value>> { let mut iter = arg_list_value.unsized_list_iter(); let single_arg = iter.next_unchecked(b, span); let arret_fun = if let Value::ArretFun(arret_fun) = single_arg { arret_fun } else { return Err(Error::Panic(error::Panic::new( span, "argument must be an Arret function".to_owned(), ))); }; let ideal_polymorph_abi = ideal_polymorph_abi_for_arret_fun(&arret_fun); let ops_fun = ehx.ops_for_arret_fun(&arret_fun, ideal_polymorph_abi); let mut categories = BTreeSet::<ops::OpCategory>::new(); add_ops_categories(&mut categories, ops_fun.ops.iter()); let category_list = boxed::List::from_values( ehx, categories.into_iter().map(op_category_to_string), boxed::Sym::new, ); Ok(Some(category_list.into())) }