aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--rprt-engine/src/evaluate.rs43
-rw-r--r--rprt-engine/src/lib.rs1
-rw-r--r--rprt-engine/src/monad.rs20
-rw-r--r--rprt-engine/src/parser.rs3
-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
-rw-r--r--rprt-engine/src/state.rs8
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>);