1use crate::calc::value::{Value, ValueRef};
2use crate::error::{EngineError, MyError, MyResult};
3use crate::read::count::Count;
4use crate::read::interface::{Directive, Interface, Operation};
5use num::CheckedSub;
6use std::cell::RefCell;
7use std::io::Write;
8use std::rc::Rc;
9
10pub enum Action<W: Write> {
11 Operation(Rc<Operation<W>>),
12 Directive(Rc<Directive<W>>, Vec<String>),
13 Definition(Vec<Action<W>>),
14 Value(ValueRef, bool),
15}
16
17impl<W: Write> Clone for Action<W> {
18 fn clone(&self) -> Self {
19 match self {
20 Self::Operation(operation) => Self::Operation(Rc::clone(operation)),
21 Self::Directive(directive, tokens) => Self::Directive(Rc::clone(directive), tokens.clone()),
22 Self::Definition(actions) => Self::Definition(actions.clone()),
23 Self::Value(value, dirty) => Self::Value(Rc::clone(value), *dirty),
24 }
25 }
26}
27
28pub struct Actions<'a, W: Write, I: Iterator<Item = &'a str>> {
29 interface: Rc<RefCell<Interface<W>>>,
30 tokens: I,
31}
32
33impl<'a, W: Write, I: Iterator<Item = &'a str>> Actions<'a, W, I> {
34 pub fn new(
35 interface: &Rc<RefCell<Interface<W>>>,
36 tokens: I,
37 ) -> Self {
38 let interface = Rc::clone(interface);
39 Self { interface, tokens }
40 }
41}
42
43impl<'a, W: Write, I: Iterator<Item = &'a str>> Iterator for Actions<'a, W, I> {
45 type Item = MyResult<(Action<W>, &'a str)>;
46
47 fn next(&mut self) -> Option<Self::Item> {
48 if let Some(token) = self.tokens.next() {
49 let interface = self.interface.borrow();
50 if let Some(operation) = interface.get_operation(token) {
51 let action = Action::Operation(operation);
52 return Some(Ok((action, token)));
53 } else if let Some(directive) = interface.get_directive(token) {
54 let mut tokens = Vec::new();
55 while let Some(token) = self.tokens.next() {
56 tokens.push(String::from(token));
57 }
58 let action = Action::Directive(directive, tokens);
59 return Some(Ok((action, token)));
60 } else if let Some(actions) = interface.get_definition(token) {
61 let action = Action::Definition(actions);
62 return Some(Ok((action, token)));
63 } else if let Some(value) = interface.get_variable(token) {
64 let action = Action::Value(value, true);
65 return Some(Ok((action, token)));
66 } else {
67 match Value::from_string(token) {
68 Ok(value) => {
69 let value = Rc::new(RefCell::new(value));
70 let action = Action::Value(value, false);
71 return Some(Ok((action, token)));
72 }
73 Err(_) => {
74 let error = EngineError::ParseError(String::from(token));
75 return Some(Err(MyError::from(error)));
76 }
77 }
78 }
79 }
80 None
81 }
82}
83
84pub fn fold_actions<W: Write>(actions: &Vec<Action<W>>) -> (Count, Count) {
85 actions.iter().fold((Count::Some(0), Count::Some(0)), fold_action)
86}
87
88fn fold_action<W: Write>((input, output): (Count, Count), action: &Action<W>) -> (Count, Count) {
89 match action {
90 Action::Operation(operation) => fold_operation(input, output, operation),
91 Action::Directive(_, _) => (input, output),
92 Action::Definition(actions) => fold_definition(input, output, actions),
93 Action::Value(_, _) => fold_value(input, output),
94 }
95}
96
97fn fold_operation<W: Write>(
118 input: Count,
119 output: Count,
120 operation: &Rc<Operation<W>>,
121) -> (Count, Count) {
122 let (input2, output2) = operation.count_parameters();
124 if let Some(output) = output.checked_sub(&input2) {
125 (input, output + output2)
127 } else {
128 let input2 = input2.checked_sub(&output).unwrap_or(Count::Some(0));
130 (input + input2, output2)
131 }
132}
133
134fn fold_definition<W: Write>(
135 input: Count,
136 output: Count,
137 actions: &Vec<Action<W>>,
138) -> (Count, Count) {
139 actions.iter().fold((input, output), fold_action)
140}
141
142fn fold_value(input: Count, output: Count) -> (Count, Count) {
143 (input, output + Count::Some(1))
144}
145
146#[cfg(test)]
148pub mod tests {
149 use crate::calc::value::tests::create_nan;
150 use crate::read::action::{fold_actions, Action};
151 use crate::read::count::Count;
152 use crate::read::interface::tests::{dummy_binary, dummy_directive, dummy_nullary, dummy_series, dummy_unary};
153 use crate::read::interface::{Completion, Directive, Operation};
154 use crate::util::text::tests::BufferWriter;
155 use std::rc::Rc;
156
157 #[test]
158 fn test_folds_values_only() {
159 let actions: Vec<Action<BufferWriter>> = vec![
160 ];
161 std::assert_eq!(fold_actions(&actions), (Count::Some(0), Count::Some(0)));
162
163 let actions: Vec<Action<BufferWriter>> = vec![
164 Action::Value(create_nan(), false),
165 Action::Value(create_nan(), false),
166 Action::Value(create_nan(), false),
167 ];
168 std::assert_eq!(fold_actions(&actions), (Count::Some(0), Count::Some(3)));
169 }
170
171 #[test]
172 fn test_folds_nullary_operation() {
173 let actions: Vec<Action<BufferWriter>> = vec![
174 Action::Value(create_nan(), false),
175 Action::Value(create_nan(), false),
176 Action::Operation(Rc::new(Operation::ValueNone(dummy_nullary))),
177 ];
178 std::assert_eq!(fold_actions(&actions), (Count::Some(0), Count::Some(3)));
179
180 let actions: Vec<Action<BufferWriter>> = vec![
181 Action::Value(create_nan(), false),
182 Action::Value(create_nan(), false),
183 Action::Operation(Rc::new(Operation::ValueNone(dummy_nullary))),
184 Action::Operation(Rc::new(Operation::ValueNone(dummy_nullary))),
185 ];
186 std::assert_eq!(fold_actions(&actions), (Count::Some(0), Count::Some(4)));
187 }
188
189 #[test]
190 fn test_folds_unary_operation() {
191 let actions: Vec<Action<BufferWriter>> = vec![
192 Action::Value(create_nan(), false),
193 Action::Value(create_nan(), false),
194 Action::Operation(Rc::new(Operation::ValueOne(dummy_unary))),
195 ];
196 std::assert_eq!(fold_actions(&actions), (Count::Some(0), Count::Some(2)));
197
198 let actions: Vec<Action<BufferWriter>> = vec![
199 Action::Value(create_nan(), false),
200 Action::Value(create_nan(), false),
201 Action::Operation(Rc::new(Operation::ValueOne(dummy_unary))),
202 Action::Operation(Rc::new(Operation::ValueOne(dummy_unary))),
203 ];
204 std::assert_eq!(fold_actions(&actions), (Count::Some(0), Count::Some(2)));
205 }
206
207 #[test]
208 fn test_folds_binary_operation() {
209 let actions: Vec<Action<BufferWriter>> = vec![
210 Action::Value(create_nan(), false),
211 Action::Value(create_nan(), false),
212 Action::Operation(Rc::new(Operation::ValueTwo(dummy_binary))),
213 ];
214 std::assert_eq!(fold_actions(&actions), (Count::Some(0), Count::Some(1)));
215
216 let actions: Vec<Action<BufferWriter>> = vec![
217 Action::Value(create_nan(), false),
218 Action::Value(create_nan(), false),
219 Action::Operation(Rc::new(Operation::ValueTwo(dummy_binary))),
220 Action::Operation(Rc::new(Operation::ValueTwo(dummy_binary))),
221 ];
222 std::assert_eq!(fold_actions(&actions), (Count::Some(1), Count::Some(1)));
223
224 let actions: Vec<Action<BufferWriter>> = vec![
225 Action::Value(create_nan(), false),
226 Action::Value(create_nan(), false),
227 Action::Operation(Rc::new(Operation::ValueTwo(dummy_binary))),
228 Action::Operation(Rc::new(Operation::ValueTwo(dummy_binary))),
229 Action::Operation(Rc::new(Operation::ValueTwo(dummy_binary))),
230 ];
231 std::assert_eq!(fold_actions(&actions), (Count::Some(2), Count::Some(1)));
232 }
233
234 #[test]
235 fn test_folds_series_operation() {
236 let actions: Vec<Action<BufferWriter>> = vec![
237 Action::Value(create_nan(), false),
238 Action::Value(create_nan(), false),
239 Action::Operation(Rc::new(Operation::ValueAll(dummy_series))),
240 ];
241 std::assert_eq!(fold_actions(&actions), (Count::All, Count::Some(1)));
242
243 let actions: Vec<Action<BufferWriter>> = vec![
244 Action::Value(create_nan(), false),
245 Action::Value(create_nan(), false),
246 Action::Value(create_nan(), false),
247 Action::Operation(Rc::new(Operation::ValueAll(dummy_series))),
248 ];
249 std::assert_eq!(fold_actions(&actions), (Count::All, Count::Some(1)));
250
251 let actions: Vec<Action<BufferWriter>> = vec![
252 Action::Value(create_nan(), false),
253 Action::Value(create_nan(), false),
254 Action::Value(create_nan(), false),
255 Action::Value(create_nan(), false),
256 Action::Operation(Rc::new(Operation::ValueAll(dummy_series))),
257 ];
258 std::assert_eq!(fold_actions(&actions), (Count::All, Count::Some(1)));
259 }
260
261 #[test]
262 fn test_folds_directive_as_noop() {
263 let actions: Vec<Action<BufferWriter>> = vec![
264 Action::Value(create_nan(), false),
265 Action::Value(create_nan(), false),
266 Action::Directive(Rc::new(Directive::EngineAll(dummy_directive, Completion::Keyword)), vec![]),
267 ];
268 std::assert_eq!(fold_actions(&actions), (Count::Some(0), Count::Some(2)));
269
270 let actions: Vec<Action<BufferWriter>> = vec![
271 Action::Value(create_nan(), false),
272 Action::Value(create_nan(), false),
273 Action::Directive(Rc::new(Directive::EngineAll(dummy_directive, Completion::Keyword)), vec![]),
274 Action::Directive(Rc::new(Directive::EngineAll(dummy_directive, Completion::Keyword)), vec![]),
275 ];
276 std::assert_eq!(fold_actions(&actions), (Count::Some(0), Count::Some(2)));
277 }
278
279 #[test]
280 fn test_folds_defined_function() {
281 let actions: Vec<Action<BufferWriter>> = vec![
282 Action::Value(create_nan(), false),
283 Action::Value(create_nan(), false),
284 Action::Operation(Rc::new(Operation::ValueNone(dummy_nullary))),
285 Action::Operation(Rc::new(Operation::ValueNone(dummy_nullary))),
286 ];
287 let actions: Vec<Action<BufferWriter>> = vec![
288 Action::Definition(actions),
289 ];
290 std::assert_eq!(fold_actions(&actions), (Count::Some(0), Count::Some(4)));
291
292 let actions: Vec<Action<BufferWriter>> = vec![
293 Action::Value(create_nan(), false),
294 Action::Value(create_nan(), false),
295 Action::Operation(Rc::new(Operation::ValueOne(dummy_unary))),
296 Action::Operation(Rc::new(Operation::ValueOne(dummy_unary))),
297 ];
298 let actions: Vec<Action<BufferWriter>> = vec![
299 Action::Definition(actions),
300 ];
301 std::assert_eq!(fold_actions(&actions), (Count::Some(0), Count::Some(2)));
302
303 let actions: Vec<Action<BufferWriter>> = vec![
304 Action::Value(create_nan(), false),
305 Action::Value(create_nan(), false),
306 Action::Operation(Rc::new(Operation::ValueTwo(dummy_binary))),
307 Action::Operation(Rc::new(Operation::ValueTwo(dummy_binary))),
308 Action::Operation(Rc::new(Operation::ValueTwo(dummy_binary))),
309 ];
310 let actions: Vec<Action<BufferWriter>> = vec![
311 Action::Definition(actions),
312 ];
313 std::assert_eq!(fold_actions(&actions), (Count::Some(2), Count::Some(1)));
314
315 let actions: Vec<Action<BufferWriter>> = vec![
316 Action::Value(create_nan(), false),
317 Action::Value(create_nan(), false),
318 Action::Operation(Rc::new(Operation::ValueAll(dummy_series))),
319 ];
320 let actions: Vec<Action<BufferWriter>> = vec![
321 Action::Definition(actions),
322 ];
323 std::assert_eq!(fold_actions(&actions), (Count::All, Count::Some(1)));
324 }
325}