diff options
| author | tslil <tslil@posteo.de> | 2026-03-21 08:49:35 +0000 |
|---|---|---|
| committer | tslil <tslil@posteo.de> | 2026-03-21 17:26:50 +0000 |
| commit | c22cc3b348bdcb446fb0e44070da36fdf6b05800 (patch) | |
| tree | 81371ff735529e7b2a5b1727be9c8b06123609e6 /rprt-engine | |
| parent | 5a5da7bc299bee12072e421d1936554690e34dd6 (diff) | |
big rework to support evaluation of selection functions, WiP
Diffstat (limited to 'rprt-engine')
| -rw-r--r-- | rprt-engine/src/evaluate.rs | 43 | ||||
| -rw-r--r-- | rprt-engine/src/lib.rs | 1 | ||||
| -rw-r--r-- | rprt-engine/src/monad.rs | 20 | ||||
| -rw-r--r-- | rprt-engine/src/parser.rs | 3 | ||||
| -rw-r--r-- | rprt-engine/src/selection_functions/function_character.rs | 31 | ||||
| -rw-r--r-- | rprt-engine/src/selection_functions/function_empty.rs | 6 | ||||
| -rw-r--r-- | rprt-engine/src/selection_functions/function_end.rs | 32 | ||||
| -rw-r--r-- | rprt-engine/src/selection_functions/mod.rs | 64 | ||||
| -rw-r--r-- | rprt-engine/src/selection_functions/result_transformation.rs | 18 | ||||
| -rw-r--r-- | rprt-engine/src/selection_functions/types.rs | 50 | ||||
| -rw-r--r-- | rprt-engine/src/state.rs | 8 |
11 files changed, 210 insertions, 66 deletions
diff --git a/rprt-engine/src/evaluate.rs b/rprt-engine/src/evaluate.rs new file mode 100644 index 0000000..f6fee8a --- /dev/null +++ b/rprt-engine/src/evaluate.rs @@ -0,0 +1,43 @@ +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<SFError>), + #[error("Not yet implemented {0}")] + UnimplementedError(&'static str), +} + +pub fn evaluate( + es: &EditorState, + comp: Composite, + left: Option<Selection>, + right: Option<Selection>, +) -> Result<StateResult, EvaluationError> { + 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 } => Err(EvaluationError::UnimplementedError("train2")), + Composite::Train3 { f, g, h } => Err(EvaluationError::UnimplementedError("train3")), + Composite::Group { operations } => Err(EvaluationError::UnimplementedError("group")), + } +} diff --git a/rprt-engine/src/lib.rs b/rprt-engine/src/lib.rs index 8886578..6f552bd 100644 --- a/rprt-engine/src/lib.rs +++ b/rprt-engine/src/lib.rs @@ -1,4 +1,5 @@ pub mod buffer; +pub mod evaluate; pub mod expression; pub mod monad; pub mod parser; diff --git a/rprt-engine/src/monad.rs b/rprt-engine/src/monad.rs index 34ff46b..ac35722 100644 --- a/rprt-engine/src/monad.rs +++ b/rprt-engine/src/monad.rs @@ -1,6 +1,6 @@ use crate::{ selection::{Selection, SelectionError}, - state::{EditorState, EvaluationResult, GroupedChangeError}, + state::{EditorState, GroupedChangeError, StateResult}, }; pub enum EvaluationStrategy { @@ -9,33 +9,33 @@ pub enum EvaluationStrategy { } #[derive(Debug)] -pub enum EvaluationError { +pub enum MonadError { Selection(SelectionError), GroupedChange(GroupedChangeError), } -impl From<SelectionError> for EvaluationError { +impl From<SelectionError> for MonadError { fn from(err: SelectionError) -> Self { - EvaluationError::Selection(err) + MonadError::Selection(err) } } -impl From<GroupedChangeError> for EvaluationError { +impl From<GroupedChangeError> for MonadError { fn from(err: GroupedChangeError) -> Self { - EvaluationError::GroupedChange(err) + MonadError::GroupedChange(err) } } pub struct EditorStateMonad { - func: Box<dyn Fn(&EditorState) -> EvaluationResult>, + func: Box<dyn Fn(&EditorState) -> StateResult>, } impl EditorStateMonad { - pub fn new(f: impl Fn(&EditorState) -> EvaluationResult + 'static) -> Self { + pub fn new(f: impl Fn(&EditorState) -> StateResult + 'static) -> Self { Self { func: Box::new(f) } } - pub fn run(&self, state: &EditorState) -> EvaluationResult { + pub fn run(&self, state: &EditorState) -> StateResult { (self.func)(state) } @@ -43,7 +43,7 @@ impl EditorStateMonad { monads: Vec<EditorStateMonad>, strategy: EvaluationStrategy, state: &mut EditorState, - ) -> Result<Selection, EvaluationError> { + ) -> Result<Selection, MonadError> { match strategy { EvaluationStrategy::Sequential => { let mut last_selection = Selection::empty(); diff --git a/rprt-engine/src/parser.rs b/rprt-engine/src/parser.rs index 3353dff..7b68473 100644 --- a/rprt-engine/src/parser.rs +++ b/rprt-engine/src/parser.rs @@ -1,5 +1,4 @@ -use crate::expression::*; -use crate::token::*; +use crate::{expression::*, token::*}; #[derive(Debug, Clone)] pub enum ParseError { diff --git a/rprt-engine/src/selection_functions/function_character.rs b/rprt-engine/src/selection_functions/function_character.rs index 0d0699f..94c0963 100644 --- a/rprt-engine/src/selection_functions/function_character.rs +++ b/rprt-engine/src/selection_functions/function_character.rs @@ -1,9 +1,12 @@ -use crate::selection::Selection; -use crate::selection_function_param; -use crate::selection_functions::types::{get_buffer, SFArguments, SFError, SFResult}; -use crate::state::EditorState; +use crate::{ + dispatch_selection_function, + selection::Selection, + selection_function, + selection_functions::types::{get_buffer, SFArguments, SFError, SFResult}, + state::EditorState, +}; -selection_function_param! { +selection_function! { name: character, param_type: usize, niladic: |(param, es): (usize, &EditorState)| { @@ -19,7 +22,7 @@ selection_function_param! { ) } -selection_function_param!( +selection_function!( name: sequential_character, param_type: usize, niladic: |_| Err(SFError::NoNiladicForm(";n").into()), @@ -33,7 +36,7 @@ selection_function_param!( } ); -selection_function_param!( +selection_function!( name: reverse_character, param_type: usize, niladic: |(param, es): (usize, &EditorState)| { @@ -53,7 +56,7 @@ selection_function_param!( ) ); -selection_function_param!( +selection_function!( name: sequential_reverse_character, param_type: usize, niladic: |_| Err(SFError::NoNiladicForm(";'n").into()), @@ -65,7 +68,7 @@ selection_function_param!( } ); -selection_function_param!( +selection_function!( name: reverse_sequential_character, param_type: usize, niladic: |_| Err(SFError::NoNiladicForm("';n").into()), @@ -76,3 +79,13 @@ selection_function_param!( Ok(Selection::Position {buffer_id, pos: if *param<int.start {int.start - *param} else {0}}) } ); + +dispatch_selection_function!( + name: selection_function_character, + param_type: usize, + base: character, + sequential: sequential_character, + reverse: reverse_character, + sequential_reverse: sequential_reverse_character, + reverse_sequential: reverse_sequential_character, +); diff --git a/rprt-engine/src/selection_functions/function_empty.rs b/rprt-engine/src/selection_functions/function_empty.rs index a817dcf..bf0a45c 100644 --- a/rprt-engine/src/selection_functions/function_empty.rs +++ b/rprt-engine/src/selection_functions/function_empty.rs @@ -1,5 +1,7 @@ -use crate::selection::Selection; -use crate::selection_functions::types::{SFArguments, SFResult}; +use crate::{ + selection::Selection, + selection_functions::types::{SFArguments, SFResult}, +}; pub fn empty_sequential(_: SFArguments) -> SFResult { Ok(Selection::empty()) diff --git a/rprt-engine/src/selection_functions/function_end.rs b/rprt-engine/src/selection_functions/function_end.rs index 3f18fd3..cec7c90 100644 --- a/rprt-engine/src/selection_functions/function_end.rs +++ b/rprt-engine/src/selection_functions/function_end.rs @@ -1,11 +1,15 @@ -use crate::selection::Selection; -use crate::selection_function; -use crate::selection_functions::types::{get_buffer, SFArguments, SFError, SFResult}; -use crate::state::EditorState; +use crate::{ + dispatch_selection_function, + selection::Selection, + selection_function, + selection_functions::types::{get_buffer, SFArguments, SFError, SFResult}, + state::EditorState, +}; selection_function! { name: end, - niladic: |es: &EditorState| { + param_type: (), + niladic: |(_, es): ((), &EditorState)| { let buf = get_buffer(es, es.current_buffer_id)?; Ok(Selection::Position { buffer_id: es.current_buffer_id, @@ -18,7 +22,8 @@ selection_function! { selection_function! { name: reverse_end, - niladic: |es: &EditorState| { + param_type: (), + niladic: |(_, es): ((), &EditorState)| { Ok(Selection::Position { buffer_id: es.current_buffer_id, pos: 0, @@ -30,9 +35,10 @@ selection_function! { selection_function! { name: sequential_end, + param_type: (), niladic: |_| Err(SFError::NoNiladicForm(";$").into()), monadic_rank0: |_, buffer_id, pos| Ok(Selection::Position { buffer_id, pos }), - monadic_rank1: |es, buffer_id, _| { + monadic_rank1: |(_, es), buffer_id, _| { let buf = get_buffer(es, buffer_id)?; Ok(Selection::Position { buffer_id, pos: buf.max_pos() }) } @@ -40,6 +46,7 @@ selection_function! { selection_function! { name: sequential_reverse_end, + param_type: (), niladic: |_| Err(SFError::NoNiladicForm(";'$").into()), monadic_rank0: |_, buffer_id, pos| { Ok(Selection::Position { buffer_id, pos }) @@ -54,6 +61,7 @@ selection_function! { selection_function! { name: reverse_sequential_end, + param_type: (), niladic: |_| Err(SFError::NoNiladicForm("';$").into()), monadic_rank0: |_, buffer_id, pos| { Ok(Selection::Position { buffer_id, pos }) @@ -65,3 +73,13 @@ selection_function! { }) } } + +dispatch_selection_function!( + name: selection_function_end, + param_type: (), + base: end, + sequential: sequential_end, + reverse: reverse_end, + sequential_reverse: sequential_reverse_end, + reverse_sequential: reverse_sequential_end, +); diff --git a/rprt-engine/src/selection_functions/mod.rs b/rprt-engine/src/selection_functions/mod.rs index 3f64be4..b753200 100644 --- a/rprt-engine/src/selection_functions/mod.rs +++ b/rprt-engine/src/selection_functions/mod.rs @@ -1,5 +1,59 @@ -pub mod function_character; -pub mod function_empty; -pub mod function_end; -pub mod result_transformation; -pub mod types; +use crate::{ + expression::{BuiltinSelectionFn, ResultTransform, SearchModifier}, + selection::Selection, + selection_functions::{ + function_character::selection_function_character, + function_end::selection_function_end, + result_transformation::{complement_transform, conditional_transform}, + types::SFArguments, + }, + state::EditorState, +}; + +mod function_character; +mod function_empty; +mod function_end; +mod result_transformation; +mod types; + +pub use crate::selection_functions::types::{SFError, SFResult}; + +pub fn evaluate_selection_function( + es: &EditorState, + sf: BuiltinSelectionFn, + search_mod: Option<SearchModifier>, + result_transform: Option<ResultTransform>, + left: Option<Selection>, + right: Option<Selection>, +) -> SFResult { + let sf_args = match (left, right) { + (None, None) => Ok(SFArguments::Niladic { es }), + (Some(left), None) => Ok(SFArguments::Monadic { es, left }), + (Some(left), Some(right)) => Ok(SFArguments::Dyadic { es, left, right }), + _ => Err(SFError::NoLeftArgument), + }?; + let res = match sf { + BuiltinSelectionFn::CharOffset(off) => { + selection_function_character(off, &sf_args, search_mod) + } + BuiltinSelectionFn::EndOfBuffer => selection_function_end((), &sf_args, search_mod), + x => Err(SFError::NotImplemented(x).into()), + }?; + + if let Some(result_transform) = result_transform { + match result_transform { + ResultTransform::Complement => complement_transform(es, res), + ResultTransform::Conditional => conditional_transform(res, &sf_args), + ResultTransform::ConditionalComplement => { + let res = complement_transform(es, res)?; + conditional_transform(res, &sf_args) + } + ResultTransform::ComplementConditional => { + let res = conditional_transform(res, &sf_args)?; + complement_transform(es, res) + } + } + } else { + Ok(res) + } +} diff --git a/rprt-engine/src/selection_functions/result_transformation.rs b/rprt-engine/src/selection_functions/result_transformation.rs index 89a071a..865038c 100644 --- a/rprt-engine/src/selection_functions/result_transformation.rs +++ b/rprt-engine/src/selection_functions/result_transformation.rs @@ -1,9 +1,11 @@ -use crate::buffer::BufferID; -use crate::selection::{Interval, Selection}; -use crate::selection_functions::types::{SFArguments, SFError, SFResult}; -use crate::state::EditorState; +use crate::{ + buffer::BufferID, + selection::{Interval, Selection}, + selection_functions::types::{SFArguments, SFError, SFResult}, + state::EditorState, +}; -pub fn complement_transform(es: &EditorState, result: Selection, _: &SFArguments) -> SFResult { +pub fn complement_transform(es: &EditorState, result: Selection) -> SFResult { fn complement_rank0( es: &EditorState, buffer_id: BufferID, @@ -55,11 +57,7 @@ pub fn complement_transform(es: &EditorState, result: Selection, _: &SFArguments result.vectorise(es, complement_rank0, complement_rank1) } -pub fn conditional_transform( - _: &EditorState, - mut result: Selection, - arg: &SFArguments, -) -> SFResult { +pub fn conditional_transform(mut result: Selection, arg: &SFArguments) -> SFResult { if !result.is_empty() { Ok(match arg { // TODO: think about this niladic case? diff --git a/rprt-engine/src/selection_functions/types.rs b/rprt-engine/src/selection_functions/types.rs index aaf0086..6bd94bf 100644 --- a/rprt-engine/src/selection_functions/types.rs +++ b/rprt-engine/src/selection_functions/types.rs @@ -1,6 +1,9 @@ -use crate::buffer::{Buffer, BufferID}; -use crate::selection::{Selection, VectoriseError}; -use crate::state::EditorState; +use crate::{ + buffer::{Buffer, BufferID}, + expression::BuiltinSelectionFn, + selection::{Selection, VectoriseError}, + state::EditorState, +}; use thiserror::Error; #[derive(Error, Debug)] @@ -9,8 +12,12 @@ pub enum SFError { BufferNotFound(BufferID), #[error("Function {0} has no dyadic form")] NoDyadicForm(&'static str), - #[error("Function {0} has no dyadic form")] + #[error("Function {0} has no niladic form")] NoNiladicForm(&'static str), + #[error("Selection functions take their primary argument on the left")] + NoLeftArgument, + #[error("{0} is not yet implemented")] + NotImplemented(BuiltinSelectionFn), } pub enum SFArguments<'a> { @@ -34,15 +41,16 @@ pub type SFResult = Result<Selection, VectoriseError<SFError>>; macro_rules! selection_function { ( name: $name:ident, + param_type: $P:ty, niladic: $niladic_body:expr, monadic_rank0: $monadic_rank0_body:expr, monadic_rank1: $monadic_rank1_body:expr ) => { - pub fn $name(arg: SFArguments) -> SFResult { + fn $name(param: $P, arg: &SFArguments) -> SFResult { match arg { - SFArguments::Niladic { es } => $niladic_body(es), + SFArguments::Niladic { es } => ($niladic_body)((param, es)), SFArguments::Monadic { es, left } => { - left.vectorise(es, $monadic_rank0_body, $monadic_rank1_body) + left.vectorise(&(param, es), $monadic_rank0_body, $monadic_rank1_body) } SFArguments::Dyadic { .. } => Err(SFError::NoDyadicForm(stringify!($name)).into()), } @@ -51,21 +59,27 @@ macro_rules! selection_function { } #[macro_export] -macro_rules! selection_function_param { +macro_rules! dispatch_selection_function { ( name: $name:ident, param_type: $P:ty, - niladic: $niladic_body:expr, - monadic_rank0: $monadic_rank0_body:expr, - monadic_rank1: $monadic_rank1_body:expr + base: $bs:ident, + sequential: $sq:ident, + reverse: $rv:ident, + sequential_reverse: $sr:ident, + reverse_sequential: $rs:ident, ) => { - pub fn $name(param: $P, arg: SFArguments) -> SFResult { - match arg { - SFArguments::Niladic { es } => ($niladic_body)((param, es)), - SFArguments::Monadic { es, left } => { - left.vectorise(&(param, es), $monadic_rank0_body, $monadic_rank1_body) - } - SFArguments::Dyadic { .. } => Err(SFError::NoDyadicForm(stringify!($name)).into()), + pub fn $name( + param: $P, + arg: &SFArguments, + search_mod: Option<crate::expression::SearchModifier>, + ) -> SFResult { + match search_mod { + None => ($bs)(param, arg), + Some(crate::expression::SearchModifier::Sequential) => ($sq)(param, arg), + Some(crate::expression::SearchModifier::Reverse) => ($rv)(param, arg), + Some(crate::expression::SearchModifier::SequentialReverse) => ($sr)(param, arg), + Some(crate::expression::SearchModifier::ReverseSequential) => ($rs)(param, arg), } } }; diff --git a/rprt-engine/src/state.rs b/rprt-engine/src/state.rs index 68283d0..80b5e86 100644 --- a/rprt-engine/src/state.rs +++ b/rprt-engine/src/state.rs @@ -1,5 +1,7 @@ -use crate::buffer::{Buffer, BufferID}; -use crate::selection::Selection; +use crate::{ + buffer::{Buffer, BufferID}, + selection::Selection, +}; use std::collections::{HashMap, HashSet}; use std::path::PathBuf; @@ -365,4 +367,4 @@ impl EditorState { } } -pub type EvaluationResult = (Selection, Vec<StateChange>); +pub type StateResult = (Selection, Vec<StateChange>); |
