aboutsummaryrefslogtreecommitdiff
path: root/rprt-engine
diff options
context:
space:
mode:
authortslil <tslil@posteo.de>2025-10-21 20:36:01 +0100
committertslil <tslil@posteo.de>2025-10-21 21:54:56 +0100
commit9f3e21628231f3fa91ab8ff45872a76e7e11fcc4 (patch)
treedd631d501a4f5eba47dac439879a9e8628556468 /rprt-engine
parentcaf3cbdd94ec8341f3233bb31c04c72f99502ed9 (diff)
Having a time with passing functions around, really feels like i'm fighting the language
Diffstat (limited to 'rprt-engine')
-rw-r--r--rprt-engine/Cargo.toml2
-rw-r--r--rprt-engine/src/lib.rs1
-rw-r--r--rprt-engine/src/selection.rs98
-rw-r--r--rprt-engine/src/selection_function.rs43
-rw-r--r--rprt-engine/src/state.rs2
5 files changed, 107 insertions, 39 deletions
diff --git a/rprt-engine/Cargo.toml b/rprt-engine/Cargo.toml
index 179c095..e0b5d3e 100644
--- a/rprt-engine/Cargo.toml
+++ b/rprt-engine/Cargo.toml
@@ -6,9 +6,9 @@ license.workspace = true
authors.workspace = true
[dependencies]
-either = "1.15.0"
logos = "0.15.1"
regex = "1.12.2"
+thiserror = "2.0.17"
[[bin]]
name = "explainer"
diff --git a/rprt-engine/src/lib.rs b/rprt-engine/src/lib.rs
index 0ae9d2d..3eda2e4 100644
--- a/rprt-engine/src/lib.rs
+++ b/rprt-engine/src/lib.rs
@@ -5,5 +5,6 @@ pub mod expression;
pub mod monad;
pub mod parser;
pub mod selection;
+pub mod selection_function;
pub mod state;
pub mod token;
diff --git a/rprt-engine/src/selection.rs b/rprt-engine/src/selection.rs
index 9e59ba5..c15512d 100644
--- a/rprt-engine/src/selection.rs
+++ b/rprt-engine/src/selection.rs
@@ -1,8 +1,8 @@
use crate::buffer::BufferID;
-use either::Either;
use std::collections::HashMap;
use std::collections::HashSet;
use std::fmt::Display;
+use thiserror::Error;
#[derive(Debug, Eq, PartialEq, PartialOrd, Ord, Clone, Copy)]
pub enum Rank {
@@ -23,21 +23,12 @@ impl Display for Rank {
}
}
-#[derive(Debug)]
+#[derive(Error, Debug)]
pub enum SelectionError {
+ #[error("Cannnot change selection of {from} to {to}")]
InvalidPromotion { from: Rank, to: Rank },
}
-impl std::fmt::Display for SelectionError {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- match self {
- SelectionError::InvalidPromotion { from, to } => {
- write!(f, "Cannot change selection of {} to {}", from, to)
- }
- }
- }
-}
-
#[derive(Debug, Clone)]
pub struct Interval {
pub start: usize,
@@ -70,6 +61,29 @@ pub enum Selection {
},
}
+// rust is stupid and i have to make a wrapper class and worse still _other
+// people_ have to deal with my wrapper class!
+#[derive(Error, Debug)]
+pub enum VectoriseError<E>
+where
+ E: std::error::Error + 'static,
+{
+ #[error("An error occurred during processing: {0}")]
+ ProcessingError(E),
+
+ #[error("A selection error occurred: {0}")]
+ SelectionError(SelectionError),
+}
+
+impl<E> From<E> for VectoriseError<E>
+where
+ E: std::error::Error + 'static,
+{
+ fn from(e: E) -> Self {
+ VectoriseError::ProcessingError(e)
+ }
+}
+
impl Selection {
pub fn empty() -> Self {
Self::MultiRanges {
@@ -257,32 +271,42 @@ impl Selection {
}
}
- pub fn vectorise<E>(
- &self,
- fn_rank_zero: &impl Fn(&BufferID, &usize) -> Result<Self, E>,
- fn_rank_one: &impl Fn(&BufferID, &Interval) -> Result<Self, E>,
- ) -> Result<Self, Either<E, SelectionError>> {
- let do_rank_one = |b: &usize, rs: &Vec<Interval>| {
- rs.iter()
- .map(|int| fn_rank_one(b, int).map_err(Either::Left))
- .collect::<Result<_, _>>()
- };
+ pub fn vectorise<S, E>(
+ fn_rank_zero: impl Fn(&S, &BufferID, usize) -> Result<Selection, E> + 'static,
+ fn_rank_one: impl Fn(&S, &BufferID, &Interval) -> Result<Selection, E> + 'static,
+ ) -> impl Fn(&S, &Selection) -> Result<Selection, VectoriseError<E>>
+ where
+ E: std::error::Error + 'static,
+ {
+ // look at this mess!
+ use VectoriseError::{ProcessingError, SelectionError};
+ move |state: &S, selection: &Selection| {
+ let do_rank_one = |b: &usize, rs: &Vec<Interval>| {
+ rs.iter()
+ .map(|int| fn_rank_one(state, b, int).map_err(ProcessingError))
+ .collect::<Result<_, _>>()
+ };
- match self {
- Self::Position { buffer, pos } => fn_rank_zero(buffer, pos).map_err(Either::Left),
- Self::Range { buffer, interval } => fn_rank_one(buffer, interval).map_err(Either::Left),
- Self::Ranges { buffer, ranges } => {
- let results = do_rank_one(buffer, ranges)?;
- Self::union(results).map_err(Either::Right)
- }
- Self::MultiRanges { multi_ranges } => {
- let all_ok: Vec<Vec<Self>> = multi_ranges
- .iter()
- .map(|(buffer, ranges)| do_rank_one(buffer, ranges))
- .collect::<Result<_, _>>()?;
- // It would seem that Rust has no built in monadic flatten, or in general cannot lift things to operate on Result... :(
- let results: Vec<Self> = all_ok.into_iter().flatten().collect();
- Self::union(results).map_err(Either::Right)
+ match selection {
+ Self::Position { buffer, pos } => {
+ fn_rank_zero(state, buffer, *pos).map_err(ProcessingError)
+ }
+ Self::Range { buffer, interval } => {
+ fn_rank_one(state, buffer, interval).map_err(VectoriseError::ProcessingError)
+ }
+ Self::Ranges { buffer, ranges } => {
+ let results = do_rank_one(buffer, ranges)?;
+ Self::union(results).map_err(SelectionError)
+ }
+ Self::MultiRanges { multi_ranges } => {
+ let all_ok: Vec<Vec<Self>> = multi_ranges
+ .iter()
+ .map(|(buffer, ranges)| do_rank_one(buffer, ranges))
+ .collect::<Result<_, _>>()?;
+ // It would seem that Rust has no built in monadic flatten, or in general cannot lift things to operate on Result... :(
+ let results: Vec<Self> = all_ok.into_iter().flatten().collect();
+ Self::union(results).map_err(SelectionError)
+ }
}
}
}
diff --git a/rprt-engine/src/selection_function.rs b/rprt-engine/src/selection_function.rs
new file mode 100644
index 0000000..6f05650
--- /dev/null
+++ b/rprt-engine/src/selection_function.rs
@@ -0,0 +1,43 @@
+use crate::buffer::BufferID;
+use crate::selection::{Interval, Selection, VectoriseError};
+use crate::state::EditorState;
+use thiserror::Error;
+
+#[derive(Error, Debug)]
+pub enum SFError {}
+
+struct SFComponents {
+ niladic: Box<dyn Fn(&EditorState) -> Result<Selection, SFError>>,
+ monadic_rank0: Box<dyn Fn(&EditorState, &BufferID, usize) -> Result<Selection, SFError>>,
+ monadic_rank1: Box<dyn Fn(&EditorState, &BufferID, &Interval) -> Result<Selection, SFError>>,
+ dyadic: Option<Box<dyn Fn(&EditorState, &Selection, &Selection) -> Result<Selection, SFError>>>,
+}
+
+pub struct SelectionFunction<E> {
+ niladic: Box<dyn Fn(&EditorState) -> Result<Selection, E>>,
+ monadic: Box<dyn Fn(&EditorState, &Selection) -> Result<Selection, E>>,
+ dyadic: Option<Box<dyn Fn(&EditorState, &Selection, &Selection) -> Result<Selection, E>>>,
+}
+
+impl From<SFComponents> for SelectionFunction<VectoriseError<SFError>> {
+ fn from(sfc: SFComponents) -> Self {
+ let dyadic: Option<Box<dyn Fn(&EditorState, &Selection, &Selection) -> _>> =
+ if let Some(func) = sfc.dyadic {
+ Some(Box::new(
+ move |editor_state: &EditorState, left: &Selection, right: &Selection| {
+ (func)(editor_state, left, right).map_err(VectoriseError::ProcessingError)
+ },
+ ))
+ } else {
+ None
+ };
+
+ Self {
+ niladic: Box::new(move |editor_state: &EditorState| {
+ (sfc.niladic)(editor_state).map_err(VectoriseError::ProcessingError)
+ }),
+ monadic: Box::new(Selection::vectorise(sfc.monadic_rank0, sfc.monadic_rank1)),
+ dyadic: dyadic,
+ }
+ }
+}
diff --git a/rprt-engine/src/state.rs b/rprt-engine/src/state.rs
index 9487d6d..bc6fbb6 100644
--- a/rprt-engine/src/state.rs
+++ b/rprt-engine/src/state.rs
@@ -21,7 +21,7 @@ pub enum StateChange {
},
}
-#[derive(Debug, Clone, PartialEq, Eq)]
+#[derive(Debug, Clone)]
pub enum GroupedChangeError {
OverlappingChanges {
buffer: BufferID,