use indexmap::IndexSet;
use toasty_core::stmt::{self, visit_mut};
use crate::engine::{eval, mir};
#[derive(Debug)]
pub(crate) struct Eval {
pub(crate) row_input: Option<mir::NodeId>,
pub(crate) inputs: IndexSet<mir::NodeId>,
pub(crate) body: eval::Func,
}
impl Eval {
pub(crate) fn compute(inputs: IndexSet<mir::NodeId>, body: eval::Func) -> Self {
Eval {
row_input: None,
inputs,
body,
}
}
pub(crate) fn map_over(
store: &mir::Store,
row_input: mir::NodeId,
inputs: IndexSet<mir::NodeId>,
body: eval::Func,
) -> Self {
debug_assert_eq!(body.args.len(), 1 + inputs.len());
debug_assert!(!inputs.contains(&row_input));
let mut arg_tys = vec![store[row_input].ty().clone()];
for input in &inputs {
arg_tys.push(store[input].ty().clone());
}
let ty = stmt::Type::list(body.ret.clone());
let mut map_body = body.into_expr();
visit_mut::walk_expr_scoped_mut(&mut map_body, 0, |expr, scope_depth| {
if let stmt::Expr::Arg(arg) = expr
&& arg.nesting == scope_depth
&& arg.position >= 1
{
arg.nesting += 1;
}
true
});
let expr = stmt::Expr::map(stmt::Expr::arg(0), map_body);
Eval {
row_input: Some(row_input),
inputs,
body: eval::Func::from_stmt_typed(expr, arg_tys, ty),
}
}
}
impl From<Eval> for mir::Node {
fn from(value: Eval) -> Self {
mir::Operation::Eval(value).into()
}
}