diff options
Diffstat (limited to 'rprt-engine')
| -rw-r--r-- | rprt-engine/src/evaluate.rs | 47 |
1 files changed, 40 insertions, 7 deletions
diff --git a/rprt-engine/src/evaluate.rs b/rprt-engine/src/evaluate.rs index cf60ad4..4f567fb 100644 --- a/rprt-engine/src/evaluate.rs +++ b/rprt-engine/src/evaluate.rs @@ -3,6 +3,7 @@ use crate::{ selection::{Selection, SelectionError, VectoriseError}, selection_functions::{evaluate_selection_function, SFError}, state::{EditorState, GroupedChangeError, StateChange, StateResult}, + text::Text, }; use thiserror::Error; @@ -21,6 +22,30 @@ pub enum EvaluationError { UnimplementedError(&'static str), #[error("Hook used in niladic context")] NiladicRightHook, + #[error("Text argument provided to a selection function")] + TextArgument, +} + +// Helper functions + +// Absolutely crazy that in 2026 Rust doesn't have a built-in Either type OR +// (even better) a way to do anonymous sum types! Of course it has anonymous +// product types, but big Cartesian doesn't want you to have + + +#[derive(Clone)] +enum Either<L, R> { + L(L), + R(R), +} + +fn ensure_selection( + left: Option<Either<Selection, Text>>, +) -> Result<Option<Selection>, EvaluationError> { + match left { + Some(Either::L(left)) => Ok(Some(left)), + None => Ok(None), + _ => Err(EvaluationError::TextArgument), + } } fn commit_if_needed( @@ -39,7 +64,7 @@ fn commit_if_needed( fn _eval( es: &mut EditorState, comp: Composite, - left: Option<Selection>, + left: Option<Either<Selection, Text>>, right: Option<Selection>, commit: bool, ) -> Result<StateResult, EvaluationError> { @@ -53,6 +78,7 @@ fn _eval( search_mod, result_transform, } => { + let left: Option<Selection> = ensure_selection(left)?; let sel = evaluate_selection_function(es, func, search_mod, result_transform, left, right) .map_err(EvaluationError::SelectionFunctionError)?; @@ -65,8 +91,12 @@ fn _eval( HookKind::Before => { let (f_result, mut changes) = _eval(es, *f, left.clone(), None, commit)?; changes = commit_if_needed(es, changes, commit); - let (sel, g_changes) = - _eval(es, *g, Some(f_result), right.or_else(|| left), commit)?; + let right = if right.is_some() { + Ok(right) + } else { + ensure_selection(left) + }?; + let (sel, g_changes) = _eval(es, *g, Either::L(f_result).into(), right, commit)?; let more_changes = commit_if_needed(es, g_changes, commit); changes.extend(more_changes); Ok((sel, changes)) @@ -75,8 +105,11 @@ fn _eval( if left.is_none() { return Err(EvaluationError::NiladicRightHook); } - let (g_result, mut changes) = - _eval(es, *g, right.or_else(|| left.clone()), None, commit)?; + let combi_left = match right { + Some(right) => Some(Either::L(right)), + None => left.clone(), + }; + let (g_result, mut changes) = _eval(es, *g, combi_left, None, commit)?; changes = commit_if_needed(es, changes, commit); let (sel, f_changes) = _eval(es, *f, left.clone(), Some(g_result), commit)?; let more_changes = commit_if_needed(es, f_changes, commit); @@ -87,7 +120,7 @@ fn _eval( Composite::Train2 { f, g } => { let (left, mut f_changes) = _eval(es, *f, left, right, commit)?; f_changes = commit_if_needed(es, f_changes, commit); - let (sel, g_changes) = _eval(es, *g, Some(left), None, commit)?; + let (sel, g_changes) = _eval(es, *g, Some(Either::L(left)), None, commit)?; let more_changes = commit_if_needed(es, g_changes, commit); f_changes.extend(more_changes); Ok((sel, f_changes)) @@ -97,7 +130,7 @@ fn _eval( f_changes = commit_if_needed(es, f_changes, commit); let (g_right, h_changes) = _eval(es, *h, left, right, commit)?; let h_changes = commit_if_needed(es, h_changes, commit); - let (sel, g_changes) = _eval(es, *g, Some(f_left), Some(g_right), commit)?; + let (sel, g_changes) = _eval(es, *g, Some(Either::L(f_left)), Some(g_right), commit)?; let g_changes = commit_if_needed(es, g_changes, commit); f_changes.extend(h_changes); f_changes.extend(g_changes); |
