aboutsummaryrefslogtreecommitdiff
path: root/rprt-engine/src/evaluate.rs
diff options
context:
space:
mode:
Diffstat (limited to 'rprt-engine/src/evaluate.rs')
-rw-r--r--rprt-engine/src/evaluate.rs48
1 files changed, 39 insertions, 9 deletions
diff --git a/rprt-engine/src/evaluate.rs b/rprt-engine/src/evaluate.rs
index a139aa3..cf60ad4 100644
--- a/rprt-engine/src/evaluate.rs
+++ b/rprt-engine/src/evaluate.rs
@@ -1,5 +1,5 @@
use crate::{
- expression::Composite,
+ expression::{Composite, HookKind},
selection::{Selection, SelectionError, VectoriseError},
selection_functions::{evaluate_selection_function, SFError},
state::{EditorState, GroupedChangeError, StateChange, StateResult},
@@ -19,6 +19,8 @@ pub enum EvaluationError {
IROApplication,
#[error("Not yet implemented {0}")]
UnimplementedError(&'static str),
+ #[error("Hook used in niladic context")]
+ NiladicRightHook,
}
fn commit_if_needed(
@@ -34,7 +36,7 @@ fn commit_if_needed(
}
}
-pub fn evaluate(
+fn _eval(
es: &mut EditorState,
comp: Composite,
left: Option<Selection>,
@@ -59,21 +61,43 @@ pub fn evaluate(
Composite::TextFunction { func, swapped } => {
Err(EvaluationError::UnimplementedError("text function"))
}
- Composite::Hook { kind, left, right } => Err(EvaluationError::UnimplementedError("hook")),
+ Composite::Hook { kind, f, g } => match kind {
+ 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 more_changes = commit_if_needed(es, g_changes, commit);
+ changes.extend(more_changes);
+ Ok((sel, changes))
+ }
+ HookKind::After => {
+ if left.is_none() {
+ return Err(EvaluationError::NiladicRightHook);
+ }
+ let (g_result, mut changes) =
+ _eval(es, *g, right.or_else(|| left.clone()), 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);
+ changes.extend(more_changes);
+ Ok((sel, changes))
+ }
+ },
Composite::Train2 { f, g } => {
- let (left, mut f_changes) = evaluate(es, *f, left, right, commit)?;
+ let (left, mut f_changes) = _eval(es, *f, left, right, commit)?;
f_changes = commit_if_needed(es, f_changes, commit);
- let (sel, g_changes) = evaluate(es, *g, Some(left), None, commit)?;
+ let (sel, g_changes) = _eval(es, *g, Some(left), None, commit)?;
let more_changes = commit_if_needed(es, g_changes, commit);
f_changes.extend(more_changes);
Ok((sel, f_changes))
}
Composite::Train3 { f, g, h } => {
- let (f_left, mut f_changes) = evaluate(es, *f, left.clone(), right.clone(), commit)?;
+ let (f_left, mut f_changes) = _eval(es, *f, left.clone(), right.clone(), commit)?;
f_changes = commit_if_needed(es, f_changes, commit);
- let (g_right, h_changes) = evaluate(es, *h, left, right, 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) = evaluate(es, *g, Some(f_left), Some(g_right), commit)?;
+ let (sel, g_changes) = _eval(es, *g, Some(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);
@@ -82,7 +106,7 @@ pub fn evaluate(
Composite::Group { operations } => {
let results: Vec<(Selection, Vec<StateChange>)> = operations
.into_iter()
- .map(|op| evaluate(es, op, left.clone(), right.clone(), commit))
+ .map(|op| _eval(es, op, left.clone(), right.clone(), commit))
.collect::<Result<_, _>>()?;
let (selections, arms) = results.into_iter().unzip();
@@ -100,3 +124,9 @@ pub fn evaluate(
}
}
}
+
+pub fn evaluate(es: &mut EditorState, comp: Composite) -> Result<Selection, EvaluationError> {
+ let (sel, changes) = _eval(es, comp, None, None, true)?;
+ es.commit_changes(changes);
+ Ok(sel)
+}