use crate::{ expression::Composite, selection::{Selection, VectoriseError}, selection_functions::{evaluate_selection_function, SFError}, state::{EditorState, StateResult}, }; use thiserror::Error; #[derive(Error, Debug)] pub enum EvaluationError { #[error("{0}")] SelectionFunctionError(VectoriseError), #[error("Invalid right-only application")] IROApplication, #[error("Not yet implemented {0}")] UnimplementedError(&'static str), } pub fn evaluate( es: &EditorState, comp: Composite, left: Option, right: Option, ) -> Result { if left.is_none() && right.is_some() { return Err(EvaluationError::IROApplication); }; match comp { Composite::SelectionFunction { func, search_mod, result_transform, } => { let sel = evaluate_selection_function(es, func, search_mod, result_transform, left, right) .map_err(EvaluationError::SelectionFunctionError)?; Ok((sel, Vec::new())) } Composite::TextFunction { func, swapped } => { Err(EvaluationError::UnimplementedError("text function")) } Composite::Hook { kind, left, right } => Err(EvaluationError::UnimplementedError("hook")), Composite::Train2 { f, g } => { let (left, mut state) = evaluate(es, *f, left, right)?; let (sel, more_state) = evaluate(es, *g, Some(left), None)?; state.extend(more_state); Ok((sel, state)) } Composite::Train3 { f, g, h } => { let (f_left, mut f_state) = evaluate(es, *f, left.clone(), right.clone())?; let (g_right, h_state) = evaluate(es, *h, left, right)?; let (sel, g_state) = evaluate(es, *g, Some(f_left), Some(g_right))?; f_state.extend(h_state); f_state.extend(g_state); Ok((sel, f_state)) } Composite::Group { operations } => { // TODO: does rust have some monadic failure map thing on first failure? let mut selections = Vec::new(); let mut states = Vec::new(); for f in operations { let (sel, state) = evaluate(es, f, left.clone(), right.clone())?; selections.extend(sel); states.extend(state); } } } }