wcore/
evaluator.rs

1use crate::models::{Range, State, Token, WCode, WFuncVariant, WTokens};
2use crate::parser::WParser;
3use crate::utils::{Utils, WFunc};
4use itertools::Itertools;
5
6pub trait WEval {
7    fn apply(&mut self, code: &str) -> Vec<WTokens>;
8    fn wsection_eval(&mut self, data: Vec<WCode>) -> Vec<WTokens>;
9    fn eval(&self, data: WTokens) -> WTokens;
10    fn dissolve(
11        &self,
12        code: &mut WTokens,
13        func: WFuncVariant,
14        argument_range: &std::ops::Range<usize>,
15        arr: WTokens,
16    );
17}
18
19impl WEval for State {
20    fn apply(&mut self, code: &str) -> Vec<WTokens> {
21        self.wsection_eval(self.parser(code))
22    }
23
24    fn wsection_eval(&mut self, data: Vec<WCode>) -> Vec<WTokens> {
25        let mut result: Vec<WTokens> = Vec::new();
26
27        for section in data {
28            match section.container {
29                Some(container) => {
30                    let mut cases = vec![];
31
32                    if let Some(container_cases) = section.cases {
33                        cases.append(&mut container_cases.clone())
34                    }
35
36                    cases.push((vec![Token::Value(1.0)], section.default_case));
37
38                    self.insert(container, cases);
39                }
40                None => result.push(self.eval(section.default_case)),
41            }
42        }
43
44        result
45    }
46
47    fn eval(&self, data: WTokens) -> WTokens {
48        let mut new_code = data;
49
50        while let Some((argument_range, func)) = new_code.first_function() {
51            if let Some((x, y)) = new_code.special_pairs("(", ")") {
52                let result = new_code[x + 1..y].to_vec();
53                new_code.splice(x..=y, self.eval(result));
54            } else {
55                let code_to_evaluate: WTokens = new_code[argument_range.clone()].to_vec();
56                self.dissolve(&mut new_code, func, &argument_range, code_to_evaluate);
57            }
58        }
59
60        new_code
61    }
62
63    fn dissolve(
64        &self,
65        code: &mut WTokens,
66        func: WFuncVariant,
67        argument_range: &std::ops::Range<usize>,
68        arr: WTokens,
69    ) {
70        match func {
71            WFuncVariant::Function(func) => {
72                let result = func(arr);
73                code.splice(argument_range.start..argument_range.end + 1, result);
74            }
75            WFuncVariant::Container(x) => {
76                let mut case: WTokens = vec![];
77                let mut container_acc: WTokens = vec![];
78
79                for container_case in self.get(&x).unwrap() {
80                    let mut joined = container_case.0.clone();
81                    joined.append(&mut container_case.1.clone());
82                    container_acc.append(&mut joined);
83
84                    let case_prefix = self.eval(self.apply(&container_case.0, &arr));
85
86                    if case_prefix[0] != Token::Value(0.0) {
87                        case = container_case.1.clone();
88                        break;
89                    }
90                }
91
92                let expanded_range = container_acc
93                    .iter()
94                    .filter(|x| matches!(x, Token::Parameter(_)))
95                    .flat_map(|range| match range {
96                        Token::Parameter(Range::Full(full)) => full.clone().collect::<Vec<_>>(),
97                        Token::Parameter(Range::From(from)) => (0..=from.end).collect::<Vec<_>>(),
98                        Token::Parameter(Range::To(to)) => {
99                            (to.start..=arr.len() - 1).collect::<Vec<_>>()
100                        }
101                        _ => panic!(),
102                    })
103                    .unique()
104                    .map(|wlang_index| arr.len() - (wlang_index + 1))
105                    .sorted()
106                    .rev()
107                    .collect::<Vec<usize>>();
108
109                let result = self.apply(&case, &arr);
110                code.splice(argument_range.end..=argument_range.end, result);
111                for n in expanded_range {
112                    code.remove(n);
113                }
114            }
115        }
116    }
117}