aboutsummaryrefslogtreecommitdiff
path: root/rprt-engine/src/monad.rs
blob: ae0df3e9bea60ec0d89d2e98bb6d86c7ec139c7b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
use crate::{
    selection::Selection,
    state::{EditorState, EvaluationResult},
};

pub enum EvaluationStrategy {
    Sequential,
    Grouped,
}

pub type MonadicState = (EditorState, EvaluationResult);

pub struct EditorStateMonad {
    func: Box<dyn Fn(EditorState) -> MonadicState>,
}

impl EditorStateMonad {
    pub fn new(f: impl Fn(EditorState) -> MonadicState + 'static) -> Self {
        Self { func: Box::new(f) }
    }

    pub fn run(&self, initial_state: EditorState) -> MonadicState {
        (self.func)(initial_state)
    }

    pub fn run_with_strategy<E>(
        monads: Vec<EditorStateMonad>,
        strategy: EvaluationStrategy,
        initial_state: EditorState,
    ) -> Result<MonadicState, E> {
        match strategy {
            EvaluationStrategy::Sequential => {
                let mut state_changes = Vec::new();
                let mut last_selection = Selection::empty();
                let mut current_state = initial_state;

                for monad in monads {
                    let (new_state, (sel, st_ch)) = monad.run(current_state);
                    current_state = new_state;
                    last_selection = sel;
                    state_changes.extend(st_ch);
                }

                Ok((current_state, (last_selection, state_changes)))
            }
            EvaluationStrategy::Grouped => {
                panic!("TODO")
            }
        }
    }
}