aboutsummaryrefslogtreecommitdiff
path: root/rprt-engine/src/selection_functions
diff options
context:
space:
mode:
Diffstat (limited to 'rprt-engine/src/selection_functions')
-rw-r--r--rprt-engine/src/selection_functions/function_character.rs31
-rw-r--r--rprt-engine/src/selection_functions/function_empty.rs6
-rw-r--r--rprt-engine/src/selection_functions/function_end.rs32
-rw-r--r--rprt-engine/src/selection_functions/mod.rs64
-rw-r--r--rprt-engine/src/selection_functions/result_transformation.rs18
-rw-r--r--rprt-engine/src/selection_functions/types.rs50
6 files changed, 150 insertions, 51 deletions
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),
}
}
};